简体   繁体   中英

How do I avoid nodejs vm script function call losing context when called function is itself in the context?

The problem: I'm using nodejs vm to run a supplied script (trusted source but not in my control). The supplied script must call back to a function I provide in the context it receives.

Functions internal to the script work as expected. But when a function supplied in the context is called, it no longer has any variables from the context provided to the called script. This short program demonstrates the problem:

var vm = require('vm');
var sandbox={console:console, myfn:function() {
        console.log("MYFN");
        console.log("MYFN: a="+a);
}, a:42};
var ctx = new vm.createContext(sandbox);
vm.runInContext("function okfn() { console.log('OKFN'); console.log('OKFN: a='+a); } console.log('TEST'); console.log('TEST: a='+a);okfn(); myfn();", ctx, {filename:"TEST"});

When it runs, I expect to see output of:

TEST
TEST: a=42
OKFN
OKFN: a=42
MYFN
MYFN: a=42

but instead, the last console.log in myfn() produces a ReferenceError: a is not defined

Is there a way to retain the context passed to the script via runInContext(), when that script makes calls to a function provided in the context itself?

Functions are bound to the global scope in which they are defined. As myfn was defined in the main script file, it will use the globals of that file. In order to bind that function to another global context, it must be redefined/re-executed in that context:

var vm = require('vm');

function myfn() {
    console.log("MYFN");
    console.log("MYFN: a="+ a);
}


var sandbox={console:console, a:42};
var ctx = new vm.createContext(sandbox);

// Evaluates the source code of myfn in the new context
// This will ensure that myfn uses the global context of 'ctx'
vm.runInContext(myfn.toString(), ctx, {filename: "TEST"});

// Retained in the context
console.log(ctx.myfn);

// Use it
vm.runInContext("function okfn() { console.log('OKFN'); console.log('OKFN: a='+a); } console.log('TEST'); console.log('TEST: a='+a);okfn();  myfn();", ctx, {filename:"TEST"});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM