Guard against global accessors
MODIFY
shim/src/stdlib.js
shim/src/stdlib.js
+import { getOwnPropertyDescriptor } from './commons';
+import { assert } from './utilities';
+
// All the following stdlib items have the same name on both our intrinsics
// object and on the global object. Unlike Infinity/NaN/undefined, these
// should all be writable and configurable.
@@ -82,15 +85,19 @@ export function getSharedGlobalDescs(unsafeGlobal) {
};
for (const name of sharedGlobalPropertyNames) {
+ const desc = getOwnPropertyDescriptor(unsafeGlobal, name);
+ if (desc) {
+ // Abort if an accessor is found on the unsafe global object instead of a
+ // data property. We should never get into this non standard situation.
+ assert('value' in desc, `unexpected accessor on global property: ${name}`);
+
descriptors[name] = {
- // todo: if there's a get/accessor on the global, do we want to invoke
- // it or throw an error?
- // todo: get a descriptor here, so we can check
- value: unsafeGlobal[name],
+ value: desc.value,
writable: true,
configurable: true
};
}
+ }
return descriptors;
}

ADD
shim/test/realm/stdlib.js
+import test from 'tape';
+import { getSharedGlobalDescs } from '../../src/stdlib';
+
+test('Global default values', t => {
+ t.plan(21);
+
+ const mockGlobal = { JSON: {}, Math: {} };
+ const descs = getSharedGlobalDescs(mockGlobal);
+
+ t.equal(Object.keys(descs).length, 5);
+
+ t.equal(descs.Infinity.value, Infinity);
+ t.ok(Number.isNaN(descs.NaN.value));
+ t.equal(descs.undefined.value, undefined);
+
+ for (const name of ['Infinity', 'NaN', 'undefined']) {
+ const desc = descs[name];
+ t.notOk(desc.enumerable, `${name} should not be enumerable`);
+ t.notOk(desc.configurable, `${name} should not be configurable`);
+ t.notOk(desc.writable, `${name} should not be writable`);
+ }
+
+ t.equal(descs.JSON.value, mockGlobal.JSON);
+ t.equal(descs.Math.value, mockGlobal.Math);
+
+ for (const name of ['JSON', 'Math']) {
+ const desc = descs[name];
+ t.notOk(desc.enumerable, `${name} should no be enumerable`);
+ t.ok(desc.configurable, `${name} should be configurable`);
+ t.ok(desc.writable, `${name} should be writable`);
+ }
+});
+
+test('Global accessor throws', t => {
+ t.plan(1);
+
+ const mockGlobal = {};
+ Object.defineProperty(mockGlobal, 'JSON', {
+ get() {
+ return Math.random();
+ }
+ });
+
+ t.throws(() => getSharedGlobalDescs(mockGlobal), /unexpected accessor on global property: JSON/);
+});

Guard against global accessors