4

JavaScript で単純な REPL (読み取り、評価、印刷、ループ) の実装を作成しています。次のように、コードと呼び出しコンテキストを分離できます。

var sandbox = {
  // Allow the input code to use predefined helper functions
  // without the preceding use of the this keyword.
  helper_fn: function() { alert("foo"); }
};

var func = new Function("with (this) { " + user_inputed_code + " }");
func.call(sandbox);

これで を閉じてuser_inputed_codethisリファラーが にsandboxアクセスし、入力されたコードが にアクセスまたは変更thisした場合に影響を与えsandboxます。

しかし、帰属コードが誤って変数割り当ての前にキーワードvarを付け忘れた場合、グローバル名前空間が汚染されることに気付きました。

これを防ぐ方法はありますか?もしそうなら、どのように(おそらく正規表現?)?これにアプローチするより良い方法はありますか?

4

2 に答える 2

2

他の人がここで議論したものとはまったく異なる 2 つのアプローチを提供します。どちらも抜本的であり、環境を比較的分離したい場合に役立ちます。

  • すべてのブラウザーで機能する最も簡単な手法は、おそらく iframe を作成し、そこにスクリプト タグを追加することです。(少なくとも古いブラウザーでは、同じドメインにある場合、非常に熱心な iframe がそれを超える可能性があることに注意してください)。それについては、この質問で説明します。
  • デフォルトで隔離された環境を持ち、メイン実行スレッドのグローバル オブジェクトにアクセスできない Web ワーカーを使用します。それについては、この質問で説明します。

より具体的には、REPL を構築している場合は、この回答を参照してください。ここでは、iframe の最初のアプローチを使用して、同じスコープ内でグローバル スコープ外のコードを評価する方法について説明します。

(私はブラウザを仮定しました。ノードでは、vmモジュールを簡単に使用して、runInContextでコンテキストを選択できます)

于 2013-07-26T13:23:14.713 に答える
1

"use strict"ありとなしの方法があることがわかりましたObject.freeze。グローバル名前空間を独自のサンドボックス オブジェクトに手動で置き換える必要があります。

var sandbox, module, func, output;
// Empty object or with defined methods / properties
// you want to expose as globals.
sandbox = {};
// A reference to an object you WANT to provide safe
// access to. In this example it's just an empty object.
module = {};
// A better version of eval:
func = new Function("module", "with(this){return(function(module,global,window){\"use strict\";return eval(\"" + code + "\");})(module,this,this)}");
output = func.call(sandbox, module);

このコードにより、global と window は、グローバル名前空間ではなく、サンドボックス化されたオブジェクトを参照できます。global変数とwindowをサンドボックス オブジェクトとしてマスカレードし、 を使用"use strict"すると、入力が の使用を逃した場合に例外がスローされますvar。また、関数をwithステートメントでラップして、サンドボックス オブジェクトで定義されたメソッドとプロパティを、それらの前に が付いているかのように機能させthis.ます。実装例 (テスト仕様付き) を確認するには、この要点を確認してください。

皆さんのアイデアに感謝します。この答えが他の人に役立つことを願っています。

于 2013-07-26T12:42:51.583 に答える