Skip to content

Commit 3b021ef

Browse files
domenicrvagg
authored andcommitted
vm: fix symbol access
By using the new SetHandler API instead of SetNamedPropertyHandler, we can intercept symbols now. This forces us to use Maybes and MaybeLocals more, since this new API does not have a non-maybe variant. Fixes: #884 PR-URL: #1773 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 7b81e4b commit 3b021ef

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

src/node_contextify.cc

+42-28
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,30 +348,34 @@ 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

349355
ContextifyContext* ctx =
350356
Unwrap<ContextifyContext>(args.Data().As<Object>());
351357

352358
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
353-
Local<Value> rv = sandbox->GetRealNamedProperty(property);
354-
if (rv.IsEmpty()) {
359+
MaybeLocal<Value> maybe_rv =
360+
sandbox->GetRealNamedProperty(ctx->context(), property);
361+
if (maybe_rv.IsEmpty()) {
355362
Local<Object> proxy_global = PersistentToLocal(isolate,
356363
ctx->proxy_global_);
357-
rv = proxy_global->GetRealNamedProperty(property);
358-
}
359-
if (!rv.IsEmpty() && rv == ctx->sandbox_) {
360-
rv = PersistentToLocal(isolate, ctx->proxy_global_);
364+
maybe_rv = proxy_global->GetRealNamedProperty(ctx->context(), property);
361365
}
362366

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

366376

367377
static void GlobalPropertySetterCallback(
368-
Local<String> property,
378+
Local<Name> property,
369379
Local<Value> value,
370380
const PropertyCallbackInfo<Value>& args) {
371381
Isolate* isolate = args.GetIsolate();
@@ -378,42 +388,46 @@ class ContextifyContext {
378388

379389

380390
static void GlobalPropertyQueryCallback(
381-
Local<String> property,
391+
Local<Name> property,
382392
const PropertyCallbackInfo<Integer>& args) {
383393
Isolate* isolate = args.GetIsolate();
384394

385395
ContextifyContext* ctx =
386396
Unwrap<ContextifyContext>(args.Data().As<Object>());
387397

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

405417

406418
static void GlobalPropertyDeleterCallback(
407-
Local<String> property,
419+
Local<Name> property,
408420
const PropertyCallbackInfo<Boolean>& args) {
409421
Isolate* isolate = args.GetIsolate();
410422

411423
ContextifyContext* ctx =
412424
Unwrap<ContextifyContext>(args.Data().As<Object>());
425+
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
426+
427+
Maybe<bool> success = sandbox->Delete(ctx->context(), property);
413428

414-
bool success = PersistentToLocal(isolate,
415-
ctx->sandbox_)->Delete(property);
416-
args.GetReturnValue().Set(success);
429+
if (success.IsJust())
430+
args.GetReturnValue().Set(success.FromJust());
417431
}
418432

419433

test/parallel/test-vm-symbols.js

+25
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)