Remove weakmaps
MODIFY
shim/src/realm.js
shim/src/realm.js
@@ -7,34 +7,10 @@ import {
createFunctionEvaluator
} from './evaluators';
import { assert } from './utilities';
-import { create, defineProperty, defineProperties, freeze, arrayConcat } from './commons';
+import { create, defineProperties, freeze, arrayConcat } from './commons';
-// Create a registry to mimic a private static members on the realm classes.
+// Mimic private members on the realm imtances.
// We define it in the same module and do not export it.
-
-const UnsafeRecForRealmClass = new WeakMap();
-
-function getUnsafeRecForRealmClass(RealmClass) {
- // Detect non-objects.
- assert(Object(RealmClass) === RealmClass, 'bad object, not a Realm constructor');
- // RealmClass has no unsafeRec. Shoud not proceed.
- assert(UnsafeRecForRealmClass.has(RealmClass), 'Realm constructor has no record');
-
- return UnsafeRecForRealmClass.get(RealmClass);
-}
-
-function registerUnsafeRecForRealmClass(RealmClass, unsafeRec) {
- // Detect non-objects.
- assert(Object(RealmClass) === RealmClass, 'bad object, not a Realm constructor');
- // RealmClass already has unsafeRec. Shoud not proceed.
- assert(!UnsafeRecForRealmClass.has(RealmClass), 'Realm constructor already has a record');
-
- UnsafeRecForRealmClass.set(RealmClass, unsafeRec);
-}
-
-// Create a registry to mimic a private members on the realm imtances.
-// We define it in the same module and do not export it.
-
const RealmRecForRealmInstance = new WeakMap();
function getRealmRecForRealmInstance(realm) {
@@ -59,16 +35,17 @@ function registerRealmRecForRealmInstance(realm, realmRec) {
function setDefaultBindings(sharedGlobalDescs, safeGlobal, safeEval, safeFunction) {
defineProperties(safeGlobal, sharedGlobalDescs);
- defineProperty(safeGlobal, 'eval', {
+ defineProperties(safeGlobal, {
+ eval: {
value: safeEval,
writable: true,
configurable: true
- });
-
- defineProperty(safeGlobal, 'Function', {
+ },
+ Function: {
value: safeFunction,
writable: true,
configurable: true
+ }
});
}
@@ -95,48 +72,43 @@ function createRealmRec(unsafeRec) {
return realmRec;
}
-function initRootRealm(selfClass, self, options) {
- options = Object(options); // Todo: sanitize
- // note: 'self' is the instance of the Realm, and 'selfClass' is the
- // Realm constructor (facade) we build in buildChildRealm().
+function initRootRealm(parentUnsafeRec, self, options) {
+ options = Object(options); // todo: sanitize
// In 'undefined' mode, intrinics are not provided, we create a root
// realm using the fresh set of new intrinics from a new context.
// todo: investigate attacks via Array.species
- const newShims = options.shims || [];
- const { allShims: oldShims } = getUnsafeRecForRealmClass(selfClass);
// todo: this accepts newShims='string', but it should reject that
- const allShims = arrayConcat(oldShims, newShims);
+ const { shims: newShims } = options;
+ const allShims = arrayConcat(parentUnsafeRec.allShims, newShims);
// The unsafe record is returned with its constructors repaired.
const unsafeRec = createNewUnsafeRec(allShims);
// Define Realm onto new sharedGlobalDescs, so it can be copied onto the
- // safeGlobal like the rest of the .
+ // safeGlobal like the rest of the globals.
// eslint-disable-next-line no-use-before-define
- const Realm = createRealmGlobalObject(unsafeRec);
- registerUnsafeRecForRealmClass(Realm, unsafeRec);
+ createRealmGlobalObject(unsafeRec);
const realmRec = createRealmRec(unsafeRec);
registerRealmRecForRealmInstance(self, realmRec);
+
// Now run all shims in the new RootRealm. We don't do this for
- // compartments
+ // compartments.
+ const { safeEvalWhichTakesEndowments } = realmRec;
for (const shim of allShims) {
- // eslint-disable-next-line no-use-before-define
- realmEvaluate(self, shim);
+ safeEvalWhichTakesEndowments(shim);
}
}
-function initCompartment(selfClass, self) {
+function initCompartment(unsafeRec, self) {
// note: 'self' is the instance of the Realm, and 'selfClass' is the
// Realm constructor (facade) we build in buildChildRealm().
// In "inherit" mode, we create a compartment realm and inherit
// the context since we share the intrinsics. We create a new
// set to allow us to define eval() and Function() for the realm.
- const unsafeRec = getUnsafeRecForRealmClass(selfClass);
-
const realmRec = createRealmRec(unsafeRec);
registerRealmRecForRealmInstance(self, realmRec);
}
@@ -177,6 +149,5 @@ function createRealmGlobalObject(unsafeRec) {
// where the Realm shim is loaded and executed).
const currentUnsafeRec = createCurrentUnsafeRec();
const Realm = createRealmFacade(currentUnsafeRec, BaseRealm);
-registerUnsafeRecForRealmClass(Realm, currentUnsafeRec);
export default Realm;

MODIFY
shim/src/realmFacade.js
shim/src/realmFacade.js
@@ -3,7 +3,10 @@ import { cleanupSource } from './utilities';
// buildChildRealm is immediately turned into a string, and this function is
// never referenced again, because it closes over the wrong intrinsics
-export function buildChildRealm(BaseRealm) {
+// todo: This function is stringified and evaluated outside of the primal
+// realms and it currently can't contain code coverage metrics.
+/* istanbul ignore file */
+export function buildChildRealm(unsafeRec, BaseRealm) {
const { initRootRealm, initCompartment, getRealmGlobal, realmEvaluate } = BaseRealm;
// This Object and Reflect are brand new, from a new unsafeRec, so no user
@@ -80,14 +83,14 @@ export function buildChildRealm(BaseRealm) {
static makeRootRealm(...args) {
// Bypass the constructor.
const r = create(Realm.prototype);
- callAndWrapError(initRootRealm, Realm, r, ...args);
+ callAndWrapError(initRootRealm, unsafeRec, r, ...args);
return r;
}
static makeCompartment(...args) {
// Bypass the constructor.
const r = create(Realm.prototype);
- callAndWrapError(initCompartment, Realm, r, ...args);
+ callAndWrapError(initCompartment, unsafeRec, r, ...args);
return r;
}
@@ -148,5 +151,5 @@ export function createRealmFacade(unsafeRec, BaseRealm) {
// values using the intrinsics of the realm's context.
// Invoke the BaseRealm constructor with Realm as the prototype.
- return unsafeEval(buildChildRealmString)(BaseRealm);
+ return unsafeEval(buildChildRealmString)(unsafeRec, BaseRealm);
}

MODIFY
shim/test/module/realmFacade.js
shim/test/module/realmFacade.js
@@ -2,6 +2,12 @@ import test from 'tape';
import sinon from 'sinon';
import { buildChildRealm, createRealmFacade } from '../../src/realmFacade';
+const unsafeRec = {
+ unsafeGlobal: global,
+ unsafeEval: eval,
+ unsafeFunction: Function
+};
+
const BaseRealm = {
initRootRealm: () => undefined,
initCompartment: () => undefined,
@@ -21,7 +27,7 @@ test('buildChildRealm - Realm callAndWrapError() invoked', t => {
throw 'initCompartment';
});
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
t.throws(() => Realm.makeRootRealm(), /initRootRealm/);
t.throws(() => Realm.makeCompartment(), /initCompartment/);
@@ -42,7 +48,7 @@ test('buildChildRealm - callAndWrapError() invoked', t => {
throw 'evaluate';
});
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
const rootRealm = Realm.makeRootRealm();
t.throws(() => rootRealm.global, /getGlobal/);
@@ -60,7 +66,7 @@ test('buildChildRealm - callAndWrapError() error types', t => {
throw error;
});
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
t.throws(() => {
error = '123';
Realm.makeRootRealm();
@@ -90,7 +96,7 @@ test('buildChildRealm - callAndWrapError() error throws', t => {
};
});
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
t.throws(() => Realm.makeRootRealm(), /unknown error/);
BaseRealm.initRootRealm.restore();
@@ -107,7 +113,7 @@ test('buildChildRealm - callAndWrapError() unknown error type', t => {
};
});
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
t.throws(() => Realm.makeRootRealm(), Error);
BaseRealm.initRootRealm.restore();
@@ -116,7 +122,7 @@ test('buildChildRealm - callAndWrapError() unknown error type', t => {
test('buildChildRealm - toString()', t => {
t.plan(2);
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
const rootRealm = Realm.makeRootRealm();
t.equals(Realm.toString(), 'function Realm() { [shim code] }');
@@ -128,7 +134,7 @@ test('buildChildRealm - Realm.makeRootRealm', t => {
sinon.spy(BaseRealm, 'initRootRealm');
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
const options = {};
Realm.makeRootRealm(options);
@@ -136,7 +142,7 @@ test('buildChildRealm - Realm.makeRootRealm', t => {
const args = BaseRealm.initRootRealm.getCall(0).args;
t.equals(args.length, 3);
- t.equals(args[0], Realm);
+ t.equals(args[0], unsafeRec);
t.ok(args[1] instanceof Realm);
t.equals(args[2], options);
@@ -148,14 +154,14 @@ test('buildChildRealm - Realm.makeCompartment', t => {
sinon.spy(BaseRealm, 'initCompartment');
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
Realm.makeCompartment();
t.equals(BaseRealm.initCompartment.callCount, 1);
const args = BaseRealm.initCompartment.getCall(0).args;
t.equals(args.length, 2);
- t.equals(args[0], Realm);
+ t.equals(args[0], unsafeRec);
t.ok(args[1] instanceof Realm);
BaseRealm.initCompartment.restore();
@@ -167,7 +173,7 @@ test('buildChildRealm - realm.global', t => {
const expectedGlobal = {};
sinon.stub(BaseRealm, 'getRealmGlobal').callsFake(() => expectedGlobal);
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
const compartment = Realm.makeCompartment();
const actualGlobal = compartment.global;
@@ -189,7 +195,7 @@ test('buildChildRealm - realm.evaluate', t => {
const source = 'abc';
const endowments = {};
- const Realm = buildChildRealm(BaseRealm);
+ const Realm = buildChildRealm(unsafeRec, BaseRealm);
const compartment = Realm.makeCompartment();
const actualResult = compartment.evaluate(source, endowments);

Remove weakmaps