I'm trying to to execute some javascript box in a sandbox environment. I'm trynig several approaches, but all the library I've tryed does not work exactly like the browser. Here is a list of test I need to pass to accomplish what I need: https://github.com/jurgob/js_questions/blob/master/src/utils/evaluateCode.test.js
Basically, this inside a nominal function should be the "global" scope, and if I declare a variable without var, or with var but in the "top level". Exactly like javascript is supposed to work. (not in strict mode, obviously). Least but not least, after the execution, your application global environment (window, in the browser) should does not have the variable set (my tests are not perfectly testing this). All those requirements are more or less expressed with the tests I wrote, so I "just" need to make them "green" :)
Here is my current implementation: https://github.com/jurgob/js_questions/blob/master/src/utils/evaluateCode.js it's just a simple eval, so it doesn't fit all the tests.
here his the attemps I did:
a) I've tried the global eval, but is not isolated (btw, there's an interesting article here: http://perfectionkills.com/global-eval-what-are-the-options/)
b) I used new Function("window", "with(window){" + code + "}")({});
, it solve the variable without var problem, but the this
inside the function is still wrong.
c) I've used https://github.com/dfkaye/vm-shim, but the code in the it(' function this = window with res = 5;',...
test is actually not sandboxed and "it(' function this = window with var res = 5;', " its failing cuz res is not assigned to the global scope
d) I tryed https://github.com/asvd/jailed, even If I don't like the idea to have iframe added to my DOM, but testing here: http://asvd.github.io/jailed/demos/web/console/ it seems not working 100% (I've opened an issue:https://github.com/asvd/jailed/issues/41
So my current Idea is that I could use acorn to bind all the funtions to the global object and execute the js in with(this), like:
const context = {
log
}
cons sCode = code // replace all "function a(){}"" with "a=a.bind(this);function a(){} "
new Function("window", "with(window){" + sCode + "}")({});
but the implementation is not that trivial and I'm not sure is the best way to do it