1

Harmony Proxies を試していて、コードを Proxy コンテキストで実行したいと考えています。つまり、コードのグローバル オブジェクトは Proxy になります。たとえば、コードで関数 foo() を呼び出すと、プロキシの get() メソッドによって管理されます。

しかし、Proxy.create() と vm.runInNewContext() を使用しても機能しません。Proxy オブジェクトが新しいコンテキスト オブジェクトによって上書きされ、プロパティが失われているようです。

var vm = require('vm');

var proxy = Proxy.create({
    get: function(a, name){
        return function(){
            console.log(arguments);
        }
    }
});

vm.runInNewContext("foo('bar')", proxy); // ReferenceError: foo is not defined

私がやろうとしていることを達成する方法はありますか?

// 編集

(function() {
    eval("this.foo('bar')");
}).call(proxy);

上記のコードはうまく機能しますが、thisステートメントを使用せずに、グローバル コンテキストを直接参照できるようにしたいと考えています。

4

3 に答える 3

1

簡単な答え: 考えないでください。:)

より長い答え: V8 のグローバル オブジェクトの処理には、フレーム、セキュリティ アクセス チェックなどのブラウザーの問題に対処するために、多くの魔法が関係しています。現状では、その魔法は、代わりにプロキシを使用することと完全に互換性がありません。 . これは最終的に変更される可能性がありますが、すぐには変更されません。

そうは言っても、そうすべきではないとも思います。グローバル オブジェクトは非常にハックな機能であり、Harmony では格下げされる予定です。これを使って汚いトリックを試みないことをお勧めします。

于 2012-06-06T15:13:07.387 に答える
1
global.__proto__ = forwarder(global.__proto__);
console.log([hello, my, name, is, bob, weeeee])

function forwarder(target){
  var traps = {
    getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor.bind(null, target),
    getOwnPropertyNames: Object.getOwnPropertyNames.bind(null, target),
    keys: Object.keys.bind(null, target),
    defineProperty: Object.defineProperty.bind(null, target),
    get: function(r,k){ return target[k] },
    set: function(r,k,v){ target[k] = v; return true },
    has: function(k){ return k in target },
    hasOwn: function(k){ return {}.hasOwnProperty.call(target, k) },
    delete: function(k){ delete target[k]; return true },
    enumerate: function(){ var i=0,k=[]; for (k[i++] in target); return k }
  };

  var names = {
    get: 1,
    set: 1,
    has: 0,
    hasOwn: 0,
    delete: 0,
    defineProperty: 0,
    getOwnPropertyDescriptor: 0
  }

  return Proxy.create(Proxy.create({
    get: function(r, trap){
      return function(a, b){
        if (trap in names)
          console.log(trap, arguments[names[trap]])
        else
          console.log(trap);

        if (trap === 'get' && !target[b]);
          return b;

        if (trap in traps)
          return traps[trap].apply(target, arguments);
      }
    }
  }), Object.getPrototypeOf(target));
}
于 2012-06-13T14:31:18.717 に答える
1

これには 2 つの方法があります。Node では、わずかに変更された contextify を使用してこれを行うことができました。Contextify は、任意のオブジェクトをグローバル コンテキストに変換して、vm モジュールと同様に実行できるようにするモジュールです。これは、オブジェクトへのアクセスを転送する名前付きプロパティ インターセプターを持つグローバル オブジェクトを作成することでこれを行います。これにより、ノードの組み込み vm のようにプロパティをコピーする代わりに、参照を「ライブ」に保つことができます。私が行った変更は、これらのアクセスが正しいプロキシ トラップをトリガーするように変更することctx->sandbox->GetRealNamedProperty(property)でした。ctx->sandbox->Get(property). has、set などの同様の変更。プロパティのリストを処理する機能 (少なくとも getOwnPropertyNames の場合) が API に公開されていないため、プロパティの列挙は正しく機能しません (また、通常のコンテキスト化でも機能しません)。

Contextify: https://github.com/brianmcd/contextify 私のフォーク: https://github.com/Benvie/contextify プルリクエスト: https://github.com/brianmcd/contextify/pull/23

2 番目の方法は普遍的に機能しますが、実際にはプロキシ グローバルにはなりません。基本的に、既存のオブジェクトごとにグローバルにプロキシを作成し、作成された関数内に必要なコードをロードして、すべてのプロパティを関数パラメーターとしてシャドウします。何かのようなもの:

var globals = Object.getOwnPropertyNames(global);
var proxies = globals.map(function(key){
  return forwardingProxy(global[key]);
});
globals.push(codeToRun);
var compiled = Function.apply(null, globals);
var returnValue = compiled.apply(forwardingProxy(global), proxies);
于 2012-06-10T15:38:05.400 に答える