require('vm') runInNewContext - Bug in treating objects #1518

Closed
gitfy opened this Issue Aug 12, 2011 · 10 comments

Comments

Projects
None yet
2 participants

gitfy commented Aug 12, 2011

Hi,
I see a problem in the way objects are handled between the current context and the vm context.

I can explain better with the following example what is happening :

var vm = require('vm');

var val = {};
console.log('Outside the VM');
console.log('Result - ' + (val.constructor == Object));
console.log('JSON conversion Result - ' + (JSON.parse(JSON.stringify(val)).constructor == Object));

var val = vm.runInNewContext("var func = function(){ var val = { }; return val;}; func();", {});

console.log('Return value from VM');
console.log('Result - ' + (val.constructor == Object));
console.log('JSON conversion Result - ' + (JSON.parse(JSON.stringify(val)).constructor == Object));

The results for the above code is :
Outside the VM
Result - true
JSON conversion Result - true

Return value from VM
Result - false
JSON conversion Result - true

The first two results show the comparison in the current context. The object is treated the same way, no issues.

The next two results show an object return from running inside the vm and observe the first equality where it fails. But when you use the conversion (stringify <-> parse) and compare the results, they become equal.

Is this a bug in the execution context of the vm or can some one explain what i am doing wrong ?

Thanks.

Owner

bnoordhuis commented Aug 13, 2011

Is this a bug in the execution context

No. Each context has distinct root objects. That is, context1.Object !== context2.Object. The Object class that your variable val is an instance of, is from a different context than the Object class you're comparing it with.

It's similar to how in Java a class Foo loaded with classloader A is distinct from that same class loaded with classloader B.

bnoordhuis closed this Aug 13, 2011

gitfy commented Aug 13, 2011

hi,
thanks for the explanation. but i need this to executed in a similar context so that things like dont break my logic. is there way to achieve this safely without using eval.

Owner

bnoordhuis commented Aug 13, 2011

You probably want vm.runInThisContext() or vm.createContext() and vm.runInContext().

gitfy commented Aug 14, 2011

I couldn't find documentation about createcontext and runincontext.....also I couldn't understand what runinthscontext means.....what this means? ....would it possible for you provide some explanation or point me to docc that illustrates.

Thanks.

Owner

bnoordhuis commented Aug 14, 2011

vm.runInThisContext() is documented here. For the other two you'll have to read the source but essentially you create a context with vm.createContext() that's shared in successive calls to vm.runInContext().

gitfy commented Aug 15, 2011

I saw that. What was not explained is, what "this" in the runInThisContext, how can i pass come context information to the code that will be executed. With runInNewContext - it was possible using the sandbox. Is there a way to same some context with runInThisContext.

Owner

bnoordhuis commented Aug 15, 2011

this is the current context.

var x = 42
console.error(require('vm').runInThisContext('x'))
// prints "42"

Please submit a pull request if the documentation has room for improvement.

gitfy commented Aug 15, 2011

Hey, thanks for help me out.

I tried that, and it doesn't work like that. For the above code, i get an error "x is not defined". That's why i kept coming back for an explanation.

Owner

bnoordhuis commented Aug 15, 2011

The example above doesn't work in the REPL or if NODE_MODULE_CONTEXTS=1 but it should work if you run it as a standalone script. Make sure you're using the latest stable or master.

gitfy commented Aug 15, 2011

I ran it as standalone script. May be in my version this is not supported yet.
I am using the version 0.4.8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment