Source code
Revision control
Copy as Markdown
Other Tools
// Ensure we create Ion ICs to cover IonCacheIRCompiler code paths.
setJitCompilerOption("ion.forceinlineCaches", 1);
// Ignore unhandled rejections when calling Promise and AsyncFunction methods.
ignoreUnhandledRejections();
// Function cloned for each test.
function test(v) {
for (var i = 0; i < 100; ++i) {
// |v.key| is a getter calling a built-in method or accessor.
v.key;
}
}
// Add |fn| as a method on |holder| and then call it using |thisValue| as the this-value.
function runTest(holder, thisValue, key, fn) {
assertEq(typeof fn, "function");
assertEq(
holder === thisValue || Object.prototype.isPrototypeOf.call(holder, Object(thisValue)),
true,
`${String(key)} can be found on thisValue when stored in holder`
);
// Add a prefix so we don't overwrite built-in methods.
var safeKey = "__" + String(key);
Object.defineProperty(holder, safeKey, {
get: fn,
configurable: true,
});
try {
var t = Function(`return ${test.toString().replaceAll("key", safeKey)}`)();
t(thisValue);
} catch {
// Intentionally ignore any errors.
}
// Also test wrappers of primitive values.
if (Object(thisValue) !== thisValue) {
try {
var t = Function(`return ${test.toString().replaceAll("key", safeKey)}`)();
t(Object(thisValue));
} catch {
// Intentionally ignore any errors.
}
}
}
// Test all methods and accessors of |object|.
function testForEach(object, holder, thisValue) {
for (var key of Reflect.ownKeys(object)) {
var desc = Reflect.getOwnPropertyDescriptor(object, key);
if (typeof desc.value === "function")
runTest(holder, thisValue, key, desc.value);
if (typeof desc.get === "function")
runTest(holder, thisValue, key, desc.get);
if (typeof desc.set === "function")
runTest(holder, thisValue, key, desc.set);
}
}
var seenProto = new Set();
// Test along the prototype chain of |objectOrPrimitive|.
function testProto(objectOrPrimitive) {
var proto = Object.getPrototypeOf(objectOrPrimitive);
while (proto) {
// Install methods on |proto| and then call wih |obj| as the this-value.
testForEach(proto, proto, objectOrPrimitive);
// Cover all objects on the prototype chain.
proto = Reflect.getPrototypeOf(proto);
// But skip already seen prototypes to ensure we don't spend too much time on this test.
if (seenProto.has(proto)) {
break;
}
seenProto.add(proto);
}
}
// Test constructor of |objectOrPrimitive|.
function testConstructor(objectOrPrimitive) {
// Install constructor methods on the prototype object and then call with |objectOrPrimitive|
// as the this-value.
testForEach(obj.constructor, Object.getPrototypeOf(objectOrPrimitive), objectOrPrimitive);
}
function testSingleton(singleton) {
var thisValue = {};
testForEach(singleton, thisValue, thisValue);
}
for (var obj of [
{},
Function(),
false,
Symbol(),
new Error(),
0,
0n,
new Date(0),
"",
/(?:)/,
[],
new Int32Array(1),
new Uint8Array(1),
new Map(),
new Set(),
new WeakMap(),
new WeakSet(),
new ArrayBuffer(1),
new SharedArrayBuffer(1),
new DataView(new ArrayBuffer(8)),
new WeakRef({}),
new FinalizationRegistry(() => {}),
new class extends Iterator{},
new Promise(() => {}),
(function*(){}).constructor,
(async function*(){}).constructor,
(async function(){}).constructor,
]) {
testProto(obj);
testConstructor(obj);
}
testSingleton(Math);
testSingleton(Atomics);
testSingleton(JSON);
testSingleton(Reflect);