Problem
JSON.parse keeps the reviver, holder/value graph, and JsonParseRecord values in raw native locals while InternalizeJSONProperty invokes user code. A reviver can trigger a moving collection; the next callback then uses stale cells.
The forced-moving witness currently aborts in bindRootedParams through internalizeJson / jsonParse because the write barrier receives a stale managed environment.
Required fix
- Give the recursive reviver traversal an explicit GC rooting/relocation contract for
holder,val,reviver, per-child results, and parse-recordValuefields. - Preserve the ECMA-262 InternalizeJSONProperty ordering and
context.sourceidentity rules. - Cover normal and abrupt reviver callbacks under forced moving collection in tree-walker and required-bytecode modes.
- Run the focused witness under TSan and the full unit/conformance gates.
Discovered while auditing synchronous defining-realm wrappers for #830. This is a separate traversal-root bug, not a caller-realm restore bug.