需求不能按预期在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作为参数。