options.sloppyGlobals: boolean to allow sloppy assigments to safeGlobal
This allows better compatibility with sloppy code, though still cannot avoid
the discrepency between "the ReferenceError in the normal case and the lack of
ReferenceError in the 'typeof' case."
MODIFY
src/realm.js
src/realm.js
@@ -89,7 +89,7 @@ function initRootRealm(parentUnsafeRec, self, options) {
// todo: investigate attacks via Array.species
// todo: this accepts newShims='string', but it should reject that
- const { shims: newShims, transforms } = options;
+ const { shims: newShims, transforms, sloppyGlobals } = options;
const allShims = arrayConcat(parentUnsafeRec.allShims, newShims);
// The unsafe record is created already repaired.
@@ -108,7 +108,7 @@ function initRootRealm(parentUnsafeRec, self, options) {
// Creating the realmRec provides the global object, eval() and Function()
// to the realm.
- const realmRec = createRealmRec(unsafeRec, transforms, options.sloppyGlobals);
+ const realmRec = createRealmRec(unsafeRec, transforms, sloppyGlobals);
// Apply all shims in the new RootRealm. We don't do this for compartments.
const { safeEvalWhichTakesEndowments } = realmRec;
@@ -127,11 +127,8 @@ function initRootRealm(parentUnsafeRec, self, options) {
function initCompartment(unsafeRec, self, options = {}) {
// note: 'self' is the instance of the Realm.
- const realmRec = createRealmRec(
- unsafeRec,
- options.transforms,
- options.sloppyGlobals
- );
+ const { transforms, sloppyGlobals } = options;
+ const realmRec = createRealmRec(unsafeRec, transforms, sloppyGlobals);
// The realmRec acts as a private field on the realm instance.
registerRealmRecForRealmInstance(self, realmRec);

MODIFY
src/scopeHandler.js
src/scopeHandler.js
@@ -75,14 +75,6 @@ export function createScopeHandler(unsafeRec, safeGlobal, sloppyGlobals) {
return target[prop];
}
- // Sloppy global properties.
- if (sloppyGlobals) {
- if (prop in sloppyGlobals) {
- return sloppyGlobals[prop];
- }
- throw ReferenceError(`${prop} is not defined`);
- }
-
// Prevent the lookup for other properties.
return undefined;
},
@@ -98,12 +90,6 @@ export function createScopeHandler(unsafeRec, safeGlobal, sloppyGlobals) {
throw new TypeError(`do not modify endowments like ${String(prop)}`);
}
- if (sloppyGlobals && !(prop in safeGlobal)) {
- // We want to capture new assignments to the global scope.
- sloppyGlobals[prop] = value;
- return true;
- }
-
safeGlobal[prop] = value;
// Return true after successful set.

MODIFY
test/module/evaluators.js
test/module/evaluators.js
@@ -90,7 +90,7 @@ test('createSafeEvaluatorWhichTakesEndowments - options.sloppyGlobals', t => {
});
const realmTransforms = [];
- const sloppyGlobals = {};
+ const sloppyGlobals = true;
const safeEval = createSafeEvaluatorWhichTakesEndowments(
createSafeEvaluatorFactory(
@@ -103,21 +103,22 @@ test('createSafeEvaluatorWhichTakesEndowments - options.sloppyGlobals', t => {
// Evaluate normally.
t.equal(safeEval('abc', { abc: 123 }), 123, 'endowment eval');
- t.throws(
- () => safeEval('def', { abc: 123 }),
- ReferenceError,
- 'no such sloppy global'
- );
- t.assert(!('def' in sloppyGlobals), 'sloppy global does not yet exist');
+ t.equal(safeEval('typeof def', { abc: 123 }), 'undefined', 'typeof works');
+
+ // FIXME: We can't have both typeof work and a reference error if no such global.
+ t.equal(safeEval('def', { abc: 123 }), undefined, 'no such global');
+
+ t.assert(!('def' in safeGlobal), 'global does not yet exist');
t.equal(
safeEval('def = abc + 333', { abc: 123 }),
456,
- 'sloppy global assignment'
+ 'sloppy global assignment works'
);
- t.equal(safeEval('def', { abc: 123 }), 456, 'sloppy global persists');
- t.equal(sloppyGlobals.def, 456, 'sloppy global uses our object');
+
+ t.equal(safeEval('def', { abc: 123 }), 456, 'assigned global persists');
+ t.equal(safeGlobal.def, 456, 'assigned global uses our safeGlobal');
} catch (e) {
- t.isNot(e, e);
+ t.isNot(e, e, 'unexpected exception');
} finally {
// eslint-disable-next-line no-proto
Function.__proto__.constructor.restore();

options.sloppyGlobals: boolean to allow sloppy assigments to safeGlobal

This allows better compatibility with sloppy code, though still cannot avoid
the discrepency between "the ReferenceError in the normal case and the lack of
ReferenceError in the 'typeof' case."