diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 81d0388a35f390..c89c89bd388379 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -26,10 +26,15 @@ using v8::HandleScope; using v8::Integer; using v8::Isolate; using v8::Local; +using v8::Maybe; +using v8::MaybeLocal; +using v8::Name; +using v8::NamedPropertyHandlerConfiguration; using v8::None; using v8::Object; using v8::ObjectTemplate; using v8::Persistent; +using v8::PropertyAttribute; using v8::PropertyCallbackInfo; using v8::Script; using v8::ScriptCompiler; @@ -201,14 +206,14 @@ class ContextifyContext { Local object_template = function_template->InstanceTemplate(); - object_template->SetNamedPropertyHandler(GlobalPropertyGetterCallback, + + NamedPropertyHandlerConfiguration config(GlobalPropertyGetterCallback, GlobalPropertySetterCallback, GlobalPropertyQueryCallback, GlobalPropertyDeleterCallback, GlobalPropertyEnumeratorCallback, CreateDataWrapper(env)); - object_template->SetAccessCheckCallbacks(GlobalPropertyNamedAccessCheck, - GlobalPropertyIndexedAccessCheck); + object_template->SetHandler(config); Local ctx = Context::New(env->isolate(), nullptr, object_template); if (!ctx.IsEmpty()) @@ -342,24 +347,8 @@ class ContextifyContext { } - static bool GlobalPropertyNamedAccessCheck(Local host, - Local key, - AccessType type, - Local data) { - return true; - } - - - static bool GlobalPropertyIndexedAccessCheck(Local host, - uint32_t key, - AccessType type, - Local data) { - return true; - } - - static void GlobalPropertyGetterCallback( - Local property, + Local property, const PropertyCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); @@ -368,22 +357,26 @@ class ContextifyContext { Unwrap(args.Data().As()); Local sandbox = PersistentToLocal(isolate, ctx->sandbox_); - Local rv = sandbox->GetRealNamedProperty(property); - if (rv.IsEmpty()) { + MaybeLocal maybe_rv = + sandbox->GetRealNamedProperty(ctx->context(), property); + if (maybe_rv.IsEmpty()) { Local proxy_global = PersistentToLocal(isolate, ctx->proxy_global_); - rv = proxy_global->GetRealNamedProperty(property); - } - if (!rv.IsEmpty() && rv == ctx->sandbox_) { - rv = PersistentToLocal(isolate, ctx->proxy_global_); + maybe_rv = proxy_global->GetRealNamedProperty(ctx->context(), property); } - args.GetReturnValue().Set(rv); + Local rv; + if (maybe_rv.ToLocal(&rv)) { + if (rv == ctx->sandbox_) + rv = PersistentToLocal(isolate, ctx->proxy_global_); + + args.GetReturnValue().Set(rv); + } } static void GlobalPropertySetterCallback( - Local property, + Local property, Local value, const PropertyCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); @@ -397,7 +390,7 @@ class ContextifyContext { static void GlobalPropertyQueryCallback( - Local property, + Local property, const PropertyCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); @@ -406,30 +399,39 @@ class ContextifyContext { Unwrap(args.Data().As()); Local sandbox = PersistentToLocal(isolate, ctx->sandbox_); - Local proxy_global = PersistentToLocal(isolate, - ctx->proxy_global_); - - bool in_sandbox = sandbox->GetRealNamedProperty(property).IsEmpty(); - bool in_proxy_global = - proxy_global->GetRealNamedProperty(property).IsEmpty(); - if (!in_sandbox || !in_proxy_global) { - args.GetReturnValue().Set(None); + Maybe maybe_prop_attr = + sandbox->GetRealNamedPropertyAttributes(ctx->context(), property); + + if (maybe_prop_attr.IsNothing()) { + Local proxy_global = PersistentToLocal(isolate, + ctx->proxy_global_); + + maybe_prop_attr = + proxy_global->GetRealNamedPropertyAttributes(ctx->context(), + property); + } + + if (maybe_prop_attr.IsJust()) { + PropertyAttribute prop_attr = maybe_prop_attr.FromJust(); + args.GetReturnValue().Set(prop_attr); } } static void GlobalPropertyDeleterCallback( - Local property, + Local property, const PropertyCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); ContextifyContext* ctx = Unwrap(args.Data().As()); + Local sandbox = PersistentToLocal(isolate, ctx->sandbox_); + + Maybe success = sandbox->Delete(ctx->context(), property); - bool success = PersistentToLocal(isolate, - ctx->sandbox_)->Delete(property); - args.GetReturnValue().Set(success); + if (success.IsJust()) + args.GetReturnValue().Set(success.FromJust()); } diff --git a/test/parallel/test-vm-preserves-property.js b/test/parallel/test-vm-preserves-property.js new file mode 100644 index 00000000000000..85ce2d6e8165c8 --- /dev/null +++ b/test/parallel/test-vm-preserves-property.js @@ -0,0 +1,25 @@ +'use strict'; + +var common = require('../common'); +var assert = require('assert'); + +var vm = require('vm'); + +var x = {}; +Object.defineProperty(x, 'prop', { + configurable: false, + enumerable: false, + writable: false, + value: 'val' +}); +var o = vm.createContext(x); + +var code = 'Object.getOwnPropertyDescriptor(this, "prop")'; +var res = vm.runInContext(code, o, 'test'); + +assert(res); +assert.equal(typeof res, 'object'); +assert.equal(res.value, 'val'); +assert.equal(res.configurable, false, 'should not be configurable'); +assert.equal(res.enumerable, false, 'should not be enumerable'); +assert.equal(res.writable, false, 'should not be writable'); diff --git a/test/parallel/test-vm-symbols.js b/test/parallel/test-vm-symbols.js new file mode 100644 index 00000000000000..d7d0ffe3af6157 --- /dev/null +++ b/test/parallel/test-vm-symbols.js @@ -0,0 +1,25 @@ +'use strict'; + +var common = require('../common'); +var assert = require('assert'); + +var vm = require('vm'); + +var symbol = Symbol(); + +function Document() { + this[symbol] = 'foo'; +} + +Document.prototype.getSymbolValue = function() { + return this[symbol]; +}; + +var context = new Document(); +vm.createContext(context); + +assert.equal(context.getSymbolValue(), 'foo', + 'should return symbol-keyed value from the outside'); + +assert.equal(vm.runInContext('this.getSymbolValue()', context), 'foo', + 'should return symbol-keyed value from the inside');