Javascript Code Runner
exec.js
(922 bytes) is a low latency javascript code runner that enables to isolate and abort javascript code execution, including setTimeout/setInterval, promises and Fetch requests. It supports all browsers.
The code is executed in an isolated container with fine grained restriction capabilities, access to DOM and the ability to return functions and objects without serialization or cloning.
For some workloads, the javascript performance appears to be better than a WebWorker in modern browsers, without blocking UI (see tests). The startup latency can be reduced to <1ms compared to ~100ms for a WebWorker (2018).
In future versions of Chrome exec.js
may be executed in a separate thread (multi-threading), offering an advantage over Web Workers. For more information, see Out-of-Process iframes (OOPIFs).
Table of contents
- Install
- Simple example
- Abortable Fetch (extension)
- Security / code isolation
- Performance
- DOM access
- Abort code execution
- Content Security Policy (CSP) Whitelist
Install
with npm:
npm install exec.js
with bower:
bower install exec.js
Usage
Include exec.js
in the HTML document.
Use var runner = new exec(code[, onmessage][, sandbox][, csp]);
to execute javascript code in an isolated container. You can provide the code as a string or as a function.
// start code runner with onmessage callbackvar runner = 'setInterval(function() {console.log("startup code")},200);onmessage=function(data){console.log("UI sent",data);};' { console; }; // start code runner with security isolation// var runner = new exec('console.log("secured code");',null,['allow-pointer-lock'],{"default-src": "domain.com","script-src":"'sha256-076c8f1ca6979ef156b510a121b69b6265011597557ca2971db5ad5a2743545f'"}); // execute code in containerrunner; // redefine onmessage callbackrunner; // post data to containerrunner; // execute code in containerrunner; // execute code in containerrunner; // post function to containerrunner; // stop code executionrunner; // this will abruptly stop any code execution including unfinished promises // chain'onmessage=function(data){console.log(data);}'null'allow-pointer-lock' ;
You can return data from your code using the postMessage(data)
function. You can receive data in the container by defining onmessage=function(e) { // e.data }
in the container.
Simple Fetch request
var runner = { ; } { // process fetch response responsetext; }; // timeout in 5 seconds;
Abortable Fetch
Include exec-fetch.js
(221 bytes) in the HTML document.
The native fetch API is now enhanced with a .abort()
method. This is not a Polyfill.
// normal fetch requestvar request = ; // abort request after 10ms;
Fine tune the timeout to test Fetch request and/or response cancellation.
Abortable fetch requires a dedicated exec.js
container per fetch request. Use a container pool to improve performance.
Performance
Enhance the performance of exec.js
when making subsequent/simultaneous requests by creating a container pool. Code isolation can be applied as a third parameter.
// create container pool for performance; // exec(5,null,[]); // pool with code isolation enabled console;var url = 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js';;;;;;console;
Abort / cancel code execution
To cancel code execution, use runner.stop()
.
var runner = 'setInterval(function() {console.log(123);},100);';;
Access to DOM
To access the DOM, use parent.document
(info). DOM access is available in all browsers.
var runner = 'setInterval(function() {var h = parent.document.createElement(\'h1\');h.innerHTML = \'test\';parent.document.body.insertBefore(h, parent.document.body.firstChild);},100);';;
Security / code isolation
It is possible to isolate the code to be executed and block access to DOM, navigation, popups, form submission and other specific privileges by passing a third parameter with an array of sandbox parameters and/or a fourth parameter with Content-Security-Policy (CSP) configuration.
// enable code isolationcodeonmessage // enable code isolation with forms and API's enabledcodenull'allow-forms''allow-pointer-lock'; // enable code isolation and block loading of images, objects and mediacodenull"img-src":"'none'""media-src":"'none'""object-src":"'none'"; // restrict resource access to domain without code isolation{ // test CSP using Fetch ;}nullnull"default-src":"domain.com";
Code isolation is disabled by default. When enabled, the allow-scripts
and allow-same-origin
sandbox parameters are enabled by default.
Content Security Policy (CSP) Whitelist
To whitelist exec.js
add script-src 'nonce-execjs'
to the Content-Security-Policy. To use the runner.exec()
method, script-src: 'unsafe-eval'
is required.