When creating a new context with Node's vm.runInNewContext
, are built-in (Object
, Function
, etc.) prototypes shared or not?
Documentation on runInNewContext
says:
Running
code
does not have access to local scope and the objectsandbox
will be used as the global object forcode
.
Is Object.prototype
in the global scope, hence not shared?
In node_script.cc:338-345
and node_script.cc:403-409
I see it's referencing the objects, so are those objects, from sandbox
, using the Object.prototype
of the parent context which calls vm.runInNewContext
and objects created in the new context using a different Object.prototype
?
(Note: vm
module is a maze: vm
module -> evals
process.binding -> node_script.cc
source)
As far as I know the code is run in a completely new context, with different global constructors for Object, Array, etc.
Object.prototype.a = function() { console.log('hello'); };
({}).a(); // 'hello'
require('vm').runInNewContext('({}).a();'); // should throw
I don't think it would really be a new context if Object::a had access to variables in the original context.
This has some implications though:
vm.runInNewContext('[];') instanceof Array; // returns false
Because that array was created with a completely different constructor, the instanceof operator will be affected.
Inside a vm.runInNewContext
, there are two Object.prototype
s: one that is created inside the new context and one that is referencing to the parent context, via the sandbox
. Apparently, Node has set the security tokens correctly, so contexts are allowed to access the parent's objects.
Is
Object.prototype
in the global scope, hence not shared?
It is not in the global scope, but in the context. It's not shared.
In node_script.cc:338-345 and node_script.cc:403-409 I see it's referencing the objects, so are those objects, from sandbox, using the Object.prototype of the parent context which calls vm.runInNewContext and objects created in the new context using a different Object.prototype?
Yes.
When creating a new context with Node's vm.runInNewContext, are built-in (Object, Function, etc.) prototypes shared or not?
Not shared.
// Test
var vm = require('vm');
var parentLog = function(message) {
process.stdout.write(message + "\n");
}
Object.prototype.test = "[parent Object.prototype.test]";
var parentObject = new String("[parent parentObject]");
var parentSandbox = {
log: parentLog,
testObject: parentObject,
};
var parentCode =
"log('vm testObject: ' + testObject);" +
"log('vm testObject.test: ' + testObject.test);" +
"log('vm create Object.prototype.test');" +
"Object.prototype.test = '[vm Object.prototype.test]';" +
"log('vm Object.prototype.test: ' + Object.prototype.test);" +
"log('vm testObject.test: ' + testObject.test);";
parentLog('pre-parent parentObject: ' + parentObject);
parentLog('pre-parent parentObject.test: ' + parentObject.test);
parentLog('pre-parent Object.prototype: ' + Object.prototype.test);
var parentScript = vm.createScript(parentCode, "<test>");
parentScript.runInNewContext(parentSandbox);
parentLog('post-parent parentObject: ' + parentObject);
parentLog('post-parent parentObject.test: ' + parentObject.test);
parentLog('post-parent Object.prototype: ' + Object.prototype.test);
Output:
pre-parent parentObject: [parent parentObject]
pre-parent parentObject.test: [parent Object.prototype.test]
pre-parent Object.prototype: [parent Object.prototype.test]
vm testObject: [parent parentObject]
vm testObject.test: [parent Object.prototype.test]
vm create Object.prototype.test
vm Object.prototype.test: [vm Object.prototype.test]
vm testObject.test: [parent Object.prototype.test]
post-parent parentObject: [parent parentObject]
post-parent parentObject.test: [parent Object.prototype.test]
post-parent Object.prototype: [parent Object.prototype.test]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With