Deferred from #183: the SetterThatIgnoresPrototypeProperties step 5a (Set(this, p, v, true)) ignores the boolean returned by set_property_value and does not honor exotic [[Set]] semantics for a receiver that reports a writable own data descriptor but whose [[Set]] returns false.
Original feedback by @chatgpt-codex-connector on PR #183 (#183):
Route existing stack writes through [[Set]]
When the receiver already has an own stack descriptor, SetterThatIgnoresPrototypeProperties requires Set(thisValue, "stack", v, true). This branch only checks descriptor bits and then ignores the boolean from set_property_value; for a module namespace object that exports stack, [[GetOwnProperty]] reports a writable own data descriptor but its [[Set]] returns false, so Object.getOwnPropertyDescriptor(Error.prototype, "stack").set.call(ns, "x") incorrectly succeeds instead of throwing. Calling the existing proxy_set/Set path and throwing on false would preserve the exotic [[Set]] behavior.
Context
src/interpreter/builtins/mod.rs — Error.prototype.stack setter, the ordinary own-data-descriptor branch: it calls cell.borrow_mut().set_property_value("stack", v) and discards the boolean.
src/interpreter/types.rs — set_property_value models exotic [[Set]] = false only for typed-array out-of-bounds indices and non-writable Array.length. For a module namespace (whose [[Set]] always returns false, §10.4.6.9) it is a non-mutating no-op that returns true, so the setter returns normally instead of throwing.
- The same gap already ships for the sibling
SetterThatIgnoresPrototypeProperties setters in src/interpreter/builtins/iterators.rs: Iterator.prototype.constructor and Iterator.prototype[Symbol.toStringTag] use the identical contains_key + set_property_value shortcut.
Why deferred
diminishing-returns — the trigger (Object.getOwnPropertyDescriptor(Error.prototype,'stack').set.call(ns,'x') on a module namespace that exports a binding named stack) is highly contrived, has zero test262 coverage (the 35 built-ins/Error/prototype/stack/ files and the Iterator weird-setter.js files all use ordinary objects / Proxies), and fixing only the Error branch would be incomplete-by-design.
Suggested fix
Factor a shared Set(O, P, V, Throw=true) -> bool path (the dispatch is currently inlined in Reflect.set and Object.assign, including the "module namespace exotic → false" branch) and route all three SetterThatIgnoresPrototypeProperties setters (Error.prototype.stack, Iterator.prototype.constructor, Iterator.prototype[Symbol.toStringTag]) through it, throwing on false.
Filed automatically by pm-autofix-pr after dual-evaluator triage by Claude Opus 4.8 and Codex (codex-cli 0.130.0), which both returned DEFER / diminishing-returns.
Deferred from #183: the
SetterThatIgnoresPrototypePropertiesstep 5a (Set(this, p, v, true)) ignores the boolean returned byset_property_valueand does not honor exotic[[Set]]semantics for a receiver that reports a writable own data descriptor but whose[[Set]]returnsfalse.Original feedback by @chatgpt-codex-connector on PR #183 (#183):
Context
src/interpreter/builtins/mod.rs—Error.prototype.stacksetter, the ordinary own-data-descriptor branch: it callscell.borrow_mut().set_property_value("stack", v)and discards the boolean.src/interpreter/types.rs—set_property_valuemodels exotic[[Set]] = falseonly for typed-array out-of-bounds indices and non-writableArray.length. For a module namespace (whose[[Set]]always returnsfalse, §10.4.6.9) it is a non-mutating no-op that returnstrue, so the setter returns normally instead of throwing.SetterThatIgnoresPrototypePropertiessetters insrc/interpreter/builtins/iterators.rs:Iterator.prototype.constructorandIterator.prototype[Symbol.toStringTag]use the identicalcontains_key+set_property_valueshortcut.Why deferred
diminishing-returns — the trigger (
Object.getOwnPropertyDescriptor(Error.prototype,'stack').set.call(ns,'x')on a module namespace that exports a binding namedstack) is highly contrived, has zero test262 coverage (the 35built-ins/Error/prototype/stack/files and the Iteratorweird-setter.jsfiles all use ordinary objects / Proxies), and fixing only the Error branch would be incomplete-by-design.Suggested fix
Factor a shared
Set(O, P, V, Throw=true) -> boolpath (the dispatch is currently inlined inReflect.setandObject.assign, including the "module namespace exotic → false" branch) and route all threeSetterThatIgnoresPrototypePropertiessetters (Error.prototype.stack, Iterator.prototype.constructor, Iterator.prototype[Symbol.toStringTag]) through it, throwing onfalse.Filed automatically by
pm-autofix-prafter dual-evaluator triage by Claude Opus 4.8 and Codex (codex-cli 0.130.0), which both returned DEFER / diminishing-returns.