首页 > 解决方案 > 更改 Node.js 中动态加载模块的全局范围

问题描述

从源动态加载模块:

var src="HERE GOES MY SOURCE"
var Module = module.constructor;
var m = new Module();
m._compile(src, 'a-path-that-does-not-exist');

需要达到以下几点:

  1. 传递一些变量/函数,以便它们可以在src脚本中全局使用。可以在“m.foo”中设置它们,但希望脚本使用“foo”而不使用“module.foo”。“global.foo”有效,但请参阅第 2 点。
  2. 如何限制src脚本访问全局范围?
  3. 如何限制src使用require或其他方式加载其他模块。
  4. 如何限制src运行异步操作?

标签: javascriptnode.jsplugins

解决方案


所有,我能想到的是将脚本包装在它自己的函数中,就像 nodejs 已经为 commonJS 模块所做的那样。这是常规包装。

(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});

如果您使用自己的包装器包装该用户代码,然后当您调用它来执行它时,您可以为 和任何其他半全局符号定义您自己的requiremodule

如果你也把'use strict'; 作为包装函数的第一行(在任何用户代码之前),那么这将消除对global对象的默认分配,x = 4因为如果没有首先明确定义,这将是一个错误x。如果您随后还创建自己的全局对象并将其作为参数传递,则可以防止任何人分配给真正的全局对象。我认为您不能阻止对预先存在的全局变量的隐式读取访问。

因此,您的包装器可能如下所示:

(function(exports, require, module, __filename, __dirname, global) {
     'use strict';
     // insert user code here before evaluating it with eval()
     // and getting the function which you can then call and pass the desired arguments
});

然后,当你调用这个函数时,你把你想要的所有参数的值传递给它(不是真实的)。


请注意,很难说这种方案的防漏性能到底如何。任何真正的安全都应该在资源受限的虚拟机中运行。


另一个想法,您可以在具有自己的原始全局变量集的工作线程中运行。因此,您完成上述所有操作并在工作线程中运行它。


在评论中解决您的问题:

是否“使用严格”;需要进入包装函数内部还是外部?

它必须是包装函数内的第一行代码,就在您插入用户代码的位置之前。这个想法是强制该包装器内的功能范围(用户代码所在的位置)处于严格模式,以限制它可以做的一些事情。

你能解释一下“我认为你不能阻止对预先存在的全局变量的隐式读取访问。”吗?如果我将自己的对象作为全局对象提供,内部脚本如何访问预先存在的全局对象?

Any code, even strict mode code can access pre-existing globals without the global prefix. While you can prevent the code from creating new globals by shadowing it with your own global in the wrapper function arguments and by forcing it into strict mode, you can't prevent strict mode code from reading existing globals because they can do so without the global prefix. So, if there's a pre-existing global called "foo", then existing code can reference that like:

 console.log(foo);

or

 foo = 12;

If there is no foo in a closer scope, the interpreter will find the foo on the global object and use that.

Note that strict mode prevents the automatic creation of a new global with something like:

 greeting = "happy birthday"

Could you elaborate more no "resource restricted VM"?

I was talking about real hardware/OS level VMs that allow you to fully control what resources a process may use (disk access, sockets, memory, hardware, etc...). It's essentially a virtual computer environment separate from any other VMs on the same system. This is a more rigorous level of control.

WorkerThread is a very interesting concept. will take a look! My understanding was that WorkerThreads provide memory isolation and the only way to share data is by sending messages (effectively creating copies)?

Yes, Worker Threads provide pretty good isolation as they start up a whole new JS engine and have their own globals. They can shared ArrayBuffers in certain ways (if you choose to do that), but normal JS variables are not accessible across thread boundaries. They would normally communicate via messaging (which is automatically synchronized through the event queue), but you could also communicate via sockets if you wanted.


推荐阅读