Require 在 vm 中没有按预期工作
Require does not work as expected within vm
下面的代码使用本机节点 vm
库,它允许您在不同的上下文中评估 javascript 字符串。
example.js
中的特定代码有一个 javascript 字符串,它添加一个 属性 .marker
值 true
到 Array
全局变量,然后需要文件 global.js
(见下文),然后记录 Array.marker
。下面的代码记录 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
并且它应该记录 false
。
如果你继续 运行 vm
之外的 javascript 字符串的内容,在它自己的文件中,你将得到预期的结果,Array.marker
将等于 false
。
Array.marker = true
require('./global.js')
console.log(Array.marker) // => false
问题是:为什么 Array.marker
没有更新为正确的值 (true
)? 我怎样才能允许从 global.js
模块中更新 Array.marker
的值?
这是原生 node.js vm
模块的问题吗?或者这不应该是可能的?还是我的设置关闭了?
更新:
我认为这个错误有点深。它与导入的 require
的行为有关,然后与 vm
的行为有关,以更准确地证明这一点。
在这里,我在一个新的 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
时,一些意想不到的事情发生了。所需的代码维护父上下文的范围。因此,使用给定的代码,您会得到意想不到的结果。由于 require 调用,vm 脚本中的全局 Array.marker
没有改变,您可以看到 require 调用正在通过设置 Array.marker
.
来编辑父作用域
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
而不是让它泄漏到父级中。
这样的东西行得通吗?
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 作为参数。
下面的代码使用本机节点 vm
库,它允许您在不同的上下文中评估 javascript 字符串。
example.js
中的特定代码有一个 javascript 字符串,它添加一个 属性 .marker
值 true
到 Array
全局变量,然后需要文件 global.js
(见下文),然后记录 Array.marker
。下面的代码记录 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
并且它应该记录 false
。
如果你继续 运行 vm
之外的 javascript 字符串的内容,在它自己的文件中,你将得到预期的结果,Array.marker
将等于 false
。
Array.marker = true
require('./global.js')
console.log(Array.marker) // => false
问题是:为什么 Array.marker
没有更新为正确的值 (true
)? 我怎样才能允许从 global.js
模块中更新 Array.marker
的值?
这是原生 node.js vm
模块的问题吗?或者这不应该是可能的?还是我的设置关闭了?
更新:
我认为这个错误有点深。它与导入的 require
的行为有关,然后与 vm
的行为有关,以更准确地证明这一点。
在这里,我在一个新的 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
时,一些意想不到的事情发生了。所需的代码维护父上下文的范围。因此,使用给定的代码,您会得到意想不到的结果。由于 require 调用,vm 脚本中的全局 Array.marker
没有改变,您可以看到 require 调用正在通过设置 Array.marker
.
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
而不是让它泄漏到父级中。
这样的东西行得通吗?
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 作为参数。