1. What is a sandbox

A sandbox, as the name suggests, allows your programs to run in an isolated environment, with no impact on other programs outside of it. By creating a separate environment like a sandbox, programs running inside the sandbox cannot permanently affect the hard disk. [1] For example, when we submit the algorithm code in LeetCode, we use sandbox to create an independent running environment to run the code and ensure the security of the machine. Use Docker to create a separate application container in the service area The closest thing to us is our browser window, and each browser window is actually a sandbox.

2. What can the JS sandbox do

As we saw earlier, the sandbox allows the program to run in an isolated environment that has no impact on the outside world. Therefore, the sandbox can serve as a relatively safe environment to run certain programs or code. Such as:

  1. JS online editor: you can sandbox the user input code to run, so as not to affect the user input information page operation.

  2. Server rendering: For example, during vUE server rendering, the server will create a sandbox using the VM in Node and run the front-end bundle code in the sandbox so as not to affect the normal operation of Node service.

  3. Evaluation of expressions in VUE templates: Evaluation of expressions in VUE templates is sandboxed and can only access a whitelist of global variables, such as Math and Date. You cannot attempt to access user-defined global variables in template expressions.

There are many other uses of the sandbox, but the purpose of the sandbox is to create a relatively independent environment for running untrusted code or programs

3. How to implement sandbox

Before when I was at the jquery source code to see the author created a immediate execution function to prevent the pollution and global variables of internal external exposure $, this is actually a simple sandbox, but it’s not safe, just a scope sandbox, is not an independent running environment, he is still able to access external global variables.

    (function(window) {
        window$=... }) (window)
Copy the code

Here are two ways to implement sandbox

3.1 Sandbox implementation using IFrame

Iframe is essentially a closed sandbox environment in which users can embed pages using iframe

    <iframe src="..."  />
Copy the code

The following figure shows some permissions controls in iframeAlthough iframe is easy to use and powerful, it has some disadvantages:

1. The URL is not synchronized. The browser refresh iframe URL status is lost, and the back forward button is unavailable.

2. UI is not synchronized and DOM structure is not shared. Imagine a pop-up with a mask layer in the bottom right corner of the iframe, and we want the pop-up to center the browser and automatically center the browser when resize.

3. The global context is completely isolated and memory variables are not shared. Iframe internal and external system communication, data synchronization and other requirements, the cookie of the main application should be transparently transmitted to the sub-applications with different root domain names to achieve the effect of free registration.

4. Slowly. Each child application entry is a process of browser context reconstruction and resource reloading.[2]

3.2 Implement JS sandbox with + new Function + proxy

Let’s start with the use of ‘with’ (not recommended by itself)

    var a = {
        b: 1
    }
    with(a) {
        console.log(b); // return 1 equal to a.b
    }
Copy the code

New Function usage method

    const fun = new Function('a'.'console.log(a)'); // Return a function
    fun('hello'); // hello
Copy the code

After a brief introduction to the use of with and new Function, combine the two

    function sandBox(code) {
        const withStr = `with(obj) { ${ code }} `;
        return new Function('obj', withStr);
    }
    const tmpObj = { a: 'hello' }
    sandBox('console.log(a)')(tmpObj); // hello;
Copy the code

Although the above method is implemented to find obj. A, but because of the characteristics of with: if the search cannot be found in OBJ, it will search up and prototype until the prototype chain is empty. So if you declare an A variable globally and don’t declare a variable in obj, console.log(a) will look up the a variable, which doesn’t satisfy the sandbox closure condition.

    // When a variable is declared externally and the object passed in does not have a teammate's key, the a variable is looked up
    function sandBox(code) {
        const withStr = `with(obj) { ${ code }} `;
        return new Function('obj', withStr);
    }
    var tmpObj = { };
    var a = 'world';
    sandBox('console.log(a)')(tmpObj); // world;
Copy the code

The solution to this problem is to use proxies

    function sandBox(code) {
        const withStr = `with(obj) { ${ code }} `;
        const fun = new Function('obj', withStr);
        return function(obj) {
            const proxy = new Proxy(obj, { has: handle });
            returnfun(proxy); }}function handle(target, key) {
        if (['console'].indexOf(key) >= 0) {
            return target[key];
        } 
        if (target.hasOwnProperty(key)) {
            return target[key];
        }
        else {
            throw `${ key } is not defined`}}var obj = { a: 'hello world' };
    var b = 'test';
    sandBox(`console.log(a)`)(obj); // hello world;
    sandBox(`console.log(b)`)(obj); // error
Copy the code

The sandbox environment in Node

Node natively implements a VM module that uses the createContext and runInContext in other VMS to create an execution context:

    const vm = require('vm');
    const code = `var c = a + ' ' + b; `;
    const context = { a: 'hello'.b: 'world', }
    vm.createContext(context);
    vm.runInContext(code, context);
    console.log(context.c); // hello world
Copy the code

conclusion

In general, the purpose of the sandbox is to create a separate environment for running unstable or untrusted programs or code that will not pollute the world.

Afterword.

A few days ago, I looked at the source code of Ant Financial’s micro front-end framework qiankun, and found that it implemented a sandbox, so I learned about the sandbox

  • If there are any errors in this article, please correct them in the comments section.

Refer to the article

Why not iframe