簡體   English   中英

在 Node.js 中為動態加載的模塊更改全局 Scope

[英]Altering Global Scope for dynamically loaded module in 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腳本訪問全局scope?
  3. 如何限制src使用require或其他方式加載其他模塊。
  4. 如何限制src運行異步操作?

所有,我能想到的是將腳本包裝在它自己的 function 中,就像 nodejs 已經為 commonJS 模塊所做的那樣。 這是常規包裝。

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

如果您使用自己的包裝器包裝該用戶代碼,然后當您調用它來執行它時,您可以為requiremodule和任何其他半全局符號定義自己的值。

如果你也把'use strict'; 作為包裝器 function 的第一行(在任何用戶代碼之前),那么這將消除對global object 的默認分配,僅使用x = 4之類的東西,因為如果沒有先明確定義x將是一個錯誤。 如果您隨后還創建自己的全局 object 並將其作為參數傳遞,則可以防止任何人分配給真正的全局 object。 我認為您不能阻止對預先存在的全局變量的隱式讀取訪問。

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

(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
});

然后,當您調用此 function 時,您將所有 arguments 的值(不是真實值)傳遞給它。


請注意,很難說這種方案的防漏性能到底如何。 任何真正的安全都應該在資源受限的虛擬機中運行。


另一個想法,您可以在具有自己的原始全局變量集的工作線程中運行。 因此,您執行上述所有操作並在工作線程中運行它。


在評論中解決您的問題:

是否“使用嚴格”; 需要 go 在包裝器 function 內部還是外部?

它必須是包裝器 function 中的第一行代碼,就在您插入用戶代碼的位置之前。 這個想法是強制 function scope(用戶代碼所在的位置)在該包裝器中處於嚴格模式,以限制它可以做的一些事情。

你能解釋一下“我認為你不能阻止對預先存在的全局變量的隱式讀取訪問。”嗎? 如果我提供自己的 object 作為全局變量,內部腳本如何訪問預先存在的全局變量?

任何代碼,甚至是嚴格模式代碼都可以在沒有global前綴的情況下訪問預先存在的全局變量。 雖然您可以通過在包裝器 function arguments 並通過強制它進入嚴格模式來阻止代碼創建新的global變量,但您不能阻止嚴格模式代碼讀取現有的全局變量,因為它們可以在沒有全局變量的情況下這樣做字首。 因此,如果有一個預先存在的名為“foo”的全局變量,那么現有代碼可以像這樣引用它:

 console.log(foo);

或者

 foo = 12;

如果在更近的 scope 中沒有foo ,解釋器將在全局 object 上找到foo並使用它。

請注意,嚴格模式會阻止自動創建新的全局,例如:

 greeting = "happy birthday"

您能否詳細說明沒有“資源受限的虛擬機”?

我說的是真正的硬件/操作系統級別的虛擬機,它們允許您完全控制進程可能使用的資源(磁盤訪問、sockets、memory、硬件等)。 它本質上是一個與同一系統上的任何其他 VM 分開的虛擬計算機環境。 這是一個更嚴格的控制水平。

WorkerThread 是一個非常有趣的概念。 會看嗎? 我的理解是 WorkerThreads 提供 memory 隔離,共享數據的唯一方法是發送消息(有效地創建副本)?

是的,工作線程提供了很好的隔離,因為它們啟動了一個全新的 JS 引擎並擁有自己的全局變量。 它們可以以某種方式共享 ArrayBuffers(如果你選擇這樣做的話),但是普通的 JS 變量不能跨線程邊界訪問。 它們通常會通過消息傳遞(通過事件隊列自動同步)進行通信,但如果需要,您也可以通過 sockets 進行通信。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM