Improved Realm
MODIFY
package.json
package.json
"watch": "ecmarkup --watch spec/index.emu index.html --css ecmarkup.css --js ecmarkup.js",
"build-shim-dev": "cross-env NODE_ENV=development rollup -c shim/rollup.config.js --watch",
"build-shim-prod": "cross-env NODE_ENV=production rollup -c shim/rollup.config.js",
- "lint": "eslint ./shim/src",
- "prettier": "prettier --config ./shim/.prettierrc --write ./shim/src/**/*.js"
+ "lint-shim": "eslint ./shim/src",
+ "prettier-shim": "prettier --config ./shim/.prettierrc --write ./shim/src/**/*.js"
},
"repository": {
"type": "git",
"dependencies": {},
"devDependencies": {
"babel-eslint": "^6.1.2",
- "babel-minify": "^0.4.1",
+ "babel-minify": "^0.4.3",
"cross-env": "^3.2.4",
"ecmarkup": "latest",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-config-prettier": "^2.9.0",
- "eslint-plugin-import": "^2.11.0",
+ "eslint-plugin-import": "^2.12.0",
"eslint-plugin-prettier": "^2.6.0",
"forever": "^0.15.2",
"prettier": "^1.12.1",

MODIFY
shim/examples/frozen-realm.js
shim/examples/frozen-realm.js
@@ -65,7 +65,7 @@ function deepFreeze(node, frozenSet) {
return node;
}
-class FrozenRealm extends RealmShim {
+class FrozenRealm extends Realm {
constructor() {
// intentionally not accepting options for now...

MODIFY
shim/examples/simple.html
shim/examples/simple.html
</p>
<script>
- var r = new RealmShim();
+ var r1 = new Realm();
+ var r2 = new r1.global.Realm({ intrinsics: 'inherit' });
// basic sanity check: they all should output true
// for now extra () are needed as a signal that it should return something :/
- console.log(1, r.eval('( JSON )'));
- console.log(2, r.eval('( JSON )') !== JSON);
- console.log(3, r.eval('( JSON )') === r.eval('( JSON )'));
- console.log(4, r.eval('( JSON )') === r.eval('( eval("JSON") )'));
+ console.log(1, r1.eval('( JSON )'));
+ console.log(2, r1.eval('( JSON )') !== JSON);
+ console.log(3, r1.eval('( JSON )') === r1.eval('( JSON )'));
+ console.log(4, r1.eval('( JSON )') === r1.eval('( eval("JSON") )'));
+
+ console.log(5, r2.eval('( JSON )'));
+ console.log(6, r2.eval('( JSON )') !== JSON);
+ console.log(7, r2.eval('( JSON )') === r2.eval('( JSON )'));
+ console.log(8, r2.eval('( JSON )') === r2.eval('( eval("JSON") )'));
+
+ console.log(9, r2.eval('( JSON )') === r1.eval('( JSON )'));
+ console.log(10, r2.eval('( eval("JSON") )') === r1.eval('( eval("JSON") )'));
document.getElementById('run').addEventListener('click', function () {
var sourceText = document.getElementById('sourceText').value;

MODIFY
shim/rollup.config.js
shim/rollup.config.js
@@ -7,7 +7,7 @@ export default {
input: path.resolve('shim/src/main.js'),
output: {
file: path.resolve(isProduction ? 'shim/dist/realm-shim.min.js' : 'shim/dist/realm-shim.js'),
- name: 'RealmShim',
+ name: 'Realm',
format: 'umd',
sourcemap: true
},

MODIFY
shim/src/deep-freeze.js
shim/src/deep-freeze.js
@@ -45,8 +45,9 @@ export function deepFreeze(node) {
// objects such as proxies won't add properties
// during traversal, before freezing.
- // Enqueued object are verified to be valid targets.
- // Throws if this fails in strict mode.
+ // Object are verified before being enqueued,
+ // therefore this is a valid candidate.
+ // Throws if this fails (strict mode).
freeze(obj);
enqueue(getPrototypeOf(obj));

MODIFY
shim/src/evaluators.js
shim/src/evaluators.js
// Portions adapted from V8 - Copyright 2016 the V8 project authors.
// https://github.com/v8/v8/blob/master/src/builtins/builtins-function.cc
-import { EvalHook, GlobalObject, Intrinsics, ShimSandbox } from './slots';
+import { GlobalObject, Intrinsics, ShimSandbox } from './symbols';
import { defineProperties } from './commons';
import { Handler } from './handler';
-export function createEvalEvaluatorFactory(sandbox) {
+export function getDirectEvalEvaluatorFactory(sandbox) {
const { unsafeFunction } = sandbox;
+ // Create a function in sloppy mode that returns
+ // a function in strict mode.
return unsafeFunction(`
with (arguments[0]) {
return function() {
@@ -18,7 +20,7 @@ export function createEvalEvaluatorFactory(sandbox) {
`);
}
-export function createEvalEvaluator(realmRec) {
+export function getDirectEvalEvaluator(realmRec) {
const sandbox = realmRec[ShimSandbox];
const globalObject = realmRec[GlobalObject];
const intrinsics = realmRec[Intrinsics];
@@ -40,11 +42,19 @@ export function createEvalEvaluator(realmRec) {
return result;
}
+ // Ensure that the different eval instances of the different
+ // realms all answer properly when used with the instanceof
+ // operator to preserve indentity.
+ const FunctionPrototype = sandbox.unsafeFunction.prototype;
+
// Mimic the native eval() function. New properties are
// by default non-writable and non-configurable.
defineProperties(evaluator, {
name: {
value: 'eval'
+ },
+ prototype: {
+ value: FunctionPrototype
}
});
@@ -52,15 +62,15 @@ export function createEvalEvaluator(realmRec) {
// need to be frozen (only the objects reachable from it).
// Once created for a realm, the reference must be updated everywhere.
- realmRec[EvalHook] = globalObject.eval = intrinsics.eval = evaluator;
+ return evaluator;
}
/**
* A safe version of the native Function which relies on
* the safety of evalEvaluator for confinement.
*/
-export function createFunctionEvaluator(realmRec) {
- const { unsafeFunction } = realmRec[ShimSandbox];
+export function getFunctionEvaluator(realmRec) {
+ const sandbox = realmRec[ShimSandbox];
const globalObject = realmRec[GlobalObject];
const intrinsics = realmRec[Intrinsics];
@@ -88,9 +98,9 @@ export function createFunctionEvaluator(realmRec) {
}
// Ensure that the different Function instances of the different
- // sandboxes all answer properly when used with the instanceof
+ // realms all answer properly when used with the instanceof
// operator to preserve indentity.
- const FunctionPrototype = unsafeFunction.prototype;
+ const FunctionPrototype = sandbox.unsafeFunction.prototype;
// Mimic the native signature. New properties are
// by default non-writable and non-configurable.
@@ -107,5 +117,5 @@ export function createFunctionEvaluator(realmRec) {
// need to be frozen (only the objects reachable from it).
// Once created for a realm, the reference must be everywhere.
- globalObject.Function = intrinsics.Function = evaluator;
+ return evaluator;
}

MODIFY
shim/src/frozen-realm.js
shim/src/frozen-realm.js
@@ -82,7 +82,7 @@ const stdlib = [
* This evaluator declares commonly used references as constants
* to allow the JIT optimizer to link to static references.
*/
-function createEvalEvaluatorFactory(sandbox) {
+function getDirectEvalEvaluatorFactory(sandbox) {
const { unsafeFunction } = sandbox;
return unsafeFunction(`
@@ -117,7 +117,7 @@ class FrozenRealm extends Realm {
}
// Supply addional parameters without modifying the original object.
- const opts = assign({ globalHook, createEvalEvaluatorFactory }, options);
+ const opts = assign({ globalHook, getDirectEvalEvaluatorFactory }, options);
super(opts);
//

MODIFY
shim/src/functions.js
shim/src/functions.js
@@ -20,7 +20,7 @@ function repairFunction(sandbox, functionName, functionDecl) {
const FunctionPrototype = getPrototypeOf(FunctionInstance);
// Block evaluation of source when calling constructor on the prototype of functions.
- const TamedFunction = unsafeFunction('throw new Error();');
+ const TamedFunction = unsafeFunction('throw new Error("Not available");');
defineProperties(TamedFunction, {
name: {
@@ -32,11 +32,8 @@ function repairFunction(sandbox, functionName, functionDecl) {
});
defineProperty(FunctionPrototype, 'constructor', { value: TamedFunction });
- // Prevent loop in case of Function.
- if (functionName !== 'Function') {
setPrototypeOf(TamedFunction, unsafeFunction.prototype.constructor);
}
-}
/**
* This block replaces the original Function constructor, and the original

MODIFY
shim/src/handler.js
shim/src/handler.js
export class Handler {
+ // Properties stored on the handler
+ // are not available from the proxy.
+
constructor(sandbox) {
const { unsafeGlobal } = sandbox;
this.unsafeGlobal = unsafeGlobal;
@@ -18,7 +21,7 @@ export class Handler {
}
return target.eval;
}
- // Properties of global.
+ // Properties of the global.
if (prop in target) {
return target[prop];
}

MODIFY
shim/src/intrinsics.js
shim/src/intrinsics.js
-import Realm from './realm';
import { getPrototypeOf } from './commons';
/**
@@ -9,8 +8,8 @@ import { getPrototypeOf } from './commons';
* https://tc39.github.io/ecma262/#table-7
* https://tc39.github.io/ecma262/#table-73
*/
-export function getIntrinsics(global) {
- const g = global;
+export function getIntrinsics(sandbox) {
+ const { unsafeGlobal: g } = sandbox;
// Anonymous intrinsics.
@@ -291,8 +290,7 @@ export function getIntrinsics(global) {
Intl: g.Intl,
// *** ESNext
-
- Realm // intentionally passing around the Realm Constructor, which could be used as a side channel, but still!
+ Realm: g.Realm
};
return intrinsics;

MODIFY
shim/src/realm.js
shim/src/realm.js
import { createSandbox } from './sandbox';
-import { createEvalEvaluator, createFunctionEvaluator } from './evaluators';
+import { getDirectEvalEvaluator, getFunctionEvaluator } from './evaluators';
import { getStdLib } from './stdlib';
import { getIntrinsics } from './intrinsics';
import { assert, IsCallable } from './utils';
@@ -9,285 +9,185 @@ import {
RealmRecord,
Intrinsics,
GlobalObject,
- GlobalThisValue,
- GlobalEnv,
- EvalHook,
- IsDirectEvalHook,
- ImportHook,
- ImportMetaHook,
+ DirectEvalEvaluator,
ShimSandbox
-} from './slots';
+} from './symbols';
-// shim specific
-function getSandbox(realmRec) {
- const sandbox = realmRec[ShimSandbox];
- assert(typeof sandbox === 'object');
- return sandbox;
-}
-
-// shim specific
-function getExecutionContext() {
+function getCurrentContext() {
// eslint-disable-next-line no-new-func
return new Function('return this')();
}
-// shim specific
function getCurrentRealmRecord() {
- const context = getExecutionContext();
- let realmRec = context[RealmRecord];
- if (realmRec === undefined) {
- // If there is no realm slot, then we are outside of a realm shim,
- // and we emulate what the current realm record should be. This is
- // a root realm and we define all fields based on the context.
+ const context = getCurrentContext();
+ if (RealmRecord in context) {
+ return context[RealmRecord];
+ }
const sandbox = createSandbox(context);
- realmRec = {
- [Intrinsics]: getIntrinsics(sandbox.unsafeGlobal),
+ const realmRec = {
+ [Intrinsics]: getIntrinsics(sandbox),
[GlobalObject]: sandbox.unsafeGlobal,
- [EvalHook]: sandbox.unsafeEval,
[ShimSandbox]: sandbox
};
- // Setup the RealmRecord for the next execution.
context[RealmRecord] = realmRec;
- }
return realmRec;
}
-// <!-- es6num="8.1.2.5" -->
-function NewGlobalEnvironment(G, thisValue) {
- // diverging from spec to accomodate the iframe as the lexical environment
- // using a class for better debugability
- class EnvironmentRecord {
- constructor(/*globalObject*/) {
- this[GlobalThisValue] = thisValue;
+function portRealmConstructor(sandbox) {
+ const { unsafeFunction, unsafeGlobal } = sandbox;
+
+ // Rebuild a Realm class using inrinsics from the sandbox,
+ // to prevent the Realm parts from breaking identity
+ // continuity. This avoids loading the Ream shim in
+ // every root realm.
+
+ // This process is simplified becuase all methods
+ // and properties on a realm instance already return
+ // values based on the intrinsics of the realm.
+
+ const sub = unsafeFunction('base', `
+function Realm() {
+ base.apply(this, arguments);
+}
+const descs = Object.getOwnPropertyDescriptors(base.prototype);
+Object.defineProperties(Realm.prototype, {
+ intrinsics: {
+ get() {
+ return descs.intrinsics.get.apply(this);
}
+ },
+ global: {
+ get() {
+ return descs.global.get.apply(this);
}
- return new EnvironmentRecord(G);
+ },
+ eval: {
+ value() {
+ return descs.eval.value.apply(this, arguments);
}
+ }
+});
+return Realm;
+`)(Realm);
-// <!-- es6num="8.2.3" -->
-function SetRealmGlobalObject(realmRec, globalObj, thisValue) {
- if (globalObj === undefined) {
- const intrinsics = realmRec[Intrinsics];
- globalObj = create(intrinsics.ObjectPrototype);
+ defineProperties(unsafeGlobal, {
+ Realm: {
+ value: sub
}
- assert(typeof globalObj === 'object');
- if (thisValue === undefined) thisValue = globalObj;
- realmRec[GlobalObject] = globalObj;
- const newGlobalEnv = NewGlobalEnvironment(globalObj, thisValue);
- realmRec[GlobalEnv] = newGlobalEnv;
- return realmRec;
+ });
}
-// <!-- es6num="8.2.4" -->
-function SetDefaultGlobalBindings(realmRec) {
- const global = realmRec[GlobalObject];
- // For each property of the Global Object specified in clause 18, do
- // ---> diverging
+function setGlobaObject(realmRec) {
const intrinsics = realmRec[Intrinsics];
- const descs = getStdLib(intrinsics);
- defineProperties(global, descs);
- // <--- diverging
- return global;
+ const globalObj = create(intrinsics.ObjectPrototype);
+ globalObj[RealmRecord] = realmRec;
+ realmRec[GlobalObject] = globalObj;
}
-// <!-- es6num="8.2.2" -->
-function CreateIntrinsics(realmRec) {
- // ---> diverging
- const sandbox = getSandbox(realmRec);
- const intrinsics = getIntrinsics(sandbox.unsafeGlobal);
- // <--- diverging
- realmRec[Intrinsics] = intrinsics;
- return intrinsics;
-}
+function createEvaluators(realmRec) {
-// <!-- proposal="11.1.1" -->
-// <!-- deprecates es6num="8.2.1" -->
-function CreateRealmRec(intrinsics, /* shim specific */ sandbox) {
- const realmRec = {
- // ES specs table-21
- [Intrinsics]: {},
- [GlobalObject]: undefined,
- [GlobalEnv]: undefined,
- // [TemplateMap]: [],
- // [HostDefined]: undefined,
+ // Divergence from specifications: the evaluators are tied to
+ // a global and they are tied to a realm and to the intrinsics
+ // of that realm.
+ const directEvalEvaluator = getDirectEvalEvaluator(realmRec);
+ const FunctionEvaluator = getFunctionEvaluator(realmRec);
- // Realm specs table-2
- [EvalHook]: undefined,
- [IsDirectEvalHook]: undefined,
- [ImportHook]: undefined,
- [ImportMetaHook]: undefined,
+ // No need to store Function.
+ realmRec[DirectEvalEvaluator] = directEvalEvaluator;
- // ---> diverging
- [ShimSandbox]: sandbox
- // <--- diverging
- };
- if (intrinsics === undefined) {
- CreateIntrinsics(realmRec);
- } else {
- // 1. Assert: In this case, _intrinsics_ must be a Record with field names listed in column one of Table 7.
- realmRec[Intrinsics] = intrinsics;
- }
- return realmRec;
-}
-
-// <!-- proposal="1.2" -->
-function InvokeDirectEvalHook(realmRec, x) {
- // 1. Assert: realm is a Realm Record.
- const fn = realmRec[EvalHook];
- if (fn === undefined) return x;
- assert(IsCallable(fn) === true);
- return fn.call(undefined, x);
+ // Limitation: export a direct evaluator.
+ const intrinsics = realmRec[Intrinsics];
+ intrinsics.eval = directEvalEvaluator;
+ intrinsics.Function = FunctionEvaluator;
}
-// <!-- es6num="18.2.1.1" -->
-function PerformEval(x, evalRealm, strictCaller, direct) {
- assert(direct === false ? strictCaller === false : true);
- if (typeof x !== 'string') return x;
- // ---> diverging
- if (direct === true) {
- x = InvokeDirectEvalHook(x, evalRealm);
- }
- return evalRealm[EvalHook](x);
+function setDefaultBindings(realmRec) {
+ const intrinsics = realmRec[Intrinsics]
+ const descs = getStdLib(intrinsics);
+ defineProperties(realmRec[GlobalObject], descs);
}
-// <!-- proposal="11.3.1" -->
-export default class Realm {
- constructor(options) {
+export default function Realm(options) {
const O = this;
- const parentRealm = getCurrentRealmRecord();
const opts = Object(options);
- let importHook = opts.importHook;
- if (importHook === 'inherit') {
- importHook = parentRealm[ImportHook];
- } else if (importHook !== undefined && IsCallable(importHook) === false) {
- throw new TypeError();
- }
-
- let importMetaHook = opts.importMetaHook;
- if (importMetaHook === 'inherit') {
- importMetaHook = parentRealm[ImportMetaHook];
- } else if (importMetaHook !== undefined && IsCallable(importMetaHook) === false) {
- throw new TypeError();
- }
-
- let evalHook = opts.evalHook;
- if (evalHook === 'inherit') {
- evalHook = parentRealm[EvalHook];
- } else if (evalHook !== undefined && IsCallable(evalHook) === false) {
- throw new TypeError();
- }
+ // Limitation: the evaluators are tied to a sandbox,
+ // and can't be completely abstracted from the inrinsics
+ // of that sandbox. We impose in the shim the restriction
+ // that intinsics must match the evaluator, and can't be
+ // provided independently.
- let isDirectEvalHook = opts.isDirectEvalHook;
- if (isDirectEvalHook === 'inherit') {
- isDirectEvalHook = parentRealm[IsDirectEvalHook];
- } else if (isDirectEvalHook !== undefined && IsCallable(isDirectEvalHook) === false) {
- throw new TypeError();
+ if ('evaluator' in opts) {
+ throw new TypeError('Realm does not support "evaluator" option.');
}
- // ---> diverging
- // Limitation: intrisics and sandbox must always match. We
- // known this early during the constuction of the realm.
- let intrinsics = opts.intrinsics;
let sandbox;
+ let intrinsics = opts.intrinsics;
if (intrinsics === 'inherit') {
- // When we inherit the intrinsics, we also must
- // inherit the sandbox.
- intrinsics = parentRealm[Intrinsics];
+ // In "inherit" mode, we create a compartment realm and inherit
+ // the sandbox since we share the intrinsics. We create a new
+ // set to allow us to define eval() anf Function() for the realm.
+ const parentRealm = getCurrentRealmRecord();
sandbox = parentRealm[ShimSandbox];
+ intrinsics = assign({}, parentRealm[Intrinsics]);
+
} else if (intrinsics === undefined) {
- // When intrinics are not specified, we
- // need to create a sandbox.
+ // When intrinics are not provided, we create a root realm
+ // using the fresh set of new intrinics from a new sandbox.
sandbox = createSandbox();
- } else {
- throw new TypeError();
- }
- // <--- diverging
+ portRealmConstructor(sandbox);
+ intrinsics = getIntrinsics(sandbox);
- const thisValue = opts.thisValue;
- if (thisValue !== undefined && typeof thisValue !== 'object') {
- throw new TypeError();
+ } else {
+ throw new TypeError('Realm only supports undefined or "inherited" intrinsics.');
}
- const realmRec = CreateRealmRec(intrinsics, sandbox);
- O[RealmRecord] = realmRec;
-
- SetRealmGlobalObject(realmRec, undefined, thisValue);
- // ---> diverging
- // Limitation: the evaluators are tied to a global object and
- // need to be created after the global object. It is process
- // also updates the intrinsics.
- createEvalEvaluator(realmRec);
- createFunctionEvaluator(realmRec);
- // <--- diverging
-
- if (importHook === undefined) {
- // new built-in function object as defined in <emu-xref href="#sec-realm-default-import-hook-functions"></emu-xref>
- importHook = function(/*referrer, specifier*/) {
- throw new TypeError();
+ const realmRec = {
+ [ShimSandbox]: sandbox,
+ [Intrinsics]: intrinsics,
+ [GlobalObject]: undefined,
+ [DirectEvalEvaluator]: undefined
};
- }
- realmRec[ImportHook] = importHook;
- if (evalHook !== undefined) {
- realmRec[EvalHook] = evalHook;
- }
- if (isDirectEvalHook !== undefined) {
- realmRec[IsDirectEvalHook] = isDirectEvalHook;
- }
-
- const init = O.init;
- if (!IsCallable(init)) throw new TypeError();
- init.call(O);
- }
-
- init() {
- const O = this;
- if (typeof O !== 'object') throw new TypeError();
- if (!(RealmRecord in O)) throw new TypeError();
- SetDefaultGlobalBindings(O[RealmRecord]);
- }
- eval(x) {
- const O = this;
- if (typeof O !== 'object') throw new TypeError();
- if (!(RealmRecord in O)) throw new TypeError();
- const evalRealm = O[RealmRecord];
- // HostEnsureCanCompileStrings(the current Realm Record, _evalRealm_).
- return PerformEval(x, evalRealm, false, false);
- }
+ setGlobaObject(realmRec);
+ createEvaluators(realmRec);
+ setDefaultBindings(realmRec);
- get stdlib() {
- const O = this;
- if (typeof O !== 'object') throw new TypeError();
- if (!(RealmRecord in O)) throw new TypeError();
- // TODO: align with spec
- const intrinsics = O[RealmRecord][Intrinsics];
- return getStdLib(intrinsics);
+ O[RealmRecord] = realmRec;
}
- get intrinsics() {
+defineProperties(Realm.prototype, {
+ intrinsics: {
+ get() {
const O = this;
if (typeof O !== 'object') throw new TypeError();
if (!(RealmRecord in O)) throw new TypeError();
- // TODO: align with spec
const intrinsics = O[RealmRecord][Intrinsics];
- return assign({}, intrinsics);
- }
-
- get global() {
+ // The object returned has its prototype
+ // match the ObjectPrototype of the realm.
+ const obj = create(intrinsics.ObjectPrototype);
+ return assign(obj, intrinsics);
+ }
+ },
+ global: {
+ get() {
const O = this;
if (typeof O !== 'object') throw new TypeError();
if (!(RealmRecord in O)) throw new TypeError();
return O[RealmRecord][GlobalObject];
}
-
- get thisValue() {
+ },
+ eval: {
+ value(x) {
const O = this;
if (typeof O !== 'object') throw new TypeError();
if (!(RealmRecord in O)) throw new TypeError();
- const envRec = O[RealmRecord][GlobalEnv];
- return envRec[GlobalThisValue];
+ const realmRec = O[RealmRecord];
+ const evaluator = realmRec[DirectEvalEvaluator]
+ return evaluator(x);
}
}
+});
Realm.toString = () => 'function Realm() { [shim code] }';
+

MODIFY
shim/src/sandbox.js
shim/src/sandbox.js
-import { createEvalEvaluatorFactory } from './evaluators';
+import { getDirectEvalEvaluatorFactory } from './evaluators';
import { sanitize } from './sanitize';
// The sandbox is shim-specific. It acts as the mechanism
@@ -7,7 +7,7 @@ import { sanitize } from './sanitize';
// must be respected since the evaluators are imposing a
// set of intrinsics, aka the "undeniables".
-function createContext() {
+function createBrowserContext() {
const iframe = document.createElement('iframe');
iframe.title = 'script';
@@ -21,8 +21,9 @@ function createContext() {
export function createSandbox(context) {
if (context === undefined) {
- context = createContext();
+ context = createBrowserContext();
}
+
// The sandbox is entirely defined by these three objects.
// Reusing the terminology from SES/Caja.
const sandbox = {
@@ -30,9 +31,11 @@ export function createSandbox(context) {
unsafeEval: context.eval,
unsafeFunction: context.Function
};
- if (sandbox.evalEvaluatorFactory === undefined) {
- sandbox.evalEvaluatorFactory = createEvalEvaluatorFactory(sandbox);
- }
+
+ // Create the evaluator factory that will generate the evaluators
+ // for each compartment realm.
+ sandbox.evalEvaluatorFactory = getDirectEvalEvaluatorFactory(sandbox);
+
sanitize(sandbox);
return sandbox;
}

DELETE
shim/src/slots.js
-export const RealmRecord = Symbol('Realm Slot');
-export const Intrinsics = Symbol('Intrinsics Slot');
-export const GlobalObject = Symbol('GlobalObject Slot');
-export const GlobalThisValue = Symbol('GlobalThisValue Slot');
-export const GlobalEnv = Symbol('GlobalEnv Slot');
-export const EvalHook = Symbol('EvalHook Slot');
-export const IsDirectEvalHook = Symbol('IsDirectEvalHook Slot');
-export const ImportHook = Symbol('ImportHook Slot');
-export const ImportMetaHook = Symbol('ImportMetaHook Slot');
-export const ShimSandbox = Symbol('Sandbox');

MODIFY
shim/src/stdlib.js
shim/src/stdlib.js
@@ -10,7 +10,10 @@ export function getStdLib(intrinsics) {
// *** 18.2 Function Properties of the Global Object
- eval: { value: i.eval },
+ // Make eval wrtitable to allow proxy to return a different
+ // value, and leave it non-unconfigurable to prevent userland
+ // from changing its descriptor and breaking an invariant.
+ eval: { value: i.eval, writable: true },
isFinite: { value: i.isFinite },
isNaN: { value: i.isNaN },
parseFloat: { value: i.parseFloat },

ADD
shim/src/symbols.js
+export const RealmRecord = Symbol('Realm Slot');
+export const Intrinsics = Symbol('Intrinsics Slot');
+export const GlobalObject = Symbol('GlobalObject Slot');
+export const DirectEvalEvaluator = Symbol('DirectEvalEvaluator Slot');
+export const ShimSandbox = Symbol('Shim Sandbox');

Improved Realm