Summary
OBJECT_META_FLAG_PROTO_OVERRIDE is documented and consumed as "the user replaced this instance's [[Prototype]]", but it is actually set by ~20 runtime prototype-wiring sites that are not user Object.setPrototypeOf calls at all. Any consumer that reads the flag as "a user override is in effect" is therefore wrong for those object families.
Why this is filed
#9244 was three separate bugs, and all three were consumers trusting that flag. They are fixed, so this is not a correctness blocker any more — the consumers now tolerate a flagged receiver. But the conflation remains, and the next consumer added on top of the flag will hit the same trap.
The two setters
object_set_static_prototype — sets OBJECT_META_FLAG_PROTO_OVERRIDE, bumps the prop-plan epoch, retires element-shape proofs, transitions object shape semantics.
object_link_class_default_prototype — the quiet sibling: records the prototype only.
Ordinary new C() uses the quiet variant (class_registry/construct.rs, construct/class_object.rs), so user classes are unaffected. The flagged population is the genuine js_object_set_prototype_of entry plus these runtime wiring sites:
intl.rs, messaging.rs, node_inspector.rs (×3), disposable.rs, web_storage.rs, node_vm.rs (×2), wasi.rs, cluster.rs (×4), dyn_eval/bridge.rs, intl/locale.rs, perf_hooks/prototypes.rs (×3), array/subclass_tests.rs
#9169 recognised one instance of this and fixed it by moving iterator_prototypes.rs::chain_to to the quiet variant — a per-site workaround rather than addressing the signal.
Suggested direction
Separate "the runtime wired this prototype" from "a user replaced this prototype": either a distinct flag set only by js_object_set_prototype_of, or move the remaining runtime wiring sites to object_link_class_default_prototype where the loud variant's side effects (epoch bump, element-shape retirement, shape-semantics transition) are not actually wanted.
Auditing which of those ~20 sites genuinely need the loud variant is the bulk of the work; several look like they want the quiet one for the same reason chain_to did.
Acceptance criteria
Summary
OBJECT_META_FLAG_PROTO_OVERRIDEis documented and consumed as "the user replaced this instance's[[Prototype]]", but it is actually set by ~20 runtime prototype-wiring sites that are not userObject.setPrototypeOfcalls at all. Any consumer that reads the flag as "a user override is in effect" is therefore wrong for those object families.Why this is filed
#9244 was three separate bugs, and all three were consumers trusting that flag. They are fixed, so this is not a correctness blocker any more — the consumers now tolerate a flagged receiver. But the conflation remains, and the next consumer added on top of the flag will hit the same trap.
The two setters
object_set_static_prototype— setsOBJECT_META_FLAG_PROTO_OVERRIDE, bumps the prop-plan epoch, retires element-shape proofs, transitions object shape semantics.object_link_class_default_prototype— the quiet sibling: records the prototype only.Ordinary
new C()uses the quiet variant (class_registry/construct.rs,construct/class_object.rs), so user classes are unaffected. The flagged population is the genuinejs_object_set_prototype_ofentry plus these runtime wiring sites:intl.rs,messaging.rs,node_inspector.rs(×3),disposable.rs,web_storage.rs,node_vm.rs(×2),wasi.rs,cluster.rs(×4),dyn_eval/bridge.rs,intl/locale.rs,perf_hooks/prototypes.rs(×3),array/subclass_tests.rs#9169 recognised one instance of this and fixed it by moving
iterator_prototypes.rs::chain_toto the quiet variant — a per-site workaround rather than addressing the signal.Suggested direction
Separate "the runtime wired this prototype" from "a user replaced this prototype": either a distinct flag set only by
js_object_set_prototype_of, or move the remaining runtime wiring sites toobject_link_class_default_prototypewhere the loud variant's side effects (epoch bump, element-shape retirement, shape-semantics transition) are not actually wanted.Auditing which of those ~20 sites genuinely need the loud variant is the bulk of the work; several look like they want the quiet one for the same reason
chain_todid.Acceptance criteria
issue_9131_prototype_method_replacementand the release blocker: #9169 regresses 4 gap tests (built-in iterator/prototype dispatch) #9244 gap tests (iterator_helpers_2874,language_types_object_part_a,object_string_wrappers,5592_class_expr_rebind_computed_accessor) all stay green.