LibJS: Reduce number of proxy traps called during for..in iteration

Before this change, we would enumerate all the keys with
[[OwnPropertyKeys]], and then do [[GetOwnPropertyDescriptor]] twice for
each key as we went through them.

We now only do one [[GetOwnPropertyDescriptor]] per key, which
drastically reduces the number of proxy traps when those are involved.
The new trap sequence matches what you get with V8, so I don't think
anyone will be unpleasantly surprised here.
This commit is contained in:
Andreas Kling 2025-03-20 13:19:28 -05:00 committed by Andreas Kling
commit 357eeba49c
Notes: github-actions[bot] 2025-03-20 22:50:55 +00:00
2 changed files with 90 additions and 49 deletions

View file

@ -0,0 +1,40 @@
test("for..in iteration Proxy traps", () => {
let traps = [];
let array = [1, 2, 3];
let from = new Proxy(array, {
getPrototypeOf: function (t) {
traps.push("getPrototypeOf");
return Reflect.getPrototypeOf(t);
},
ownKeys: function (t) {
traps.push("ownKeys");
return Reflect.ownKeys(t);
},
has: function (t, p) {
traps.push("has");
return Reflect.has(t, p);
},
getOwnPropertyDescriptor: function (t, p) {
traps.push("getOwnPropertyDescriptor");
return Reflect.getOwnPropertyDescriptor(t, p);
},
});
const to = [];
for (const prop in from) {
to.push(prop);
from.pop();
}
expect(to).toEqual(["0", "1"]);
expect(traps).toEqual([
"ownKeys",
"getPrototypeOf",
"getOwnPropertyDescriptor",
"getOwnPropertyDescriptor",
"getOwnPropertyDescriptor",
"getOwnPropertyDescriptor",
"getOwnPropertyDescriptor",
"getOwnPropertyDescriptor",
]);
});