You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Five web builtins return undefined for a prototype-method value-read, and URL.prototype.toString silently resolves to the wrong function #10808
Reading a prototype method as a value returns undefined for five web builtins, and returns the wrong function for a sixth. Confirmed empirically, not inferred.
These are the remaining members of the deliberate #10555 group in crates/perry-runtime/src/object/global_this/proto_methods.rs, whose arms install only a Symbol.toStringTag descriptor. The seventh member, URLSearchParams, is fixed by #10759 / PR #10807; this issue covers the other six, audited while fixing it.
Results
builtin
value-read of a prototype method
verdict
AbortController
typeof undefined
same defect
AbortSignal
typeof undefined
same defect
CustomEvent
typeof undefined
same defect
Event
typeof undefined
same defect
EventTarget
typeof undefined
same defect
URL — .prototype.toJSON
typeof undefined
same defect
URL — .prototype.toString
resolves to a callable — the wrong one
worse; see below
Why URL.prototype.toString is the more dangerous case
The other failures are loud: you read a method, get undefined, and the next .call() throws. URL.prototype.toString instead resolves to the inherited generic Object.prototype.toString, which is callable and returns "[object URL]" rather than the URL string.
So it does not throw. It silently returns a plausible-looking wrong value. Any code that reads toString as a value — a serializer, a logger, a template helper, anything doing String(x) through an indirection — gets "[object URL]" where Node gives the href. That is a correctness bug that no crash will surface.
Mechanism
The #10555 group's arms were written on the premise that these builtins' methods are reached by type-directed static dispatch or handle tables, so reified prototype closures were unnecessary — each arm installs only the toStringTag descriptor for reflection. That premise holds for x.method() and has no answer for a method read as a value: the read finds nothing installed and falls through to undefined, or in URL's case to an inherited generic.
This is a gap in a deliberate design rather than a set of forgotten entries, which matters for the fix: the question is what a statically-dispatched builtin should do when one of its methods is read as a value, not why six entries were missed.
Note on scope
Filed as an audit result, deliberately not fixed alongside #10759 — that PR fixes one member and this issue records the other six with evidence. Whoever takes this should decide whether the right remedy is six more arms or a general answer for the group, and URL.prototype.toString should be handled first: it is the only one that fails silently.
Activity
fix(runtime): keep both web-prototype installs and pay the raw-handle…
fix(runtime): keep both web-prototype installs and pay the raw-handle…
fix(runtime): keep both web-prototype installs and pay the raw-handle…