Skip to content

Commit 9634531

Browse files
committed
vm: fix symbol access
By using the new SetHandler API instead of SetNamedPropertyHandler, we can intercept symbols now. Fixes #884.
1 parent a40dbfd commit 9634531

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

src/node_contextify.cc

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ using v8::HandleScope;
2626
using v8::Integer;
2727
using v8::Isolate;
2828
using v8::Local;
29+
using v8::Maybe;
30+
using v8::MaybeLocal;
31+
using v8::Name;
32+
using v8::NamedPropertyHandlerConfiguration;
2933
using v8::None;
3034
using v8::Object;
3135
using v8::ObjectTemplate;
@@ -202,12 +206,14 @@ class ContextifyContext {
202206

203207
Local<ObjectTemplate> object_template =
204208
function_template->InstanceTemplate();
205-
object_template->SetNamedPropertyHandler(GlobalPropertyGetterCallback,
209+
210+
NamedPropertyHandlerConfiguration config(GlobalPropertyGetterCallback,
206211
GlobalPropertySetterCallback,
207212
GlobalPropertyQueryCallback,
208213
GlobalPropertyDeleterCallback,
209214
GlobalPropertyEnumeratorCallback,
210215
CreateDataWrapper(env));
216+
object_template->SetHandler(config);
211217

212218
Local<Context> ctx = Context::New(env->isolate(), nullptr, object_template);
213219
if (!ctx.IsEmpty())
@@ -342,7 +348,7 @@ class ContextifyContext {
342348

343349

344350
static void GlobalPropertyGetterCallback(
345-
Local<String> property,
351+
Local<Name> property,
346352
const PropertyCallbackInfo<Value>& args) {
347353
Isolate* isolate = args.GetIsolate();
348354
HandleScope scope(isolate);
@@ -351,22 +357,26 @@ class ContextifyContext {
351357
Unwrap<ContextifyContext>(args.Data().As<Object>());
352358

353359
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
354-
Local<Value> rv = sandbox->GetRealNamedProperty(property);
355-
if (rv.IsEmpty()) {
360+
MaybeLocal<Value> maybe_rv =
361+
sandbox->GetRealNamedProperty(ctx->context(), property);
362+
if (maybe_rv.IsEmpty()) {
356363
Local<Object> proxy_global = PersistentToLocal(isolate,
357364
ctx->proxy_global_);
358-
rv = proxy_global->GetRealNamedProperty(property);
359-
}
360-
if (!rv.IsEmpty() && rv == ctx->sandbox_) {
361-
rv = PersistentToLocal(isolate, ctx->proxy_global_);
365+
maybe_rv = proxy_global->GetRealNamedProperty(ctx->context(), property);
362366
}
363367

364-
args.GetReturnValue().Set(rv);
368+
Local<Value> rv;
369+
if (maybe_rv.ToLocal(&rv)) {
370+
if (rv == ctx->sandbox_)
371+
rv = PersistentToLocal(isolate, ctx->proxy_global_);
372+
373+
args.GetReturnValue().Set(rv);
374+
}
365375
}
366376

367377

368378
static void GlobalPropertySetterCallback(
369-
Local<String> property,
379+
Local<Name> property,
370380
Local<Value> value,
371381
const PropertyCallbackInfo<Value>& args) {
372382
Isolate* isolate = args.GetIsolate();
@@ -380,7 +390,7 @@ class ContextifyContext {
380390

381391

382392
static void GlobalPropertyQueryCallback(
383-
Local<String> property,
393+
Local<Name> property,
384394
const PropertyCallbackInfo<Integer>& args) {
385395
Isolate* isolate = args.GetIsolate();
386396
HandleScope scope(isolate);
@@ -389,35 +399,39 @@ class ContextifyContext {
389399
Unwrap<ContextifyContext>(args.Data().As<Object>());
390400

391401
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
392-
Local<Object> proxy_global = PersistentToLocal(isolate,
393-
ctx->proxy_global_);
394-
395-
if (sandbox->HasRealNamedProperty(property)) {
396-
PropertyAttribute propAttr =
397-
sandbox->GetRealNamedPropertyAttributes(property).FromJust();
398-
args.GetReturnValue().Set(propAttr);
399-
} else if (proxy_global->HasRealNamedProperty(property)) {
400-
PropertyAttribute propAttr =
401-
proxy_global->GetRealNamedPropertyAttributes(property).FromJust();
402-
args.GetReturnValue().Set(propAttr);
403-
} else {
404-
args.GetReturnValue().Set(None);
402+
403+
Maybe<PropertyAttribute> maybe_prop_attr =
404+
sandbox->GetRealNamedPropertyAttributes(ctx->context(), property);
405+
406+
if (maybe_prop_attr.IsNothing()) {
407+
Local<Object> proxy_global = PersistentToLocal(isolate,
408+
ctx->proxy_global_);
409+
410+
maybe_prop_attr =
411+
proxy_global->GetRealNamedPropertyAttributes(ctx->context(), property);
412+
}
413+
414+
if (maybe_prop_attr.IsJust()) {
415+
PropertyAttribute prop_attr = maybe_prop_attr.FromJust();
416+
args.GetReturnValue().Set(prop_attr);
405417
}
406418
}
407419

408420

409421
static void GlobalPropertyDeleterCallback(
410-
Local<String> property,
422+
Local<Name> property,
411423
const PropertyCallbackInfo<Boolean>& args) {
412424
Isolate* isolate = args.GetIsolate();
413425
HandleScope scope(isolate);
414426

415427
ContextifyContext* ctx =
416428
Unwrap<ContextifyContext>(args.Data().As<Object>());
429+
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
430+
431+
Maybe<bool> success = sandbox->Delete(ctx->context(), property);
417432

418-
bool success = PersistentToLocal(isolate,
419-
ctx->sandbox_)->Delete(property);
420-
args.GetReturnValue().Set(success);
433+
if (success.IsJust())
434+
args.GetReturnValue().Set(success.FromJust());
421435
}
422436

423437

test/parallel/test-vm-symbols.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
var common = require('../common');
4+
var assert = require('assert');
5+
6+
var vm = require('vm');
7+
8+
var symbol = Symbol();
9+
10+
function Document() {
11+
this[symbol] = 'foo';
12+
}
13+
14+
Document.prototype.getSymbolValue = function() {
15+
return this[symbol];
16+
};
17+
18+
var context = new Document();
19+
vm.createContext(context);
20+
21+
assert.equal(context.getSymbolValue(), 'foo',
22+
'should return symbol-keyed value from the outside');
23+
24+
assert.equal(vm.runInContext('this.getSymbolValue()', context), 'foo',
25+
'should return symbol-keyed value from the inside');

0 commit comments

Comments
 (0)