diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 804d0154fac10a..ee175fa9c29f6f 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -209,7 +209,17 @@ class ContextifyContext { CHECK(!ctx.IsEmpty()); ctx->SetSecurityToken(env->context()->GetSecurityToken()); + + // We need to tie the lifetime of the sandbox object with the lifetime of + // newly created context. We do this by making them hold references to each + // other. The context can directly hold a reference to the sandbox as an + // embedder data field. However, we cannot hold a reference to a v8::Context + // directly in an Object, we instead hold onto the new context's global + // object instead (which then has a reference to the context). ctx->SetEmbedderData(kSandboxObjectIndex, sandbox_obj); + sandbox_obj->SetHiddenValue( + FIXED_ONE_BYTE_STRING(env->isolate(), "_contextifyHiddenGlobal"), + ctx->Global()); env->AssignToContext(ctx); diff --git a/test/parallel/test-vm-create-and-run-in-context.js b/test/parallel/test-vm-create-and-run-in-context.js index 94527598ca27b1..15efc8f527b8c9 100644 --- a/test/parallel/test-vm-create-and-run-in-context.js +++ b/test/parallel/test-vm-create-and-run-in-context.js @@ -1,4 +1,5 @@ 'use strict'; +// Flags: --expose-gc require('../common'); var assert = require('assert'); @@ -18,3 +19,11 @@ console.error('test updating context'); result = vm.runInContext('var foo = 3;', context); assert.equal(3, context.foo); assert.equal('lala', context.thing); + +// https://github.com/nodejs/node/issues/5768 +console.error('run in contextified sandbox without referencing the context'); +var sandbox = {x: 1}; +vm.createContext(sandbox); +gc(); +vm.runInContext('x = 2', sandbox); +// Should not crash.