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
URLSearchParams methods unreachable through dynamically-typed access (append is not a function) #5961
constu=newURL("https://x.com/p");consto: any=[u.searchParams][0];// any type-erasing indirectionconsole.log("T",typeofo.append);try{o.append("a","1");console.log("OK",u.toString());}catch(e){console.log("ERR",String(e));}
node: T function → OK https://x.com/p?a=1
perry-compiled: T undefined → ERR TypeError: append is not a function
Mechanism
create_url_search_params_object (perry-runtime url/search_params.rs) allocates the native URLSearchParams as an ordinary object with class_id == 0 holding _entries/_owner fields — deliberately (the shape-guard in try_read_as_search_params relies on it). Its methods exist only via static, type-inference-directed lowering (perry-codegen/expr/url_main.rs routes sp.append(...) to js_url_search_params_append when receiver_class_name infers URLSearchParams). The instance itself carries no vtable and no prototype: Object.getPrototypeOf(sp) is Object.prototype, Object.keys(sp) is ["_entries","_owner"].
So the moment the receiver's static type is lost — any, a heterogeneous container, a minified bundle where inference can't track the value — the generic dynamic member read finds nothing and every method call throws X is not a function. Real-world hit: a bundled app's auth-URL builder doing eleven url.searchParams.append(...) calls fails at runtime while the identical code passes when extracted (where inference succeeds).
typeof o.append === "undefined" (not a thrown lookup) confirms it's the plain-object field-miss path.
Fix direction
Make native URLSearchParams methods reachable dynamically. Two shapes:
Dynamic-fallback dispatch (surgical): in the generic member-get/method-call miss path, when the receiver shape-matches URLSearchParams (class_id == 0 + leading _entries key, as try_read_as_search_params already checks) and the name is one of the URLSearchParams surface (append/delete/entries/forEach/get/getAll/has/keys/set/sort/toString/values/size), return/invoke the corresponding js_url_search_params_* native. Mirrors how other natives expose a *_method_value surface.
Real identity (structural): allocate URLSearchParams with a reserved registered class id + vtable entries for the natives, updating the class_id == 0 shape-guards (try_read_as_search_params, MIMEParams disambiguation) accordingly.
The same audit likely applies to sibling natives whose methods are static-lowering-only (e.g. Headers via js_headers_method_value, URL itself) — worth checking typeof (x as any).method for each.
Activity
fix(runtime): guard URLSearchParams shape probe against non-object re…
fix(runtime): guard URLSearchParams shape probe against non-object re…
fix(runtime): AbortSignal parity — accept in events helpers + dynamic…
fix(url): route URLSearchParams subclass instances to their native ba…
fix(url): route URLSearchParams subclass instances to their native ba…
fix(url): route URLSearchParams subclass instances to their native ba…
fix(url): route URLSearchParams subclass instances to their native ba…
fix(url): route URLSearchParams subclass instances to their native ba…