Skip to content

Latest commit

 

History

History
98 lines (69 loc) · 2.8 KB

EXAMPLES.md

File metadata and controls

98 lines (69 loc) · 2.8 KB

Realm API usage

iframes vs realms

If you're using anonymous iframes today to "evaluate" javascript code in a different realm, you can replace it with a new Realm, as a more performant option, e.g.:

const globalOne = window;
let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const globalTwo = iframe.contentWindow;

will become:

const globalOne = window;
const globalTwo = new Realm().global;

Indirect evaluation

This operation should be equivalent, in both scenarios:

globalOne.eval('1 + 2'); // yield 3
globalTwo.eval('1 + 2'); // yield 3

Direct evaluation

This operation should be equivalent, in both scenarios:

globalOne.eval('eval("1 + 2")'); // yield 3
globalTwo.eval('eval("1 + 2")'); // yield 3

Identity Discontinuity

Considering that you're creating a brand new realm, with its brand new global variable, the identity discontinuity is still present, just like in the iframe example:

let a1 = globalOne.eval('[1,2,3]');
let a2 = globalTwo.eval('[1,2,3]');
a1.prototype === a2.prototype; // yield false
a1 instanceof globalTwo.Array; // yield false
a2 instanceof globalOne.Array; // yield false

Note: There is not solution for this with iframes, the only possible partial-solution is to use with statement which has some performance implications. With the Realm API, you will have more flexibility to avoid this issue.

Non-intrinsics

If you attempt to evaluate code that uses something other than EcmaScript intrinsics, the code will fail to evaluate in the realm without the proper configuration, e.g.:

globalOne.eval('console.log(1)'); // yield a log message: "1"
globalTwo.eval('console.log(1)'); // throw an error: console is undefined

To solve this, you can add a new global binding in the realm that implements the console API, e.g.:

globalTwo.console = globalOne.console;

Note: keep in mind that this will provide authority for code in the realm to walk its way up into the globalOne object by using the prototype chain of the new global called console, e.g.:

globalTwo.eval('console.log.constructor("return this")()') === globalOne; // yield true

Instead, you can provide a fully functional console API that closes over to the outer realm's console object. This way you don't leak authority to the newly created Realm.

node's vm objects vs realms

If you're using node's vm module today to "evaluate" javascript code in a different realm, you can replace it with a new Realm, e.g.:

const vm = require('vm');
const script = new vm.Script('this');
const globalOne = global;
const globalTwo = script.runInContext(new vm.createContext());

will become:

const globalOne = global;
const globalTwo = new Realm().global;

Note: these two are equivalent in functionality.