Node JavaScript contexts sharing built-in prototypes?
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 -开发者_如何学Python> 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.
Conclusion
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.
The test
// 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]
精彩评论