【问题标题】:Eval code in node's global scope from within a module模块内节点全局范围内的评估代码
【发布时间】:2017-04-21 19:35:58
【问题描述】:

一般:在 node.js 中,如何访问正在执行的文件的范围?

示例:我有一个模块 (mod.js) 和一个需要它的文件 (main.js)。在 mod.js 中,我需要执行一个 eval() 来访问 main.js 的范围,如下所示:

mod.js:

exports.runCode = function(code) {
  var x = 1;
  // do some stuff to x and code
  return eval(code) + x;
}

main.js:

var amod = require('./mod');

var func = function(a,b) {
  return a + b;
}

console.log(amod.runCode('2+2'));    // works fine
console.log(amod.runCode('func()')); // ReferenceError: func is not defined

重击:

$ node main


到目前为止,我已经尝试过使用节点的全局、虚拟机和进程对象,以及各种闭包

还要注意,我只能控制 mod.js,而不是 main.js(是的,我知道安全隐患)

【问题讨论】:

  • 把mod.js改成exports.runCode = eval
  • 这是一个最小的例子。 -- runCode() 函数还有其他部分(我现在更新了上面的代码以显示这一点)
  • 那么是的,从 mod.js 访问 main.js 的范围是不可能的,你能做的最好的事情是 amod.runCode('func = ' + func + '; func(1, 2)') 或者只是 global.func = func 在 main.js 中。
  • 如果您的代码不比您的示例复杂,那么您可以简单地对函数进行字符串化,它就会起作用。 console.log(amod.runCode(`(${func.toString()})(2, 2)`)); 否则无法访问。我也错过了你的笔记I only have control over mod.js :)
  • 任意复杂

标签: javascript node.js scope eval


【解决方案1】:

根据rednoyz 的反馈,我意识到执行范围将是函数“定义”而不是模块。所以这里有一个新版本的 define 来修复它。

exports.define = function(__code) {
   eval.call(module, __code);
}

我还进行了测试以避免我在上一篇文章中犯的一些错误。

var amod = require('./mod');

amod.define("var f=function(a,b) {return a + b;}");
amod.define("var g=function(a,b) {return a*b;}");

console.log(amod.runCode('2+2'));    // works fine - 5
console.log(amod.runCode('f(2,3)')); // works fine - 6
console.log(amod.runCode('g(3,4)')); // works fine - 13

【讨论】:

  • 不要使用eval.call。它什么也没做。
  • 再说一次,如果我能控制 main.js,那就没问题了。这个想法是 main.js 由 mod.js 的用户编写,编写他们想要的任意函数,然后在可能包含或不包含函数调用的长文本字符串上调用单个 runCode() 函数。
  • 仍然不理想,但也许更好的是允许用户编写通用函数,然后将它们传递给 mod.js: function f(){...} amod.addToScope(f);需要测试这是否真的有效......
  • 似乎要做到这一点,我需要一种为特定上下文调用 eval 的方法(正如 Bergi 指出的那样,eval.call(...) 不起作用)
  • 亲爱的rednyz,你能粘贴你的代码吗?我实际上测试了第二篇文章中粘贴的所有内容,包括 eval.call 但也许我错过了一些东西。
【解决方案2】:

不幸的是,您必须在模块本身中定义要在模块中使用的函数,您可能可以编写一个新函数将这些函数注入模块的范围,

exports.define = function(__code) {
   eval(__code);
}

使用新的定义接口

amod.define('func = function(a,b) {
  return a + b;
}');

您还可以使用其他模式,例如将所有函数定义定义为一个对象并将其传递给模块以获取访问权限,或者您可以使用@idbehold 建议的全局范围

如果您破解了跨两个模块共享范围的方法,请与我们分享。

【讨论】:

  • 实际上,如果我不使用“var”而只说“func=function(){...}”,它似乎可以工作,但它并没有真正帮助,因为我可能已经定义了函数这样:函数 func() {...}
猜你喜欢
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2019-01-23
  • 1970-01-01
相关资源
最近更新 更多