2016-11-14 5 views
0

ノード内のVMのコンテキストでどのように値を取得しますか。ノードのコアvmモジュールから値を取得する

コンテキストを作成してスクリプトを実行すると、util.inspect([[context]])を使用しますか?

もし私がしたら、それは連載されて戻ってくるのですか?それは '\'null'\'

に戻ってくる、私はutil.inspect("null")何らかの理由で

いずれも理由がわからんし、また、ノードVMのモジュールで実行コンテキストから値を取得するにはどのような最良の方法は?

私はまた、いくつかのマイクロベンチマークを行いました。新しいコンテキストの作成は、thisContextでの実行よりもはるかに遅いようです。また、私はタイムアウトを取り除くと、そのように見える多くのを実行しているようです。

だから、漏れを起こさないためにグローバルを使わずにこのコンテキストを使いたいと思っています。また、このパフォーマンスをスピードアップしようとしています。

このコードのコンテキストは、私が大惨事な正規表現をサンドボックスしようとしていることです。

global.mapperContext = { 
    result: false 
}; 

const scriptString = ` 
    global.mapperContext.result = true; 

    if ("${string}".match(${regex})) { 
    global.mapperContext.result = false; 
    } 
`; 

const vmScript = new vm.script(scriptString); 

try { 
    vmScript.runInThisContext({ timeout: 1000 }); 
} catch (e) { 
    // Do something with error 
} 

// This works but I dont like attaching things to the global object. 
// I could cause memory leaks... 
console.log(global.mapperContext); 
const mapperContext = { result }; 

const scriptString = ` 
(function IIFE() { 

    result = true; 

    if ("${string}".match(${regex})) { 
    result = false; 
    } 

})() 
`; 

const sandbox = vm.createContext(mapperContext); 
const script = new vm.script(scriptString); 

script.runInContext(script, sandbox, {timeout: 1000}); 

// This result is serialized and is hard to parse. 
util.inspect(sandbox.result); 
+0

達成しようとしているものの簡単な(コード)例を提供できますか? – mscdex

+0

@mscdexチケットを更新しました。 –

答えて

2

あなたのコードはほとんど正しいですが、あなたのscript.runInContext()ではなく、次のようになります。その変更に伴い

script.runInContext(sandbox, {timeout: 1000}); 

は、あなたがブール値としてsandbox.resultが表示されるはずです。

パフォーマンスが向上する限り、script.runInContext()への複数のコールで​​変数を再利用できるようにする必要があります。

他にも、値セットごとに新しいスクリプトを作成するのではなく、同じスクリプトに渡すことで、文字列と正規表現の値を再利用できる汎用スクリプトを作成することもできます。たとえば:あなたも考えるかもしれ

const vm = require('vm'); 
const mapperContext = { result: false, string: 'bar', regex: /baa/ }; 

const scriptString = ` 
(function IIFE() { 

    result = true; 

    if (regex.test(string)) { 
    result = false; 
    } 

})() 
`; 

// Only perform these two calls once ... 
const sandbox = vm.createContext(mapperContext); 
const script = new vm.Script(scriptString); 

// ... and then run the script as many times as needed ... 
script.runInContext(sandbox, {timeout: 1000}); 
console.dir(sandbox.result); 

// ... 

mapperContext.string = 'foo'; 
mapperContext.regex = /foo/; 
script.runInContext(sandbox, {timeout: 1000}); 
console.dir(sandbox.result); 

// ... 

一つのねじれは、単純に関数内でグローバル(result)、戻り値はscript.runInContext()の戻り値として利用可能であるそのように設定するのではなく、ブール値を返すことです。たとえば:

const vm = require('vm'); 
const mapperContext = { string: 'bar', regex: /baa/ }; 
const scriptString = 'regex.test(string);'; 
const sandbox = vm.createContext(mapperContext); 
const script = new vm.Script(scriptString); 
var ret; 

ret = script.runInContext(sandbox, {timeout: 1000}); 
console.dir(ret); 

// ... 

mapperContext.string = 'foo'; 
mapperContext.regex = /foo/; 
ret = script.runInContext(sandbox, {timeout: 1000}); 
console.dir(ret); 

// ... 

最後に、もちろんあなたは、タイムアウトがある場合に、try-catchブロック内script.runInContext()にあなたの呼び出しをラップすることを確認したくなるでしょう。パフォーマンス(ノード前ノードv7.0.0)では、ノードv7、V8がtry-catch(またはtry-finally)を含む関数全体を完全に非最適化するため、別の関数でこのtry-catchを分離する必要があります。

const vm = require('vm'); 

function tryRun(string, regex, timeout) { 
    var ctx = tryRun.ctx; 
    var sandbox = tryRun.sandbox; 
    var script = tryRun.script; 
    if (!ctx) { 
    ctx = tryRun.ctx = { string: string, regex: regex }; 
    sandbox = tryRun.sandbox = vm.createContext(ctx); 
    script = tryRun.script = new vm.Script('regex.test(string)'); 
    } else { 
    ctx.string = string; 
    ctx.regex = regex; 
    } 
    timeout = timeout || 1000; 
    try { 
    return script.runInContext(sandbox, {timeout}); 
    } catch (ex) { 
    return ex; 
    } 
} 

console.dir(tryRun('bar', /baa/)); 

// ... 

console.dir(tryRun('foo', /foo/)); 

// ... 

// Example of timeout 
console.dir(tryRun('xxxx'.repeat(100), /(x+x+)+y/)); 

// ... 
+0

ありがとう。私はそれらのショットを与えるよ! –

関連する問題