2016-04-26 7 views
11

Chciałbym uruchomić plik JavaScript innej firmy (nie mam dużej kontroli nad jego zawartością) w węźle i uzyskać dostęp do zmiennej globalnej utworzonej przez ten plik w jego kontekście.Uruchom kod js w oddzielnym kontekście i uzyskaj dostęp do jego globalnej zmiennej

Są dwie rzeczy, które już za:

  1. przebiegu kod w vm piaskownicy. Problem polega na tym, że nie wiem, jak poprawnie utworzyć kontekst, ponieważtworzy się kontekst, ponieważ vm.createContext([sandbox]) nie zapewnia automatycznie podstawowych rzeczy, takich jak console lub require lub cokolwiek innego niż skrypt, który chcę uruchomić.

    Jest nieco wpadki, ponieważ dokumentacja wyraźnie stwierdza (Kopalnia nacisk):

    If given a sandbox object, will "contextify" that sandbox so that it can be used in calls to vm.runInContext() or script.runInContext(). Inside scripts run as such, sandbox will be the global object, retaining all its existing properties but also having the built-in objects and functions any standard global object has.

    Jakie są „wbudowanych obiektów i funkcji każdy standard globalny obiekt został”? Naiwnie zakładam, że to rzeczy takie jak console, process, require itd. Ale jeśli tak, API nie działa, ponieważ te nie są ustawione. Prawdopodobnie coś tu nie rozumiem.

    var sandbox = vm.createContext({foo: 'foo'}); 
    var code = 'console.log(foo);'; 
    vm.runInContext(code, sandbox); 
    

    co skutkuje:

    evalmachine.:1
    console.log(foo);
    ^
    ReferenceError: console is not defined

  2. Uruchamianie kodu w child process. Ale nie mogę znaleźć żadnej dokumentacji dotyczącej dostępu do zmiennych globalnych procesów potomnych. Jestem zakładając, że jedynym sposobem komunikowania się z procesem potomnym jest przekazywanie komunikatów, ale mimo to wydaje się być z rodzica na dziecko okrągły, a nie inny sposób ...

Zasadniczo Utknąłem . Halp.

+0

@dandavis Dowolny typ (możliwy do serializacji). – Oleg

+0

'child_process.exec (polecenie [, opcje] [, oddzwanianie])' callback zapewnia wyjście do bufora stdOut, więc jeśli twój podproces 'console.logs (strJSON)', możesz odzyskać go w callbacku . inne dobre sposoby są skomplikowane, ale możesz używać HTTP lub plików tymczasowych po prostu do wykonania niektórych zadań ... "IPC" – dandavis

+0

@dandavis Myślałem o tym, ale kod może zrobić własne logowanie i wolałbym nie ingerować . – Oleg

Odpowiedz

5

Można użyć advanced vm/sandbox for Node.js

var VM = require('vm2').NodeVM; // https://github.com/patriksimek/vm2#nodevm 

var options = { 
    console: 'inherit', 
    sandbox: { 
     foo: 'foo' 
    } 
} 

vm = new VM(options); 

var code = ` 
    console.log(foo); 
    oldFoo = foo; 
    foo = Math.random(); 
`; 

vm.run(code); 

console.log(vm.context.oldFoo, vm.context.foo); 
+0

Wygląda schludnie i działa całkiem nieźle, +1. Występują jednak problemy dotyczące krawędzi. Na przykład zauważyłem brak obsługi dla "process.exit". – Oleg

+0

Możesz użyć 'try {vm.run} catch (e) {}', aby odpowiedzieć na takie przypadki? –

0

Jak o właśnie mijając rodziców console w kontekście?

const vm = require('vm'); 

var sandbox = { 
    console: console 
}; 

var context = new vm.createContext(sandbox); 
var script = new vm.Script('console.log("foo")'); 

script.runInContext(context); 
+0

Zastanowiłem się nad tym i problem polega na tym, że uruchamiany kod może wymagać innych rzeczy, takich jak 'require',' process', '__dirname' ... Nie mogę i niestety wymienić ich wszystkich. – Oleg

+0

Założę się, że nie chcesz dać niezaufanemu kodowi dostępu do tych symboli. Jeśli tak, po prostu przekazuj 'global' jako' sandbox'. –

Powiązane problemy