- Stage 1
- @dherman
- @caridy
- @erights
You can view the spec rendered as HTML.
- worked on this during ES2015 time frame, so never went through stages process
- got punted to later (rightly so!)
- goal of this proposal: resume work on this, reassert committee interest via advancing to stage 2
- original idea from @dherman: What are Realms?
- sandbox
- iframe without DOM
- principled version of Node's
'vm'
module - sync Worker
- security isolation (with synchronous but coarse-grained communication channel)
- plugins (e.g., spreadsheet functions)
- in-browser code editors
- server-side rendering
- testing/mocking (e.g., jsdom)
- in-browser transpilation
let realm = new Realm();
let outerGlobal = window;
let innerGlobal = realm.global;
let f = realm.evaluate("(function() { return 17 })");
f() === 17 // true
Reflect.getPrototypeOf(f) === outerGlobal.Function.prototype // false
Reflect.getPrototypeOf(f) === innerGlobal.Function.prototype // true
class EmptyRealm extends Realm {
constructor(...args) { super(...args); }
init() { /* do nothing */ }
}
class FakeWindow extends Realm {
init() {
super.init(); // install the standard primordials
let global = this.global;
global.document = new FakeDocument(...);
global.alert = new Proxy(fakeAlert, { ... });
...
}
}
The transform
trap provides a way to preprocess any sourceText value before it is evaluated, and it applies to direct and indirect evaluation alike. E.g.:
const r = new Realm({
transform(sourceText) {
return remapXToY(sourceText);
},
});
r.global.y = 1;
const a = r.evaluate(`let x = 2; eval("x")`); // yields 1 after remapping `x` to the global `y`.
const b = r.evaluate(`let x = 3; (0, eval)("x")`); // yields 1 after remapping `x` to the global `y`.
For mode details about how to implement a JS dialects with Realms, check the following gist:
- https://gist.github.com/dherman/9146568 (outdated API, but the same principle applies).
The isDirectEval
trap provides a way to control when certain invocation to an eval
identifier qualifies as direct eval. This is important if you plan to replace the eval
intrinsic to provide your own evaluation mechanism:
const r = new Realm({
isDirectEval(func) {
return func === r.customEval;
},
});
function customEval(sourceText) {
return compile(sourceText);
}
r.global.eval = customEval; // providing a custom evaluation mechanism
const source = `
let x = 1;
(function foo() {
let x = 2;
eval('x'); // yields 2 if `compile` doesn't alter the code
(0,eval)('x'); // yields 1 if `compile` doesn't alter the code
})();
`;
r.evaluate(source);
const r = new Realm({
import(referrerNamespace, specifier) {
return getPromiseForNamespaceObjFor(specifier); // invokes your own mechanism to resolve to a namespace
}
});
const ns = r.evaluate('import("foo")'); // where referrerNamespace is null, and specifier is "foo"
A shim implementation of the Realm API can be found here.
And you can play around with the Shim here.
The source for the spec text is located in spec/index.emu and it is written in ecmarkup language.
When modifying the spec text, you should be able to build the HTML version in
index.html
by using the following command:
npm install
npm run build
open index.html
Alternative, you can use npm run watch
.