需求不能按预期在vm内工作

下面的代码使用本地节点vm库,它允许您在不同的上下文中计算javascriptstring。

example.js的特定代码有一个javascriptstring,它向Array全局variables添加属性.marker ,值为true ,然后需要文件global.js (见下文),然后loggingArray.marker 。 下面的代码logging为true

 var vm = require('vm') var code = [ 'Array.marker = true', "require('./global.js')", 'console.log(Array.marker)', // => true ].join('\n') var script = new vm.Script(code, { filename: 'example.js' }) script.runInNewContext({ 'require': require, 'console': console }) 

以下是global.js的内容,它是一个将Array.marker的值更改为false的简单模块。

 var hi = function () { Array.marker = false } module.exports = hi() 

这里应该发生的事情是, vm中的代码应该将Array.marker设置为true那么global.js模块应该将其值更改为false并且它应该logging为false

如果你继续在vm之外运行javascriptstring的内容,在它自己的文件中,你会得到预期的结果, Array.marker将等于false

 Array.marker = true require('./global.js') console.log(Array.marker) // => false 

问题是: 为什么Array.marker没有更新到正确的值( true )? 我怎样才能让Array.marker的值从global.js模块中更新?

这是本地node.js vm模块的问题? 或者这不应该是可能的? 还是我的设置closures?

更新:

我认为这个bug更深一点。 它更多地与导入的require的行为,然后它与vm ,以更准确地certificate这一点。

这里我改变了一个新的vm上下文中的Array.marker的值,你可以看到它在vm运行后对全局的Array.marker没有影响。 这是预期的行为,因为我没有把任何东西传入vm

 var vm = require('vm') var code = [ 'Array.marker = true', ].join('\n') vm.runInNewContext(code) console.log(Array.marker) // => undefined [expected] 

然而,当我把require带入vm时,会发生一些非常意想不到的事 所需的代码保持父上下文的范围。 所以用给定的代码,你会得到意想不到的结果。 vm脚本Array.marker由于require调用而没有更改,您可以通过设置Array.marker来看到require调用正在编辑父范围。

 var vm = require('vm') var code = [ 'Array.marker = true', "require(\'./global.js\')", 'console.log(Array.marker)' // => true [unexpected] ].join('\n') vm.runInNewContext(code, { require: require, console: console }) console.log(Array.marker) // => false [unexpected] 

真正的问题是如何在vm实例化一个新的require实例,而不是导入父vm ? 保持它本地化的vm而不是让它泄漏到父母。

会这样的工作吗?

 var gbl = require('./global.js'); scriptText = "Array.marker = true; gbl(Array.marker);" var context = vm.createContext(); var script = vm.createScript(scriptText); var fn = script.runInContext(context); fn(gbl); 

您需要更改global.js中的函数来接受Array.marker作为参数。