Commit 20c21d4
* fix(hir): #5912 — new URL()/TextEncoder()/etc. ignore lexical shadowing
`new URL(...)` (and URLSearchParams/URLPattern/TextEncoder/TextDecoder)
were dispatched by bare identifier name with no check for whether the
name actually resolves to the global constructor or is shadowed by a
local function/class — unlike sibling well-known constructors
(Function, Object) in the same match, which already guard on
lookup_local/lookup_func/lookup_class.
Real packages ship their own tolerant polyfills under these names
(found via @mixmark-io/domino's lib/URL.js, which defines
`function URL(url) { ... }` and calls `new URL()` with zero args
against its own constructor) and hit perry's native WHATWG URL
constructor instead, which requires at least one argument.
The same unguarded name match also existed in a second, independent
spot: `static_receiver_class` (used to decide whether `.toString()` /
`.toJSON()` / `JSON.stringify()` on a receiver should route through
the native Date/URL fast paths) classified any `new URL(...)` — or a
local typed as `URL` — as the native type by name alone, so even after
fixing the construction site, printing/serializing a shadowed
instance still silently substituted native URL output.
Fixes both sites by checking `lookup_local`/`lookup_func`/
`lookup_class` before applying the native lowering, matching the
existing shadowing-guard pattern used elsewhere in expr_new.rs.
* fix(hir): #5912 CodeRabbit follow-up — globalThis escape hatch, alias, imported bindings
Three issues from CodeRabbit's review of the initial fix:
1. Real regression: the static_receiver_class shadowing guard collapsed
`new globalThis.URL(...)` and bare `new URL(...)` into the same
class_name capture, so a locally-shadowed URL made even the explicit
globalThis-qualified form misclassify as "Object" and lose the
native fast path. Track which callee shape matched and only apply
the shadow check to the bare-identifier form.
2. Coverage gap: `const MyURL = URL; new MyURL()` bypassed the
shadowing guard entirely via the resolve_class_alias branch, which
runs before the later callee_local_at_entry/lookup_func/lookup_class
checks. Added the same shadowing check there, against the
ALIAS-RESOLVED name (aliases are name-keyed, not scope-aware).
3. Coverage gap: an imported binding shadowing one of these names
(`import { URL } from "./polyfill"`) wasn't covered by the
lookup_local/lookup_func/lookup_class triplet. Added
lookup_imported_func alongside it in expr_new.rs (module-level
registry, safe to query fresh — unlike lookup_local, this one isn't
subject to the scope-stack-disturbance issue callee_local_at_entry
exists to avoid, so no special snapshotting needed).
static_receiver.rs's own guard now calls the existing
`shadows_unqualified_global` helper (already covers all four cases)
instead of reimplementing three of them by hand.
Extended the regression test with both the globalThis-escape-hatch and
alias cases; both match node byte-for-byte.
---------
Co-authored-by: Ralph <ralph@skelpo.com>
1 parent 8426fa3 commit 20c21d4
3 files changed
Lines changed: 123 additions & 11 deletions
File tree
- crates/perry-hir/src/lower
- expr_call
- test-files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
54 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
55 | 63 | | |
56 | 64 | | |
57 | 65 | | |
58 | 66 | | |
59 | 67 | | |
60 | | - | |
61 | | - | |
| 68 | + | |
| 69 | + | |
62 | 70 | | |
63 | 71 | | |
64 | | - | |
| 72 | + | |
65 | 73 | | |
66 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
67 | 90 | | |
68 | 91 | | |
69 | 92 | | |
| |||
139 | 162 | | |
140 | 163 | | |
141 | 164 | | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
142 | 173 | | |
143 | 174 | | |
144 | 175 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
416 | 416 | | |
417 | 417 | | |
418 | 418 | | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
419 | 425 | | |
420 | | - | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
421 | 429 | | |
422 | 430 | | |
423 | 431 | | |
| |||
941 | 949 | | |
942 | 950 | | |
943 | 951 | | |
944 | | - | |
945 | | - | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
946 | 975 | | |
947 | 976 | | |
948 | 977 | | |
949 | 978 | | |
950 | 979 | | |
951 | 980 | | |
952 | | - | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
953 | 987 | | |
954 | 988 | | |
955 | 989 | | |
| |||
993 | 1027 | | |
994 | 1028 | | |
995 | 1029 | | |
996 | | - | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
997 | 1036 | | |
998 | 1037 | | |
999 | 1038 | | |
| |||
1002 | 1041 | | |
1003 | 1042 | | |
1004 | 1043 | | |
1005 | | - | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
1006 | 1050 | | |
1007 | 1051 | | |
1008 | 1052 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
0 commit comments