@scriptc/compiler 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/LICENSE +202 -0
  2. package/ambient/package.json +3 -0
  3. package/ambient/scriptc-node-fallback.d.ts +3001 -0
  4. package/ambient/scriptc-overrides.d.ts +95 -0
  5. package/ambient/scriptc.d.ts +74 -0
  6. package/dist/backend/cc.d.ts +169 -0
  7. package/dist/backend/cc.js +897 -0
  8. package/dist/backend/cc.js.map +1 -0
  9. package/dist/backend/emission/emit-async.d.ts +145 -0
  10. package/dist/backend/emission/emit-async.js +996 -0
  11. package/dist/backend/emission/emit-async.js.map +1 -0
  12. package/dist/backend/emission/emit-exprs.d.ts +3 -0
  13. package/dist/backend/emission/emit-exprs.js +5947 -0
  14. package/dist/backend/emission/emit-exprs.js.map +1 -0
  15. package/dist/backend/emission/emit-island.d.ts +45 -0
  16. package/dist/backend/emission/emit-island.js +271 -0
  17. package/dist/backend/emission/emit-island.js.map +1 -0
  18. package/dist/backend/emission/emit-shapes.d.ts +142 -0
  19. package/dist/backend/emission/emit-shapes.js +575 -0
  20. package/dist/backend/emission/emit-shapes.js.map +1 -0
  21. package/dist/backend/emission/emit-stmts.d.ts +78 -0
  22. package/dist/backend/emission/emit-stmts.js +960 -0
  23. package/dist/backend/emission/emit-stmts.js.map +1 -0
  24. package/dist/backend/emission/emit-types.d.ts +65 -0
  25. package/dist/backend/emission/emit-types.js +652 -0
  26. package/dist/backend/emission/emit-types.js.map +1 -0
  27. package/dist/backend/emission/emit-walkers.d.ts +154 -0
  28. package/dist/backend/emission/emit-walkers.js +1587 -0
  29. package/dist/backend/emission/emit-walkers.js.map +1 -0
  30. package/dist/backend/emission/emitter.d.ts +452 -0
  31. package/dist/backend/emission/emitter.js +1249 -0
  32. package/dist/backend/emission/emitter.js.map +1 -0
  33. package/dist/backend/emission/may-throw.d.ts +15 -0
  34. package/dist/backend/emission/may-throw.js +250 -0
  35. package/dist/backend/emission/may-throw.js.map +1 -0
  36. package/dist/backend/llvm/blocks.d.ts +21 -0
  37. package/dist/backend/llvm/blocks.js +68 -0
  38. package/dist/backend/llvm/blocks.js.map +1 -0
  39. package/dist/backend/llvm/classes.d.ts +84 -0
  40. package/dist/backend/llvm/classes.js +438 -0
  41. package/dist/backend/llvm/classes.js.map +1 -0
  42. package/dist/backend/llvm/dyn.d.ts +123 -0
  43. package/dist/backend/llvm/dyn.js +2624 -0
  44. package/dist/backend/llvm/dyn.js.map +1 -0
  45. package/dist/backend/llvm/emitter.d.ts +3 -0
  46. package/dist/backend/llvm/emitter.js +10087 -0
  47. package/dist/backend/llvm/emitter.js.map +1 -0
  48. package/dist/backend/llvm/shapes.d.ts +78 -0
  49. package/dist/backend/llvm/shapes.js +754 -0
  50. package/dist/backend/llvm/shapes.js.map +1 -0
  51. package/dist/backend/llvm/unsupported.d.ts +6 -0
  52. package/dist/backend/llvm/unsupported.js +12 -0
  53. package/dist/backend/llvm/unsupported.js.map +1 -0
  54. package/dist/backend/llvm/walkers.d.ts +58 -0
  55. package/dist/backend/llvm/walkers.js +793 -0
  56. package/dist/backend/llvm/walkers.js.map +1 -0
  57. package/dist/backend/mangle.d.ts +124 -0
  58. package/dist/backend/mangle.js +232 -0
  59. package/dist/backend/mangle.js.map +1 -0
  60. package/dist/coverage/report.d.ts +64 -0
  61. package/dist/coverage/report.js +226 -0
  62. package/dist/coverage/report.js.map +1 -0
  63. package/dist/diagnostics/diagnostic.d.ts +140 -0
  64. package/dist/diagnostics/diagnostic.js +458 -0
  65. package/dist/diagnostics/diagnostic.js.map +1 -0
  66. package/dist/diagnostics/render.d.ts +11 -0
  67. package/dist/diagnostics/render.js +58 -0
  68. package/dist/diagnostics/render.js.map +1 -0
  69. package/dist/frontend/cjs-lexer.d.ts +20 -0
  70. package/dist/frontend/cjs-lexer.js +813 -0
  71. package/dist/frontend/cjs-lexer.js.map +1 -0
  72. package/dist/frontend/lowering/http2-constants.d.ts +1 -0
  73. package/dist/frontend/lowering/http2-constants.js +251 -0
  74. package/dist/frontend/lowering/http2-constants.js.map +1 -0
  75. package/dist/frontend/lowering/lib-boundary.d.ts +6 -0
  76. package/dist/frontend/lowering/lib-boundary.js +143 -0
  77. package/dist/frontend/lowering/lib-boundary.js.map +1 -0
  78. package/dist/frontend/lowering/lower-assert.d.ts +18 -0
  79. package/dist/frontend/lowering/lower-assert.js +1269 -0
  80. package/dist/frontend/lowering/lower-assert.js.map +1 -0
  81. package/dist/frontend/lowering/lower-builtins.d.ts +511 -0
  82. package/dist/frontend/lowering/lower-builtins.js +5249 -0
  83. package/dist/frontend/lowering/lower-builtins.js.map +1 -0
  84. package/dist/frontend/lowering/lower-calls.d.ts +581 -0
  85. package/dist/frontend/lowering/lower-calls.js +6281 -0
  86. package/dist/frontend/lowering/lower-calls.js.map +1 -0
  87. package/dist/frontend/lowering/lower-classes.d.ts +727 -0
  88. package/dist/frontend/lowering/lower-classes.js +4701 -0
  89. package/dist/frontend/lowering/lower-classes.js.map +1 -0
  90. package/dist/frontend/lowering/lower-comptime.d.ts +53 -0
  91. package/dist/frontend/lowering/lower-comptime.js +244 -0
  92. package/dist/frontend/lowering/lower-comptime.js.map +1 -0
  93. package/dist/frontend/lowering/lower-containers.d.ts +483 -0
  94. package/dist/frontend/lowering/lower-containers.js +6281 -0
  95. package/dist/frontend/lowering/lower-containers.js.map +1 -0
  96. package/dist/frontend/lowering/lower-dgram.d.ts +20 -0
  97. package/dist/frontend/lowering/lower-dgram.js +319 -0
  98. package/dist/frontend/lowering/lower-dgram.js.map +1 -0
  99. package/dist/frontend/lowering/lower-emitter.d.ts +10 -0
  100. package/dist/frontend/lowering/lower-emitter.js +688 -0
  101. package/dist/frontend/lowering/lower-emitter.js.map +1 -0
  102. package/dist/frontend/lowering/lower-enums.d.ts +22 -0
  103. package/dist/frontend/lowering/lower-enums.js +235 -0
  104. package/dist/frontend/lowering/lower-enums.js.map +1 -0
  105. package/dist/frontend/lowering/lower-expando.d.ts +35 -0
  106. package/dist/frontend/lowering/lower-expando.js +276 -0
  107. package/dist/frontend/lowering/lower-expando.js.map +1 -0
  108. package/dist/frontend/lowering/lower-exprs.d.ts +524 -0
  109. package/dist/frontend/lowering/lower-exprs.js +8099 -0
  110. package/dist/frontend/lowering/lower-exprs.js.map +1 -0
  111. package/dist/frontend/lowering/lower-generators.d.ts +50 -0
  112. package/dist/frontend/lowering/lower-generators.js +421 -0
  113. package/dist/frontend/lowering/lower-generators.js.map +1 -0
  114. package/dist/frontend/lowering/lower-inspect.d.ts +20 -0
  115. package/dist/frontend/lowering/lower-inspect.js +1069 -0
  116. package/dist/frontend/lowering/lower-inspect.js.map +1 -0
  117. package/dist/frontend/lowering/lower-island.d.ts +108 -0
  118. package/dist/frontend/lowering/lower-island.js +650 -0
  119. package/dist/frontend/lowering/lower-island.js.map +1 -0
  120. package/dist/frontend/lowering/lower-mixins.d.ts +96 -0
  121. package/dist/frontend/lowering/lower-mixins.js +534 -0
  122. package/dist/frontend/lowering/lower-mixins.js.map +1 -0
  123. package/dist/frontend/lowering/lower-modules.d.ts +135 -0
  124. package/dist/frontend/lowering/lower-modules.js +1613 -0
  125. package/dist/frontend/lowering/lower-modules.js.map +1 -0
  126. package/dist/frontend/lowering/lower-namespaces.d.ts +168 -0
  127. package/dist/frontend/lowering/lower-namespaces.js +706 -0
  128. package/dist/frontend/lowering/lower-namespaces.js.map +1 -0
  129. package/dist/frontend/lowering/lower-server.d.ts +90 -0
  130. package/dist/frontend/lowering/lower-server.js +3471 -0
  131. package/dist/frontend/lowering/lower-server.js.map +1 -0
  132. package/dist/frontend/lowering/lower-stmts.d.ts +361 -0
  133. package/dist/frontend/lowering/lower-stmts.js +5341 -0
  134. package/dist/frontend/lowering/lower-stmts.js.map +1 -0
  135. package/dist/frontend/lowering/lower-stream.d.ts +88 -0
  136. package/dist/frontend/lowering/lower-stream.js +1533 -0
  137. package/dist/frontend/lowering/lower-stream.js.map +1 -0
  138. package/dist/frontend/lowering/lower-test.d.ts +27 -0
  139. package/dist/frontend/lowering/lower-test.js +353 -0
  140. package/dist/frontend/lowering/lower-test.js.map +1 -0
  141. package/dist/frontend/lowering/lowerer.d.ts +1748 -0
  142. package/dist/frontend/lowering/lowerer.js +6256 -0
  143. package/dist/frontend/lowering/lowerer.js.map +1 -0
  144. package/dist/frontend/lowering/surfaces.d.ts +272 -0
  145. package/dist/frontend/lowering/surfaces.js +1096 -0
  146. package/dist/frontend/lowering/surfaces.js.map +1 -0
  147. package/dist/frontend/npm-static.d.ts +55 -0
  148. package/dist/frontend/npm-static.js +300 -0
  149. package/dist/frontend/npm-static.js.map +1 -0
  150. package/dist/frontend/npm.d.ts +330 -0
  151. package/dist/frontend/npm.js +1259 -0
  152. package/dist/frontend/npm.js.map +1 -0
  153. package/dist/frontend/program.d.ts +186 -0
  154. package/dist/frontend/program.js +2172 -0
  155. package/dist/frontend/program.js.map +1 -0
  156. package/dist/frontend/provenance-registry.d.ts +48 -0
  157. package/dist/frontend/provenance-registry.js +87 -0
  158. package/dist/frontend/provenance-registry.js.map +1 -0
  159. package/dist/frontend/provenance.d.ts +6 -0
  160. package/dist/frontend/provenance.js +459 -0
  161. package/dist/frontend/provenance.js.map +1 -0
  162. package/dist/frontend/resolve.d.ts +56 -0
  163. package/dist/frontend/resolve.js +682 -0
  164. package/dist/frontend/resolve.js.map +1 -0
  165. package/dist/frontend/shared.d.ts +60 -0
  166. package/dist/frontend/shared.js +232 -0
  167. package/dist/frontend/shared.js.map +1 -0
  168. package/dist/frontend/ts7/adapter.d.ts +7 -0
  169. package/dist/frontend/ts7/adapter.js +54 -0
  170. package/dist/frontend/ts7/adapter.js.map +1 -0
  171. package/dist/frontend/ts7/ast.d.ts +50 -0
  172. package/dist/frontend/ts7/ast.js +211 -0
  173. package/dist/frontend/ts7/ast.js.map +1 -0
  174. package/dist/frontend/ts7/census-check.d.ts +1 -0
  175. package/dist/frontend/ts7/census-check.js +12 -0
  176. package/dist/frontend/ts7/census-check.js.map +1 -0
  177. package/dist/frontend/ts7/checker.d.ts +140 -0
  178. package/dist/frontend/ts7/checker.js +544 -0
  179. package/dist/frontend/ts7/checker.js.map +1 -0
  180. package/dist/frontend/ts7/enums.d.ts +18 -0
  181. package/dist/frontend/ts7/enums.js +43 -0
  182. package/dist/frontend/ts7/enums.js.map +1 -0
  183. package/dist/frontend/ts7/program.d.ts +99 -0
  184. package/dist/frontend/ts7/program.js +278 -0
  185. package/dist/frontend/ts7/program.js.map +1 -0
  186. package/dist/frontend/ts7/world-check.d.ts +3 -0
  187. package/dist/frontend/ts7/world-check.js +34 -0
  188. package/dist/frontend/ts7/world-check.js.map +1 -0
  189. package/dist/frontend/types.d.ts +205 -0
  190. package/dist/frontend/types.js +2485 -0
  191. package/dist/frontend/types.js.map +1 -0
  192. package/dist/index.d.ts +85 -0
  193. package/dist/index.js +424 -0
  194. package/dist/index.js.map +1 -0
  195. package/dist/ir/nodes.d.ts +4334 -0
  196. package/dist/ir/nodes.js +1906 -0
  197. package/dist/ir/nodes.js.map +1 -0
  198. package/dist/ir/serialize.d.ts +4 -0
  199. package/dist/ir/serialize.js +34 -0
  200. package/dist/ir/serialize.js.map +1 -0
  201. package/dist/ir/validate.d.ts +36 -0
  202. package/dist/ir/validate.js +4884 -0
  203. package/dist/ir/validate.js.map +1 -0
  204. package/package.json +30 -6
  205. package/README.md +0 -3
  206. package/index.js +0 -2
@@ -0,0 +1,650 @@
1
+ /* Island-boundary lowering: jsval marshaling into the island (jsvalIn and
2
+ * its boundary fences), island-expression detection, the island method-call
3
+ * surface (Math and number/string methods under --dynamic), and the npm
4
+ * package boundary fences for node_modules-declared symbols. */
5
+ import * as ts from "../ts7/adapter.js";
6
+ import { F64, JSVAL, MAX_ISLAND_CALLBACK_ARITY, STRING, VOID, canMarshalTypedFuncIntoIsland, isUnitType } from "../../ir/nodes.js";
7
+ import { ISLAND_SURFACE, STATIC_MATH_FNS, boundaryIntoIslandMsg } from "./surfaces.js";
8
+ import { requiresDynamicApiDiag, requiresDynamicPackageDiag } from "../../diagnostics/diagnostic.js";
9
+ import { isCjsJsFile, locOf, npmPackageNameOf } from "../program.js";
10
+ import { pureReemittable } from "./lower-exprs.js";
11
+ import { PoisonError, newFnCtx, own } from "./lowerer.js";
12
+ /** True iff the checker's type for this node maps to jsval ('any') —
13
+ * the island test in front of every engine-op lowering (receivers,
14
+ * callees, assignment targets). ALSO true for an identifier bound to an
15
+ * island-HANDLE local whose declared type says otherwise (`const {
16
+ * readFileSync } = await import("fs")` — the binding's declared
17
+ * function/Buffer type never held the value; the handle is the value's
18
+ * only story), so its uses dispatch to engine ops instead of
19
+ * re-reporting the declared type. The one exclusion is promise-mapped
20
+ * declared types: a package promise held as a handle keeps its existing
21
+ * checker-driven dispatch (the await/.catch bridge lowerings own it). */
22
+ export function isIslandExpr(L, node) {
23
+ const mapped = L.mapTypeOf(L.typeOf(node));
24
+ if (mapped?.kind === "jsval")
25
+ return true;
26
+ if (mapped?.kind !== "promise" && ts.isIdentifier(node)) {
27
+ const local = L.resolveLocal(node);
28
+ if (local?.type.kind === "jsval")
29
+ return true;
30
+ // File-scope handle bindings (a module global slotted jsval by the
31
+ // island-pattern or unchecked-overload rules) take the same rule as
32
+ // locals: the handle is the value's only story.
33
+ if (!local && L.globalOf(node)?.type.kind === "jsval")
34
+ return true;
35
+ }
36
+ return false;
37
+ }
38
+ /** Marshal a static value into the island (--dynamic): primitives by
39
+ * value, JSON-safe composites as a deep copy (the documented aliasing
40
+ * divergence). Values with no island representation — closures, class
41
+ * instances, promises, un-validated 'unknown' — are rejected with the
42
+ * boundary message. */
43
+ export function jsvalIn(L, e, node) {
44
+ if (e.type.kind === "jsval")
45
+ return e;
46
+ // Bare unit literals (`undefined` / `null` in an 'any' slot): the
47
+ // engine's own units — unit-typed expressions are literals (units have
48
+ // no other producers), so dropping the operand loses nothing.
49
+ if (isUnitType(e.type)) {
50
+ return { kind: "jsOp", op: e.type.kind === "undefinedT" ? "undefLit" : "nullLit", args: [], type: JSVAL, loc: e.loc };
51
+ }
52
+ if (e.type.kind === "dyn") {
53
+ L.unsupported("SC1100", node, "passing 'unknown' values into dynamically-executed ('any'-typed) code (validate with 'as <type>' first)");
54
+ }
55
+ // Closures cross INTO the island as host functions — THE package
56
+ // callback pattern (`.action((a, b) => ...)`). Unannotated params stay
57
+ // 'any' (contextual typing against package signatures) and pass through
58
+ // as handles; TYPED params convert at call time through the validated-
59
+ // exit machinery (strict primitives, JSON round-trip composites,
60
+ // `T | undefined` taking the undefined arm for an absent argument), so
61
+ // a conversion failure throws back into the island as a TypeError.
62
+ // Anything outside both shapes gets the specific fix, not the generic
63
+ // boundary recitation.
64
+ if (e.type.kind === "func" &&
65
+ !canMarshalTypedFuncIntoIsland(e.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
66
+ L.unsupported("SC1090", node, `functions with this signature crossing into dynamically-executed code ` +
67
+ `(a callback passed to a package/'any' API may take 'any' parameters — ` +
68
+ `leave them unannotated so contextual typing keeps them 'any' — or parameters ` +
69
+ `convertible at the boundary (number, string, boolean, JSON-safe ` +
70
+ `records/arrays/unions, 'T | undefined'), and return 'any', void, number, ` +
71
+ `string, boolean, a JSON-safe composite, or a Promise of the primitive kinds${e.type.kind === "func" && e.type.params.length > MAX_ISLAND_CALLBACK_ARITY
72
+ ? `; at most ${MAX_ISLAND_CALLBACK_ARITY} parameters`
73
+ : ""})`);
74
+ }
75
+ if (e.type.kind !== "func" && !L.boundarySafe(e.type)) {
76
+ // A RegExp crossing INTO the island (`z.string().regex(/^a+$/)` —
77
+ // the validation-pattern argument): the engine compiles its own
78
+ // from source+flags. A fresh engine RegExp per marshal — identity
79
+ // and lastIndex state do not cross (SEMANTICS.md). Only literal
80
+ // and pure-read spellings lower (the rebuild reads the operand
81
+ // twice); computed regex values keep the boundary fence.
82
+ if (e.type.kind === "regex") {
83
+ const re = islandRegexpOf(e);
84
+ if (re)
85
+ return re;
86
+ }
87
+ // jsval-BEARING composites (an `any[]` value, a record holding one)
88
+ // have no JSON marshal but an honest per-field/per-element island
89
+ // construction — the same lift the implicit coercion path uses.
90
+ if (L.jsvalLiftable(e.type))
91
+ return L.jsvalLiftExpr(e, e.loc);
92
+ L.unsupported("SC1090", node, boundaryIntoIslandMsg(L.fmt(e.type)));
93
+ }
94
+ return { kind: "jsMarshal", value: e, type: JSVAL, loc: e.loc };
95
+ }
96
+ /** A static RegExp value as a fresh ENGINE RegExp — `new RegExp(source,
97
+ * flags)` in the island, the pattern TEXT crossing (both worlds compile
98
+ * the ES-spec grammar). Literals rebuild from their own pattern/flags;
99
+ * pure reads (a regex-typed binding) read the source/flags intrinsics —
100
+ * the rebuild emits the operand twice, so effectful producers return
101
+ * null into the caller's boundary fence. */
102
+ export function islandRegexpOf(e) {
103
+ if (e.type.kind !== "regex")
104
+ return null;
105
+ const loc = e.loc;
106
+ let src;
107
+ let flags;
108
+ if (e.kind === "regexLit") {
109
+ src = { kind: "strLit", value: e.pattern, type: STRING, loc };
110
+ flags = { kind: "strLit", value: e.flags, type: STRING, loc };
111
+ }
112
+ else if (pureReemittable(e)) {
113
+ src = { kind: "regexIntrinsic", method: "source", receiver: e, args: [], type: STRING, loc };
114
+ flags = { kind: "regexIntrinsic", method: "flags", receiver: e, args: [], type: STRING, loc };
115
+ }
116
+ else {
117
+ return null;
118
+ }
119
+ const ctor = { kind: "jsOp", op: "globalGet", name: "RegExp", args: [], type: JSVAL, loc };
120
+ return {
121
+ kind: "jsOp",
122
+ op: "construct",
123
+ args: [
124
+ ctor,
125
+ { kind: "jsMarshal", value: src, type: JSVAL, loc },
126
+ { kind: "jsMarshal", value: flags, type: JSVAL, loc },
127
+ ],
128
+ type: JSVAL,
129
+ loc,
130
+ };
131
+ }
132
+ /** The gate on every ISLAND_SURFACE lowering: under --dynamic the caller
133
+ * proceeds to engine ops; without it the use site is a per-site SC2012
134
+ * (poison-recovered, so every site in the program reports — and the
135
+ * coverage report groups them under "runs with --dynamic"). */
136
+ export function requireDynamicApi(L, feature, node) {
137
+ if (L.dynamic)
138
+ return;
139
+ L.pushDiag(requiresDynamicApiDiag(feature, locOf(node)));
140
+ throw new PoisonError();
141
+ }
142
+ /** Resolves an identifier to an island-backed ambient GLOBAL function
143
+ * (parseFloat, isFinite). Provenance, not name: the
144
+ * symbol's declaration must live in the ambient file, so a user function
145
+ * named `parseFloat` never matches. */
146
+ export function islandGlobalFnOf(L, ident) {
147
+ const entry = own(ISLAND_SURFACE.globals, ident.text);
148
+ if (!entry)
149
+ return null;
150
+ const symbol = L.resolveValueSymbol(ident);
151
+ if (!symbol || !L.isStdlibSymbol(symbol))
152
+ return null;
153
+ return entry;
154
+ }
155
+ /** USER-code `fetch(url)` / `fetch(url, init)` — the island-backed ambient
156
+ * global (provenance, not the name: a user's own `fetch` never matches).
157
+ * The engine's own fetch executes (the same one embedded npm code calls —
158
+ * scr_fetch.c over the native net/tls stack): the url marshals in (strings; template
159
+ * results), an init OBJECT LITERAL builds natively in the island through
160
+ * the existing 'any'-contextual literal path (RequestInit maps to jsval,
161
+ * so field values marshal individually and an AbortSignal handle passes
162
+ * straight through), and the engine's promise bridges to a static
163
+ * `promise of jsval` (jsBridgePromise) — `await fetch(...)` parks the
164
+ * fiber like any await and resumes with the Response HANDLE. Member
165
+ * reads/calls on the handle are engine ops; typed extraction happens at
166
+ * the user's narrowing sites through the validated-exit machinery.
167
+ * Without --dynamic every call site is its own SC2012. Null for
168
+ * anything that isn't THE ambient fetch, so lowerCall keeps trying. */
169
+ export function lowerFetchCall(L, call) {
170
+ const callee = call.expression;
171
+ if (!ts.isIdentifier(callee) || callee.text !== "fetch")
172
+ return null;
173
+ if (call.questionDotToken)
174
+ return null;
175
+ const symbol = L.resolveValueSymbol(callee);
176
+ if (!symbol || !L.isStdlibSymbol(symbol))
177
+ return null;
178
+ if (call.arguments.length < 1 || call.arguments.length > 2)
179
+ return null;
180
+ L.requireDynamicApi("'fetch'", call);
181
+ const loc = locOf(call);
182
+ const fetchFn = { kind: "jsOp", op: "globalGet", name: "fetch", args: [], type: JSVAL, loc };
183
+ // Init OBJECT LITERALS build natively in the island (the general
184
+ // 'any'-contextual literal path can't claim them: the optional param's
185
+ // contextual type is `RequestInit | undefined`, a union) — field
186
+ // values marshal individually, so an AbortSignal HANDLE passes
187
+ // through and dashed header keys ("content-type") are plain engine
188
+ // property names. Non-literal inits marshal as a whole (JSON-safe
189
+ // records; a signal field inside one fences with the boundary rule).
190
+ const args = call.arguments.map((a) => ts.isObjectLiteralExpression(a) ? lowerIslandObjectLiteral(L, a) : L.jsvalIn(L.lowerExpr(a), a));
191
+ const raw = { kind: "jsOp", op: "callFn", args: [fetchFn, ...args], type: JSVAL, loc };
192
+ return { kind: "jsBridgePromise", value: raw, type: { kind: "promise", inner: JSVAL }, loc };
193
+ }
194
+ /** Dynamic `import(spec)` — the island's module system at a USER site.
195
+ * Under --dynamic the call lowers to island.importDyn(key): the engine
196
+ * loads the module (embedded npm graph, a shipped local .js/.mjs the
197
+ * build embedded, or a builtin shim — collectDynamicImports resolved and
198
+ * embedded the specifier at collection time) and answers an ENGINE
199
+ * promise of the namespace object, bridged to a static
200
+ * `Promise<jsval>` (jsBridgePromise, the fetch precedent) — so `await
201
+ * import(x)` parks the fiber and resumes with the namespace HANDLE, and
202
+ * a load/evaluation failure crosses as a catchable rejection, exactly
203
+ * where Node puts it. Specifiers must be string literals: the module
204
+ * graph is a BUILD-time artifact — a runtime-computed name has nothing
205
+ * to embed, and the fence says so. Static builds report the per-site
206
+ * SC2012. Null for anything that isn't `import(...)`. */
207
+ export function lowerDynamicImportCall(L, call) {
208
+ if (call.expression.kind !== ts.SyntaxKind.ImportKeyword)
209
+ return null;
210
+ L.requireDynamicApi("'import()'", call);
211
+ const loc = locOf(call);
212
+ const arg = call.arguments[0];
213
+ if (arg === undefined || !ts.isStringLiteralLike(arg)) {
214
+ L.unsupported("SC1090", call, "dynamic import() of computed specifiers (the module graph embeds at " +
215
+ "build time — the specifier must be a string literal)");
216
+ }
217
+ if (call.arguments.length !== 1) {
218
+ L.unsupported("SC1090", call, "dynamic import() with import attributes");
219
+ }
220
+ const res = L.dynImports.get(`${call.getSourceFile().fileName}\u0000${arg.text}`);
221
+ if (!res) {
222
+ // Collection walks every file before bodies lower, so a missing
223
+ // entry is a lowerer bug, not user error.
224
+ throw new Error(`lowerer bug: unresolved dynamic import '${arg.text}'`);
225
+ }
226
+ if (res.kind === "program-module") {
227
+ return lowerOwnModuleImport(L, call, arg);
228
+ }
229
+ if (res.kind !== "module") {
230
+ throw new PoisonError(); // resolution failed — collection reported it
231
+ }
232
+ const raw = {
233
+ kind: "libCall",
234
+ fn: "island.importDyn",
235
+ args: [{ kind: "strLit", value: res.key, type: STRING, loc }],
236
+ type: JSVAL,
237
+ loc,
238
+ };
239
+ return { kind: "jsBridgePromise", value: raw, type: { kind: "promise", inner: JSVAL }, loc };
240
+ }
241
+ /** Dynamic `import()` of one of the program's OWN modules: the compiled
242
+ * module's exports, marshaled into the engine as a namespace object.
243
+ * The site lowers to `Promise.resolve().then(<builder>)` in the engine —
244
+ * the builder is a synthesized compiled function (dynNsBuilderOf) that
245
+ * runs on the engine MICROTASK, calls the target module's run-once %init
246
+ * (Node's evaluation point for a module first reached through import():
247
+ * after the importer's synchronous code, before the .then handlers), and
248
+ * returns the exports object. Node differences (numbered divergences,
249
+ * pinned in island.test.ts): the namespace is a SNAPSHOT taken when the
250
+ * import resolves (Node's is live), a plain engine object (no Module
251
+ * toStringTag, keys still sorted like Node's, each import minting a
252
+ * fresh object where Node caches one), and exports with no island
253
+ * representation (classes, generic functions, un-marshalable
254
+ * signatures) cross as trap functions that throw a pointed TypeError
255
+ * when USED — the namespace still builds, exactly like Node still
256
+ * resolves it. */
257
+ function lowerOwnModuleImport(L, call, arg) {
258
+ const loc = locOf(call);
259
+ let dep = null;
260
+ const modSym = L.checker.getSymbolAtLocation(arg);
261
+ for (const d of (modSym ? L.checker.declarationsOf(modSym) : [])) {
262
+ if (ts.isSourceFile(d) && !d.isDeclarationFile) {
263
+ dep = d;
264
+ break;
265
+ }
266
+ }
267
+ if (dep !== null && (dep.fileName.endsWith(".cts") || isCjsJsFile(dep))) {
268
+ L.unsupported("SC1090", call, `dynamic import of the program's own CommonJS module '${arg.text}' ` +
269
+ "(its namespace comes from module.exports through Node's CJS lexer, " +
270
+ "which has no compiled story — require it, or import it statically)");
271
+ }
272
+ const builder = dep !== null ? dynNsBuilderOf(L, dep, loc) : null;
273
+ if (builder === null) {
274
+ L.unsupported("SC1090", call, `dynamic import of the program's own module '${arg.text}' ` +
275
+ "(this module is not part of the compiled module graph — import it statically)");
276
+ }
277
+ const promiseCtor = { kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc };
278
+ const resolved = { kind: "jsOp", op: "callMethod", name: "resolve", args: [promiseCtor], type: JSVAL, loc };
279
+ const builderFn = { kind: "func", params: [], ret: JSVAL };
280
+ const marshaled = {
281
+ kind: "jsMarshal",
282
+ value: { kind: "closure", fnName: builder, captures: [], type: builderFn, loc },
283
+ type: JSVAL,
284
+ loc,
285
+ };
286
+ const chained = { kind: "jsOp", op: "callMethod", name: "then", args: [resolved, marshaled], type: JSVAL, loc };
287
+ return { kind: "jsBridgePromise", value: chained, type: { kind: "promise", inner: JSVAL }, loc };
288
+ }
289
+ /** The namespace-BUILDER function for one program module, synthesized on
290
+ * first demand and shared by every import() of that module (deterministic
291
+ * name per file tag, so the discovery and emit passes agree). Body: the
292
+ * module's guarded %init (skipped for the entry — it is running or ran),
293
+ * then `return { <sorted exports> }` as an engine object. Null when the
294
+ * module never joined the compiled graph (no %init exists — an empty
295
+ * preflight order or a cycle the extension refused). */
296
+ function dynNsBuilderOf(L, dep, loc) {
297
+ const cached = L.dynNsBuilders.get(dep);
298
+ if (cached !== undefined)
299
+ return cached;
300
+ const initName = L.initNameOf.get(dep);
301
+ if (initName === undefined)
302
+ return null;
303
+ const rawTag = L.fileTag.get(dep) ?? "";
304
+ const name = `%dynns.${rawTag === "" ? "e." : rawTag.replace(/^%/, "")}`;
305
+ L.dynNsBuilders.set(dep, name);
306
+ L.fnStack.push(newFnCtx(true, null, null, JSVAL));
307
+ try {
308
+ const body = [];
309
+ if (dep !== L.entry) {
310
+ body.push({
311
+ kind: "exprStmt",
312
+ expr: { kind: "call", callee: initName, args: [], type: VOID, loc },
313
+ loc,
314
+ });
315
+ }
316
+ // Node sorts module-namespace keys (code-unit order); tsc erases
317
+ // type-only exports, so only VALUE exports appear.
318
+ const entries = [];
319
+ const modSym = L.checker.getSymbolAtLocation(dep);
320
+ modSym?.getExports().forEach((sym, key) => {
321
+ const n = String(key);
322
+ if (!n.startsWith("__") && n !== "export=")
323
+ entries.push([n, sym]);
324
+ });
325
+ entries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
326
+ const args = [];
327
+ for (const [exportName, sym] of entries) {
328
+ const value = exportJsvalValue(L, exportName, sym, loc);
329
+ if (value === null)
330
+ continue;
331
+ args.push({ kind: "jsMarshal", value: { kind: "strLit", value: exportName, type: STRING, loc }, type: JSVAL, loc }, value);
332
+ }
333
+ body.push({ kind: "return", value: { kind: "jsOp", op: "objLit", args, type: JSVAL, loc }, loc });
334
+ const ctx = L.ctx;
335
+ L.liftedFns.push({
336
+ name,
337
+ params: [],
338
+ returnType: JSVAL,
339
+ locals: ctx.locals,
340
+ captures: ctx.captures ?? [],
341
+ body,
342
+ loc,
343
+ });
344
+ }
345
+ finally {
346
+ L.fnStack.pop();
347
+ }
348
+ return name;
349
+ }
350
+ /** One export's island value for the namespace object — the jsvalIn
351
+ * marshal set (primitives and JSON-safe composites by deep copy, units as
352
+ * the engine's own, marshalable closures as host functions, jsval-bearing
353
+ * composites through the per-field lift), with every UN-marshalable
354
+ * export crossing as a trap function that throws a pointed TypeError when
355
+ * called or constructed — the namespace still builds (Node resolves it;
356
+ * only the USE has no compiled story). Null for exports that do not exist
357
+ * at runtime (type-only). */
358
+ function exportJsvalValue(L, name, sym, loc) {
359
+ const trap = (what) => islandTrapFnValue(L, `the '${name}' export is ${what} of the compiled program, which cannot cross into dynamically-executed code yet`, loc);
360
+ let resolved = sym;
361
+ if (sym.flags & ts.SymbolFlags.Alias) {
362
+ // `export type { x }` / `export { type x }`: erased at runtime.
363
+ for (const d of L.checker.declarationsOf(sym)) {
364
+ if (ts.isExportSpecifier(d)) {
365
+ const exportDecl = d.parent.parent;
366
+ if (d.isTypeOnly || (ts.isExportDeclaration(exportDecl) && exportDecl.isTypeOnly))
367
+ return null;
368
+ }
369
+ if (ts.isImportSpecifier(d)) {
370
+ const clause = d.parent.parent;
371
+ if (d.isTypeOnly || (ts.isImportClause(clause) && clause.phaseModifier === ts.SyntaxKind.TypeKeyword))
372
+ return null;
373
+ }
374
+ }
375
+ resolved = L.checker.getAliasedSymbol(sym);
376
+ }
377
+ if (!(resolved.flags & ts.SymbolFlags.Value))
378
+ return null; // pure type surface
379
+ const g = L.globalsBySymbol.get(resolved);
380
+ if (g) {
381
+ const ref = { kind: "varRef", localId: g.id, type: g.type, loc };
382
+ if (ref.type.kind === "jsval")
383
+ return ref;
384
+ if (isUnitType(ref.type)) {
385
+ return { kind: "jsOp", op: ref.type.kind === "undefinedT" ? "undefLit" : "nullLit", args: [], type: JSVAL, loc };
386
+ }
387
+ if (ref.type.kind === "func") {
388
+ return canMarshalTypedFuncIntoIsland(ref.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))
389
+ ? { kind: "jsMarshal", value: ref, type: JSVAL, loc }
390
+ : trap(`a function value of type '${L.fmt(ref.type)}'`);
391
+ }
392
+ if (L.boundarySafe(ref.type))
393
+ return { kind: "jsMarshal", value: ref, type: JSVAL, loc };
394
+ if (L.jsvalLiftable(ref.type))
395
+ return L.jsvalLiftExpr(ref, loc);
396
+ return trap(`a value of type '${L.fmt(ref.type)}'`);
397
+ }
398
+ const sig = L.fnSigsBySymbol.get(resolved);
399
+ const decl0 = L.checker.declarationsOf(resolved).find((d) => ts.isFunctionDeclaration(d) && (ts.isSourceFile(d.parent) || L.nsBlocks.get(d.parent) === "flattened"));
400
+ if (sig && decl0) {
401
+ if (!sig.params.every((p) => p.mode === "required")) {
402
+ return trap("a function with optional, default, or rest parameters");
403
+ }
404
+ const funcType = {
405
+ kind: "func",
406
+ params: sig.params.map((p) => p.type),
407
+ ret: sig.returnType,
408
+ };
409
+ if (!canMarshalTypedFuncIntoIsland(funcType, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
410
+ return trap(`a function of type '${L.fmt(funcType)}'`);
411
+ }
412
+ L.noteEdge(sig.name);
413
+ return {
414
+ kind: "jsMarshal",
415
+ value: { kind: "closure", fnName: sig.name, captures: [], type: funcType, loc },
416
+ type: JSVAL,
417
+ loc,
418
+ };
419
+ }
420
+ if (L.genericFnsBySymbol.has(resolved))
421
+ return trap("a generic function");
422
+ const flags = resolved.flags;
423
+ if (flags & ts.SymbolFlags.Class)
424
+ return trap("a class");
425
+ if (flags & ts.SymbolFlags.Enum)
426
+ return trap("an enum object");
427
+ if (flags & ts.SymbolFlags.ValueModule || flags & ts.SymbolFlags.NamespaceModule) {
428
+ return trap("a namespace object");
429
+ }
430
+ return trap("a binding");
431
+ }
432
+ /** An engine value whose any USE throws: `new Function("<throw>")` — a
433
+ * real engine function, so the namespace member reads back fine (Node's
434
+ * namespace holds the value too), property probes answer like a
435
+ * function's, and calling or `new`-ing it runs the body, which throws
436
+ * the pointed TypeError. */
437
+ function islandTrapFnValue(L, message, loc) {
438
+ void L;
439
+ const code = `throw new TypeError(${JSON.stringify(message)})`;
440
+ return {
441
+ kind: "jsOp",
442
+ op: "construct",
443
+ args: [
444
+ { kind: "jsOp", op: "globalGet", name: "Function", args: [], type: JSVAL, loc },
445
+ { kind: "jsMarshal", value: { kind: "strLit", value: code, type: STRING, loc }, type: JSVAL, loc },
446
+ ],
447
+ type: JSVAL,
448
+ loc,
449
+ };
450
+ }
451
+ /** An object literal built NATIVELY in the island — one engine object,
452
+ * each field marshaled individually (nested object/array literals
453
+ * recurse, island handles pass straight through, everything else takes
454
+ * the JSON-safe copy-marshal). The same jsOp the 'any'-contextual
455
+ * literal path emits, callable from lowerings that KNOW the literal is
456
+ * island-bound (fetch's init) even when the contextual type is a union
457
+ * the generic path declines. Identifier AND string-literal keys — engine
458
+ * property names have no identifier restriction ("content-type"). */
459
+ export function lowerIslandObjectLiteral(L, expr) {
460
+ const loc = locOf(expr);
461
+ const args = [];
462
+ for (const prop of expr.properties) {
463
+ if (!ts.isPropertyAssignment(prop) ||
464
+ !(ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name))) {
465
+ L.unsupported("SC1090", prop, "this property form in an island-built object literal (only `name: value` is supported)");
466
+ }
467
+ const nameLoc = locOf(prop.name);
468
+ args.push({
469
+ kind: "jsMarshal",
470
+ value: { kind: "strLit", value: prop.name.text, type: STRING, loc: nameLoc },
471
+ type: JSVAL, loc: nameLoc,
472
+ });
473
+ const init = prop.initializer;
474
+ if (ts.isObjectLiteralExpression(init)) {
475
+ args.push(lowerIslandObjectLiteral(L, init));
476
+ }
477
+ else if (ts.isArrayLiteralExpression(init) && !init.elements.some(ts.isSpreadElement)) {
478
+ const elems = init.elements.map((el) => L.jsvalIn(L.lowerExpr(el), el));
479
+ args.push({ kind: "jsOp", op: "arrLit", args: elems, type: JSVAL, loc: locOf(init) });
480
+ }
481
+ else {
482
+ args.push(L.jsvalIn(L.lowerExpr(init), init));
483
+ }
484
+ }
485
+ return { kind: "jsOp", op: "objLit", args, type: JSVAL, loc };
486
+ }
487
+ /** Method calls on the island-backed ambient surface: `Math.<fn>(...)`
488
+ * (the engine's own Math object executes) and the number/string methods
489
+ * the static runtime doesn't implement (`x.toFixed(2)`,
490
+ * `s.toUpperCase()`, ...). Each site is self-contained — the receiver
491
+ * and arguments marshal in, the engine executes with JS-exact semantics,
492
+ * and the result exits (validated) to the DECLARED static return type,
493
+ * so no jsval leaks into the program's types. tsc has already checked
494
+ * receiver, arity, and argument types against ambient/scriptc.d.ts; an
495
+ * ambient member missing from ISLAND_SURFACE returns null into the
496
+ * existing generic rejections. */
497
+ export function lowerIslandMethodCall(L, call, access) {
498
+ if (L.chainBlocked(access, call))
499
+ return null;
500
+ const name = access.name.text;
501
+ const loc = locOf(call);
502
+ const finish = (receiver, entry) => {
503
+ const args = call.arguments.map((a) => L.jsvalIn(L.lowerExpr(a), a));
504
+ const result = {
505
+ kind: "jsOp", op: "callMethod", name, args: [receiver, ...args], type: JSVAL, loc,
506
+ };
507
+ return { kind: "jsExit", value: result, type: entry.ret, loc };
508
+ };
509
+ // `AbortSignal.timeout(ms)` / `.abort(reason?)` / `.any(signals)` —
510
+ // the fetch-cancellation ambient: the engine's own AbortSignal mints
511
+ // the signal, which stays a HANDLE (its checker type, AbortSignal,
512
+ // maps to jsval — see ISLAND_AMBIENT_TYPES) so it can ride a
513
+ // RequestInit literal into fetch without a JSON detour. The prelude
514
+ // implements all three statics.
515
+ {
516
+ const sigMember = L.stdlibGlobalMember(access, "AbortSignal");
517
+ if ((sigMember === "timeout" || sigMember === "abort" || sigMember === "any") &&
518
+ call.arguments.length <= 1 &&
519
+ (sigMember === "abort" || call.arguments.length === 1)) {
520
+ L.requireDynamicApi(`'AbortSignal.${sigMember}'`, call);
521
+ const args = call.arguments.map((a) => L.jsvalIn(L.lowerExpr(a), a));
522
+ const signalGlobal = {
523
+ kind: "jsOp", op: "globalGet", name: "AbortSignal", args: [], type: JSVAL, loc,
524
+ };
525
+ return {
526
+ kind: "jsOp", op: "callMethod", name: sigMember,
527
+ args: [signalGlobal, ...args], type: JSVAL, loc,
528
+ };
529
+ }
530
+ }
531
+ const isMath = L.stdlibGlobalMember(access, "Math") !== null;
532
+ // The STATIC Math members (floor/min/max/random): one C call IS the
533
+ // JS operation — no island, no --dynamic. Only the tabled arity with
534
+ // plain (non-spread) arguments takes this path; other forms fall
535
+ // through to the spread fold / island / lib fence below.
536
+ const staticMath = isMath ? own(STATIC_MATH_FNS, name) : undefined;
537
+ if (staticMath &&
538
+ call.arguments.length === staticMath.arity &&
539
+ call.arguments.every((a) => !ts.isSpreadElement(a))) {
540
+ const args = call.arguments.map((a) => L.lowerExprExpecting(a, F64));
541
+ return { kind: "libCall", fn: staticMath.fn, args, type: F64, loc };
542
+ }
543
+ // `Math.max(...xs)` / `Math.min(...xs)` over a number[]: a STATIC
544
+ // runtime fold (JS-exact: NaN poisons, ±0 order by the JS rules, the
545
+ // empty array yields ∓Infinity like the zero-arg calls) — no island
546
+ // involved, so it works without --dynamic too. Only the exact
547
+ // one-spread form lowers; mixed spread/positional argument lists keep
548
+ // the nest-calls fence.
549
+ if (isMath &&
550
+ (name === "max" || name === "min") &&
551
+ call.arguments.length === 1 &&
552
+ ts.isSpreadElement(call.arguments[0])) {
553
+ const spread = call.arguments[0];
554
+ const src = L.lowerExpr(spread.expression);
555
+ if (src.type.kind !== "array" || src.type.elem.kind !== "f64") {
556
+ L.unsupported("SC1090", spread, `spreading '${L.fmt(src.type)}' into Math.${name} (only a number[] spreads)`);
557
+ }
558
+ return {
559
+ kind: "libCall",
560
+ fn: name === "max" ? "math.maxArr" : "math.minArr",
561
+ args: [src],
562
+ type: F64,
563
+ loc,
564
+ };
565
+ }
566
+ const mathFn = isMath ? own(ISLAND_SURFACE.math.fns, name) : undefined;
567
+ if (mathFn && call.arguments.length === mathFn.args.length) {
568
+ L.requireDynamicApi(`'Math.${name}'`, call);
569
+ return finish({ kind: "jsOp", op: "globalGet", name: "Math", args: [], type: JSVAL, loc }, mathFn);
570
+ }
571
+ const kind = L.mapTypeOf(L.typeOf(access.expression))?.kind;
572
+ const entry = kind === "f64"
573
+ ? own(ISLAND_SURFACE.number, name)
574
+ : kind === "string"
575
+ ? own(ISLAND_SURFACE.string, name)
576
+ : undefined;
577
+ if (!entry || call.arguments.length !== entry.args.length)
578
+ return null;
579
+ if (!L.isStdlibMember(access))
580
+ return null;
581
+ L.requireDynamicApi(`'.${name}()' on ${kind === "f64" ? "numbers" : "strings"}`, call);
582
+ return finish(L.jsvalIn(L.lowerExpr(access.expression), access.expression), entry);
583
+ }
584
+ /** `Math.PI` / `Math.E` property READS: getProp off globalGet("Math"),
585
+ * exiting to the declared number type. Math methods referenced without a
586
+ * call are rejected specifically (no value form exists, --dynamic or
587
+ * not). Null for non-Math receivers (the property chain keeps trying). */
588
+ export function lowerMathProperty(L, expr) {
589
+ const member = L.stdlibGlobalMember(expr, "Math");
590
+ if (member === null)
591
+ return null;
592
+ const loc = locOf(expr);
593
+ const propType = own(ISLAND_SURFACE.math.props, member);
594
+ if (propType !== undefined) {
595
+ L.requireDynamicApi(`'Math.${member}'`, expr);
596
+ const math = { kind: "jsOp", op: "globalGet", name: "Math", args: [], type: JSVAL, loc };
597
+ const read = { kind: "jsOp", op: "getProp", name: member, args: [math], type: JSVAL, loc };
598
+ return { kind: "jsExit", value: read, type: propType, loc };
599
+ }
600
+ if (own(ISLAND_SURFACE.math.fns, member) !== undefined ||
601
+ own(STATIC_MATH_FNS, member) !== undefined) {
602
+ L.unsupported("SC1090", expr, `Math methods as values (call '${member}' directly)`);
603
+ }
604
+ return null; // declared-but-untabled members fall through generically
605
+ }
606
+ /** The npm package a type is declared by ("commander", "@scope/pkg"),
607
+ * or null when the type isn't package-declared. Union parts are searched
608
+ * too: `string | Command` fails mapping as a whole, but the blame (and
609
+ * the --dynamic attribution) belongs to the package-declared part. */
610
+ export function npmPackageOf(L, type) {
611
+ const pkg = L.npmPackageOfSymbol(type.getAliasSymbol() ?? type.getSymbol());
612
+ if (pkg)
613
+ return pkg;
614
+ if (type.isUnionType()) {
615
+ for (const part of type.getTypes()) {
616
+ const partPkg = L.npmPackageOf(part);
617
+ if (partPkg)
618
+ return partPkg;
619
+ }
620
+ }
621
+ return null;
622
+ }
623
+ /** The npm chokepoint for member reads and method calls in a STATIC
624
+ * build: a receiver whose type (or member whose symbol) a package's
625
+ * .d.ts declares means the operation runs in the embedded engine —
626
+ * attribute the site to the package instead of the generic property/
627
+ * method rejection. No-op under --dynamic (the island paths claimed
628
+ * these) and for non-package receivers, so callers' fallbacks apply. */
629
+ export function npmMemberFence(L, access) {
630
+ if (L.dynamic)
631
+ return;
632
+ const pkg = L.npmPackageOf(L.typeOf(access.expression)) ??
633
+ L.npmPackageOfSymbol(L.checker.getSymbolAtLocation(access.name));
634
+ if (!pkg)
635
+ return;
636
+ L.pushDiag(requiresDynamicPackageDiag(pkg, locOf(access)));
637
+ throw new PoisonError();
638
+ }
639
+ /** The npm package a SYMBOL is declared by, or null. The symbol half of
640
+ * npmPackageOf, also asked directly for import-alias bindings (whose
641
+ * aliased symbol is the package's export). */
642
+ export function npmPackageOfSymbol(L, sym) {
643
+ const decls = sym ? L.checker.declarationsOf(sym) : undefined;
644
+ if (!decls || decls.length === 0)
645
+ return null;
646
+ if (!decls.every((d) => L.isNpmFile(d.getSourceFile())))
647
+ return null;
648
+ return npmPackageNameOf(decls[0].getSourceFile().fileName);
649
+ }
650
+ //# sourceMappingURL=lower-island.js.map