* fix(js): structuredClone cycles through Error.cause and clones own __proto__ (#419, #420)
The structuredClone polyfill had two correctness/parity gaps in _structuredClone:
- The Error branch recursed into `cause` before recording the clone in `seen`,
so a cycle through the error (e.cause === e) recursed until the stack
overflowed. Chrome clones such graphs and preserves identity. Fix: seen.set
the clone before recursing into cause. (#419)
- The generic-object branch built the clone on the source's prototype and
copied properties by assignment, so an own enumerable `__proto__` data
property (exactly what JSON.parse('{"__proto__":…}') produces) went through
the inherited __proto__ setter and reparented the clone instead of copying
the property. Fix: clone plain objects onto Object.prototype (like Chrome)
and define each property instead of assigning it. (#420)
Adds two parity tests to structured_clone_crypto_parity.rs; full obscura-cdp
suite (73) green.
* perf(js): keep structuredClone fast path for all keys but __proto__
The own-__proto__ fix copied every own property with Object.defineProperty
to avoid triggering the inherited prototype setter. That is ~3x slower
than plain assignment per key, so cloning a large object regressed
(~75ms -> ~228ms for a 1000-key object x200).
Only the __proto__ key needs defineProperty; every other key is safe to
assign. Special-case it so the fast path applies to all other keys.
Measured back to parity with main (85ms vs 85ms); the own-__proto__
correctness test still passes.
---------
Co-authored-by: SGavrl <277843151+SGavrl@users.noreply.github.com>