Skip to content

Commit bfac1c4

Browse files
committed
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
1 parent e4587f4 commit bfac1c4

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Ensure we create Ion ICs to cover IonCacheIRCompiler code paths.
2+
setJitCompilerOption("ion.forceinlineCaches", 1);
3+
4+
// Ignore unhandled rejections when calling Promise and AsyncFunction methods.
5+
ignoreUnhandledRejections();
6+
7+
// Function cloned for each test.
8+
function test(v) {
9+
for (var i = 0; i < 100; ++i) {
10+
// |v.key| is a getter calling a built-in method or accessor.
11+
v.key;
12+
}
13+
}
14+
15+
// Add |fn| as a method on |holder| and then call it using |thisValue| as the this-value.
16+
function runTest(holder, thisValue, key, fn) {
17+
assertEq(typeof fn, "function");
18+
assertEq(
19+
holder === thisValue || Object.prototype.isPrototypeOf.call(holder, Object(thisValue)),
20+
true,
21+
`${String(key)} can be found on thisValue when stored in holder`
22+
);
23+
24+
// Add a prefix so we don't overwrite built-in methods.
25+
var safeKey = "__" + String(key);
26+
27+
Object.defineProperty(holder, safeKey, {
28+
get: fn,
29+
configurable: true,
30+
});
31+
32+
try {
33+
var t = Function(`return ${test.toString().replaceAll("key", safeKey)}`)();
34+
t(thisValue);
35+
} catch {
36+
// Intentionally ignore any errors.
37+
}
38+
39+
// Also test wrappers of primitive values.
40+
if (Object(thisValue) !== thisValue) {
41+
try {
42+
var t = Function(`return ${test.toString().replaceAll("key", safeKey)}`)();
43+
t(Object(thisValue));
44+
} catch {
45+
// Intentionally ignore any errors.
46+
}
47+
}
48+
}
49+
50+
// Test all methods and accessors of |object|.
51+
function testForEach(object, holder, thisValue) {
52+
for (var key of Reflect.ownKeys(object)) {
53+
var desc = Reflect.getOwnPropertyDescriptor(object, key);
54+
if (typeof desc.value === "function")
55+
runTest(holder, thisValue, key, desc.value);
56+
if (typeof desc.get === "function")
57+
runTest(holder, thisValue, key, desc.get);
58+
if (typeof desc.set === "function")
59+
runTest(holder, thisValue, key, desc.set);
60+
}
61+
}
62+
63+
var seenProto = new Set();
64+
65+
// Test along the prototype chain of |objectOrPrimitive|.
66+
function testProto(objectOrPrimitive) {
67+
var proto = Object.getPrototypeOf(objectOrPrimitive);
68+
69+
while (proto) {
70+
// Install methods on |proto| and then call wih |obj| as the this-value.
71+
testForEach(proto, proto, objectOrPrimitive);
72+
73+
// Cover all objects on the prototype chain.
74+
proto = Reflect.getPrototypeOf(proto);
75+
76+
// But skip already seen prototypes to ensure we don't spend too much time on this test.
77+
if (seenProto.has(proto)) {
78+
break;
79+
}
80+
seenProto.add(proto);
81+
}
82+
}
83+
84+
// Test constructor of |objectOrPrimitive|.
85+
function testConstructor(objectOrPrimitive) {
86+
// Install constructor methods on the prototype object and then call with |objectOrPrimitive|
87+
// as the this-value.
88+
testForEach(obj.constructor, Object.getPrototypeOf(objectOrPrimitive), objectOrPrimitive);
89+
}
90+
91+
function testSingleton(singleton) {
92+
var thisValue = {};
93+
testForEach(singleton, thisValue, thisValue);
94+
}
95+
96+
for (var obj of [
97+
// Fundamental Objects <https://tc39.es/ecma262/#sec-fundamental-objects>.
98+
{},
99+
Function(),
100+
false,
101+
Symbol(),
102+
new Error(),
103+
104+
// Numbers and Dates <https://tc39.es/ecma262/#sec-numbers-and-dates>
105+
0,
106+
0n,
107+
new Date(0),
108+
109+
// Text Processing <https://tc39.es/ecma262/#sec-text-processing>
110+
"",
111+
/(?:)/,
112+
113+
// Indexed Collections <https://tc39.es/ecma262/#sec-indexed-collections>
114+
[],
115+
new Int32Array(1),
116+
new Uint8Array(1),
117+
118+
// Keyed Collections <https://tc39.es/ecma262/#sec-keyed-collections>
119+
new Map(),
120+
new Set(),
121+
new WeakMap(),
122+
new WeakSet(),
123+
124+
// Structured Data <https://tc39.es/ecma262/#sec-structured-data>
125+
new ArrayBuffer(1),
126+
new SharedArrayBuffer(1),
127+
new DataView(new ArrayBuffer(8)),
128+
129+
// Managing Memory <https://tc39.es/ecma262/#sec-managing-memory>
130+
new WeakRef({}),
131+
new FinalizationRegistry(() => {}),
132+
133+
// Control Abstraction Objects <https://tc39.es/ecma262/#sec-control-abstraction-objects>
134+
new class extends Iterator{},
135+
new Promise(() => {}),
136+
(function*(){}).constructor,
137+
(async function*(){}).constructor,
138+
(async function(){}).constructor,
139+
]) {
140+
testProto(obj);
141+
testConstructor(obj);
142+
}
143+
144+
testSingleton(Math);
145+
testSingleton(Atomics);
146+
testSingleton(JSON);
147+
testSingleton(Reflect);

0 commit comments

Comments
 (0)