0

バックグラウンド

Backbone.sync を置き換える Backbone.jsのBackbone.dualStorageプラグインのテストに取り組んでいます。

これはブラウザ プラグインですが、jasmine-node を使用してテストしています。windowvm.createContext を使用してブラウザーをシミュレートするために、coffeescript ソースをノード環境にロードします。

vm = require 'vm'
fs = require 'fs'
coffee = require 'coffee-script'
backboneDualstoragePath = './backbone.dualstorage.coffee'
source = fs.readFileSync(backboneDualstoragePath, 'utf8')
window = require('./global_test_context.coffee').window
context = vm.createContext window
coffee.eval source, sandbox: context, filename: backboneDualstoragePath
exports.window = context

これはうまく機能します。私のテストでは、にアクセスできますwindow.foo。foo は、global_test_context.coffee のウィンドウ オブジェクトにエクスポートされた属性です。

Jasmine スパイを使用して、ウィンドウ サンドボックスの下にネストされたオブジェクトのメソッドを再定義できます。例えば:

spyOn(window.Store.prototype, 'create').andReturn(true)
window.Store.create() # The spy is called
window.localsync.create() # This function instantiates a Store object and calls create on it
                          # The spy is called

ただし、コンテキストの直接属性をスパイまたは変更しようとすると、サンドボックス コンテキスト内で変更が見られません。

spyOn(window, 'localsync').andReturn(true)
window.localsync() # The spy is called
window.dualsync() # This function references the global localsync
                  # The original localsync is called

vm.createContext のドキュメントには次のように書かれています。

(V8) コンテキストは、組み込みオブジェクトと関数のセットと共にグローバル オブジェクトで構成されます。オプションの引数 initSandbox は、コンテキストによって使用されるグローバル オブジェクトの初期コンテンツをシードするために浅いコピーされます。

したがって、属性をウィンドウ変数から vm コンテキストにコピーするように思えます。この時点以降にスパイまたはその他の方法で変更する場合windowは、vm コンテキストを使用して、.xml という名前の属性としてエクスポートしますwindow。したがって、上記の段落は無関係だと思いますが、間違っている場合に備えて含めたいと思いました。

質問

イベントの流れは次のようになります。

window = vm.createContext({globalVariables: forTesting...})

# similiar to vm.runInContext(backboneDualstorageSource, window)
coffee.eval(backboneDualstorageSource, sandbox: window)

# localsync and dualsync are both defined in the backboneDualstorageSource
spyOn(window, 'localsync')
window.dualsync() # calls the original localsync instead of the spy

VM コンテキストの属性を変更した後、VM 内の「グローバル」属性/関数への参照が変更されないのはなぜですか? これを理解したい。

テスト中のブラウザ スクリプトで /spyOn グローバルを変更できるようにするには、どうすればこれを回避できますか?

ソースを自由に見て、この質問のスニペットと比較して、実際にどのように記述されているかをよく理解してください。

編集

残りのテスト済みコードと同様に、コンテキストで実行される eval 内にスパイを作成することで、この問題を回避することができました。https://github.com/nilbus/Backbone.dualStorage/commit/eb6c2b21を参照してください

グローバル変数にアクセスできるにもかかわらず、コンテキスト内ではグローバル変数を変更できるが、コンテキスト外では変更できない理由を誰かが説明できますか?

4

2 に答える 2

0

私があなたの問題を正しく理解していれば、evalの後にコンテキストを変更しても、すでに評価されているスクリプトには影響しません。コンテキストに新しいメンバーを追加する必要がなく、既存のメンバーを変更するだけでよい場合は、最新のノード(現時点では0.8.x)で正常に機能しているgetterを使用します。

于 2012-10-30T18:24:02.127 に答える
-1

globalキーで1 レベル下がらないように、次のことを試してください。

window = vm.createContext({variablesForTesting.. })
于 2012-10-30T14:43:04.107 に答える