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
URL exposes its twelve components as own enumerable instance properties; node keeps them as accessors on URL.prototype (Object.keys, for...in, spread all diverge) #10823
URL stores its twelve components as own enumerable properties on the instance. Node keeps all of
them as accessors on URL.prototype and gives the instance zero own properties, so every operation
that enumerates an object disagrees.
Anything that walks own properties therefore diverges: for...in, object spread {...u}, Object.assign({}, u), Object.entries, a deepStrictEqual against a plain object, and any
serializer that enumerates rather than calling toJSON.
The brand and JSON.stringify happen to match, so a test that only checks those passes — which is
probably why this has not been noticed.
Cause
URL is one of the web classes that is already a real ObjectHeader rather than a registry handle,
but its components are written as ordinary instance fields rather than installed as accessors on a URL.prototype. Related, from crates/perry-runtime/src/object/to_string_tag.rs:18-32, the same
family of classes has a second half of this gap:
AbortController / AbortSignal / EventTarget / Event / CustomEvent (real ObjectHeaders
whose instances are never linked to their .prototype object via object_static_prototype, so
the generic own/inherited-property walk in object_to_string_tag_property can never reach a tag
installed there).
So for this group the prototype objects exist but instances are not linked to them, and state that
belongs on the prototype as accessors is kept on the instance instead.
Fix
Install the components as accessors on a real URL.prototype and link instances to it with object_static_prototype, leaving the instance with no own properties. The runtime already has the
pieces: class_registry/prototype_objects.rsensure_function_prototype_object() builds a real
prototype and mirrors methods onto it, object/iterator_prototypes.rsbuild_family_proto() is a
working template, and ObjectMeta.prototype is a direct write.
Worth checking the same way: AbortController, AbortSignal, Event, CustomEvent, DOMException, EventTarget, URLSearchParams.
Why this is being filed now
It is the shape a planned change must not reproduce. #10821 proposes turning the thirteen native
handle families into ordinary objects to give them identity and put them on the single property-read
path. Done naively — state in instance fields — that would give thirteen more classes exactly this
bug. Done correctly — state behind prototype accessors, instance with zero own keys — it matches
node, which is also what node itself does for all of these classes.
Activity
feat(runtime): setTimeout / setInterval / setImmediate return ordinar…
feat(runtime): TextEncoder / TextDecoder instances are ordinary objec…
feat(runtime): setTimeout / setInterval / setImmediate return ordinar…