Add tests for ShadowRealm globalThis

This commit is contained in:
Leo Balter 2021-10-12 15:02:48 -07:00 committed by Rick Waldron
parent e9cea2125c
commit 8ff255a5ec
3 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,105 @@
// Copyright (C) 2021 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-shadowrealm.prototype.evaluate
description: >
The ShadowRealm global must include ECMAScript global properties
info: |
ShadowRealm ( )
...
3. Let realmRec be CreateRealm().
4. Set O.[[ShadowRealm]] to realmRec.
...
10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]).
12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]).
SetDefaultGlobalBindings ( realmRec )
1. Let global be realmRec.[[GlobalObject]].
2. For each property of the Global Object specified in clause 19, do
a. Let name be the String value of the property name.
b. Let desc be the fully populated data Property Descriptor for the property, containing the specified attributes for the property. For properties listed in 19.2, 19.3, or 19.4 the value of the [[Value]] attribute is the corresponding intrinsic object from realmRec.
c. Perform ? DefinePropertyOrThrow(global, name, desc).
3. Return global.
features: [ShadowRealm]
includes: [compareArray.js]
---*/
assert.sameValue(
typeof ShadowRealm.prototype.evaluate,
'function',
'This test must fail if ShadowRealm.prototype.evaluate is not a function'
);
const r = new ShadowRealm();
const properties = [
'globalThis',
'Infinity',
'NaN',
'undefined',
'eval',
'isFinite',
'isNaN',
'parseFloat',
'parseInt',
'decodeURI',
'decodeURIComponent',
'encodeURI',
'encodeURIComponent',
'AggregateError',
'Array',
'ArrayBuffer',
'BigInt',
'BigInt64Array',
'BigUint64Array',
'Boolean',
'DataView',
'Date',
'Error',
'EvalError',
'FinalizationRegistry',
'Float32Array',
'Float64Array',
'Function',
'Int8Array',
'Int16Array',
'Int32Array',
'Map',
'Number',
'Object',
'Promise',
'Proxy',
'RangeError',
'ReferenceError',
'RegExp',
'Set',
'SharedArrayBuffer',
'String',
'Symbol',
'SyntaxError',
'TypeError',
'Uint8Array',
'Uint8ClampedArray',
'Uint16Array',
'Uint32Array',
'URIError',
'WeakMap',
'WeakRef',
'WeakSet',
'Atomics',
'JSON',
'Math',
'Reflect',
];
const available = properties.filter(name => {
// This test is intentionally not using wrapped functions.
// This test should not depend on wrapped functions.
return r.evaluate(`Object.prototype.hasOwnProperty.call(globalThis, '${name}')`);
});
// This comparison is intentional to list difference in names if the the assertion fails
assert.compareArray(properties, available);

View File

@ -0,0 +1,98 @@
// Copyright (C) 2021 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-shadowrealm.prototype.evaluate
description: >
Properties of globalThis must be configurable
info: |
ShadowRealm ( )
...
3. Let realmRec be CreateRealm().
4. Set O.[[ShadowRealm]] to realmRec.
...
10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]).
12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]).
Runtime Semantics: HostInitializeShadowRealm ( realm )
HostInitializeShadowRealm is an implementation-defined abstract operation
used to inform the host of any newly created realms from the ShadowRealm
constructor. Its return value is not used, though it may throw an exception.
The idea of this hook is to initialize host data structures related to the
ShadowRealm, e.g., for module loading.
The host may use this hook to add properties to the ShadowRealm's global
object. Those properties must be configurable.
features: [ShadowRealm]
---*/
assert.sameValue(
typeof ShadowRealm.prototype.evaluate,
'function',
'This test must fail if ShadowRealm.prototype.evaluate is not a function'
);
const r = new ShadowRealm();
const anyMissed = r.evaluate(`
// These names are the only exception as non configurable values.
// Yet, they don't represent any object value.
const esNonConfigValues = [
'undefined',
'Infinity',
'NaN'
];
const entries = Object.entries(Object.getOwnPropertyDescriptors(globalThis));
const missed = entries
.filter(entry => entry[1].configurable === false)
.map(([name]) => name)
.filter(name => !esNonConfigValues.includes(name))
.join(', ');
missed;
`);
assert.sameValue(anyMissed, '', 'All globalThis properties must be configurable');
const result = r.evaluate(`
const ObjectKeys = Object.keys;
const hasOwn = Object.prototype.hasOwnProperty;
const savedGlobal = globalThis;
const names = Object.keys(Object.getOwnPropertyDescriptors(globalThis));
// These names are the only exception as non configurable values.
// Yet, they don't represent any object value.
const esNonConfigValues = [
'undefined',
'Infinity',
'NaN'
];
// Delete every name except globalThis, for now
names.filter(name => {
if (esNonConfigValues.includes(name)) {
return false;
}
if (name !== 'globalThis') {
delete globalThis[name];
return hasOwn.call(globalThis, name);
}
});
delete globalThis['globalThis'];
if (hasOwn.call(savedGlobal, 'globalThis')) {
names.push('globalThis');
}
const failedDelete = names.join(', ');
failedDelete;
`);
assert.sameValue(result, '', 'deleting any globalThis property must be effective');

View File

@ -0,0 +1,66 @@
// Copyright (C) 2021 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-shadowrealm.prototype.evaluate
description: >
The globalThis must be an ordinary object from OrdinaryObjectCreate
info: |
ShadowRealm ( )
...
3. Let realmRec be CreateRealm().
4. Set O.[[ShadowRealm]] to realmRec.
...
10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
11. Perform ? SetDefaultGlobalBindings(O.[[ShadowRealm]]).
12. Perform ? HostInitializeShadowRealm(O.[[ShadowRealm]]).
SetRealmGlobalObject ( realmRec, globalObj, thisValue )
1. If globalObj is undefined, then
a. Let intrinsics be realmRec.[[Intrinsics]].
b. Set globalObj to ! OrdinaryObjectCreate(intrinsics.[[%Object.prototype%]]).
2. Assert: Type(globalObj) is Object.
3. If thisValue is undefined, set thisValue to globalObj.
...
OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )
1. Let internalSlotsList be « [[Prototype]], [[Extensible]] ».
2. If additionalInternalSlotsList is present, append each of its elements to internalSlotsList.
3. Let O be ! MakeBasicObject(internalSlotsList).
4. Set O.[[Prototype]] to proto.
5. Return O.
MakeBasicObject ( internalSlotsList )
...
5. If internalSlotsList contains [[Extensible]], set obj.[[Extensible]] to true.
features: [ShadowRealm]
---*/
assert.sameValue(
typeof ShadowRealm.prototype.evaluate,
'function',
'This test must fail if ShadowRealm.prototype.evaluate is not a function'
);
const r = new ShadowRealm();
assert.sameValue(
r.evaluate('Object.getPrototypeOf(globalThis) === Object.prototype'),
true,
'The [[Prototype]] of globalThis is Object.prototype'
);
assert.sameValue(
r.evaluate('Object.isExtensible(globalThis)'),
true,
'globalThis is extensible'
);
assert.sameValue(
r.evaluate('globalThis.constructor === Object'),
true,
'globalThis.constructor is Object'
);