Sandbox Code Using Web Workers

Last updated on Tuesday, March 5th, 2019 @ 9:29AM.

I recently wrote following code to see if I could leverage Web Workers for running YourJS Console code:

How To Use It

Sandbox is a prototype that can be used to run JavaScript code in an environment that has no access to the environment from which it is called. You can create an instance by doing the following:

var sb = new Sandbox();

The Sandbox constructor can be called with one argument which will be interpreted as the code to initialize the sandbox:

var sb = new Sandbox('const fullName = "John Smith";');
sb.run('console.log(`My name is ${fullName}.`);');

Here are the available functions:

  • Sandbox.prototype.restart(…)

    Terminates and restarts the sandbox while allowing for different initial code. Once called anything run in the previous sandbox will be terminated.

    Parameters

    • opt_initCode
      Optional. The code initialize the sandbox with. If not specified the sandbox will be initialized with the initialization code that was optionally specified when the sandbox was instantiated.
  • Sandbox.prototype.terminate()

    Terminates the sandbox thereby preventing any further calls to eval(…), run(…) or importScripts(…) from doing anything.
  • Sandbox.prototype.eval

    Evaluates the specified code in the sandbox's global scope but in it's own block-level.

    Parameters

    • code
      The code to be executed.
    • opt_callback
      Optional. If specified this callback function will be called with the result of the evaluated expression as long as the result can be cloned.
  • Sandbox.prototype.run

    Runs the specified code in the sandbox's global block-level.

    Parameters

    • code
      The code to be executed.
  • Sandbox.prototype.importScripts

    Imports the specified script(s) into the sandbox.

    Parameters

    • scriptUrls
      One or more URLs to scripts that should be imported into the sandbox.

Drawbacks

This solution is nice but it has a few drawbacks:

  • One major drawback that prevents me from actually using it for the YourJS Console is the fact that you can't receive Function or Error objects from it (as is brought by this MDN page).
  • Another Drawback is that it doesn't give me the ability to really run a segment of code in the global block without using eval(). The reason I was hoping to be able to do this is because if you open up the real JS console in your browser you will see that it is possible to define constants that will persist by using the const keyword. On the hand, if you run the same code using global eval (eg. const name = "John Smith";) the constant name will not be available to any code outside of the code that is run by that eval() call. In other words, the name constant is not actually added to the global scope (not even if you use this technique to evaluate globally). It is important to note that setTimeout() will execute the code globally but as is the case with script injection you will not be able to get the return value.

In Conclusion…

This is a nice solution to be able to run code in a sandboxed environment. The fact that there are limitations on the communication between web workers and the browser presents limitations for the sandbox solution. The fact that this solution doesn't allow for a true global block-level solution to calling eval() prevents me from using it to replace the current sandboxing system that is used by YourJS Console. Feel free to use this Sandbox prototype in your code. Happy coding!!!