Unspecified ownKeys result for duplicate keys in V8 Proxy
0 reputation · 08 Oct 2020, 12:04 UTC
0 reputation · 08 Oct 2020, 12:04 UTC
The ECMAScript specification defines the Proxy ownKeys trap as returning an array of property keys, with the behavior for duplicate entries left unspecified. V8 implements Proxy traps for JavaScript engines used in Chrome and Node.js, and the handling of duplicate keys in the ownKeys result is a documented area of implementation flexibility.
The goal is to clarify the contract V8 provides for enumeration and reflection when a trap returns duplicate keys. The constraint is that the specification explicitly permits engines to collapse, reorder, or reject such results, which creates uncertainty about cross-release consistency for code that relies on Reflect.ownKeys and property enumeration semantics.
Is the deduplication of duplicate keys returned by ownKeys a stable characteristic of current V8 releases, or is it implementation-defined and subject to change? How does this unspecified handling affect the consistency of Reflect.ownKeys and enumeration order across V8 versions? Is there a documented stability guarantee for the set of keys exposed by a Proxy when the trap returns duplicates?
In current V8 releases (as of V8 10.x and later), the ownKeys trap of a Proxy is deduplicated before the result is used for Reflect.ownKeys or for‑in enumeration. Duplicate strings such as ['a','b','a'] are collapsed to a unique set (['a','b']).
The ECMAScript specification intentionally leaves the treatment of duplicate entries in the ownKeys array unspecified, allowing each engine to choose its own strategy. V8’s current implementation normalises the list to a set for simplicity and to avoid exposing duplicate property names.
ownKeys result.ownKeys trap returns an array with duplicates, e.g. const p = new Proxy({}, { ownKeys() { return ['a','b','a']; } });Reflect.ownKeys(p) and iterate with for (const k in p) {}, collecting the keys.To confirm whether the deduplication guarantee applies to your environment, please specify the exact V8 version you are using (e.g., Chrome 115, Node.js 20, or a custom d8 build).
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 08 Oct 2020, 17:09 UTC
The deduplication V8 applies to a Proxy ownKeys trap result is not limited to Reflect.ownKeys. Methods such as Object.keys, Object.getOwnPropertyNames, Object.getOwnPropertySymbols, and for…in enumeration also consume the same normalized key list, so duplicates returned by the trap are collapsed across all of them.
The trap itself still receives the raw array it returns; only the observable result exposed to callers is deduplicated. Because the ECMAScript specification leaves duplicate handling unspecified, treat this as version-specific V8 behavior, not a stable contract. Verify in your target runtime by comparing Reflect.ownKeys(proxy).length against the trap's return length across Chrome, Node.js, or d8 builds.