commit 0e723420e06dfa157bf01cde88ca68400471973c
parent 5b4768d1dd6709c9e7e08b67fc94664396902d1c
Author: André Bargull <andre.bargull@gmail.com>
Date: Mon, 20 Oct 2025 12:27:44 +0000
Bug 1991402 - Part 20: Add exhaustive test for built-in objects. r=spidermonkey-reviewers,jandem
Add an exhaustive test to ensure all built-in inlinable methods can be called
as getters from Ion ICs.
Differential Revision: https://phabricator.services.mozilla.com/D268352
Diffstat:
1 file changed, 147 insertions(+), 0 deletions(-)
diff --git a/js/src/jit-test/tests/cacheir/inlinable-native-accessor-7.js b/js/src/jit-test/tests/cacheir/inlinable-native-accessor-7.js
@@ -0,0 +1,147 @@
+// 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 [
+ // Fundamental Objects <https://tc39.es/ecma262/#sec-fundamental-objects>.
+ {},
+ Function(),
+ false,
+ Symbol(),
+ new Error(),
+
+ // Numbers and Dates <https://tc39.es/ecma262/#sec-numbers-and-dates>
+ 0,
+ 0n,
+ new Date(0),
+
+ // Text Processing <https://tc39.es/ecma262/#sec-text-processing>
+ "",
+ /(?:)/,
+
+ // Indexed Collections <https://tc39.es/ecma262/#sec-indexed-collections>
+ [],
+ new Int32Array(1),
+ new Uint8Array(1),
+
+ // Keyed Collections <https://tc39.es/ecma262/#sec-keyed-collections>
+ new Map(),
+ new Set(),
+ new WeakMap(),
+ new WeakSet(),
+
+ // Structured Data <https://tc39.es/ecma262/#sec-structured-data>
+ new ArrayBuffer(1),
+ new SharedArrayBuffer(1),
+ new DataView(new ArrayBuffer(8)),
+
+ // Managing Memory <https://tc39.es/ecma262/#sec-managing-memory>
+ new WeakRef({}),
+ new FinalizationRegistry(() => {}),
+
+ // Control Abstraction Objects <https://tc39.es/ecma262/#sec-control-abstraction-objects>
+ 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);