@scriptc/compiler 0.2.9 → 0.3.0

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 (505) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +2 -36
  2. package/ambient/scriptc-overrides.d.ts +1 -25
  3. package/ambient/scriptc.d.ts +1 -9
  4. package/dist/backend/cycle-analysis.d.ts +56 -0
  5. package/dist/backend/cycle-analysis.js +175 -14
  6. package/dist/backend/cycle-analysis.js.map +1 -1
  7. package/dist/backend/cycle-analysis.test.js +95 -2
  8. package/dist/backend/cycle-analysis.test.js.map +1 -1
  9. package/dist/backend/cycle-mutability.d.ts +3 -7
  10. package/dist/backend/cycle-mutability.js +4 -30
  11. package/dist/backend/cycle-mutability.js.map +1 -1
  12. package/dist/backend/executable-features.d.ts +1 -1
  13. package/dist/backend/executable-features.js +3 -8
  14. package/dist/backend/executable-features.js.map +1 -1
  15. package/dist/backend/immutability.d.ts +57 -0
  16. package/dist/backend/immutability.js +178 -0
  17. package/dist/backend/immutability.js.map +1 -0
  18. package/dist/backend/immutability.test.js +131 -0
  19. package/dist/backend/immutability.test.js.map +1 -0
  20. package/dist/backend/library-pack.js +0 -2
  21. package/dist/backend/library-pack.js.map +1 -1
  22. package/dist/backend/linker.js +1 -1
  23. package/dist/backend/linker.js.map +1 -1
  24. package/dist/backend/llvm/borrowed-inputs.d.ts +9 -2
  25. package/dist/backend/llvm/borrowed-inputs.js +31 -3
  26. package/dist/backend/llvm/borrowed-inputs.js.map +1 -1
  27. package/dist/backend/llvm/checked-narrows.test.js +1 -1
  28. package/dist/backend/llvm/classes.d.ts +28 -0
  29. package/dist/backend/llvm/classes.js +48 -14
  30. package/dist/backend/llvm/classes.js.map +1 -1
  31. package/dist/backend/llvm/classes.test.js +134 -6
  32. package/dist/backend/llvm/classes.test.js.map +1 -1
  33. package/dist/backend/llvm/common.d.ts +13 -0
  34. package/dist/backend/llvm/common.js +13 -0
  35. package/dist/backend/llvm/common.js.map +1 -1
  36. package/dist/backend/llvm/constant-callbacks.d.ts +1 -1
  37. package/dist/backend/llvm/constant-callbacks.js +3 -3
  38. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  39. package/dist/backend/llvm/constant-callbacks.test.js +1 -1
  40. package/dist/backend/llvm/dense-array-access.js +5 -4
  41. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  42. package/dist/backend/llvm/dense-array-access.test.js +10 -2
  43. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  44. package/dist/backend/llvm/dyn.d.ts +2 -1
  45. package/dist/backend/llvm/dyn.js +3 -76
  46. package/dist/backend/llvm/dyn.js.map +1 -1
  47. package/dist/backend/llvm/emitter.d.ts +67 -19
  48. package/dist/backend/llvm/emitter.js +443 -226
  49. package/dist/backend/llvm/emitter.js.map +1 -1
  50. package/dist/backend/llvm/emitter.test.js +21 -3
  51. package/dist/backend/llvm/emitter.test.js.map +1 -1
  52. package/dist/backend/llvm/expr-async.test.js +1 -1
  53. package/dist/backend/llvm/expr-calls.js +14 -6
  54. package/dist/backend/llvm/expr-calls.js.map +1 -1
  55. package/dist/backend/llvm/expr-containers.js +41 -14
  56. package/dist/backend/llvm/expr-containers.js.map +1 -1
  57. package/dist/backend/llvm/expr-control.js +4 -107
  58. package/dist/backend/llvm/expr-control.js.map +1 -1
  59. package/dist/backend/llvm/expr-dispatch.d.ts +1 -2
  60. package/dist/backend/llvm/expr-dispatch.js +0 -41
  61. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  62. package/dist/backend/llvm/expr-dynamic.d.ts +1 -1
  63. package/dist/backend/llvm/expr-dynamic.js +13 -27
  64. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  65. package/dist/backend/llvm/expr-primitives.js +30 -3
  66. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  67. package/dist/backend/llvm/expr-primitives.test.js +55 -2
  68. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  69. package/dist/backend/llvm/expr-stream-bridges.js +4 -4
  70. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  71. package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
  72. package/dist/backend/llvm/lib-dispatch.js +0 -1
  73. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  74. package/dist/backend/llvm/lib-filesystem.js +0 -13
  75. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  76. package/dist/backend/llvm/lib-shared.js +0 -8
  77. package/dist/backend/llvm/lib-shared.js.map +1 -1
  78. package/dist/backend/llvm/local-array-reads.js +3 -3
  79. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  80. package/dist/backend/llvm/local-array-reads.test.js +1 -1
  81. package/dist/backend/llvm/local-union-storage.test.js +1 -1
  82. package/dist/backend/llvm/loop-array-borrows.d.ts +5 -2
  83. package/dist/backend/llvm/loop-array-borrows.js +27 -8
  84. package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
  85. package/dist/backend/llvm/map-number-lookup.d.ts +14 -0
  86. package/dist/backend/llvm/map-number-lookup.js +33 -2
  87. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  88. package/dist/backend/llvm/map-read-lifetimes.d.ts +5 -0
  89. package/dist/backend/llvm/map-read-lifetimes.js +20 -4
  90. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  91. package/dist/backend/llvm/map-read-lifetimes.test.js +25 -3
  92. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  93. package/dist/backend/llvm/reference-writes.d.ts +124 -0
  94. package/dist/backend/llvm/reference-writes.js +1090 -0
  95. package/dist/backend/llvm/reference-writes.js.map +1 -0
  96. package/dist/backend/llvm/shapes.d.ts +8 -5
  97. package/dist/backend/llvm/shapes.js +37 -13
  98. package/dist/backend/llvm/shapes.js.map +1 -1
  99. package/dist/backend/llvm/shapes.test.js +3 -3
  100. package/dist/backend/llvm/stack-unions.test.js +1 -1
  101. package/dist/backend/llvm/string-construction.test.js +1 -1
  102. package/dist/backend/llvm/string-lifetimes.test.js +40 -11
  103. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  104. package/dist/backend/llvm/string-reads.d.ts +3 -0
  105. package/dist/backend/llvm/string-reads.js +31 -0
  106. package/dist/backend/llvm/string-reads.js.map +1 -1
  107. package/dist/backend/llvm/switch-dispatch.d.ts +2 -2
  108. package/dist/backend/llvm/switch-dispatch.js +35 -22
  109. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  110. package/dist/backend/llvm/switch-dispatch.test.js +29 -11
  111. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  112. package/dist/backend/llvm/walk-borrows.d.ts +8 -1
  113. package/dist/backend/llvm/walk-borrows.js +15 -4
  114. package/dist/backend/llvm/walk-borrows.js.map +1 -1
  115. package/dist/backend/may-throw.d.ts +36 -2
  116. package/dist/backend/may-throw.js +308 -21
  117. package/dist/backend/may-throw.js.map +1 -1
  118. package/dist/backend/may-throw.test.js +147 -2
  119. package/dist/backend/may-throw.test.js.map +1 -1
  120. package/dist/backend/native/artifact-stamps.js +0 -2
  121. package/dist/backend/native/artifact-stamps.js.map +1 -1
  122. package/dist/backend/native/cache-warm.d.ts +1 -1
  123. package/dist/backend/native/cache-warm.js +2 -3
  124. package/dist/backend/native/cache-warm.js.map +1 -1
  125. package/dist/backend/native/compiler-fingerprint.d.ts +1 -1
  126. package/dist/backend/native/compiler-fingerprint.js +4 -7
  127. package/dist/backend/native/compiler-fingerprint.js.map +1 -1
  128. package/dist/backend/native/contracts.d.ts +3 -28
  129. package/dist/backend/native/driver.js +1 -3
  130. package/dist/backend/native/driver.js.map +1 -1
  131. package/dist/backend/native/executable.d.ts +0 -15
  132. package/dist/backend/native/executable.js +17 -172
  133. package/dist/backend/native/executable.js.map +1 -1
  134. package/dist/backend/native/tool-identity.js +0 -1
  135. package/dist/backend/native/tool-identity.js.map +1 -1
  136. package/dist/backend/native/vendor.d.ts +1 -1
  137. package/dist/backend/native/vendor.js +1 -1
  138. package/dist/backend/native/vendor.js.map +1 -1
  139. package/dist/backend/native-link-info-core.d.ts +0 -2
  140. package/dist/backend/native-link-info-core.js.map +1 -1
  141. package/dist/backend/native-toolchain.test.js +23 -33
  142. package/dist/backend/native-toolchain.test.js.map +1 -1
  143. package/dist/backend/publication.d.ts +5 -0
  144. package/dist/backend/publication.js +10 -0
  145. package/dist/backend/publication.js.map +1 -1
  146. package/dist/backend/publication.test.js +1 -1
  147. package/dist/backend/runtime-abi.d.ts +2 -2
  148. package/dist/backend/runtime-abi.js +2 -2
  149. package/dist/backend/runtime-pack-core.d.ts +1 -2
  150. package/dist/backend/runtime-pack-core.js +5 -14
  151. package/dist/backend/runtime-pack-core.js.map +1 -1
  152. package/dist/backend/runtime-pack-targets.test.js +3 -8
  153. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  154. package/dist/backend/runtime-pack.test.js +22 -19
  155. package/dist/backend/runtime-pack.test.js.map +1 -1
  156. package/dist/backend/target-diagnostics.d.ts +0 -5
  157. package/dist/backend/target-diagnostics.js +1 -11
  158. package/dist/backend/target-diagnostics.js.map +1 -1
  159. package/dist/backend/target-diagnostics.test.js +1 -1
  160. package/dist/backend/vendor-archives.d.ts +1 -7
  161. package/dist/backend/vendor-archives.js +9 -189
  162. package/dist/backend/vendor-archives.js.map +1 -1
  163. package/dist/backend/vendor-inputs.d.ts +0 -1
  164. package/dist/backend/vendor-inputs.js +0 -1
  165. package/dist/backend/vendor-inputs.js.map +1 -1
  166. package/dist/backend/warm-cache.js +3 -5
  167. package/dist/backend/warm-cache.js.map +1 -1
  168. package/dist/cli/command.js +4 -8
  169. package/dist/cli/command.js.map +1 -1
  170. package/dist/cli/host.d.ts +1 -1
  171. package/dist/cli/usage.d.ts +1 -5
  172. package/dist/cli/usage.js +4 -9
  173. package/dist/cli/usage.js.map +1 -1
  174. package/dist/compat/fetch-profile.d.ts +2 -2
  175. package/dist/compat/fetch-profile.js +16 -25
  176. package/dist/compat/fetch-profile.js.map +1 -1
  177. package/dist/compile-types.d.ts +2 -17
  178. package/dist/contracts/check.d.ts +8 -0
  179. package/dist/contracts/check.js +1573 -0
  180. package/dist/contracts/check.js.map +1 -0
  181. package/dist/coverage/report.d.ts +5 -22
  182. package/dist/coverage/report.js +12 -76
  183. package/dist/coverage/report.js.map +1 -1
  184. package/dist/coverage/surface-manifest.d.ts +3 -3
  185. package/dist/coverage/surface-manifest.js +22 -27
  186. package/dist/coverage/surface-manifest.js.map +1 -1
  187. package/dist/coverage/verdict-cache.d.ts +1 -3
  188. package/dist/coverage/verdict-cache.js +2 -7
  189. package/dist/coverage/verdict-cache.js.map +1 -1
  190. package/dist/diagnostics/diagnostic.d.ts +11 -60
  191. package/dist/diagnostics/diagnostic.js +39 -118
  192. package/dist/diagnostics/diagnostic.js.map +1 -1
  193. package/dist/diagnostics/envelope.d.ts +3 -4
  194. package/dist/diagnostics/envelope.js +0 -9
  195. package/dist/diagnostics/envelope.js.map +1 -1
  196. package/dist/diagnostics/envelope.test.js +1 -1
  197. package/dist/diagnostics/envelope.test.js.map +1 -1
  198. package/dist/executable/executable-cache.d.ts +0 -3
  199. package/dist/executable/executable-cache.js +2 -4
  200. package/dist/executable/executable-cache.js.map +1 -1
  201. package/dist/executable/executable-cache.test.js +0 -4
  202. package/dist/executable/executable-cache.test.js.map +1 -1
  203. package/dist/executable/prepare.js +14 -2
  204. package/dist/executable/prepare.js.map +1 -1
  205. package/dist/frontend/analysis.js +10 -10
  206. package/dist/frontend/analysis.js.map +1 -1
  207. package/dist/frontend/cjs-syntax.js +0 -88
  208. package/dist/frontend/cjs-syntax.js.map +1 -1
  209. package/dist/frontend/contract-types.d.ts +50 -0
  210. package/dist/frontend/contract-types.js +232 -0
  211. package/dist/frontend/contract-types.js.map +1 -0
  212. package/dist/frontend/dts-paths.d.ts +1 -1
  213. package/dist/frontend/dts-paths.js +1 -1
  214. package/dist/frontend/lowering/abstract-equality.js +1 -4
  215. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  216. package/dist/frontend/lowering/array-values.js +4 -11
  217. package/dist/frontend/lowering/array-values.js.map +1 -1
  218. package/dist/frontend/lowering/builtins/arguments.js +0 -13
  219. package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
  220. package/dist/frontend/lowering/builtins/crypto.d.ts +0 -4
  221. package/dist/frontend/lowering/builtins/crypto.js +0 -4
  222. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  223. package/dist/frontend/lowering/builtins/json.js +1 -39
  224. package/dist/frontend/lowering/builtins/json.js.map +1 -1
  225. package/dist/frontend/lowering/builtins/module-resolution.d.ts +0 -15
  226. package/dist/frontend/lowering/builtins/module-resolution.js +5 -44
  227. package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
  228. package/dist/frontend/lowering/builtins/numbers.d.ts +0 -6
  229. package/dist/frontend/lowering/builtins/numbers.js +6 -57
  230. package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
  231. package/dist/frontend/lowering/builtins/promises.js +4 -67
  232. package/dist/frontend/lowering/builtins/promises.js.map +1 -1
  233. package/dist/frontend/lowering/builtins/workers.js +1 -1
  234. package/dist/frontend/lowering/builtins/workers.js.map +1 -1
  235. package/dist/frontend/lowering/call-arguments.d.ts +1 -37
  236. package/dist/frontend/lowering/call-arguments.js +11 -94
  237. package/dist/frontend/lowering/call-arguments.js.map +1 -1
  238. package/dist/frontend/lowering/call-signatures.d.ts +1 -6
  239. package/dist/frontend/lowering/call-signatures.js +16 -68
  240. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  241. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +19 -4
  242. package/dist/frontend/lowering/class-dynamic-dispatch.js +168 -98
  243. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  244. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +44 -4
  245. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  246. package/dist/frontend/lowering/class-method-mutations.js +0 -2
  247. package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
  248. package/dist/frontend/lowering/class-protocols.js +1 -1
  249. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  250. package/dist/frontend/lowering/coercions/function-adapters.js +5 -35
  251. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  252. package/dist/frontend/lowering/coercions/state.d.ts +0 -1
  253. package/dist/frontend/lowering/coercions/state.js +0 -1
  254. package/dist/frontend/lowering/coercions/state.js.map +1 -1
  255. package/dist/frontend/lowering/coercions/structural-plans.js +2 -4
  256. package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
  257. package/dist/frontend/lowering/coercions/structural.js +2 -12
  258. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  259. package/dist/frontend/lowering/coercions/unions.d.ts +12 -0
  260. package/dist/frontend/lowering/coercions/unions.js +63 -1
  261. package/dist/frontend/lowering/coercions/unions.js.map +1 -1
  262. package/dist/frontend/lowering/containers/array-callbacks.js +9 -28
  263. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  264. package/dist/frontend/lowering/containers/array-construction.js +2 -3
  265. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  266. package/dist/frontend/lowering/containers/array-methods.js +10 -54
  267. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  268. package/dist/frontend/lowering/containers/bytes.js +0 -1
  269. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  270. package/dist/frontend/lowering/containers/callback-arguments.js +2 -10
  271. package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
  272. package/dist/frontend/lowering/containers/collection-methods.js +1 -6
  273. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  274. package/dist/frontend/lowering/containers/indexed-objects.js +0 -2
  275. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  276. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +0 -6
  277. package/dist/frontend/lowering/containers/string-and-regexp.js +2 -10
  278. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  279. package/dist/frontend/lowering/expressions/evaluation-safety.js +0 -3
  280. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  281. package/dist/frontend/lowering/expressions/native-proxy.js +1 -1
  282. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  283. package/dist/frontend/lowering/expressions/nullish-assignment.js +0 -1
  284. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  285. package/dist/frontend/lowering/expressions/object-literals.d.ts +0 -8
  286. package/dist/frontend/lowering/expressions/object-literals.js +8 -35
  287. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  288. package/dist/frontend/lowering/expressions/optional-chains.d.ts +0 -4
  289. package/dist/frontend/lowering/expressions/optional-chains.js +7 -67
  290. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  291. package/dist/frontend/lowering/function-context.js +0 -1
  292. package/dist/frontend/lowering/function-context.js.map +1 -1
  293. package/dist/frontend/lowering/generic-functions.js +0 -1
  294. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  295. package/dist/frontend/lowering/lib-boundary.js +10 -77
  296. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  297. package/dist/frontend/lowering/lower-array-sort.js +1 -10
  298. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  299. package/dist/frontend/lowering/lower-array-sort.test.js +2 -2
  300. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
  301. package/dist/frontend/lowering/lower-assert.js +2 -3
  302. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  303. package/dist/frontend/lowering/lower-async-iteration.js +1 -1
  304. package/dist/frontend/lowering/lower-calls.d.ts +2 -27
  305. package/dist/frontend/lowering/lower-calls.js +56 -465
  306. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  307. package/dist/frontend/lowering/lower-classes.js +11 -49
  308. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  309. package/dist/frontend/lowering/lower-comptime.js +2 -3
  310. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  311. package/dist/frontend/lowering/lower-enums.js +5 -8
  312. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  313. package/dist/frontend/lowering/lower-event-emitter.js +3 -4
  314. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  315. package/dist/frontend/lowering/lower-expando.js +3 -5
  316. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  317. package/dist/frontend/lowering/lower-exprs.d.ts +0 -8
  318. package/dist/frontend/lowering/lower-exprs.js +133 -908
  319. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  320. package/dist/frontend/lowering/lower-functions.js +2 -5
  321. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  322. package/dist/frontend/lowering/lower-inspect.js +1 -50
  323. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  324. package/dist/frontend/lowering/lower-modules.d.ts +0 -43
  325. package/dist/frontend/lowering/lower-modules.js +25 -329
  326. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  327. package/dist/frontend/lowering/lower-modules.test.js +5 -5
  328. package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
  329. package/dist/frontend/lowering/lower-server.js +0 -30
  330. package/dist/frontend/lowering/lower-server.js.map +1 -1
  331. package/dist/frontend/lowering/lower-stdlib.d.ts +98 -0
  332. package/dist/frontend/lowering/{lower-island.js → lower-stdlib.js} +97 -1160
  333. package/dist/frontend/lowering/lower-stdlib.js.map +1 -0
  334. package/dist/frontend/lowering/lower-stmts.d.ts +0 -16
  335. package/dist/frontend/lowering/lower-stmts.js +58 -1016
  336. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  337. package/dist/frontend/lowering/lower-stmts.test.js +1 -1
  338. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
  339. package/dist/frontend/lowering/lower-stream.js +1 -3
  340. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  341. package/dist/frontend/lowering/lowerer.d.ts +26 -151
  342. package/dist/frontend/lowering/lowerer.js +120 -770
  343. package/dist/frontend/lowering/lowerer.js.map +1 -1
  344. package/dist/frontend/lowering/lowerer.test.js +4 -51
  345. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  346. package/dist/frontend/lowering/narrowing-stability.d.ts +100 -0
  347. package/dist/frontend/lowering/narrowing-stability.js +1174 -0
  348. package/dist/frontend/lowering/narrowing-stability.js.map +1 -0
  349. package/dist/frontend/lowering/narrowing-stability.test.js +150 -0
  350. package/dist/frontend/lowering/narrowing-stability.test.js.map +1 -0
  351. package/dist/frontend/lowering/optional-arguments.js +0 -2
  352. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  353. package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
  354. package/dist/frontend/lowering/strict-equality.js +1 -1
  355. package/dist/frontend/lowering/strict-equality.js.map +1 -1
  356. package/dist/frontend/lowering/surfaces.d.ts +6 -45
  357. package/dist/frontend/lowering/surfaces.js +5 -65
  358. package/dist/frontend/lowering/surfaces.js.map +1 -1
  359. package/dist/frontend/module-syntax.d.ts +0 -3
  360. package/dist/frontend/module-syntax.js.map +1 -1
  361. package/dist/frontend/npm-node.d.ts +0 -7
  362. package/dist/frontend/npm-node.js +0 -7
  363. package/dist/frontend/npm-node.js.map +1 -1
  364. package/dist/frontend/npm-static-rewrite-syntax.d.ts +1 -1
  365. package/dist/frontend/npm-static-rewrite-syntax.js +6 -82
  366. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
  367. package/dist/frontend/npm-static.d.ts +1 -1
  368. package/dist/frontend/npm-static.js +6 -71
  369. package/dist/frontend/npm-static.js.map +1 -1
  370. package/dist/frontend/npm.d.ts +3 -319
  371. package/dist/frontend/npm.js +6 -1007
  372. package/dist/frontend/npm.js.map +1 -1
  373. package/dist/frontend/npm.test.js +2 -197
  374. package/dist/frontend/npm.test.js.map +1 -1
  375. package/dist/frontend/pipeline-native.js +1 -2
  376. package/dist/frontend/pipeline-native.js.map +1 -1
  377. package/dist/frontend/pipeline.d.ts +3 -11
  378. package/dist/frontend/pipeline.js +37 -56
  379. package/dist/frontend/pipeline.js.map +1 -1
  380. package/dist/frontend/pipeline.test.js +12 -6
  381. package/dist/frontend/pipeline.test.js.map +1 -1
  382. package/dist/frontend/program.d.ts +0 -34
  383. package/dist/frontend/program.js +13 -98
  384. package/dist/frontend/program.js.map +1 -1
  385. package/dist/frontend/provenance-core.d.ts +0 -4
  386. package/dist/frontend/provenance-core.js +4 -37
  387. package/dist/frontend/provenance-core.js.map +1 -1
  388. package/dist/frontend/provenance-registry.d.ts +0 -4
  389. package/dist/frontend/provenance-registry.js +0 -20
  390. package/dist/frontend/provenance-registry.js.map +1 -1
  391. package/dist/frontend/resolve.d.ts +0 -12
  392. package/dist/frontend/resolve.js +0 -34
  393. package/dist/frontend/resolve.js.map +1 -1
  394. package/dist/frontend/runtime-resolve.js +2 -2
  395. package/dist/frontend/runtime-resolve.js.map +1 -1
  396. package/dist/frontend/services-node.js +2 -3
  397. package/dist/frontend/services-node.js.map +1 -1
  398. package/dist/frontend/services.d.ts +1 -8
  399. package/dist/frontend/services.js +2 -22
  400. package/dist/frontend/services.js.map +1 -1
  401. package/dist/frontend/services.test.js +0 -38
  402. package/dist/frontend/services.test.js.map +1 -1
  403. package/dist/frontend/tsc-codes.js +0 -11
  404. package/dist/frontend/tsc-codes.js.map +1 -1
  405. package/dist/frontend/type-mapper.d.ts +2 -27
  406. package/dist/frontend/type-mapper.js +85 -153
  407. package/dist/frontend/type-mapper.js.map +1 -1
  408. package/dist/index.d.ts +1 -1
  409. package/dist/index.js +7 -10
  410. package/dist/index.js.map +1 -1
  411. package/dist/ir/api.d.ts +1 -1
  412. package/dist/ir/api.js +1 -1
  413. package/dist/ir/api.js.map +1 -1
  414. package/dist/ir/builtin-effects.js +0 -5
  415. package/dist/ir/builtin-effects.js.map +1 -1
  416. package/dist/ir/builtin-signatures.d.ts +1 -1
  417. package/dist/ir/builtin-signatures.js +1 -55
  418. package/dist/ir/builtin-signatures.js.map +1 -1
  419. package/dist/ir/constant-globals.test.js +1 -1
  420. package/dist/ir/constant-tables.test.js +1 -1
  421. package/dist/ir/final-fields.test.js +1 -1
  422. package/dist/ir/initializer-bindings.test.js +1 -1
  423. package/dist/ir/int32-slots.d.ts +29 -3
  424. package/dist/ir/int32-slots.js +152 -66
  425. package/dist/ir/int32-slots.js.map +1 -1
  426. package/dist/ir/int32-slots.test.js +1 -1
  427. package/dist/ir/integer-loops.js +3 -0
  428. package/dist/ir/integer-loops.js.map +1 -1
  429. package/dist/ir/integer-loops.test.js +26 -1
  430. package/dist/ir/integer-loops.test.js.map +1 -1
  431. package/dist/ir/integer-ranges.d.ts +20 -0
  432. package/dist/ir/integer-ranges.js +178 -21
  433. package/dist/ir/integer-ranges.js.map +1 -1
  434. package/dist/ir/integer-ranges.test.js +148 -3
  435. package/dist/ir/integer-ranges.test.js.map +1 -1
  436. package/dist/ir/ir.d.ts +44 -284
  437. package/dist/ir/ir.js +10 -259
  438. package/dist/ir/ir.js.map +1 -1
  439. package/dist/ir/ir.test.js +2 -7
  440. package/dist/ir/ir.test.js.map +1 -1
  441. package/dist/ir/runtime-features.d.ts +3 -30
  442. package/dist/ir/runtime-features.js +5 -41
  443. package/dist/ir/runtime-features.js.map +1 -1
  444. package/dist/ir/scalar-records.test.js +1 -1
  445. package/dist/ir/serialize.d.ts +6 -2
  446. package/dist/ir/serialize.js +11 -3
  447. package/dist/ir/serialize.js.map +1 -1
  448. package/dist/ir/traverse.js +0 -21
  449. package/dist/ir/traverse.js.map +1 -1
  450. package/dist/ir/unshare.d.ts +14 -0
  451. package/dist/ir/unshare.js +60 -0
  452. package/dist/ir/unshare.js.map +1 -0
  453. package/dist/ir/unshare.test.js +115 -0
  454. package/dist/ir/unshare.test.js.map +1 -0
  455. package/dist/ir/validate.js +9 -207
  456. package/dist/ir/validate.js.map +1 -1
  457. package/dist/ir/validate.test.js +6 -6
  458. package/dist/library/fence-eval.test.js +1 -1
  459. package/dist/library/int-infer.test.js +4 -4
  460. package/dist/library/library-cache.test.js +5 -5
  461. package/dist/library/prepare.js +14 -20
  462. package/dist/library/prepare.js.map +1 -1
  463. package/dist/native/cli.js +0 -2
  464. package/dist/native/cli.js.map +1 -1
  465. package/dist/native/compiler.test.js +2 -4
  466. package/dist/native/compiler.test.js.map +1 -1
  467. package/dist/native/prepare.js +2 -4
  468. package/dist/native/prepare.js.map +1 -1
  469. package/dist/native/sanitizer.js +2 -16
  470. package/dist/native/sanitizer.js.map +1 -1
  471. package/dist/native/sanitizer.test.js +0 -3
  472. package/dist/native/sanitizer.test.js.map +1 -1
  473. package/dist/startup-cache.js +0 -2
  474. package/dist/startup-cache.js.map +1 -1
  475. package/package.json +20 -20
  476. package/surface-manifest.json +80 -88
  477. package/dist/backend/llvm/expr-island.d.ts +0 -15
  478. package/dist/backend/llvm/expr-island.js +0 -709
  479. package/dist/backend/llvm/expr-island.js.map +0 -1
  480. package/dist/frontend/lowering/coercions/island.d.ts +0 -37
  481. package/dist/frontend/lowering/coercions/island.js +0 -350
  482. package/dist/frontend/lowering/coercions/island.js.map +0 -1
  483. package/dist/frontend/lowering/lower-island.d.ts +0 -229
  484. package/dist/frontend/lowering/lower-island.js.map +0 -1
  485. package/dist/frontend/lowering/lower-island.test.js +0 -56
  486. package/dist/frontend/lowering/lower-island.test.js.map +0 -1
  487. package/dist/frontend/npm-fetch-analysis.d.ts +0 -17
  488. package/dist/frontend/npm-fetch-analysis.js +0 -109
  489. package/dist/frontend/npm-fetch-analysis.js.map +0 -1
  490. package/dist/frontend/npm-fetch-analysis.test.js +0 -130
  491. package/dist/frontend/npm-fetch-analysis.test.js.map +0 -1
  492. package/dist/frontend/npm-fetch-node.d.ts +0 -2
  493. package/dist/frontend/npm-fetch-node.js +0 -12
  494. package/dist/frontend/npm-fetch-node.js.map +0 -1
  495. package/dist/frontend/npm-fetch-syntax.d.ts +0 -6
  496. package/dist/frontend/npm-fetch-syntax.js +0 -202
  497. package/dist/frontend/npm-fetch-syntax.js.map +0 -1
  498. package/dist/native/runtime-typescript.d.ts +0 -4
  499. package/dist/native/runtime-typescript.js +0 -74
  500. package/dist/native/runtime-typescript.js.map +0 -1
  501. package/dist/native/runtime-typescript.test.js +0 -41
  502. package/dist/native/runtime-typescript.test.js.map +0 -1
  503. /package/dist/{frontend/lowering/lower-island.test.d.ts → backend/immutability.test.d.ts} +0 -0
  504. /package/dist/frontend/{npm-fetch-analysis.test.d.ts → lowering/narrowing-stability.test.d.ts} +0 -0
  505. /package/dist/{native/runtime-typescript.test.d.ts → ir/unshare.test.d.ts} +0 -0
@@ -19,15 +19,16 @@ import { constituentTypes } from "../ts7/checker.js";
19
19
  import { dirname } from "node:path";
20
20
  import * as posix from "node:path/posix";
21
21
  import { checkedClassAssertion, checkedClassUnionAssertion } from "./class-assertions.js";
22
+ import { checkedArmExtraction } from "./coercions/unions.js";
22
23
  import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
23
24
  import { lowerUnionFieldRead, lowerUnionFieldWrite } from "./expressions/union-fields.js";
24
25
  import { captureContextArguments } from "./function-context.js";
25
26
  import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
26
27
  import { wasiGuestPath } from "../../wasi-paths.js";
27
- import { BIGINT_T, BYTES_ELEMENT_NAME, BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, JSVAL, NULL_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_ERROR_CLASSES, SEARCH_PARAMS_T, STRING, UNDEFINED_T, VOID, arrayOf, canAdaptDynFuncTo, canDynCheckTo, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isSupportedArrayElem, isUnitType, jsOpResultKind, shapeHasAccessorSlots, typeEquals, typeKey, unionContainerArmsOk, } from "../../ir/ir.js";
28
+ import { BIGINT_T, BYTES_ELEMENT_NAME, BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, NULL_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_ERROR_CLASSES, SEARCH_PARAMS_T, STRING, UNDEFINED_T, VOID, arrayOf, canAdaptDynFuncTo, canDynCheckTo, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isSupportedArrayElem, isUnitType, shapeHasAccessorSlots, typeEquals, typeKey, unionContainerArmsOk, } from "../../ir/ir.js";
28
29
  import { cjsClassExprWholeExportOf, cjsExportAssignmentOf, cjsExportDiscardReason, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeEsmFile, locOf, } from "../program.js";
29
- import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, COMPOUND_ASSIGN_OPS, ISLAND_SURFACE, isChildSurfaceMember, MAP_METHODS, NARROW_FIRST, SET_METHODS, STRING_INDEX_METHODS, STR_METHODS, UNSUPPORTED_EXPR, sideEffectFreeOptionValue, stdlibGlobalNameOf, } from "./surfaces.js";
30
- import { UNSUPPORTED, blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
30
+ import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, COMPOUND_ASSIGN_OPS, STDLIB_SURFACE, isChildSurfaceMember, MAP_METHODS, NARROW_FIRST, SET_METHODS, STRING_INDEX_METHODS, STR_METHODS, UNSUPPORTED_EXPR, sideEffectFreeOptionValue, stdlibGlobalNameOf, } from "./surfaces.js";
31
+ import { UNSUPPORTED, blockedBindingUseDiag, unsupportedPackageValueDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
31
32
  import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
32
33
  import { lowerCollectionSpread } from "./containers/collection-methods.js";
33
34
  import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, lowerSafeBytesRead, } from "./array-values.js";
@@ -52,11 +53,11 @@ import { lowerYield } from "./lower-generators.js";
52
53
  import { errorPropertyRead, errorPropertyWrite, errorToStringCall } from "./error-methods.js";
53
54
  import { lowerStreamProperty, lowerStreamStateProperty, streamSidesOf } from "./lower-stream.js";
54
55
  import { unionWideningTags } from "../../ir/analysis.js";
55
- import { isSafeToDiscard, isSafeToMoveConditionEarlier, isSafeToRepeat, } from "./expressions/evaluation-safety.js";
56
+ import { isSafeToDiscard, isSafeToRepeat } from "./expressions/evaluation-safety.js";
56
57
  import { globalSymbolKey } from "./expressions/global-symbols.js";
57
58
  import { lowerShortCircuitAssignment } from "./expressions/nullish-assignment.js";
58
59
  import { hasOptionalChainGuard, isOptionalChainTail, isRequireMainFilename, } from "./expressions/optional-chains.js";
59
- import { conditionalSpreadOf, foldedStringKeyOf } from "./expressions/object-literals.js";
60
+ import { foldedStringKeyOf } from "./expressions/object-literals.js";
60
61
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
61
62
  import { fenceNodeModuleMutation, isNodeModuleValue, lowerNodeModuleIdentifier, lowerNodeModuleProperty, lowerRequireCacheElement, lowerRequireCacheHas, lowerRequireMainProperty, } from "./lower-node-module.js";
62
63
  import { lowerAbstractEquality } from "./abstract-equality.js";
@@ -377,335 +378,6 @@ function lowerExprInner(lowerer, expr) {
377
378
  }
378
379
  lowerer.unsupported("SC1090", expr, "'void' with an effectful operand in value position (hoist the operand to its own statement — statement-position 'void e' and void-returning arrow bodies compile)");
379
380
  }
380
- // Literals in an `any`-typed slot (the CONTEXTUAL type is what the
381
- // record/array lowerings would consult) build natively in the island:
382
- // each value lowers statically and marshals in. An UNMAPPABLE
383
- // contextual type falls back to the literal's own type, exactly like
384
- // lowerObjectLiteral's fallback — a package call's options parameter
385
- // is often an unmappable intersection while the literal's own type
386
- // absorbs to jsval (a bare-jsval field, an npm-typed member).
387
- if ((ts.isObjectLiteralExpression(expr) || ts.isArrayLiteralExpression(expr)) &&
388
- (() => {
389
- const ctxTs = lowerer.checker.getContextualType(expr);
390
- const mapped = (ctxTs ? lowerer.mapTypeOf(ctxTs) : null) ?? lowerer.mapTypeOf(lowerer.typeOf(expr));
391
- if (mapped?.kind !== "jsval")
392
- return false;
393
- // The tsgo readonly-[] panic repair (see lowerArrayLiteral): an
394
- // EMPTY array literal under a const assertion is the empty tuple —
395
- // its `any` answer is a panicked query, not an island slot.
396
- if (ts.isArrayLiteralExpression(expr) &&
397
- expr.elements.length === 0 &&
398
- underConstAssertion(expr)) {
399
- return false;
400
- }
401
- // A JS variable INITIALIZER whose BINDING registered as a
402
- // checked-dynamic module global (the typedef-annotated
403
- // doc-builder consts whose JSDoc types degraded — DYN slots):
404
- // the island build could never land (no engine→dyn crossing
405
- // exists), so the literal takes its own world's path instead —
406
- // the dyn literal, or a static record the slot converts.
407
- if (isJsSourceFile(expr.getSourceFile()) &&
408
- ts.isVariableDeclaration(expr.parent) &&
409
- expr.parent.initializer === expr &&
410
- ts.isIdentifier(expr.parent.name)) {
411
- const bindSym = lowerer.checker.getSymbolAtLocation(expr.parent.name);
412
- const g = bindSym ? lowerer.globalsBySymbol.get(bindSym) : undefined;
413
- if (g?.type.kind === "dyn")
414
- return false;
415
- }
416
- // A PROJECT-DECLARED contextual type that only ABSORBED to the
417
- // island (a doc-builder typedef whose field's JSDoc type
418
- // reference degraded to checker-`any` — the tsgo multi-file
419
- // value-as-type residue) is not an npm slot: when the literal's
420
- // OWN type maps statically, it builds that way — the binding's
421
- // checked-dynamic slot takes the dyn conversion. Genuinely
422
- // island slots (npm .d.ts provenance, plain `any`) keep the
423
- // native build.
424
- if (ctxTs !== undefined && (ctxTs.flags & ts.TypeFlags.Any) === 0) {
425
- // Intersection/tuple typedefs (`Line & {readonly soft: true}`)
426
- // carry provenance on the ALIAS symbol.
427
- const sym = ctxTs.getSymbol() ?? ctxTs.getAliasSymbol();
428
- const decls = sym ? lowerer.checker.declarationsOf(sym) : [];
429
- const projectDeclared = decls.length > 0 &&
430
- decls.every((d) => {
431
- const sf = d.getSourceFile();
432
- return !sf.isDeclarationFile && !sf.fileName.includes("/node_modules/");
433
- });
434
- if (projectDeclared) {
435
- // A spread already stored in the island must copy there too.
436
- // Later overrides can make the literal's own inferred shape
437
- // appear static without making that source a native record.
438
- if (ts.isObjectLiteralExpression(expr) &&
439
- expr.properties.some((p) => ts.isSpreadAssignment(p) &&
440
- lowerer.mapTypeOf(lowerer.typeOf(p.expression))?.kind === "jsval")) {
441
- return true;
442
- }
443
- const own = lowerer.mapTypeOf(lowerer.typeOf(expr));
444
- if (own?.kind === "record" || own?.kind === "array")
445
- return false;
446
- }
447
- }
448
- return true;
449
- })()) {
450
- if (ts.isObjectLiteralExpression(expr)) {
451
- // Two engine literals when a CONDITIONAL spread participates
452
- // (`{ a, ...(c ? { k: v } : {}) }` — the optional-key idiom): the
453
- // whole literal becomes `c ? objLit(with) : objLit(without)`. The
454
- // shared properties' nodes ride BOTH arms (exactly one arm
455
- // evaluates, so each property still evaluates once); the reorder
456
- // of `c` before earlier properties is unobservable because the
457
- // condition must be a side-effect-free read. The spread arm's keys
458
- // are truly ABSENT when the empty arm is taken — engine-exact
459
- // (`"k" in o` is false), which the static record path can't say.
460
- const argsWithout = [];
461
- const argsWith = [];
462
- const getters = [];
463
- let spread = null;
464
- // A MEMBER a JS file cannot lower or marshal: defer like a
465
- // statement fence, shaped by what the member IS. A FUNCTION-shaped
466
- // member (a generic function as a value, a signature with
467
- // checked-dynamic parameters — the doc-builder public aggregate's
468
- // degraded pieces) becomes a host closure that THROWS the captured
469
- // diagnostic when invoked — building the aggregate compiles and
470
- // only a CALL through the island stops the run. A DATA-shaped
471
- // member must NOT become a callable (the retired fence box's
472
- // silent wrong answers: typeof said "function", downstream errors
473
- // blamed the wrong thing — the withPlugins `plugins:` slot), so it
474
- // defines through the engine's getter machinery instead: READING
475
- // the member throws the diagnostic — the honest granularity, since
476
- // using the value is exactly what cannot be answered. `getterName`
477
- // null keeps the closure shape (function-shaped members, and the
478
- // conditional-spread arms where getters cannot combine).
479
- const islandMemberFence = (diagsBefore, err, valueNode, getterName = null) => {
480
- if (!isJsSourceFile(expr.getSourceFile()))
481
- throw err;
482
- const fence = lowerer.deferToRuntimeFence(diagsBefore, valueNode, {
483
- kind: "closure",
484
- name: () => `%fn${lowerer.lambdaCounter++}_islfence`,
485
- returnType: VOID,
486
- type: { kind: "func", params: [], ret: VOID },
487
- });
488
- if (!fence)
489
- throw err;
490
- if (getterName !== null) {
491
- getters.push({
492
- name: getterName,
493
- fn: lowerer.jsvalIn(fence, valueNode),
494
- loc: locOf(valueNode),
495
- });
496
- return null;
497
- }
498
- return lowerer.jsvalIn(fence, valueNode);
499
- };
500
- // The member's SHAPE decides the fence's granularity: syntactic
501
- // functions and checker-callable values keep the call-time
502
- // closure; everything else (call results, awaits, data reads —
503
- // the withPlugins `plugins:` shape) fences at the READ.
504
- const funcShapedMember = (p) => {
505
- if (ts.isMethodDeclaration(p))
506
- return true;
507
- const src = ts.isPropertyAssignment(p)
508
- ? p.initializer
509
- : ts.isShorthandPropertyAssignment(p)
510
- ? p.name
511
- : null;
512
- if (!src || !ts.isExpression(src))
513
- return true; // unknown form: keep the closure shape
514
- let inner = src;
515
- while (ts.isParenthesizedExpression(inner))
516
- inner = inner.expression;
517
- if (ts.isArrowFunction(inner) || ts.isFunctionExpression(inner))
518
- return true;
519
- return lowerer.checker.getCallSignatures(lowerer.typeOf(src)).length > 0;
520
- };
521
- const pushProp = (name, value, valueNode, into) => {
522
- const diagsBefore = lowerer.diags.length;
523
- let marshaled;
524
- try {
525
- marshaled = lowerer.jsvalIn(value, valueNode);
526
- }
527
- catch (err) {
528
- // A value that LOWERED but cannot cross (a promise, a class
529
- // instance): func-typed values keep the call-time closure;
530
- // data-shaped values fence at the read (the getter), unless a
531
- // conditional spread owns the literal (getters cannot combine).
532
- if (!(err instanceof PoisonError))
533
- throw err;
534
- const asGetter = value.type.kind !== "func" && spread === null;
535
- const fence = islandMemberFence(diagsBefore, err, valueNode, asGetter ? name.text : null);
536
- if (fence === null)
537
- return; // registered as a fence getter — no data property
538
- marshaled = fence;
539
- }
540
- for (const args of into) {
541
- args.push({
542
- kind: "jsMarshal",
543
- value: { kind: "strLit", value: name.text, type: STRING, loc: locOf(name) },
544
- type: JSVAL,
545
- loc: locOf(name),
546
- });
547
- args.push(marshaled);
548
- }
549
- };
550
- const spreadSrcs = [];
551
- let sawPlainProp = false;
552
- for (const prop of expr.properties) {
553
- if (ts.isSpreadAssignment(prop)) {
554
- const cs = conditionalSpreadOf(prop.expression);
555
- if (cs && cs !== "unsupported" && !spread) {
556
- if (spreadSrcs.length > 0) {
557
- lowerer.unsupported("SC1090", prop, "a conditional spread mixed with plain spreads in an 'any'-typed object literal");
558
- }
559
- const cond = lowerer.lowerCondition(cs.cond);
560
- if (!isSafeToMoveConditionEarlier(cond)) {
561
- lowerer.unsupported("SC1090", prop, "conditional spreads with effectful conditions in an 'any'-typed object literal (bind the condition to a const first)");
562
- }
563
- spread = { cond, whenTrue: cs.whenTrue };
564
- for (const p of cs.props) {
565
- const v = ts.isPropertyAssignment(p)
566
- ? lowerer.lowerExpr(p.initializer)
567
- : lowerer.lowerShorthandValue(p);
568
- pushProp(p.name, v, p, [argsWith]);
569
- }
570
- continue;
571
- }
572
- // A PLAIN spread (`{ ...options, plugins }` — the withPlugins
573
- // argument-rebuild shape): the source copies into the fresh
574
- // engine object through the spec's CopyDataProperties (the
575
- // objSpread op). Spreads must precede explicit properties
576
- // (the composition applies explicit keys AFTER the copies —
577
- // JS's later-wins — which a spread after them would invert);
578
- // mixing with a conditional spread keeps the fence.
579
- if (cs === undefined || cs === null) {
580
- if (sawPlainProp || spread) {
581
- lowerer.unsupported("SC1090", prop, "object spread after explicit properties (or mixed with a conditional spread) in an 'any'-typed object literal — spreads must come first");
582
- }
583
- spreadSrcs.push(lowerer.jsvalIn(lowerer.lowerExpr(prop.expression), prop.expression));
584
- continue;
585
- }
586
- lowerer.unsupported("SC1090", prop, "this spread form in an 'any'-typed object literal (one `...(c ? { k: v } : {})` conditional spread is supported — bind other shapes to a const and set keys explicitly)");
587
- }
588
- sawPlainProp = true;
589
- // `name: value`, the shorthand `{ name }` (the value is the
590
- // identifier itself, resolved through the shorthand VALUE symbol
591
- // like the static record path), and METHODS — `{ load() {...} }`
592
- // is a function expression under a shorthand name, marshaled
593
- // like any closure value (this-uses keep the static path's
594
- // rejection); everything else keeps the fence. Identifier and
595
- // string-literal keys — engine property names have no
596
- // identifier restriction ("content-type").
597
- const name = prop.name;
598
- // A GET accessor (`get root() { return ROOT_INDENT; }` — the
599
- // doc-printer's self-referential root-indent shape): the body
600
- // lowers as a zero-param closure marshaled into the engine, and
601
- // the property defines through the engine's own getter
602
- // machinery AFTER the literal builds (the defineGetter op) —
603
- // reads through the handle invoke it natively. `this` in the
604
- // body keeps the object-method rejection; setters stay fenced.
605
- if (ts.isGetAccessorDeclaration(prop) &&
606
- prop.body &&
607
- name &&
608
- (ts.isIdentifier(name) || ts.isStringLiteral(name))) {
609
- lowerer.rejectThisInObjectMethod(prop.body);
610
- getters.push({
611
- name: name.text,
612
- fn: lowerer.jsvalIn(lowerer.lowerLambda(prop), prop),
613
- loc: locOf(prop),
614
- });
615
- continue;
616
- }
617
- // A member VALUE that cannot lower at all (a generic function
618
- // referenced as a value — the aggregate's `align`): the same
619
- // call-time fence deferral pushProp applies to marshal failures.
620
- let value = null;
621
- const valueDiagsBefore = lowerer.diags.length;
622
- try {
623
- value = ts.isPropertyAssignment(prop)
624
- ? lowerer.lowerExpr(prop.initializer)
625
- : ts.isShorthandPropertyAssignment(prop)
626
- ? lowerer.lowerShorthandValue(prop)
627
- : ts.isMethodDeclaration(prop) && prop.body
628
- ? (lowerer.rejectThisInObjectMethod(prop.body), lowerer.lowerLambda(prop))
629
- : null;
630
- }
631
- catch (err) {
632
- if (!(err instanceof PoisonError))
633
- throw err;
634
- const nameText = name && (ts.isIdentifier(name) || ts.isStringLiteral(name)) ? name.text : null;
635
- const asGetter = nameText !== null && spread === null && !funcShapedMember(prop);
636
- value = islandMemberFence(valueDiagsBefore, err, prop, asGetter ? nameText : null);
637
- if (value === null)
638
- continue; // registered as a fence getter — no data property
639
- }
640
- if (value && name && (ts.isIdentifier(name) || ts.isStringLiteral(name))) {
641
- pushProp(name, value, prop, [argsWithout, argsWith]);
642
- }
643
- else {
644
- lowerer.unsupported("SC1090", prop, "this property form in an 'any'-typed object literal (only `name: value`, shorthand names, methods, and get accessors are supported)");
645
- }
646
- }
647
- const withGetters = (obj) => getters.reduce((acc, g) => ({
648
- kind: "jsOp",
649
- op: "defineGetter",
650
- args: [
651
- acc,
652
- {
653
- kind: "jsMarshal",
654
- value: { kind: "strLit", value: g.name, type: STRING, loc: g.loc },
655
- type: JSVAL,
656
- loc: g.loc,
657
- },
658
- g.fn,
659
- ],
660
- type: JSVAL,
661
- loc: g.loc,
662
- }), obj);
663
- if (!spread) {
664
- if (spreadSrcs.length === 0) {
665
- return withGetters({ kind: "jsOp", op: "objLit", args: argsWithout, type: JSVAL, loc });
666
- }
667
- // Plain spreads compose left to right onto a fresh object, the
668
- // explicit properties merging LAST (JS's later-wins): spread
669
- // sources evaluate before later property values by nesting
670
- // order, exactly the source order.
671
- let acc = { kind: "jsOp", op: "objLit", args: [], type: JSVAL, loc };
672
- for (const src of spreadSrcs) {
673
- acc = { kind: "jsOp", op: "objSpread", args: [acc, src], type: JSVAL, loc };
674
- }
675
- if (argsWithout.length > 0) {
676
- acc = {
677
- kind: "jsOp",
678
- op: "objSpread",
679
- args: [acc, { kind: "jsOp", op: "objLit", args: argsWithout, type: JSVAL, loc }],
680
- type: JSVAL,
681
- loc,
682
- };
683
- }
684
- return withGetters(acc);
685
- }
686
- if (getters.length > 0) {
687
- lowerer.unsupported("SC1090", expr, "get accessors combined with conditional spreads in an 'any'-typed object literal");
688
- }
689
- const withLit = { kind: "jsOp", op: "objLit", args: argsWith, type: JSVAL, loc };
690
- const withoutLit = {
691
- kind: "jsOp",
692
- op: "objLit",
693
- args: argsWithout,
694
- type: JSVAL,
695
- loc,
696
- };
697
- return {
698
- kind: "ternary",
699
- cond: spread.cond,
700
- then: spread.whenTrue ? withLit : withoutLit,
701
- else_: spread.whenTrue ? withoutLit : withLit,
702
- type: JSVAL,
703
- loc,
704
- };
705
- }
706
- const args = expr.elements.map((el) => lowerer.jsvalIn(lowerer.lowerExpr(el), el));
707
- return { kind: "jsOp", op: "arrLit", args, type: JSVAL, loc };
708
- }
709
381
  if (ts.isTypeOfExpression(expr)) {
710
382
  if (lowerer.isStdlibGlobal(expr.expression, "process"))
711
383
  return { kind: "strLit", value: "object", type: STRING, loc };
@@ -759,7 +431,7 @@ function lowerExprInner(lowerer, expr) {
759
431
  tested = tested.expression;
760
432
  if (ts.isIdentifier(tested)) {
761
433
  const sym = lowerer.checker.getSymbolAtLocation(tested);
762
- if (!sym && !lowerer.dynamic) {
434
+ if (!sym) {
763
435
  return { kind: "strLit", value: "undefined", type: STRING, loc };
764
436
  }
765
437
  if (lowerer.isStdlibSymbol(sym)) {
@@ -774,9 +446,6 @@ function lowerExprInner(lowerer, expr) {
774
446
  // still evaluates: calls, getters, and checked reads can have effects
775
447
  // or throw. Only trivial operands may disappear.
776
448
  let operand = deferredSlotOr(lowerer, runtimeOptionalStorageOperand(lowerer, expr.expression) ?? lowerer.lowerExpr(expr.expression));
777
- if (operand.type.kind === "jsval") {
778
- return { kind: "jsOp", op: "typeof", args: [operand], type: STRING, loc };
779
- }
780
449
  // A checker-narrowed dyn read arrives as a VALIDATED extraction
781
450
  // (maybeNarrow's dynCheck bridge). typeof needs no extraction — the
782
451
  // dyn kind table answers the question directly, and answers it even
@@ -825,6 +494,13 @@ function lowerExprInner(lowerer, expr) {
825
494
  // tests, so only side-effect-free reads compose — and when every arm
826
495
  // agrees the whole expression folds to that one string (dropping only
827
496
  // the pure read, the trust-the-checker bet lowerUnitComparison makes).
497
+ // An effectful producer (a getter) evaluates once into a hidden local.
498
+ const prelude = [];
499
+ if (operand.type.kind === "union" && !isSafeToRepeat(operand)) {
500
+ const local = lowerer.declareHiddenLocal("%typeofOperand", operand.type);
501
+ prelude.push({ kind: "varDecl", localId: local.id, init: operand, loc });
502
+ operand = varRef(local.id, operand.type, loc);
503
+ }
828
504
  if (operand.type.kind === "union" && isSafeToRepeat(operand)) {
829
505
  const def = lowerer.unions.get(operand.type.unionId);
830
506
  const answers = def?.arms.map(typeofAnswer);
@@ -875,7 +551,9 @@ function lowerExprInner(lowerer, expr) {
875
551
  loc,
876
552
  };
877
553
  }
878
- return result;
554
+ return prelude.length > 0
555
+ ? { kind: "seqExpr", stmts: prelude, result, type: STRING, loc }
556
+ : result;
879
557
  }
880
558
  }
881
559
  if (operand.type.kind === "dyn") {
@@ -1236,19 +914,14 @@ function lowerExprInner(lowerer, expr) {
1236
914
  if (lowerer.cjsLocalModuleBindingOf(expr)) {
1237
915
  lowerer.unsupported("SC1090", expr, `module namespace objects as values (access '${expr.text}' members directly)`);
1238
916
  }
1239
- if (lowerer.islandGlobalFnOf(expr)) {
1240
- // Island-backed functions have no closure representation (they
1241
- // lower to engine ops at call sites only).
917
+ if (lowerer.stdlibGlobalFnOf(expr)) {
1242
918
  lowerer.unsupported("SC1090", expr, `library functions as values (call '${expr.text}' directly)`);
1243
919
  }
1244
- // npm import bindings in a STATIC build: the binding's value lives
1245
- // in the embedded engine — the per-package requires-dynamic
1246
- // diagnostic, not the generic fallthrough. (Under --dynamic these
1247
- // resolve as jsval globals above.)
1248
- if (!lowerer.dynamic) {
920
+ // A declaration-only npm binding has no compiled runtime value.
921
+ {
1249
922
  const pkg = lowerer.npmPackageOfSymbol(lowerer.resolveValueSymbol(expr) ?? undefined);
1250
923
  if (pkg) {
1251
- lowerer.pushDiag(requiresDynamicPackageDiag(pkg, loc));
924
+ lowerer.pushDiag(unsupportedPackageValueDiag(pkg, loc));
1252
925
  throw new PoisonError();
1253
926
  }
1254
927
  }
@@ -1346,13 +1019,13 @@ function lowerExprInner(lowerer, expr) {
1346
1019
  }
1347
1020
  return { kind: "closure", fnName: name, captures: [], type, loc };
1348
1021
  }
1349
- if (!lowerer.dynamic && lowerer.isStdlibGlobal(expr, "crypto"))
1022
+ if (lowerer.isStdlibGlobal(expr, "crypto"))
1350
1023
  return { kind: "libCall", fn: "crypto.native", args: [], type: DYN, loc };
1351
1024
  const nativeAlias = stdlibGlobalNameOf(lowerer, expr);
1352
1025
  if (nativeAlias === "Buffer" && expr.text !== "Buffer") {
1353
1026
  return { kind: "strLit", value: "[builtin Buffer]", type: STRING, loc };
1354
1027
  }
1355
- if (!lowerer.dynamic && lowerer.isStdlibGlobal(expr, "fetch")) {
1028
+ if (lowerer.isStdlibGlobal(expr, "fetch")) {
1356
1029
  return { kind: "libCall", fn: "fetch.function", args: [], type: DYN, loc };
1357
1030
  }
1358
1031
  // The lib fence's IDENTIFIER chokepoint: the real standard library
@@ -1368,7 +1041,7 @@ function lowerExprInner(lowerer, expr) {
1368
1041
  // global, one token; what a token cannot do (be called, answer
1369
1042
  // typeof "function") meets per-site fences/divergences, and
1370
1043
  // SEMANTICS.md documents the stance.
1371
- if (!lowerer.dynamic && stdlibGlobalNameOf(lowerer, expr) === "globalThis") {
1044
+ if (stdlibGlobalNameOf(lowerer, expr) === "globalThis") {
1372
1045
  return lowerGlobalValue(lowerer, expr);
1373
1046
  }
1374
1047
  {
@@ -1378,13 +1051,6 @@ function lowerExprInner(lowerer, expr) {
1378
1051
  const canonical = stdlibGlobalNameOf(lowerer, expr) ?? expr.text;
1379
1052
  return { kind: "strLit", value: `[builtin ${canonical}]`, type: STRING, loc };
1380
1053
  }
1381
- // In a dynamic TypeScript build, the real global object is the
1382
- // escape hatch for host capabilities without static lowering.
1383
- // Direct globalThis.member uses still take their static surface
1384
- // paths; an explicit `as any` or `: any` can reach engine ops.
1385
- if (lowerer.dynamic && expr.text === "globalThis") {
1386
- return { kind: "jsOp", op: "globalGet", name: "globalThis", args: [], type: JSVAL, loc };
1387
- }
1388
1054
  // The families with a WHY: each hint states what makes the
1389
1055
  // surface genuinely non-static (or what to use instead).
1390
1056
  const globalHints = {
@@ -1633,9 +1299,8 @@ function lowerExprInner(lowerer, expr) {
1633
1299
  const promiseArm = def.arms[promiseTag];
1634
1300
  const inner = promiseArm.kind === "promise" ? promiseArm.inner : VOID;
1635
1301
  const units = def.arms.filter(isUnitType);
1636
- if (inner.kind === "union" || inner.kind === "dyn" || inner.kind === "jsval") {
1302
+ if (inner.kind === "union" || inner.kind === "dyn") {
1637
1303
  // A union inner would need an arm-wise re-tag into the result
1638
- // union; dyn/jsval inners have their own boundary stories.
1639
1304
  lowerer.unsupported("SC1090", expr, `awaiting '${lowerer.fmt(value.type)}' (the promise's inner type has no combined result union — await the promise arm after narrowing instead)`);
1640
1305
  }
1641
1306
  let type;
@@ -1665,27 +1330,6 @@ function lowerExprInner(lowerer, expr) {
1665
1330
  if (value.type.kind === "dyn") {
1666
1331
  return { kind: "libCall", fn: "async.awaitDyn", args: [value], type: DYN, loc };
1667
1332
  }
1668
- // A jsval whose CHECKER type is a promise is a package-returned
1669
- // promise: the value lives in the engine. Bridge it — a static
1670
- // promise the engine promise settles (fulfillment = the retained
1671
- // handle or void, rejection = the bridged reason) — and await
1672
- // THAT: the fiber parks like any await, resumes with the settled
1673
- // jsval, or re-throws the crossed rejection.
1674
- if (value.type.kind === "jsval") {
1675
- // ANY island value bridges — the runtime's Promise.resolve(v)
1676
- // .then(...) wiring awaits thenables and non-thenables exactly
1677
- // like JS (`await reg.load()` where the checker only knows
1678
- // 'any' must still park on the returned engine promise).
1679
- const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1680
- const inner = mapped?.kind === "promise" && mapped.inner.kind === "void" ? VOID : JSVAL;
1681
- const bridged = {
1682
- kind: "jsBridgePromise",
1683
- value,
1684
- type: { kind: "promise", inner },
1685
- loc,
1686
- };
1687
- return { kind: "awaitExpr", value: bridged, type: inner, loc };
1688
- }
1689
1333
  // A TYPED non-promise operand (`await 42`, an awaited record):
1690
1334
  // JS awaits non-thenables through exactly one microtask turn and
1691
1335
  // yields the value itself — evaluate the operand, hop, answer it.
@@ -1755,9 +1399,7 @@ function lowerExprInner(lowerer, expr) {
1755
1399
  return lowerer.lowerBinary(expr);
1756
1400
  if (ts.isCallExpression(expr)) {
1757
1401
  // The tail of an optional chain whose `?.` sits deeper
1758
- // (`x?.trim().toLowerCase()`): the whole tail short-circuits with
1759
- // the guard, so it lowers as one chain (dyn/island receivers keep
1760
- // their own undefined-propagating reads — see isOptionalChainTail).
1402
+ // (`x?.trim().toLowerCase()`): the whole tail short-circuits together.
1761
1403
  if (isOptionalChainTail(lowerer, expr))
1762
1404
  return lowerer.lowerOptionalChain(expr);
1763
1405
  return lowerer.lowerCall(expr);
@@ -1799,7 +1441,7 @@ function lowerExprInner(lowerer, expr) {
1799
1441
  return lowerer.lowerSuperAccessorRead(expr);
1800
1442
  }
1801
1443
  // Enum member reads (`E.A`) fold to their compile-time constants —
1802
- // claimed FIRST so no receiver-shaped path (records, islands, the
1444
+ // claimed FIRST so no receiver-shaped path (records, the
1803
1445
  // identifier fence on the enum object) sees them. lower-enums.ts.
1804
1446
  {
1805
1447
  const en = lowerEnumAccess(lowerer, expr);
@@ -1858,7 +1500,7 @@ function lowerExprInner(lowerer, expr) {
1858
1500
  loc,
1859
1501
  };
1860
1502
  }
1861
- if (!lowerer.dynamic && lowerer.stdlibGlobalMember(expr, "Object") === "freeze") {
1503
+ if (lowerer.stdlibGlobalMember(expr, "Object") === "freeze") {
1862
1504
  const name = "%builtin.Object.freeze";
1863
1505
  if (!lowerer.liftedFns.some((fn) => fn.name === name))
1864
1506
  lowerer.liftedFns.push({
@@ -1899,8 +1541,7 @@ function lowerExprInner(lowerer, expr) {
1899
1541
  // in a native program. Declared globals retain their own lowering;
1900
1542
  // arbitrary global-object mutation remains fenced. Preserve a dyn
1901
1543
  // undefined value so stored probes compose with optional calls.
1902
- if (!lowerer.dynamic &&
1903
- stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
1544
+ if (stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
1904
1545
  !lowerer.checker.getPropertyOfType(lowerer.typeOf(expr.expression), expr.name.text)) {
1905
1546
  return dynUndefinedExpr(loc);
1906
1547
  }
@@ -1926,63 +1567,11 @@ function lowerExprInner(lowerer, expr) {
1926
1567
  lowerer.fenceStaticResponseMember(expr, "read");
1927
1568
  lowerer.fenceStaticHeadersMember(expr, "read");
1928
1569
  lowerer.fenceStaticReadableStreamMember(expr, "read");
1929
- // Island receiver: o.x is an engine property read (getProp may throw
1930
1570
  // — reading off null/undefined — bridged catchably like everything
1931
1571
  // at the boundary). `o?.x` arrives here too, through the chain
1932
1572
  // lowering's re-dispatch (a questionDotToken past the gate above is
1933
1573
  // always chain-handled; the receiver reads back as the chain's
1934
1574
  // bound handle).
1935
- if (lowerer.isIslandExpr(expr.expression)) {
1936
- const receiver = lowerer.lowerExpr(expr.expression);
1937
- // The checker said 'any' but the VALUE lives in the checked-dynamic tree (`this`
1938
- // in a plain JS function — dyn.this — or a checked-dynamic local
1939
- // behind an any-typed spelling): the property read is the checked-dynamic tree's
1940
- // own keyed read, dyn results and dyn chains exactly like every
1941
- // checked-dynamic member access (a nullish receiver throws V8's
1942
- // catchable TypeError, exactly Node). Never a jsOp over a dyn —
1943
- // the two dynamic worlds don't share a value representation.
1944
- if (receiver.type.kind === "dyn") {
1945
- return {
1946
- kind: "dynKeyGet",
1947
- key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
1948
- value: receiver,
1949
- type: DYN,
1950
- loc,
1951
- };
1952
- }
1953
- const read = {
1954
- kind: "jsOp",
1955
- op: "getProp",
1956
- name: expr.name.text,
1957
- args: [receiver],
1958
- type: JSVAL,
1959
- loc,
1960
- };
1961
- // A member the .d.ts DECLARES as a primitive exits eagerly to that
1962
- // static type (`f.mediaType` on a package handle IS a string):
1963
- // primitives copy by value across the boundary — no aliasing, no
1964
- // cost — and every static consumer (intrinsics, templates,
1965
- // comparisons) works on the result. Trust-but-verify: a lying
1966
- // declaration throws the catchable TypeError instead of smuggling
1967
- // a mistyped handle into string ops. A Uint8Array member exits the
1968
- // same way (`result.audio.uint8Array` — the generated-media
1969
- // payload) as a validated u8 COPY, the boundary's aliasing stance
1970
- // (divergences 44/45; engine Buffers pass — they ARE Uint8Arrays).
1971
- // Other composites stay handles (eager JSON copies would change
1972
- // aliasing), and chain-handled reads stay jsval (the chain's unit
1973
- // path is the engine's undefined — see lowerOptionalChain).
1974
- if (!expr.questionDotToken) {
1975
- const declared = lowerer.mapTypeOf(lowerer.typeOf(expr));
1976
- if (declared &&
1977
- (declared.kind === "f64" ||
1978
- declared.kind === "bool" ||
1979
- declared.kind === "string" ||
1980
- (declared.kind === "bytes" && declared.elem === "u8"))) {
1981
- return { kind: "jsExit", value: read, type: declared, loc };
1982
- }
1983
- }
1984
- return read;
1985
- }
1986
1575
  // `m.index` on a for-of-over-matchAll binding reads the companion-
1987
1576
  // index array at this iteration's cursor — always a number: every
1988
1577
  // drained row matched, so the lib's `.index` is never undefined
@@ -2258,13 +1847,13 @@ function lowerExprInner(lowerer, expr) {
2258
1847
  isJsSourceFile(expr.getSourceFile())) {
2259
1848
  const canonical = stdlibGlobalNameOf(lowerer, expr);
2260
1849
  if (canonical !== null) {
2261
- if (!lowerer.dynamic && canonical === "globalThis")
1850
+ if (canonical === "globalThis")
2262
1851
  return lowerGlobalValue(lowerer, expr);
2263
- if (!lowerer.dynamic && canonical === "ArrayBuffer")
1852
+ if (canonical === "ArrayBuffer")
2264
1853
  return { kind: "libCall", fn: "arrayBuffer.constructor", args: [], type: DYN, loc };
2265
- if (!lowerer.dynamic && canonical === "fetch")
1854
+ if (canonical === "fetch")
2266
1855
  return { kind: "libCall", fn: "fetch.function", args: [], type: DYN, loc };
2267
- if (!lowerer.dynamic && Object.values(BYTES_ELEMENT_NAME).includes(canonical))
1856
+ if (Object.values(BYTES_ELEMENT_NAME).includes(canonical))
2268
1857
  return {
2269
1858
  kind: "libCall",
2270
1859
  fn: "bytes.constructor",
@@ -2919,7 +2508,7 @@ export function lowerTernary(lowerer, expr, expected) {
2919
2508
  (lowerer.typeOf(expr).flags & ts.TypeFlags.Any) !== 0) {
2920
2509
  const a = thenRaw.type;
2921
2510
  const b = elseRaw.type;
2922
- const staticArm = (t) => t.kind !== "dyn" && t.kind !== "caught" && t.kind !== "jsval" && t.kind !== "void";
2511
+ const staticArm = (t) => t.kind !== "dyn" && t.kind !== "caught" && t.kind !== "void";
2923
2512
  if (staticArm(a) && staticArm(b)) {
2924
2513
  if (typeEquals(a, b)) {
2925
2514
  anyJoin = a;
@@ -3149,6 +2738,11 @@ export function maybeNarrow(lowerer, expr, node) {
3149
2738
  if (narrowed?.kind === "object" &&
3150
2739
  narrowed.className !== expr.type.className &&
3151
2740
  lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
2741
+ if (lowerer.narrowing.untrusted(node, narrowed)) {
2742
+ const checked = checkedClassAssertion(lowerer, expr, narrowed, expr.loc);
2743
+ if (checked)
2744
+ return checked;
2745
+ }
3152
2746
  return { kind: "downcast", value: expr, type: narrowed, loc: expr.loc };
3153
2747
  }
3154
2748
  return expr;
@@ -3181,9 +2775,8 @@ export function maybeNarrow(lowerer, expr, node) {
3181
2775
  const narrowedTs = lowerer.typeOf(node);
3182
2776
  const narrowed = lowerer.mapTypeOf(narrowedTs);
3183
2777
  // `Array.isArray(u)` on a union with one readonly array/tuple arm: the
3184
- // lib predicate narrows to `any[]`, either directly or intersected
3185
- // with the original union. That checker type can map to the island's
3186
- // array-of-handles, nothing, or a synthetic intersection record — but
2778
+ // lib predicate narrows to `any[]`, possibly intersected with another
2779
+ // type. That mapping may be a checked value or a synthetic record, but
3187
2780
  // the tag test proved the union's one array-valued arm, so bridge to it
3188
2781
  // with the same trusted unionNarrow the mapped case below builds.
3189
2782
  if (lowerer.checkerAnyArrayType(narrowedTs)) {
@@ -3191,6 +2784,9 @@ export function maybeNarrow(lowerer, expr, node) {
3191
2784
  const arrayTags = lowerer.arrayValueTags(expr.type.unionId);
3192
2785
  if (arrayTags.length === 1) {
3193
2786
  const arm = def.arms[arrayTags[0]];
2787
+ const checked = checkedStaleArm(lowerer, node, expr, arrayTags[0], arm);
2788
+ if (checked)
2789
+ return checked;
3194
2790
  return {
3195
2791
  kind: "unionNarrow",
3196
2792
  unionId: expr.type.unionId,
@@ -3224,6 +2820,9 @@ export function maybeNarrow(lowerer, expr, node) {
3224
2820
  const values = literalValues(lowerer.checker.getTypeOfSymbol(property));
3225
2821
  const arm = values && literalUnionArm(def, values, (id) => lowerer.shapes.get(id));
3226
2822
  if (arm) {
2823
+ const checked = checkedStaleArm(lowerer, node, expr, lowerer.armTag(expr.type.unionId, arm), arm);
2824
+ if (checked)
2825
+ return checked;
3227
2826
  return {
3228
2827
  kind: "unionNarrow",
3229
2828
  unionId: expr.type.unionId,
@@ -3249,6 +2848,10 @@ export function maybeNarrow(lowerer, expr, node) {
3249
2848
  arm.kind !== "object" ||
3250
2849
  !lowerer.isSubclassOf(narrowed.className, arm.className)) &&
3251
2850
  lowerer.isSubclassOf(narrowed.className, valueType.className)) {
2851
+ const checked = checkedStaleArm(lowerer, node, expr, valueTag, valueType, narrowed);
2852
+ if (checked) {
2853
+ return checkedClassAssertion(lowerer, checked, narrowed, expr.loc) ?? checked;
2854
+ }
3252
2855
  return {
3253
2856
  kind: "downcast",
3254
2857
  value: {
@@ -3265,6 +2868,9 @@ export function maybeNarrow(lowerer, expr, node) {
3265
2868
  }
3266
2869
  return expr;
3267
2870
  }
2871
+ const checked = checkedStaleArm(lowerer, node, expr, tag, narrowed);
2872
+ if (checked)
2873
+ return checked;
3268
2874
  return {
3269
2875
  kind: "unionNarrow",
3270
2876
  unionId: expr.type.unionId,
@@ -3274,6 +2880,60 @@ export function maybeNarrow(lowerer, expr, node) {
3274
2880
  loc: expr.loc,
3275
2881
  };
3276
2882
  }
2883
+ /** The checked form of maybeNarrow's arm extraction for a narrowing the
2884
+ * checker may hold past code that replaced the value (a call clearing the
2885
+ * property; see NarrowingStability). Every other arm throws the TypeError
2886
+ * Node raises for the operation consuming the read (`Cannot read
2887
+ * properties of undefined (reading 'x')`, `o.f is not a function`), or the
2888
+ * stranded-value TypeError where Node would carry the value on. Null when
2889
+ * the narrowing is provably current. `narrowed` is the checker's type when
2890
+ * it refines the arm (a subclass view). */
2891
+ function checkedStaleArm(lowerer, node, value, tag, arm, narrowed = arm) {
2892
+ if (value.type.kind !== "union" || tag < 0)
2893
+ return null;
2894
+ if (!lowerer.narrowing.untrusted(node, narrowed))
2895
+ return null;
2896
+ const inPlace = checkedArmExtraction(lowerer, value, tag, arm, (found) => staleReadMessage(node, found));
2897
+ if (inPlace)
2898
+ return inPlace;
2899
+ const helper = lowerer.narrowedArmHelper(value.type.unionId, arm, value.loc);
2900
+ return helper ? lowerer.checkedNarrowCall(helper, value, arm, value.loc) : null;
2901
+ }
2902
+ /** Node's TypeError for the operation consuming `node` when it holds a
2903
+ * value of type `found`, or null where Node would not throw. */
2904
+ function staleReadMessage(node, found) {
2905
+ let child = node;
2906
+ let parent = node.parent;
2907
+ while (ts.isParenthesizedExpression(parent)) {
2908
+ child = parent;
2909
+ parent = parent.parent;
2910
+ }
2911
+ if (ts.isCallExpression(parent) && parent.expression === child && !parent.questionDotToken) {
2912
+ return found.kind === "func" ? null : `${node.getText()} is not a function`;
2913
+ }
2914
+ const unit = found.kind === "undefinedT" ? "undefined" : found.kind === "nullT" ? "null" : null;
2915
+ if (unit === null)
2916
+ return null;
2917
+ if (!(ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) ||
2918
+ parent.expression !== child ||
2919
+ parent.questionDotToken)
2920
+ return null;
2921
+ let key = null;
2922
+ if (ts.isPropertyAccessExpression(parent))
2923
+ key = parent.name.text;
2924
+ else if (ts.isStringLiteral(parent.argumentExpression))
2925
+ key = parent.argumentExpression.text;
2926
+ else if (ts.isNumericLiteral(parent.argumentExpression))
2927
+ key = String(Number(parent.argumentExpression.text));
2928
+ if (key === null)
2929
+ return null;
2930
+ const store = parent.parent;
2931
+ return ts.isBinaryExpression(store) &&
2932
+ store.left === parent &&
2933
+ store.operatorToken.kind === ts.SyntaxKind.EqualsToken
2934
+ ? `Cannot set properties of ${unit} (setting '${key}')`
2935
+ : `Cannot read properties of ${unit} (reading '${key}')`;
2936
+ }
3277
2937
  /** A runtime-optional slot can be assigned while a truthy guard is in
3278
2938
  * force. TypeScript then types a direct member receiver as the plain arm,
3279
2939
  * even though an OOB-safe assignment may have restored undefined. Check
@@ -3661,18 +3321,6 @@ function volatileEnvRead(e) {
3661
3321
  }
3662
3322
  return null;
3663
3323
  }
3664
- /** `x == null` / `x != null` — JS's idiomatic null-OR-undefined test, the
3665
- * ONE loose comparison with static semantics: `== null` matches exactly
3666
- * null and undefined (0, "", and false do not). Requires a syntactic
3667
- * null LITERAL on either side; the other operand's unit arms become a
3668
- * runtime tag test — one `unionIsTag` when the union has a single unit
3669
- * arm, a short-circuit pair over both tags otherwise (that shape re-emits
3670
- * the operand, so only side-effect-free reads compose; anything else
3671
- * keeps the fence). A unit-literal operand folds (null and undefined are
3672
- * mutually loose-equal), and a non-nullable operand folds statically —
3673
- * the same trust-the-checker bet as lowerUnitComparison. Null (fence)
3674
- * when this isn't a null-literal comparison or the operand has no
3675
- * lowering here (dyn/jsval/void). */
3676
3324
  function lowerLooseNullCompare(lowerer, expr, loc) {
3677
3325
  const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
3678
3326
  const unwrap = (e) => ts.isParenthesizedExpression(e) ? unwrap(e.expression) : e;
@@ -3737,7 +3385,7 @@ function lowerLooseNullCompare(lowerer, expr, loc) {
3737
3385
  loc,
3738
3386
  };
3739
3387
  }
3740
- if (other.type.kind === "jsval" || other.type.kind === "void") {
3388
+ if (other.type.kind === "void") {
3741
3389
  return null; // no static tag to test — keep the fence
3742
3390
  }
3743
3391
  // The env-volatility escape (see lowerUnitComparison): a narrowed
@@ -3894,10 +3542,8 @@ function isMemberReceiver(node) {
3894
3542
  function lowerNullishPair(lowerer, expr, loc, left) {
3895
3543
  if (left.type.kind === "dyn") {
3896
3544
  // `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
3897
- // runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default;
3898
- // a wrapped island value routes to the engine's test, defensively:
3899
- // the wrap constructor scalar-normalizes engine null/undefined
3900
- // away). Both sides live in the checked-dynamic tree — the right converts through
3545
+ // runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default).
3546
+ // Both sides live in the checked-dynamic tree — the right converts through
3901
3547
  // the usual boundary and evaluates lazily in its branch; a default
3902
3548
  // with no dyn representation keeps the fence.
3903
3549
  const right = lowerer.coerceToExpected(lowerer.lowerExpr(expr.right), DYN);
@@ -3906,13 +3552,6 @@ function lowerNullishPair(lowerer, expr, loc, left) {
3906
3552
  }
3907
3553
  return { kind: "nullish", left, right, type: DYN, loc };
3908
3554
  }
3909
- if (left.type.kind === "jsval") {
3910
- // `a ?? b` on an ISLAND value: the engine's own nullish test — the
3911
- // left evaluates once, the right runs lazily in its branch and
3912
- // marshals in (the emitter's jsval nullish arm).
3913
- const right = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
3914
- return { kind: "nullish", left, right, type: JSVAL, loc };
3915
- }
3916
3555
  if (left.type.kind !== "union")
3917
3556
  return left;
3918
3557
  const def = lowerer.unions.get(left.type.unionId);
@@ -4356,10 +3995,6 @@ export function ensureBool(lowerer, e, node) {
4356
3995
  // tag (plus the scalar payload for number/string).
4357
3996
  return { kind: "dynTest", test: "truthy", value: e, type: BOOL, loc: e.loc };
4358
3997
  }
4359
- if (e.type.kind === "jsval") {
4360
- // ToBoolean of an island value — the engine answers (never throws).
4361
- return { kind: "jsOp", op: "truthy", args: [e], type: BOOL, loc: e.loc };
4362
- }
4363
3998
  if (e.type.kind === "union") {
4364
3999
  lowerer.requireTruthyUnion(e.type.unionId, node);
4365
4000
  return { kind: "toBool", operand: e, type: BOOL, loc: e.loc };
@@ -4377,23 +4012,15 @@ export function ensureBool(lowerer, e, node) {
4377
4012
  }
4378
4013
  lowerer.badType(node, lowerer.typeOf(node));
4379
4014
  }
4380
- /** Truthiness needs a ToBoolean per arm: dyn/caught arms have none (a
4381
- * dynamic ToBoolean over the checked-dynamic tree / the snapshot box) — fence those
4382
- * unions; every other arm kind is answerable (units false, scalars and
4383
- * strings by value, refs true, jsval by the engine). */
4384
4015
  export function requireTruthyUnion(lowerer, unionId, node) {
4385
4016
  const def = lowerer.unions.get(unionId);
4386
4017
  if (def && def.arms.every((a) => a.kind !== "dyn" && a.kind !== "caught"))
4387
4018
  return;
4388
4019
  lowerer.unsupported("SC1090", node, `union-typed conditions with 'unknown' arms (${NARROW_FIRST})`);
4389
4020
  }
4390
- /** Strict equality needs a per-arm comparison: units, scalars, strings,
4391
- * and ref kinds (pointer identity) all have one; dyn/caught arms have no
4392
- * static equality and jsval arms would need the engine's `===` — those
4393
- * unions keep the narrow-first fence. */
4394
4021
  export function eqComparableUnion(lowerer, unionId) {
4395
4022
  const def = lowerer.unions.get(unionId);
4396
- return (!!def && def.arms.every((a) => a.kind !== "dyn" && a.kind !== "caught" && a.kind !== "jsval"));
4023
+ return !!def && def.arms.every((a) => a.kind !== "dyn" && a.kind !== "caught");
4397
4024
  }
4398
4025
  /** Property access on a string or array receiver: `.length` lowers to the
4399
4026
  * matching intrinsic; a bare method reference (`const f = s.slice` — a
@@ -4801,9 +4428,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
4801
4428
  return null;
4802
4429
  }
4803
4430
  if (kind === "f64") {
4804
- // The only ambient members on numbers are island-backed methods; a
4805
- // bare reference has no value form regardless of --dynamic.
4806
- if (own(ISLAND_SURFACE.number, name) !== undefined) {
4431
+ if (own(STDLIB_SURFACE.number, name) !== undefined) {
4807
4432
  lowerer.unsupported("SC1090", expr, `number methods as values (call '${name}' directly)`);
4808
4433
  }
4809
4434
  return null;
@@ -4847,22 +4472,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
4847
4472
  ? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
4848
4473
  : lowerer.maybeNarrow(receiver, expr.expression);
4849
4474
  }
4850
- // An island handle behind a typed-array .d.ts surface: the engine
4851
4475
  // property read, exiting at the declared number type (the array
4852
- // .length rule). Chain-handled reads stay jsval.
4853
- if (receiver.type.kind === "jsval") {
4854
- const read = {
4855
- kind: "jsOp",
4856
- op: "getProp",
4857
- name,
4858
- args: [receiver],
4859
- type: JSVAL,
4860
- loc,
4861
- };
4862
- if (expr.questionDotToken)
4863
- return read;
4864
- return { kind: "jsExit", value: read, type: F64, loc };
4865
- }
4866
4476
  return { kind: "bytesIntrinsic", method: name, receiver, args: [], type: F64, loc };
4867
4477
  }
4868
4478
  if (name === "byteOffset") {
@@ -4941,24 +4551,6 @@ export function lowerIntrinsicProperty(lowerer, expr) {
4941
4551
  ? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
4942
4552
  : lowerer.maybeNarrow(receiver, expr.expression);
4943
4553
  }
4944
- // An island handle behind an array-typed .d.ts surface
4945
- // (`parts().length` on a declared `string[]` return — arrays never
4946
- // exit eagerly, so the value stays jsval): an engine property read,
4947
- // exiting at the declared number type. Chain-handled reads stay
4948
- // jsval (the island chain's body must be a handle).
4949
- if (receiver.type.kind === "jsval") {
4950
- const read = {
4951
- kind: "jsOp",
4952
- op: "getProp",
4953
- name: "length",
4954
- args: [receiver],
4955
- type: JSVAL,
4956
- loc: locOf(expr),
4957
- };
4958
- if (expr.questionDotToken)
4959
- return read;
4960
- return { kind: "jsExit", value: read, type: F64, loc: locOf(expr) };
4961
- }
4962
4554
  // A CHECKED-DYNAMIC value behind an array-typed checker spelling
4963
4555
  // (`Object.keys(u).length` — the dyn walk answers a dyn array while
4964
4556
  // tsc spells string[]): the runtime-world dispatch — a dyn keyed
@@ -4984,7 +4576,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
4984
4576
  if (kind === "string"
4985
4577
  ? own(STR_METHODS, name) !== undefined ||
4986
4578
  STRING_INDEX_METHODS.has(name) ||
4987
- own(ISLAND_SURFACE.string, name) !== undefined
4579
+ own(STDLIB_SURFACE.string, name) !== undefined
4988
4580
  : ARRAY_METHODS.has(name)) {
4989
4581
  lowerer.unsupported("SC1090", expr, `${kind} methods as values (call '${name}' directly)`);
4990
4582
  }
@@ -5089,11 +4681,8 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
5089
4681
  !(ts.isIdentifier(el) && el.text === "undefined"));
5090
4682
  const ownUnhelpful = mapped === null ||
5091
4683
  mapped.kind === "dyn" ||
5092
- // The checker echoing the context union back as the literal's
5093
- // own type decides nothing either — nor does an island ('any')
5094
- // residue under a STATIC union slot.
4684
+ // The checker may echo the context union rather than infer this literal.
5095
4685
  mapped.kind === "union" ||
5096
- mapped.kind === "jsval" ||
5097
4686
  (mapped.kind === "array" && nonUnitElems && lowerer.unitOnlyElem(mapped.elem));
5098
4687
  if (ownUnhelpful) {
5099
4688
  const def = lowerer.unions.get(ctxUnion.unionId);
@@ -5141,11 +4730,9 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
5141
4730
  tryLowerExpression(lowerer, element.expression)?.type.kind === "dyn"))
5142
4731
  mapped = DYN;
5143
4732
  // An EMPTY literal under a CONST ASSERTION whose type queries panicked
5144
- // (tsgo's readonly-[] TupleType conversion — the facade answers `any`,
5145
- // which maps to nothing statically and to an island value under
5146
- // --dynamic): the value is provably the empty tuple; ride the
5147
- // unit-element array, mapType's own `[] as const` rule.
5148
- if ((mapped === null || mapped.kind === "jsval") &&
4733
+ // (tsgo's readonly-[] TupleType conversion) uses a unit-element array,
4734
+ // mapType's own `[] as const` rule.
4735
+ if (mapped === null &&
5149
4736
  expr.elements.length === 0 &&
5150
4737
  (tsType.flags & ts.TypeFlags.Any) !== 0 &&
5151
4738
  underConstAssertion(expr)) {
@@ -5175,22 +4762,7 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
5175
4762
  // tsc padded an UNDER-LENGTH literal against an optional-element
5176
4763
  // tuple context (`options || []` with `options?: [string?,
5177
4764
  // number?]` — the instantiated type spells every position, the
5178
- // literal spells fewer): no fixed shape holds it, but the
5179
- // engine's real arrays do — under --dynamic the literal builds
5180
- // island-native with its ACTUAL elements, length exact. Static
5181
- // builds keep the type fence (badType's dynamic probe tells the
5182
- // --dynamic story).
5183
- if (lowerer.dynamic &&
5184
- expr.elements.length < shape.fields.length &&
5185
- expr.elements.every((el) => !ts.isOmittedExpression(el))) {
5186
- return {
5187
- kind: "jsOp",
5188
- op: "arrLit",
5189
- args: expr.elements.map((el) => lowerer.jsvalIn(lowerer.lowerExpr(el), el)),
5190
- type: JSVAL,
5191
- loc,
5192
- };
5193
- }
4765
+ // literal spells fewer): no fixed shape holds it.
5194
4766
  lowerer.badType(expr, tsType);
5195
4767
  }
5196
4768
  const byName = new Map(shape.fields.map((f) => [f.name, f.type]));
@@ -5293,10 +4865,9 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
5293
4865
  while (ts.isParenthesizedExpression(srcNode))
5294
4866
  srcNode = srcNode.expression;
5295
4867
  lowerer.fenceStaticHeadersIteration(el.expression);
5296
- let src = lowerer.lowerDynamicHeadersSpread(el.expression, type) ??
5297
- (ts.isConditionalExpression(srcNode)
5298
- ? lowerTernary(lowerer, srcNode, type)
5299
- : lowerer.lowerExpr(el.expression));
4868
+ let src = ts.isConditionalExpression(srcNode)
4869
+ ? lowerTernary(lowerer, srcNode, type)
4870
+ : lowerer.lowerExpr(el.expression);
5300
4871
  src = lowerCollectionSpread(lowerer, src, el.expression) ?? src;
5301
4872
  // `[...new SymbolIterator]`: a CLASS ITERABLE drains through its
5302
4873
  // own protocol into a fresh element array (classIteratorDrainCall
@@ -5851,33 +5422,6 @@ export function lowerElementAccess(lowerer, expr) {
5851
5422
  return lowerer.maybeNarrow({ kind: "dynKeyGet", value: receiver, key, type: DYN, loc: locOf(expr) }, expr);
5852
5423
  }
5853
5424
  }
5854
- if (receiverIr?.kind === "jsval") {
5855
- // Dispatch follows the RUNTIME world (383(d)): a checker-'any'
5856
- // receiver whose value LOWERED checked-dynamic (`bag.list[0]` where
5857
- // bag.list is a routed keyed read off a wrapped island value) takes
5858
- // the dyn keyed read below — the routed JSVAL arm reads the real
5859
- // engine element; a jsval-lowered receiver keeps the island read.
5860
- const recv = lowerer.lowerExpr(expr.expression);
5861
- if (recv.type.kind !== "dyn")
5862
- return islandElementRead(lowerer, expr, recv);
5863
- const rawKey = lowerer.lowerExpr(expr.argumentExpression);
5864
- const key = rawKey.type.kind === "string"
5865
- ? rawKey
5866
- : rawKey.type.kind === "f64"
5867
- ? { kind: "toString", operand: rawKey, type: STRING, loc: rawKey.loc }
5868
- : null;
5869
- if (key) {
5870
- const opt = hasOptionalChainGuard(expr.expression);
5871
- return lowerer.maybeNarrow({
5872
- kind: "dynKeyGet",
5873
- key,
5874
- ...(opt ? { optional: true } : {}),
5875
- value: recv,
5876
- type: DYN,
5877
- loc: locOf(expr),
5878
- }, expr);
5879
- }
5880
- }
5881
5425
  // Typed-array element read `b[i]` — like arrayGet with a scalar
5882
5426
  // result; any invalid index traps (the array discipline; JS would
5883
5427
  // read undefined — divergence 4's policy).
@@ -5894,12 +5438,6 @@ export function lowerElementAccess(lowerer, expr) {
5894
5438
  ? lowerer.checkedNarrowCall(helper, recv, present, locOf(expr.expression))
5895
5439
  : lowerer.maybeNarrow(recv, expr.expression);
5896
5440
  }
5897
- // A typed-array .d.ts surface whose VALUE is an island handle
5898
- // (`data()[0]` on a declared Uint8Array return — call results only
5899
- // exit primitives eagerly): the engine element read, exiting at the
5900
- // declared number type.
5901
- if (recv.type.kind === "jsval")
5902
- return islandElementRead(lowerer, expr, recv);
5903
5441
  const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
5904
5442
  if (isJsSourceFile(expr.getSourceFile()) && recv.type.kind === "bytes") {
5905
5443
  return {
@@ -5951,14 +5489,6 @@ export function lowerElementAccess(lowerer, expr) {
5951
5489
  const shape = lowerer.shapes.get(receiverIr.shapeId);
5952
5490
  if (shape?.tuple) {
5953
5491
  let obj = lowerer.lowerExpr(expr.expression);
5954
- // A tuple-typed .d.ts surface whose VALUE is an island handle
5955
- // (`pair()[0]` on a declared `[number, string]` return — the
5956
- // anonymous tuple type has no npm symbol, so the checker maps it
5957
- // structurally while the call result stays an engine array): the
5958
- // read rides engine ops, exiting at the declared per-index type
5959
- // like the array path.
5960
- if (obj.type.kind === "jsval")
5961
- return islandElementRead(lowerer, expr, obj);
5962
5492
  if (obj.type.kind === "dyn") {
5963
5493
  // Object.entries over a checked value stores each pair in the
5964
5494
  // dynamic tree even when the checker names a tuple type.
@@ -6009,14 +5539,6 @@ export function lowerElementAccess(lowerer, expr) {
6009
5539
  : lowerer.maybeNarrow(get, expr);
6010
5540
  }
6011
5541
  if (shape && !shape.tuple) {
6012
- // A record-typed .d.ts surface whose VALUE is an island handle
6013
- // (`headers()["x-id"]` on a declared `Record<string, string>`
6014
- // return — the stdlib alias maps structurally while the call
6015
- // result stays an engine object): the read rides engine ops with
6016
- // the declared-value exit, never a recordKeyGet over a jsval.
6017
- const obj = lowerer.lowerExpr(expr.expression);
6018
- if (obj.type.kind === "jsval")
6019
- return islandElementRead(lowerer, expr, obj);
6020
5542
  return lowerer.lowerRecordKeyRead(expr, receiverIr.shapeId, shape);
6021
5543
  }
6022
5544
  }
@@ -6243,14 +5765,6 @@ export function lowerElementAccess(lowerer, expr) {
6243
5765
  ? lowerer.checkedNarrowCall(helper, arr, present, locOf(expr.expression))
6244
5766
  : lowerer.maybeNarrow(arr, expr.expression);
6245
5767
  }
6246
- // The checker sees an array but the VALUE is an island handle (an
6247
- // array-typed .d.ts surface: `parts()[0]` on a declared `string[]`
6248
- // return, `issue.path[0]` on a declared member — arrays never exit
6249
- // eagerly, so the call/member read stays jsval): the read rides
6250
- // engine ops with the declared-element exit, never a static arrayGet
6251
- // over a jsval (the validator ICE).
6252
- if (arr.type.kind === "jsval")
6253
- return islandElementRead(lowerer, expr, arr);
6254
5768
  // The checker sees an array but the VALUE lowered checked-dynamic (a
6255
5769
  // jsdoc-typed default export from a .js module — signature 14): the
6256
5770
  // read rides the dynCheck boundary when the array shape is one the checked-dynamic tree
@@ -6328,33 +5842,6 @@ export function lowerElementAccess(lowerer, expr) {
6328
5842
  // narrows literal-index element accesses).
6329
5843
  return lowerer.maybeNarrow({ kind: "arrayGet", arr, index, type: elemT, loc: locOf(expr) }, expr);
6330
5844
  }
6331
- /** `o[k]` where the RECEIVER is an island value — a jsval-mapped checker
6332
- * type, or an array/tuple-typed .d.ts surface whose lowered value is a
6333
- * handle. The key marshals in (any JS key kind — the engine does its
6334
- * own ToPropertyKey) and the result stays island, EXCEPT when the
6335
- * checker declares the element a primitive (`parts()[0]` on a declared
6336
- * `string[]`): those exit eagerly to the static type, exactly the
6337
- * island property-read rule (trust-but-verify — a lying declaration
6338
- * throws the catchable TypeError; tsc puts the `| undefined` of a
6339
- * short-circuiting chain on the OUTERMOST expression, so chain tails
6340
- * never map primitive here). Chain-handled reads (`v?.[0]`) stay jsval
6341
- * — the chain's unit path is the engine's undefined. */
6342
- function islandElementRead(lowerer, expr, obj) {
6343
- const loc = locOf(expr);
6344
- const key = lowerer.jsvalIn(lowerer.lowerExpr(expr.argumentExpression), expr.argumentExpression);
6345
- const read = { kind: "jsOp", op: "getIdx", args: [obj, key], type: JSVAL, loc };
6346
- if (!expr.questionDotToken) {
6347
- const declared = lowerer.mapTypeOf(lowerer.typeOf(expr));
6348
- if (declared &&
6349
- (declared.kind === "f64" ||
6350
- declared.kind === "bool" ||
6351
- declared.kind === "string" ||
6352
- (declared.kind === "bytes" && declared.elem === "u8"))) {
6353
- return { kind: "jsExit", value: read, type: declared, loc };
6354
- }
6355
- }
6356
- return read;
6357
- }
6358
5845
  /** `r[k]` over a (non-tuple) record shape. A LITERAL key naming a declared
6359
5846
  * field is the bracket spelling of field access (the ONLY spelling tsc
6360
5847
  * permits for signature-declared fields under
@@ -7108,39 +6595,6 @@ export function lowerElementWrite(lowerer, expr) {
7108
6595
  if (receiver?.type.kind === "array")
7109
6596
  receiverIr = receiver.type;
7110
6597
  }
7111
- if (receiverIr?.kind === "jsval") {
7112
- const obj = lowerer.lowerExpr(target.expression);
7113
- // Dispatch follows the RUNTIME world (383(d)): a checker-'any'
7114
- // receiver whose value LOWERED checked-dynamic takes the dyn keyed
7115
- // write — the routed JSVAL arm lands it on the real engine object.
7116
- if (obj.type.kind === "dyn") {
7117
- const loc = locOf(expr);
7118
- const rawKey = lowerer.lowerExpr(target.argumentExpression);
7119
- const key = rawKey.type.kind === "f64" || rawKey.type.kind === "bool" || rawKey.type.kind === "dyn"
7120
- ? { kind: "toString", operand: rawKey, type: STRING, loc: rawKey.loc }
7121
- : rawKey;
7122
- if (key.type.kind !== "string") {
7123
- lowerer.unsupported("SC1090", target.argumentExpression, `'${lowerer.fmt(key.type)}'-typed keys in keyed writes through 'unknown' values`);
7124
- }
7125
- const value = lowerer.coerceToExpected(lowerer.lowerExpr(expr.right), DYN);
7126
- if (value.type.kind !== "dyn") {
7127
- lowerer.unsupported("SC1100", expr.right, `assigning '${lowerer.fmt(value.type)}' values through 'unknown' receivers`);
7128
- }
7129
- return {
7130
- kind: "exprStmt",
7131
- expr: { kind: "libCall", fn: "dyn.keySet", args: [obj, key, value], type: VOID, loc },
7132
- loc,
7133
- };
7134
- }
7135
- const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
7136
- const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
7137
- const loc = locOf(expr);
7138
- return {
7139
- kind: "exprStmt",
7140
- expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc },
7141
- loc,
7142
- };
7143
- }
7144
6598
  // A checked-dynamic receiver TYPE (`unknown[]` and the collapsed
7145
6599
  // `(string | object)[]` map to DYN wholesale now): the dyn keyed
7146
6600
  // write — dyn.keySet. Number keys canonicalize through the JS-exact
@@ -7194,18 +6648,6 @@ export function lowerElementWrite(lowerer, expr) {
7194
6648
  // the runtime coerces JS-exactly; invalid indices are ignored.
7195
6649
  if (receiverIr?.kind === "bytes") {
7196
6650
  const recv = lowerer.lowerExpr(target.expression);
7197
- // The write twin: a typed-array .d.ts surface whose VALUE is a
7198
- // handle takes the engine keyed write.
7199
- if (recv.type.kind === "jsval") {
7200
- const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
7201
- const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
7202
- const loc = locOf(expr);
7203
- return {
7204
- kind: "exprStmt",
7205
- expr: { kind: "jsOp", op: "setIdx", args: [recv, key, value], type: VOID, loc },
7206
- loc,
7207
- };
7208
- }
7209
6651
  const index = lowerer.lowerExpr(target.argumentExpression);
7210
6652
  if (index.type.kind === "dyn" && recv.type.kind === "bytes") {
7211
6653
  return {
@@ -7224,24 +6666,11 @@ export function lowerElementWrite(lowerer, expr) {
7224
6666
  // — literal indices only, like the read.
7225
6667
  if (receiverIr?.kind === "record") {
7226
6668
  const shape = lowerer.shapes.get(receiverIr.shapeId);
7227
- // A record/tuple-typed .d.ts surface whose VALUE is an island
7228
- // handle: the engine keyed write (the read dispatch's twin), never
7229
- // a recordSet/recordKeySet over a jsval.
7230
6669
  if (shape) {
7231
6670
  const obj = lowerer.lowerExpr(target.expression);
7232
6671
  if (hasClassPayload(lowerer, obj.type)) {
7233
6672
  lowerer.unsupported("SC1090", target, "computed property writes through structural views of class instances (use a declared literal key)");
7234
6673
  }
7235
- if (obj.type.kind === "jsval") {
7236
- const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
7237
- const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
7238
- const loc = locOf(expr);
7239
- return {
7240
- kind: "exprStmt",
7241
- expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc },
7242
- loc,
7243
- };
7244
- }
7245
6674
  // A record-mapped CHECKER type over a VALUE living in the checked-dynamic tree (a
7246
6675
  // JS file-scope object-literal global): the checked-dynamic keyed
7247
6676
  // write — dyn.keySet (later writes win, insertion order; Node's
@@ -7406,9 +6835,8 @@ export function lowerElementWrite(lowerer, expr) {
7406
6835
  // arm above — later writes win in insertion order, number keys
7407
6836
  // canonicalize through the JS-exact formatter (ToPropertyKey's string
7408
6837
  // side), index keys on dyn arrays set/extend elements, and non-object
7409
- // receivers throw Node's TypeErrors at runtime. An UNMAPPED checker
7410
- // type (static `any` — mapTypeOf answers null without --dynamic)
7411
- // probes the receiver's own lowered world: a dyn value takes the same
6838
+ // receivers throw Node's TypeErrors at runtime. An unmapped checker type
6839
+ // probes the receiver's lowered representation: a dyn value takes the same
7412
6840
  // write, anything else falls through to the fences.
7413
6841
  if (receiverIr?.kind === "dyn" || receiverIr?.kind === "object" || receiverIr === null) {
7414
6842
  const obj = receiverIr !== null
@@ -7448,19 +6876,6 @@ export function lowerElementWrite(lowerer, expr) {
7448
6876
  lowerer.unsupported("SC1090", target, "assignment to non-array elements");
7449
6877
  }
7450
6878
  let arr = lowerer.lowerExpr(target.expression);
7451
- // The write twin of the island element read: an array-typed .d.ts
7452
- // surface whose VALUE is a handle takes the engine keyed write, never
7453
- // a static arraySet over a jsval.
7454
- if (arr.type.kind === "jsval") {
7455
- const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
7456
- const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
7457
- const loc = locOf(expr);
7458
- return {
7459
- kind: "exprStmt",
7460
- expr: { kind: "jsOp", op: "setIdx", args: [arr, key, value], type: VOID, loc },
7461
- loc,
7462
- };
7463
- }
7464
6879
  if (arr.type.kind === "union" &&
7465
6880
  lowerer.armTag(arr.type.unionId, UNDEFINED_T) >= 0 &&
7466
6881
  receiverIr.kind === "array") {
@@ -7548,10 +6963,6 @@ export function ensureString(lowerer, e, node) {
7548
6963
  const boxed = { kind: "dynFrom", value: e, type: DYN, loc: e.loc };
7549
6964
  return { kind: "toString", operand: boxed, type: STRING, loc: e.loc };
7550
6965
  }
7551
- if (e.type.kind === "jsval") {
7552
- // String(v) in the engine — JS-exact (and Node-exact in templates).
7553
- return { kind: "jsOp", op: "toStr", args: [e], type: STRING, loc: e.loc };
7554
- }
7555
6966
  if (e.type.kind === "object") {
7556
6967
  // String(err) / `${err}` uses the same dispatch as err.toString().
7557
6968
  for (let c = lowerer.classes.get(e.type.className) ?? null; c; c = c.base) {
@@ -7793,12 +7204,8 @@ export function lowerAsExpression(lowerer, expr) {
7793
7204
  const use = runtimeOptionalUseOf(expr);
7794
7205
  if (inner.type.kind === "union" && runtimeOptionalAssertionErases(lowerer, expr, inner, use))
7795
7206
  return inner;
7796
- if (inner.type.kind !== "dyn" && inner.type.kind !== "jsval") {
7797
- // A STATIC value cast `as any` is the explicit island entrance.
7207
+ if (inner.type.kind !== "dyn") {
7798
7208
  const targetTs0 = lowerer.checker.getTypeFromTypeNode(expr.type);
7799
- if (targetTs0.flags & ts.TypeFlags.Any && lowerer.dynamic) {
7800
- return lowerer.jsvalIn(inner, expr.expression);
7801
- }
7802
7209
  const target = lowerer.mapTypeOf(targetTs0);
7803
7210
  if (target?.kind === "object") {
7804
7211
  const asserted = checkedClassAssertion(lowerer, inner, target, locOf(expr));
@@ -7876,25 +7283,6 @@ export function lowerAsExpression(lowerer, expr) {
7876
7283
  }
7877
7284
  return inner; // erasure, unchanged
7878
7285
  }
7879
- if (inner.type.kind === "jsval") {
7880
- // The island exit. `as any` on an island value is erasure; a static
7881
- // target compiles to a VALIDATED extraction (strict primitives; the
7882
- // JSON round-trip + dynCheck walker for composites) that throws a
7883
- // catchable TypeError on mismatch — same trust-but-verify rule as
7884
- // the dyn boundary. Targets with no extraction are rejected.
7885
- const targetTs = lowerer.checker.getTypeFromTypeNode(expr.type);
7886
- if (targetTs.flags & ts.TypeFlags.Any)
7887
- return inner;
7888
- const target = lowerer.mapTypeOf(targetTs);
7889
- if (!target)
7890
- lowerer.badType(expr.type, targetTs);
7891
- if (!lowerer.boundarySafe(target)) {
7892
- lowerer.unsupported("SC1090", expr, `a checked cast of 'any' to '${lowerer.fmt(target)}' ` +
7893
- `(an 'any' value can only be validated against JSON-representable types: ` +
7894
- `number, string, boolean, records, arrays, and unions of those)`);
7895
- }
7896
- return { kind: "jsExit", value: inner, type: target, loc: locOf(expr) };
7897
- }
7898
7286
  const targetTs = lowerer.checker.getTypeFromTypeNode(expr.type);
7899
7287
  const target = lowerer.mapTypeOf(targetTs) ?? dynFallbackType(lowerer, expr.type, targetTs);
7900
7288
  if (!target)
@@ -7963,9 +7351,6 @@ export function lowerPrefixUnary(lowerer, expr) {
7963
7351
  switch (expr.operator) {
7964
7352
  case ts.SyntaxKind.MinusToken: {
7965
7353
  const raw = lowerer.lowerExpr(expr.operand);
7966
- if (raw.type.kind === "jsval") {
7967
- return { kind: "jsOp", op: "neg", args: [raw], type: JSVAL, loc };
7968
- }
7969
7354
  if (raw.type.kind === "bigint") {
7970
7355
  return { kind: "libCall", fn: "bigint.neg", args: [raw], type: BIGINT_T, loc };
7971
7356
  }
@@ -7987,9 +7372,6 @@ export function lowerPrefixUnary(lowerer, expr) {
7987
7372
  // Unary + is ToNumber; on an already-number operand it's identity,
7988
7373
  // and a STRING operand runs the runtime's ECMA-exact StringToNumber
7989
7374
  // (num.fromString — Number(aString)'s lowering, scr_string.c).
7990
- if (raw.type.kind === "jsval") {
7991
- return { kind: "jsOp", op: "plus", args: [raw], type: JSVAL, loc };
7992
- }
7993
7375
  if (raw.type.kind === "string") {
7994
7376
  return { kind: "libCall", fn: "num.fromString", args: [raw], type: F64, loc };
7995
7377
  }
@@ -8281,38 +7663,6 @@ function seqExprSafeStmt(s) {
8281
7663
  return false;
8282
7664
  }
8283
7665
  }
8284
- /** Run one supported `any` binary operation in the island. Checked-dynamic
8285
- * operands marshal in only after lowerBinary's identity-preserving native
8286
- * cases have had their chance (notably dyn strict equality). */
8287
- function lowerAnyBinaryInIsland(lowerer, expr, left, right, loc) {
8288
- const op = expr.operatorToken.kind;
8289
- const JS_BIN = {
8290
- [ts.SyntaxKind.PlusToken]: "add",
8291
- [ts.SyntaxKind.MinusToken]: "sub",
8292
- [ts.SyntaxKind.AsteriskToken]: "mul",
8293
- [ts.SyntaxKind.SlashToken]: "div",
8294
- [ts.SyntaxKind.PercentToken]: "mod",
8295
- [ts.SyntaxKind.AsteriskAsteriskToken]: "pow",
8296
- [ts.SyntaxKind.LessThanToken]: "lt",
8297
- [ts.SyntaxKind.LessThanEqualsToken]: "le",
8298
- [ts.SyntaxKind.GreaterThanToken]: "gt",
8299
- [ts.SyntaxKind.GreaterThanEqualsToken]: "ge",
8300
- [ts.SyntaxKind.EqualsEqualsEqualsToken]: "eq",
8301
- [ts.SyntaxKind.ExclamationEqualsEqualsToken]: "neq",
8302
- };
8303
- const jop = JS_BIN[op];
8304
- if (jop === undefined) {
8305
- lowerer.unsupported("SC1090", expr, `operator '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}' on 'any' values`);
8306
- }
8307
- const type = jsOpResultKind(jop) === "bool" ? BOOL : JSVAL;
8308
- return {
8309
- kind: "jsOp",
8310
- op: jop,
8311
- args: [lowerer.jsvalIn(left, expr.left), lowerer.jsvalIn(right, expr.right)],
8312
- type,
8313
- loc,
8314
- };
8315
- }
8316
7666
  export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
8317
7667
  const loc = locOf(expr);
8318
7668
  const read = {
@@ -8324,27 +7674,6 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
8324
7674
  const rhs = lowerer.lowerExpr(expr.right);
8325
7675
  const numericRead = lowerOptionalNumber(lowerer, read, loc);
8326
7676
  const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
8327
- if (target.type.kind === "jsval" || rhs.type.kind === "jsval") {
8328
- const JS_COMPOUND = {
8329
- "+": "add",
8330
- "-": "sub",
8331
- "*": "mul",
8332
- "/": "div",
8333
- "%": "mod",
8334
- "**": "pow",
8335
- };
8336
- const jop = JS_COMPOUND[compound];
8337
- if (jop === undefined)
8338
- lowerer.unsupported("SC1043", expr);
8339
- const wrapped = {
8340
- kind: "jsOp",
8341
- op: jop,
8342
- args: [lowerer.jsvalIn(read, expr.left), lowerer.jsvalIn(rhs, expr.right)],
8343
- type: JSVAL,
8344
- loc,
8345
- };
8346
- return lowerer.coerceInto(expr, wrapped, target.type);
8347
- }
8348
7677
  if (compound === "+" &&
8349
7678
  (target.type.kind === "string" ||
8350
7679
  (target.type.kind === "union" &&
@@ -8622,49 +7951,6 @@ export function lowerBinary(lowerer, expr) {
8622
7951
  };
8623
7952
  }
8624
7953
  }
8625
- // `h.k = v` on an ISLAND receiver in VALUE position: the engine
8626
- // property write (setProp throws the engine's TypeErrors on
8627
- // nullish receivers, bridged catchably), the RHS value threaded
8628
- // through as the expression's value.
8629
- if (ts.isPropertyAccessExpression(expr.left) &&
8630
- !expr.left.questionDotToken &&
8631
- lowerer.isIslandExpr(expr.left.expression)) {
8632
- const recv = lowerer.lowerExpr(expr.left.expression);
8633
- const recvTmp = lowerer.declareHiddenLocal("%setRecv", recv.type);
8634
- const rhsVal = lowerer.lowerExpr(expr.right);
8635
- const valTmp = lowerer.declareHiddenLocal("%setVal", rhsVal.type);
8636
- const valRef = () => ({
8637
- kind: "varRef",
8638
- localId: valTmp.id,
8639
- type: rhsVal.type,
8640
- loc,
8641
- });
8642
- return {
8643
- kind: "seqExpr",
8644
- stmts: [
8645
- { kind: "varDecl", localId: recvTmp.id, init: recv, loc },
8646
- { kind: "varDecl", localId: valTmp.id, init: rhsVal, loc },
8647
- {
8648
- kind: "exprStmt",
8649
- expr: {
8650
- kind: "jsOp",
8651
- op: "setProp",
8652
- name: expr.left.name.text,
8653
- args: [
8654
- { kind: "varRef", localId: recvTmp.id, type: recv.type, loc },
8655
- lowerer.jsvalIn(valRef(), expr.right),
8656
- ],
8657
- type: VOID,
8658
- loc,
8659
- },
8660
- loc,
8661
- },
8662
- ],
8663
- result: valRef(),
8664
- type: rhsVal.type,
8665
- loc,
8666
- };
8667
- }
8668
7954
  // `h.k = v` on a CHECKED-DYNAMIC receiver in VALUE position
8669
7955
  // (`var _ = module.exports = foo`): receiver first, then RHS
8670
7956
  // (JS's reference-before-value order), the keyed write, and the
@@ -8980,34 +8266,20 @@ export function lowerBinary(lowerer, expr) {
8980
8266
  }
8981
8267
  }
8982
8268
  }
8983
- // `any`-origin operands (tsc rejects these operator forms on real
8984
- // `unknown`, so in a checker-clean TS program only `any` reaches
8985
- // here): JS's full coercion semantics (ToPrimitive, NaN, string +)
8986
- // live in the engine — the dynamic-family fence, so the island
8987
- // retry lifts the site. Genuine unknown keeps the SC1100 story.
8269
+ // Unsupported `any`-origin operations get their specific diagnostic;
8270
+ // unknown retains the narrowing diagnostic below.
8988
8271
  if ((left.type.kind === "dyn" && lowerer.anyOrigin(expr.left)) ||
8989
8272
  (right.type.kind === "dyn" && lowerer.anyOrigin(expr.right))) {
8990
8273
  // `JSON.parse` and other checked-dynamic producers deliberately
8991
8274
  // remain dyn when assigned to an `any` local: eagerly converting
8992
8275
  // the binding would deep-copy its data and sever aliases. At an
8993
- // operator the dynamic build can cross only the operands and let
8994
- // the engine apply JS's exact coercion semantics. Static builds
8995
- // retain the SC2011 promise that --dynamic lifts this site.
8996
- if (lowerer.dynamic)
8997
- return lowerAnyBinaryInIsland(lowerer, expr, left, right, loc);
8276
+ // unsupported operator, require an explicit represented type.
8998
8277
  lowerer.anyOpFence(`the '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}' operator`, expr);
8999
8278
  }
9000
8279
  // tsc allows ===/!== on unknown (arithmetic/comparisons it rejects
9001
8280
  // itself); a dynamic equality would need a dyn walk — validate first.
9002
8281
  lowerer.unsupported("SC1100", expr, "operators on 'unknown' values");
9003
8282
  }
9004
- // Operators over 'any' execute in the island with JS-exact semantics
9005
- // (ToPrimitive, NaN, string +): both operands marshal in, the engine
9006
- // computes. Comparisons come back as static bools; arithmetic stays
9007
- // an island value ('1 as any + "x"' is a string over there).
9008
- if (left.type.kind === "jsval" || right.type.kind === "jsval") {
9009
- return lowerAnyBinaryInIsland(lowerer, expr, left, right, loc);
9010
- }
9011
8283
  if (left.type.kind === "bigint" && right.type.kind === "bigint") {
9012
8284
  const binary = {
9013
8285
  [ts.SyntaxKind.PlusToken]: "bigint.add",
@@ -9705,16 +8977,6 @@ function lowerLogicalPair(lowerer, expr, left) {
9705
8977
  loc,
9706
8978
  };
9707
8979
  }
9708
- if (left.type.kind === "jsval" || right.type.kind === "jsval") {
9709
- return {
9710
- kind: "logical",
9711
- op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
9712
- left: lowerer.jsvalIn(left, expr.left),
9713
- right: lowerer.jsvalIn(right, expr.right),
9714
- type: JSVAL,
9715
- loc,
9716
- };
9717
- }
9718
8980
  if (isJsSourceFile(expr.getSourceFile()) &&
9719
8981
  op === ts.SyntaxKind.AmpersandAmpersandToken &&
9720
8982
  left.type.kind === "union" &&
@@ -9765,10 +9027,7 @@ function lowerLogicalPair(lowerer, expr, left) {
9765
9027
  left.type.kind === "union") {
9766
9028
  const leftArms = lowerer.unions.get(left.type.unionId)?.arms;
9767
9029
  const rightArms = right.type.kind === "union" ? lowerer.unions.get(right.type.unionId)?.arms : [right.type];
9768
- const rightIsStatic = rightArms?.every((arm) => arm.kind !== "dyn" &&
9769
- arm.kind !== "caught" &&
9770
- arm.kind !== "jsval" &&
9771
- arm.kind !== "void") ?? false;
9030
+ const rightIsStatic = rightArms?.every((arm) => arm.kind !== "dyn" && arm.kind !== "caught" && arm.kind !== "void") ?? false;
9772
9031
  if (leftArms &&
9773
9032
  rightArms &&
9774
9033
  rightIsStatic &&
@@ -10105,12 +9364,6 @@ export function lowerCaughtTypeofTest(lowerer, expr, loc) {
10105
9364
  }
10106
9365
  return null;
10107
9366
  }
10108
- /** The static `typeof` answer for a union ARM's IR type, or null when the
10109
- * arm has no fixed answer. Unit arms are known (`typeof undefined` is
10110
- * "undefined", `typeof null` is "object" — JS's oldest wart, preserved
10111
- * exactly); every ref kind is a JS object ("object"), func arms would be
10112
- * "function" (unions never carry them — defensive), and the jsval/dyn/
10113
- * caught/void/union kinds cannot appear as arms. */
10114
9367
  function typeofAnswer(arm) {
10115
9368
  switch (arm.kind) {
10116
9369
  case "f64":
@@ -10675,22 +9928,7 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10675
9928
  const sockTest = lowerSocketInstanceOf(lowerer, expr, loc);
10676
9929
  if (sockTest !== null)
10677
9930
  return sockTest;
10678
- // An ISLAND class as the RHS (`v instanceof Boom` on a package-
10679
- // exported class — the safeParse-style error narrowing): the spec's
10680
- // InstanceofOperator runs in the engine (Symbol.hasInstance included;
10681
- // a non-object RHS throws the engine's own TypeError, catchably).
10682
- // The LHS marshals in — island handles pass through, static
10683
- // primitives answer false exactly like the spec's non-object rule,
10684
- // and unmarshalable statics (class instances, catch bindings — the
10685
- // payload is a name/message snapshot, never the engine object) keep
10686
- // jsvalIn's honest fences.
10687
- if (lowerer.isIslandExpr(expr.right) && !lowerer.caughtLocalOf(expr.left)) {
10688
- const left = lowerer.jsvalIn(lowerer.lowerExpr(expr.left), expr.left);
10689
- const right = lowerer.lowerExpr(expr.right);
10690
- return { kind: "jsOp", op: "instanceOf", args: [left, right], type: BOOL, loc };
10691
- }
10692
- if (!lowerer.dynamic &&
10693
- (lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map"))) {
9931
+ if (lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map")) {
10694
9932
  const collection = lowerer.isStdlibGlobal(expr.right, "Map") ? "map" : "set";
10695
9933
  const value = lowerer.lowerExpr(expr.left);
10696
9934
  if (value.type.kind === "union") {
@@ -10751,18 +9989,6 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10751
9989
  }
10752
9990
  if (lowerer.isStdlibGlobal(expr.right, "WeakMap") ||
10753
9991
  lowerer.isStdlibGlobal(expr.right, "WeakSet")) {
10754
- if (lowerer.dynamic) {
10755
- const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.left), expr.left);
10756
- const ctor = {
10757
- kind: "jsOp",
10758
- op: "globalGet",
10759
- name: lowerer.isStdlibGlobal(expr.right, "WeakMap") ? "WeakMap" : "WeakSet",
10760
- args: [],
10761
- type: JSVAL,
10762
- loc,
10763
- };
10764
- return { kind: "jsOp", op: "instanceOf", args: [value, ctor], type: BOOL, loc };
10765
- }
10766
9992
  const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
10767
9993
  return {
10768
9994
  kind: "libCall",
@@ -12619,12 +11845,11 @@ function lowerUnionKeyedRead(lowerer, expr, unionId, value, key, literalField) {
12619
11845
  }
12620
11846
  if (joinArms.length === 0)
12621
11847
  return null;
12622
- // The join must be a BUILDABLE union: arm kinds the union invariants
12623
- // admit (no dyn/jsval/generator arms; containers only beside unit
12624
- // siblings). The caller owns the diagnostic for a refused join.
11848
+ // The join must satisfy native union invariants. The caller owns the
11849
+ // diagnostic when a container or opaque arm prevents that join.
12625
11850
  if (joinArms.length > 1 &&
12626
11851
  (!unionContainerArmsOk(joinArms) ||
12627
- joinArms.some((a) => a.kind === "dyn" || a.kind === "jsval" || a.kind === "generator" || a.kind === "caught"))) {
11852
+ joinArms.some((a) => a.kind === "dyn" || a.kind === "generator" || a.kind === "caught"))) {
12628
11853
  return null;
12629
11854
  }
12630
11855
  joinArms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));