@scriptc/compiler 0.2.1 → 0.2.3

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 (315) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +158 -31
  2. package/dist/backend/cycle-analysis.js +63 -50
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/cycle-analysis.test.js +51 -0
  5. package/dist/backend/cycle-analysis.test.js.map +1 -1
  6. package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
  7. package/dist/backend/llvm/borrowed-receivers.js +58 -0
  8. package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
  9. package/dist/backend/llvm/call-lifetimes.d.ts +20 -0
  10. package/dist/backend/llvm/call-lifetimes.js +179 -0
  11. package/dist/backend/llvm/call-lifetimes.js.map +1 -0
  12. package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
  13. package/dist/backend/llvm/call-lifetimes.test.js +205 -0
  14. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
  15. package/dist/backend/llvm/dyn.d.ts +5 -2
  16. package/dist/backend/llvm/dyn.js +163 -47
  17. package/dist/backend/llvm/dyn.js.map +1 -1
  18. package/dist/backend/llvm/emitter.d.ts +37 -1
  19. package/dist/backend/llvm/emitter.js +209 -21
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/emitter.test.js +29 -2
  22. package/dist/backend/llvm/emitter.test.js.map +1 -1
  23. package/dist/backend/llvm/expr-async.js +1 -1
  24. package/dist/backend/llvm/expr-async.js.map +1 -1
  25. package/dist/backend/llvm/expr-calls.js +42 -5
  26. package/dist/backend/llvm/expr-calls.js.map +1 -1
  27. package/dist/backend/llvm/expr-containers.js +75 -13
  28. package/dist/backend/llvm/expr-containers.js.map +1 -1
  29. package/dist/backend/llvm/expr-dynamic.js +31 -6
  30. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  31. package/dist/backend/llvm/expr-primitives.js +6 -5
  32. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  33. package/dist/backend/llvm/expr-records.js +1 -1
  34. package/dist/backend/llvm/expr-records.js.map +1 -1
  35. package/dist/backend/llvm/expr-stream-bridges.js +75 -19
  36. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  37. package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
  38. package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
  39. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  40. package/dist/backend/llvm/lib-dispatch.js +41 -3
  41. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  42. package/dist/backend/llvm/lib-filesystem.js +12 -9
  43. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  44. package/dist/backend/llvm/lib-shared.js +70 -2
  45. package/dist/backend/llvm/lib-shared.js.map +1 -1
  46. package/dist/backend/llvm/local-array-reads.d.ts +44 -0
  47. package/dist/backend/llvm/local-array-reads.js +313 -0
  48. package/dist/backend/llvm/local-array-reads.js.map +1 -0
  49. package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
  50. package/dist/backend/llvm/local-array-reads.test.js +446 -0
  51. package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
  52. package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
  53. package/dist/backend/llvm/map-read-lifetimes.js +128 -0
  54. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
  55. package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
  56. package/dist/backend/llvm/map-read-lifetimes.test.js +123 -0
  57. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
  58. package/dist/backend/llvm/shapes.js +1 -0
  59. package/dist/backend/llvm/shapes.js.map +1 -1
  60. package/dist/backend/llvm/split.js +15 -5
  61. package/dist/backend/llvm/split.js.map +1 -1
  62. package/dist/backend/llvm/split.test.js +17 -0
  63. package/dist/backend/llvm/split.test.js.map +1 -1
  64. package/dist/backend/llvm/stack-unions.d.ts +20 -0
  65. package/dist/backend/llvm/stack-unions.js +61 -0
  66. package/dist/backend/llvm/stack-unions.js.map +1 -0
  67. package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
  68. package/dist/backend/llvm/stack-unions.test.js +241 -0
  69. package/dist/backend/llvm/stack-unions.test.js.map +1 -0
  70. package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
  71. package/dist/backend/llvm/string-lifetimes.js +70 -0
  72. package/dist/backend/llvm/string-lifetimes.js.map +1 -0
  73. package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
  74. package/dist/backend/llvm/string-lifetimes.test.js +230 -0
  75. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
  76. package/dist/backend/mangle.d.ts +2 -0
  77. package/dist/backend/mangle.js +4 -0
  78. package/dist/backend/mangle.js.map +1 -1
  79. package/dist/backend/may-throw.js +71 -29
  80. package/dist/backend/may-throw.js.map +1 -1
  81. package/dist/backend/may-throw.test.js +104 -1
  82. package/dist/backend/may-throw.test.js.map +1 -1
  83. package/dist/backend/native-codegen.d.ts +1 -1
  84. package/dist/backend/native-codegen.js +4 -3
  85. package/dist/backend/native-codegen.js.map +1 -1
  86. package/dist/backend/native-codegen.test.js +11 -0
  87. package/dist/backend/native-codegen.test.js.map +1 -1
  88. package/dist/backend/native-toolchain.d.ts +2 -2
  89. package/dist/backend/native-toolchain.js +2 -0
  90. package/dist/backend/native-toolchain.js.map +1 -1
  91. package/dist/backend/target-diagnostics.d.ts +5 -0
  92. package/dist/backend/target-diagnostics.js +72 -1
  93. package/dist/backend/target-diagnostics.js.map +1 -1
  94. package/dist/backend/target-diagnostics.test.d.ts +1 -0
  95. package/dist/backend/target-diagnostics.test.js +68 -0
  96. package/dist/backend/target-diagnostics.test.js.map +1 -0
  97. package/dist/coverage/surface-manifest.js +5 -3
  98. package/dist/coverage/surface-manifest.js.map +1 -1
  99. package/dist/executable/executable-cache.d.ts +7 -3
  100. package/dist/executable/executable-cache.js +47 -11
  101. package/dist/executable/executable-cache.js.map +1 -1
  102. package/dist/executable/executable-cache.test.js +109 -2
  103. package/dist/executable/executable-cache.test.js.map +1 -1
  104. package/dist/executable/prepare.js +2 -1
  105. package/dist/executable/prepare.js.map +1 -1
  106. package/dist/frontend/builtin-modules.d.ts +1 -1
  107. package/dist/frontend/builtin-modules.js +1 -1
  108. package/dist/frontend/builtin-modules.js.map +1 -1
  109. package/dist/frontend/function-completion.d.ts +6 -0
  110. package/dist/frontend/function-completion.js +50 -0
  111. package/dist/frontend/function-completion.js.map +1 -0
  112. package/dist/frontend/input-tracker.js +3 -3
  113. package/dist/frontend/input-tracker.js.map +1 -1
  114. package/dist/frontend/input-tracker.test.js +38 -2
  115. package/dist/frontend/input-tracker.test.js.map +1 -1
  116. package/dist/frontend/lowering/abstract-equality.js +5 -1
  117. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  118. package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
  119. package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
  120. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
  121. package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
  122. package/dist/frontend/lowering/checked-promise-all.js +31 -0
  123. package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
  124. package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
  125. package/dist/frontend/lowering/class-callbacks.js +7 -6
  126. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  127. package/dist/frontend/lowering/class-construction.d.ts +2 -0
  128. package/dist/frontend/lowering/class-construction.js +34 -5
  129. package/dist/frontend/lowering/class-construction.js.map +1 -1
  130. package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
  131. package/dist/frontend/lowering/class-descriptors.js +12 -5
  132. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  133. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
  134. package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
  135. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  136. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
  137. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  138. package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
  139. package/dist/frontend/lowering/class-instance-constructor.js +11 -41
  140. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  141. package/dist/frontend/lowering/class-method-values.d.ts +16 -0
  142. package/dist/frontend/lowering/class-method-values.js +60 -29
  143. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  144. package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
  145. package/dist/frontend/lowering/class-prototypes.js +69 -10
  146. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  147. package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
  148. package/dist/frontend/lowering/class-runtime-statics.js +26 -8
  149. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
  150. package/dist/frontend/lowering/class-static-data.d.ts +1 -0
  151. package/dist/frontend/lowering/class-static-data.js +4 -2
  152. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  153. package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
  154. package/dist/frontend/lowering/collection-ingestion.js +215 -0
  155. package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
  156. package/dist/frontend/lowering/containers/bytes.js +19 -4
  157. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  158. package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
  159. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  160. package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
  161. package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
  162. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
  163. package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
  164. package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
  165. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
  166. package/dist/frontend/lowering/expressions/object-literals.js +31 -1
  167. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  168. package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
  169. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  170. package/dist/frontend/lowering/import-meta.d.ts +10 -0
  171. package/dist/frontend/lowering/import-meta.js +52 -0
  172. package/dist/frontend/lowering/import-meta.js.map +1 -0
  173. package/dist/frontend/lowering/lower-assert.js +105 -41
  174. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  175. package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
  176. package/dist/frontend/lowering/lower-builtin-values.js +22 -1
  177. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  178. package/dist/frontend/lowering/lower-builtins.d.ts +7 -22
  179. package/dist/frontend/lowering/lower-builtins.js +439 -95
  180. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  181. package/dist/frontend/lowering/lower-calls.js +289 -76
  182. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  183. package/dist/frontend/lowering/lower-classes.d.ts +5 -0
  184. package/dist/frontend/lowering/lower-classes.js +443 -29
  185. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  186. package/dist/frontend/lowering/lower-containers.d.ts +6 -2
  187. package/dist/frontend/lowering/lower-containers.js +79 -20
  188. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  189. package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
  190. package/dist/frontend/lowering/lower-exprs.js +329 -170
  191. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  192. package/dist/frontend/lowering/lower-generators.js +5 -1
  193. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  194. package/dist/frontend/lowering/lower-inspect.js +58 -1
  195. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  196. package/dist/frontend/lowering/lower-island.js +4 -0
  197. package/dist/frontend/lowering/lower-island.js.map +1 -1
  198. package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
  199. package/dist/frontend/lowering/lower-island.test.js +51 -0
  200. package/dist/frontend/lowering/lower-island.test.js.map +1 -0
  201. package/dist/frontend/lowering/lower-modules.d.ts +1 -3
  202. package/dist/frontend/lowering/lower-modules.js +186 -82
  203. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  204. package/dist/frontend/lowering/lower-modules.test.js +69 -1
  205. package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
  206. package/dist/frontend/lowering/lower-stmts.js +172 -103
  207. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  208. package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
  209. package/dist/frontend/lowering/lower-stmts.test.js +77 -0
  210. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
  211. package/dist/frontend/lowering/lower-stream.js +2 -0
  212. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  213. package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
  214. package/dist/frontend/lowering/lower-system-errors.js +29 -0
  215. package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
  216. package/dist/frontend/lowering/lower-url.d.ts +2 -1
  217. package/dist/frontend/lowering/lower-url.js +32 -9
  218. package/dist/frontend/lowering/lower-url.js.map +1 -1
  219. package/dist/frontend/lowering/lowerer.d.ts +30 -12
  220. package/dist/frontend/lowering/lowerer.js +268 -49
  221. package/dist/frontend/lowering/lowerer.js.map +1 -1
  222. package/dist/frontend/lowering/lowerer.test.js +38 -0
  223. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  224. package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
  225. package/dist/frontend/lowering/module-namespace-elements.js +54 -0
  226. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
  227. package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
  228. package/dist/frontend/lowering/object-factory-new.js +27 -14
  229. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  230. package/dist/frontend/lowering/surfaces.d.ts +3 -2
  231. package/dist/frontend/lowering/surfaces.js +93 -33
  232. package/dist/frontend/lowering/surfaces.js.map +1 -1
  233. package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
  234. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  235. package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
  236. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  237. package/dist/frontend/module-syntax.d.ts +1 -1
  238. package/dist/frontend/module-syntax.js +8 -1
  239. package/dist/frontend/module-syntax.js.map +1 -1
  240. package/dist/frontend/module-syntax.test.js +10 -0
  241. package/dist/frontend/module-syntax.test.js.map +1 -1
  242. package/dist/frontend/npm.d.ts +4 -0
  243. package/dist/frontend/npm.js +86 -33
  244. package/dist/frontend/npm.js.map +1 -1
  245. package/dist/frontend/npm.test.js +103 -0
  246. package/dist/frontend/npm.test.js.map +1 -1
  247. package/dist/frontend/pipeline-native.js +2 -1
  248. package/dist/frontend/pipeline-native.js.map +1 -1
  249. package/dist/frontend/program.js +4 -2
  250. package/dist/frontend/program.js.map +1 -1
  251. package/dist/frontend/services-node.js +3 -2
  252. package/dist/frontend/services-node.js.map +1 -1
  253. package/dist/frontend/services.d.ts +5 -1
  254. package/dist/frontend/services.js +9 -1
  255. package/dist/frontend/services.js.map +1 -1
  256. package/dist/frontend/services.test.js +21 -0
  257. package/dist/frontend/services.test.js.map +1 -1
  258. package/dist/frontend/ts7/ast-node.d.ts +2 -0
  259. package/dist/frontend/ts7/ast-node.js +30 -4
  260. package/dist/frontend/ts7/ast-node.js.map +1 -1
  261. package/dist/frontend/ts7/ast-node.test.js +60 -1
  262. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  263. package/dist/frontend/type-mapper.js +89 -14
  264. package/dist/frontend/type-mapper.js.map +1 -1
  265. package/dist/frontend/union-discriminants.js +22 -7
  266. package/dist/frontend/union-discriminants.js.map +1 -1
  267. package/dist/index.js +19 -12
  268. package/dist/index.js.map +1 -1
  269. package/dist/ir/analysis.js +1 -0
  270. package/dist/ir/analysis.js.map +1 -1
  271. package/dist/ir/integer-loops.d.ts +7 -0
  272. package/dist/ir/integer-loops.js +23 -0
  273. package/dist/ir/integer-loops.js.map +1 -1
  274. package/dist/ir/integer-loops.test.d.ts +1 -0
  275. package/dist/ir/integer-loops.test.js +41 -0
  276. package/dist/ir/integer-loops.test.js.map +1 -0
  277. package/dist/ir/ir.d.ts +44 -26
  278. package/dist/ir/ir.js +69 -11
  279. package/dist/ir/ir.js.map +1 -1
  280. package/dist/ir/ir.test.js +18 -0
  281. package/dist/ir/ir.test.js.map +1 -1
  282. package/dist/ir/serialize.js +21 -1
  283. package/dist/ir/serialize.js.map +1 -1
  284. package/dist/ir/serialize.test.js +21 -0
  285. package/dist/ir/serialize.test.js.map +1 -1
  286. package/dist/ir/traverse.d.ts +0 -3
  287. package/dist/ir/traverse.js +33 -20
  288. package/dist/ir/traverse.js.map +1 -1
  289. package/dist/ir/validate.js +216 -80
  290. package/dist/ir/validate.js.map +1 -1
  291. package/dist/ir/validate.test.js +244 -1
  292. package/dist/ir/validate.test.js.map +1 -1
  293. package/dist/library/compiler-self-identity.js +1 -1
  294. package/dist/library/compiler-self-identity.test.js +2 -2
  295. package/dist/library/compiler-self-identity.test.js.map +1 -1
  296. package/dist/library/fence-eval.js +9 -2
  297. package/dist/library/fence-eval.js.map +1 -1
  298. package/dist/library/fence-eval.test.d.ts +1 -0
  299. package/dist/library/fence-eval.test.js +21 -0
  300. package/dist/library/fence-eval.test.js.map +1 -0
  301. package/dist/library/int-infer.d.ts +2 -2
  302. package/dist/library/int-infer.js +10 -7
  303. package/dist/library/int-infer.js.map +1 -1
  304. package/dist/library/int-infer.test.js +44 -0
  305. package/dist/library/int-infer.test.js.map +1 -1
  306. package/dist/library/prepare.js +2 -1
  307. package/dist/library/prepare.js.map +1 -1
  308. package/dist/native/runtime-typescript.d.ts +4 -0
  309. package/dist/native/runtime-typescript.js +61 -0
  310. package/dist/native/runtime-typescript.js.map +1 -0
  311. package/dist/native/runtime-typescript.test.d.ts +1 -0
  312. package/dist/native/runtime-typescript.test.js +41 -0
  313. package/dist/native/runtime-typescript.test.js.map +1 -0
  314. package/package.json +20 -20
  315. package/surface-manifest.json +385 -29
@@ -1,5 +1,5 @@
1
1
  import { arrayOf, BYTES_ELEMENT_NAME, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, CHILDWRITER_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, ffiClassType, ffiSourceParamTypes, FILEHANDLE_T, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isJsonSafeType, isJsonStringifySafeType, isRefCounted, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, shapeHasAccessorSlots, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey, unionContainerArmsOk, URL_T, VOID } from "./ir.js";
2
- import { BIGINT_T } from "./ir.js";
2
+ import { BIGINT_T, DYN_CLASS_PROPERTIES } from "./ir.js";
3
3
  import { unionWideningTags } from "./analysis.js";
4
4
  import { alwaysReturns } from "./control-flow.js";
5
5
  /** Per-method signature for strIntrinsic: `argTypes` lists every argument
@@ -26,6 +26,7 @@ export const STR_INTRINSIC_SIGS = {
26
26
  padEnd: { argTypes: [F64, STRING], minArgs: 2, result: STRING },
27
27
  toLowerCase: { argTypes: [], minArgs: 0, result: STRING },
28
28
  toUpperCase: { argTypes: [], minArgs: 0, result: STRING },
29
+ normalize: { argTypes: [STRING], minArgs: 1, result: STRING },
29
30
  isWellFormed: { argTypes: [], minArgs: 0, result: BOOL },
30
31
  toWellFormed: { argTypes: [], minArgs: 0, result: STRING },
31
32
  cpAt: { argTypes: [F64], minArgs: 1, result: STRING },
@@ -63,6 +64,10 @@ export const LIB_FN_SIGS = {
63
64
  "fetch.start": { argTypes: [STRING, DYN], result: { kind: "promise", inner: DYN } },
64
65
  "fetch.responseNew": { argTypes: [DYN, DYN], result: DYN },
65
66
  "fetch.input": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
67
+ "abort.controllerNew": { argTypes: [], result: DYN },
68
+ "abort.timeout": { argTypes: [DYN], result: DYN },
69
+ "abort.now": { argTypes: [DYN], result: DYN },
70
+ "abort.any": { argTypes: [DYN], result: DYN },
66
71
  "fetch.function": { argTypes: [], result: DYN },
67
72
  "fetch.requestNew": { argTypes: [DYN, DYN], result: DYN },
68
73
  "fetch.headersNew": { argTypes: [DYN], result: DYN },
@@ -130,6 +135,7 @@ export const LIB_FN_SIGS = {
130
135
  "dyn.defineProperty": { argTypes: [DYN, DYN, DYN], result: DYN },
131
136
  "dyn.getOwnPropertyDescriptor": { argTypes: [DYN, DYN], result: DYN },
132
137
  "dyn.arrayProtoCall": { argTypes: [DYN, STRING, DYN], result: DYN },
138
+ "dyn.promiseAll": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
133
139
  "dyn.typeof": { argTypes: [DYN], result: STRING },
134
140
  "dyn.objectTag": { argTypes: [DYN], result: STRING },
135
141
  "module.registryInit": { argTypes: [F64], result: VOID },
@@ -229,6 +235,7 @@ export const LIB_FN_SIGS = {
229
235
  "os.totalmem": { argTypes: [], result: F64 },
230
236
  "process.umask": { argTypes: [F64], result: F64 },
231
237
  "process.chdir": { argTypes: [STRING], result: VOID },
238
+ "process.loadEnvFile": { argTypes: [DYN], result: VOID },
232
239
  "process.exiting": { argTypes: [], result: BOOL },
233
240
  "net.getAutoSelTimeout": { argTypes: [], result: F64 },
234
241
  "net.setAutoSelTimeout": { argTypes: [F64], result: VOID },
@@ -338,6 +345,10 @@ export const LIB_FN_SIGS = {
338
345
  "bigint.dataViewSet": { argTypes: [BYTES_U8, F64, BIGINT_T, BOOL], result: VOID },
339
346
  "url.new": { argTypes: [STRING], result: URL_T },
340
347
  "url.newBase": { argTypes: [STRING, STRING], result: URL_T },
348
+ "url.canParse": { argTypes: [STRING], result: BOOL },
349
+ "url.canParseBase": { argTypes: [STRING, STRING], result: BOOL },
350
+ "url.parse": { argTypes: [STRING], result: DYN },
351
+ "url.parseBase": { argTypes: [STRING, STRING], result: DYN },
341
352
  "url.protocol": { argTypes: [URL_T], result: STRING },
342
353
  "url.origin": { argTypes: [URL_T], result: STRING },
343
354
  "url.username": { argTypes: [URL_T], result: STRING },
@@ -347,8 +358,13 @@ export const LIB_FN_SIGS = {
347
358
  "url.port": { argTypes: [URL_T], result: STRING },
348
359
  "url.pathname": { argTypes: [URL_T], result: STRING },
349
360
  "url.href": { argTypes: [URL_T], result: STRING },
361
+ "url.set": { argTypes: [URL_T, STRING, STRING], result: VOID },
362
+ "url.setChecked": { argTypes: [URL_T, STRING, DYN], result: VOID },
350
363
  "url.fileURLToPathUrl": { argTypes: [URL_T], result: STRING },
351
364
  "url.fileURLToPathChecked": { argTypes: [DYN], result: STRING },
365
+ "url.fileURLToPathOptions": { argTypes: [DYN, DYN], result: STRING },
366
+ "url.fileURLToPathBuffer": { argTypes: [DYN, DYN], result: BYTES_U8 },
367
+ "url.pathToFileURLChecked": { argTypes: [DYN, DYN], result: URL_T },
352
368
  "url.fileURLToPathStr": { argTypes: [STRING], result: STRING },
353
369
  "url.pathToFileURL": { argTypes: [STRING], result: URL_T },
354
370
  "url.pathToFileURLPlatform": { argTypes: [STRING, BOOL], result: URL_T },
@@ -388,12 +404,34 @@ export const LIB_FN_SIGS = {
388
404
  "qs.escape": { argTypes: [STRING], result: STRING },
389
405
  "qs.unescape": { argTypes: [STRING], result: STRING },
390
406
  "util.parseArgs": { argTypes: [DYN], result: DYN },
407
+ "util.parseEnv": { argTypes: [DYN], result: DYN },
408
+ "util.getSystemErrorName": { argTypes: [DYN], result: STRING },
409
+ "util.getSystemErrorMessage": { argTypes: [DYN], result: STRING },
410
+ "util.systemErrorEntries": { argTypes: [], result: DYN },
411
+ "util.stripVTControlCharacters": { argTypes: [DYN], result: STRING },
412
+ "util.toUSVString": { argTypes: [DYN], result: STRING },
413
+ "util.isDeepStrictEqual": { argTypes: [DYN, DYN, DYN], result: BOOL },
414
+ "util.styleText": { argTypes: [DYN, DYN, DYN], result: STRING },
415
+ "util.typeIs": { argTypes: [DYN, STRING], result: BOOL },
416
+ "util.typeValue": { argTypes: [DYN, STRING], result: DYN },
391
417
  "fs.statSync": { argTypes: [STRING], result: STATS_T },
392
418
  "fs.lstatSync": { argTypes: [STRING], result: STATS_T },
393
419
  "fs.fstatSync": { argTypes: [F64], result: STATS_T },
394
420
  "fs.fchmodSync": { argTypes: [F64, F64], result: VOID },
395
421
  "fs.fsyncSync": { argTypes: [F64], result: VOID },
396
- "fs.linkSync": { argTypes: [STRING, STRING], result: VOID },
422
+ "fs.fdatasyncSync": { argTypes: [F64], result: VOID },
423
+ "fs.ftruncateSync": { argTypes: [F64, F64], result: VOID },
424
+ "fs.utimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
425
+ "fs.futimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
426
+ "fs.lutimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
427
+ "fs.readvSync": { argTypes: [F64, arrayOf(BYTES_U8), F64], result: F64 },
428
+ "fs.writevSync": { argTypes: [F64, arrayOf(BYTES_U8), F64], result: F64 },
429
+ "fs.linkSync": { argTypes: [DYN, DYN], result: VOID },
430
+ "fs.symlinkSync": { argTypes: [DYN, DYN, DYN], result: VOID },
431
+ "fs.readlinkSync": { argTypes: [DYN, DYN], result: DYN },
432
+ "fs.statfsSync": { argTypes: [DYN, DYN], result: DYN },
433
+ "fs.readlinkSyncStr": { argTypes: [DYN, DYN], result: STRING },
434
+ "fs.readlinkSyncBuffer": { argTypes: [DYN, DYN], result: BYTES_U8 },
397
435
  "fs.openSync": { argTypes: [STRING, STRING], result: F64 },
398
436
  "fs.openNumericSync": { argTypes: [STRING, F64, F64], result: F64 },
399
437
  "fs.readSync": { argTypes: [F64, BYTES_U8, F64, F64, F64], result: F64 },
@@ -964,6 +1002,10 @@ export const LIB_FN_SIGS = {
964
1002
  "crypto.pbkdf2": { argTypes: [BYTES_U8, BYTES_U8, F64, F64, STRING], result: BYTES_U8 },
965
1003
  "crypto.randomBytesCb": { argTypes: [F64, null], result: VOID },
966
1004
  "crypto.pbkdf2Cb": { argTypes: [BYTES_U8, BYTES_U8, F64, F64, STRING, null], result: VOID },
1005
+ "crypto.hkdf": { argTypes: [STRING, BYTES_U8, BYTES_U8, BYTES_U8, F64], result: DYN },
1006
+ "crypto.hkdfCb": { argTypes: [STRING, BYTES_U8, BYTES_U8, BYTES_U8, F64, null], result: VOID },
1007
+ "crypto.scrypt": { argTypes: [BYTES_U8, BYTES_U8, F64, DYN], result: BYTES_U8 },
1008
+ "crypto.scryptCb": { argTypes: [BYTES_U8, BYTES_U8, F64, DYN, null], result: VOID },
967
1009
  // The Buffer statics and the fs/zlib Buffer forms: fixed always-u8
968
1010
  // signatures (Buffer IS a Uint8Array — one bytes kind).
969
1011
  "buffer.fromStr": { argTypes: [STRING, STRING], result: BYTES_U8 },
@@ -1031,6 +1073,14 @@ export const LIB_FN_SIGS = {
1031
1073
  "fsp.mkdirRecursiveMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
1032
1074
  "fsp.unlink": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
1033
1075
  "fsp.chmod": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
1076
+ "fsp.link": { argTypes: [DYN, DYN], result: { kind: "promise", inner: VOID } },
1077
+ "fsp.symlink": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
1078
+ "fsp.readlink": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
1079
+ "fsp.statfs": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
1080
+ "fsp.readlinkStr": { argTypes: [DYN, DYN], result: { kind: "promise", inner: STRING } },
1081
+ "fsp.readlinkBuffer": { argTypes: [DYN, DYN], result: { kind: "promise", inner: BYTES_U8 } },
1082
+ "fsp.utimes": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
1083
+ "fsp.lutimes": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
1034
1084
  "fsp.rename": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
1035
1085
  "fsp.readdir": { argTypes: [STRING], result: { kind: "promise", inner: arrayOf(STRING) } },
1036
1086
  // Result is promise<call-site Dirent record array>; the libCall case
@@ -1043,6 +1093,13 @@ export const LIB_FN_SIGS = {
1043
1093
  "fsp.open": { argTypes: [STRING, STRING, F64], result: { kind: "promise", inner: FILEHANDLE_T } },
1044
1094
  "fileHandle.fd": { argTypes: [FILEHANDLE_T], result: F64 },
1045
1095
  "fileHandle.close": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: VOID } },
1096
+ "fileHandle.sync": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: VOID } },
1097
+ "fileHandle.datasync": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: VOID } },
1098
+ "fileHandle.truncate": { argTypes: [FILEHANDLE_T, F64], result: { kind: "promise", inner: VOID } },
1099
+ "fileHandle.chmod": { argTypes: [FILEHANDLE_T, F64], result: { kind: "promise", inner: VOID } },
1100
+ "fileHandle.utimes": { argTypes: [FILEHANDLE_T, DYN, DYN], result: { kind: "promise", inner: VOID } },
1101
+ "fileHandle.readv": { argTypes: [FILEHANDLE_T, arrayOf(BYTES_U8), F64], result: { kind: "promise", inner: VOID } },
1102
+ "fileHandle.writev": { argTypes: [FILEHANDLE_T, arrayOf(BYTES_U8), F64], result: { kind: "promise", inner: VOID } },
1046
1103
  // read/write carry call-site result record shapes; the validator checks
1047
1104
  // those below, so promise<void> is only a table sentinel.
1048
1105
  "fileHandle.read": { argTypes: [FILEHANDLE_T, BYTES_U8, F64, F64, F64, BOOL], result: { kind: "promise", inner: VOID } },
@@ -1180,9 +1237,14 @@ export const LIB_FN_SIGS = {
1180
1237
  "dyn.packPushSpread": { argTypes: [DYN, DYN, STRING], result: VOID },
1181
1238
  "dyn.packPushSpreadIter": { argTypes: [DYN, DYN], result: VOID },
1182
1239
  "dyn.reflectApply": { argTypes: [DYN, DYN, DYN], result: DYN },
1240
+ "dyn.reflectGet": { argTypes: [DYN, DYN, DYN], result: DYN },
1241
+ "dyn.reflectSet": { argTypes: [DYN, DYN, DYN, DYN], result: BOOL },
1242
+ "dyn.reflectDefine": { argTypes: [DYN, DYN, DYN], result: BOOL },
1243
+ "dyn.abstractEq": { argTypes: [DYN, DYN], result: BOOL },
1183
1244
  "dyn.assignAll": { argTypes: [DYN, DYN], result: DYN },
1184
1245
  "dyn.objCreateNullProto": { argTypes: [], result: DYN },
1185
1246
  "dyn.arrayPrototype": { argTypes: [], result: DYN },
1247
+ "dyn.arrayConstructor": { argTypes: [], result: DYN },
1186
1248
  "dyn.objectPrototype": { argTypes: [], result: DYN },
1187
1249
  "dyn.functionApply": { argTypes: [], result: DYN },
1188
1250
  "dyn.builtinMethod": { argTypes: [STRING, STRING], result: DYN },
@@ -1191,6 +1253,9 @@ export const LIB_FN_SIGS = {
1191
1253
  "dyn.classInherit": { argTypes: [DYN, DYN], result: DYN },
1192
1254
  "dyn.classSuper": { argTypes: [DYN, DYN, DYN], result: VOID },
1193
1255
  "dyn.assignPrototype": { argTypes: [DYN, DYN, DYN], result: DYN },
1256
+ "dyn.definePrototypeProps": { argTypes: [DYN, DYN, DYN], result: DYN },
1257
+ "dyn.bagGet": { argTypes: [DYN, STRING, DYN], result: DYN },
1258
+ "dyn.bagSet": { argTypes: [DYN, STRING, DYN, DYN], result: VOID },
1194
1259
  "dyn.objCreate": { argTypes: [DYN], result: DYN },
1195
1260
  "dyn.objCreateWithProperties": { argTypes: [DYN, DYN], result: DYN },
1196
1261
  "dyn.getPrototype": { argTypes: [DYN], result: DYN },
@@ -1356,6 +1421,9 @@ export const LIB_FN_SIGS = {
1356
1421
  "assert.shapeEnd": { argTypes: [STRING, BOOL], result: VOID },
1357
1422
  "assert.regexErrTest": { argTypes: [REGEX, { kind: "object", className: "%Error" }], result: BOOL },
1358
1423
  "assert.unwantedRejection": { argTypes: [{ kind: "object", className: "%Error" }, STRING, BOOL], result: VOID },
1424
+ "assert.unwantedError": { argTypes: [STRING, BOOL, STRING, BOOL], result: VOID },
1425
+ "assert.noErrorPredicate": { argTypes: [DYN, DYN], result: BOOL },
1426
+ "assert.regexDynTest": { argTypes: [REGEX, DYN], result: BOOL },
1359
1427
  "assert.expectsErrDyn": { argTypes: [DYN, DYN, STRING, BOOL], result: VOID },
1360
1428
  // assert.ifError's typed entries (always throw; unit args never
1361
1429
  // lower). The error slot is program-dependent — any %Error-hierarchy
@@ -1485,6 +1553,11 @@ export const LIB_FN_SIGS = {
1485
1553
  "text.decodeLegacyOptions": { argTypes: [BYTES_U8, F64, BOOL, BOOL], result: STRING },
1486
1554
  "text.decodeLegacy": { argTypes: [BYTES_U8, F64], result: STRING },
1487
1555
  "text.decoderEncoding": { argTypes: [DYN], result: F64 },
1556
+ "text.decoderName": { argTypes: [F64], result: STRING },
1557
+ "text.encodeInto": { argTypes: [DYN, DYN], result: DYN },
1558
+ "buffer.isAscii": { argTypes: [DYN], result: BOOL },
1559
+ "buffer.isUtf8": { argTypes: [DYN], result: BOOL },
1560
+ "buffer.transcode": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
1488
1561
  "fs.mkdirRecursiveSync": { argTypes: [STRING], result: VOID },
1489
1562
  "fs.rmOptsSync": { argTypes: [STRING, BOOL, BOOL], result: VOID },
1490
1563
  "fs.rmRetrySync": { argTypes: [STRING, BOOL, BOOL, F64, F64], result: VOID },
@@ -1722,6 +1795,7 @@ export function validateModule(mod) {
1722
1795
  });
1723
1796
  }
1724
1797
  const classesByName = new Map();
1798
+ const classFields = new Map();
1725
1799
  for (const cls of mod.classes ?? []) {
1726
1800
  if (classesByName.has(cls.name)) {
1727
1801
  errors.push({ message: `duplicate class "${cls.name}"`, loc: cls.loc });
@@ -1751,6 +1825,9 @@ export function validateModule(mod) {
1751
1825
  if (cls.jsLength !== undefined && (!Number.isSafeInteger(cls.jsLength) || cls.jsLength < 0)) {
1752
1826
  errors.push({ message: `class ${cls.name}: invalid constructor length`, loc: cls.loc });
1753
1827
  }
1828
+ if (cls.tracksOwnFields && (cls.runtime || cls.fields.find((field) => field.name === DYN_CLASS_PROPERTIES)?.type.kind !== "dyn")) {
1829
+ errors.push({ message: `class ${cls.name}: field presence tracking requires a native dyn property bag`, loc: cls.loc });
1830
+ }
1754
1831
  if (cls.prototypeDataHelper !== undefined) {
1755
1832
  const helper = functionsByName.get(cls.prototypeDataHelper);
1756
1833
  if (!helper || helper.params.length !== 0 || helper.returnType.kind !== "dyn" || helper.captures !== undefined || helper.classCaptures !== undefined) {
@@ -1771,16 +1848,24 @@ export function validateModule(mod) {
1771
1848
  errors.push({ message: `class ${cls.name}: invalid symbol field metadata`, loc: cls.loc });
1772
1849
  }
1773
1850
  }
1774
- const seen = new Set();
1851
+ // Reuse duplicate detection as the field index for function validation.
1852
+ // Array.find selected the first field, even in an invalid duplicate layout.
1853
+ const seen = new Map();
1775
1854
  for (const f of cls.fields) {
1776
1855
  if (seen.has(f.name)) {
1777
1856
  errors.push({ message: `class ${cls.name}: duplicate field "${f.name}"`, loc: cls.loc });
1778
1857
  }
1779
- seen.add(f.name);
1858
+ else
1859
+ seen.set(f.name, f.type);
1780
1860
  if (isUnitType(f.type)) {
1781
1861
  errors.push({ message: `class ${cls.name}: field "${f.name}" is ${f.type.kind}`, loc: cls.loc });
1782
1862
  }
1783
1863
  }
1864
+ // Duplicate class names, like classesByName, select the last declaration.
1865
+ if (seen.size > 0)
1866
+ classFields.set(cls.name, seen);
1867
+ else
1868
+ classFields.delete(cls.name);
1784
1869
  // Constructor presence is checked at `new` sites (below): a class kept
1785
1870
  // only for its layout/type (reachability never constructs it) carries
1786
1871
  // no constructor function, and that is fine — nothing calls it.
@@ -1857,30 +1942,41 @@ export function validateModule(mod) {
1857
1942
  }
1858
1943
  const noLoc = { file: mod.sourceFile, start: 0, end: 0 };
1859
1944
  const recordsById = new Map();
1945
+ const recordIds = new Set((mod.records ?? []).map((record) => record.id));
1946
+ const recordValidation = new Map();
1860
1947
  for (const rec of mod.records ?? []) {
1861
1948
  if (recordsById.has(rec.id)) {
1862
1949
  errors.push({ message: `duplicate record shape "${rec.id}"`, loc: noLoc });
1863
1950
  }
1864
1951
  recordsById.set(rec.id, rec);
1865
- const seen = new Set();
1952
+ const fields = new Map();
1866
1953
  for (const f of rec.fields) {
1867
- if (seen.has(f.name)) {
1954
+ if (fields.has(f.name)) {
1868
1955
  errors.push({ message: `record ${rec.id}: duplicate field "${f.name}"`, loc: noLoc });
1869
1956
  }
1870
- seen.add(f.name);
1957
+ else
1958
+ fields.set(f.name, f.type);
1871
1959
  // Unit kinds (undefinedT/nullT) exist only as union arms — a BARE
1872
1960
  // unit field is as malformed as a void one. dyn and jsval slots
1873
1961
  // are valid; both are refcounted values held by the record shape.
1874
1962
  if (f.type.kind === "void" || isUnitType(f.type)) {
1875
1963
  errors.push({ message: `record ${rec.id}: field "${f.name}" is ${f.type.kind}`, loc: noLoc });
1876
1964
  }
1877
- if (f.type.kind === "record" && !new Set((mod.records ?? []).map((r) => r.id)).has(f.type.shapeId)) {
1965
+ if (f.type.kind === "record" && !recordIds.has(f.type.shapeId)) {
1878
1966
  errors.push({
1879
1967
  message: `record ${rec.id}: field "${f.name}" references undeclared shape "${f.type.shapeId}"`,
1880
1968
  loc: noLoc,
1881
1969
  });
1882
1970
  }
1883
1971
  }
1972
+ // Reads historically use the first duplicate field, while literal and
1973
+ // clone checks use the last. Preserve both on malformed shapes; valid
1974
+ // shapes share one index. All indexes belong to this validation call.
1975
+ recordValidation.set(rec.id, {
1976
+ fields,
1977
+ initializationFields: fields.size === rec.fields.length ? fields : new Map(rec.fields.map((field) => [field.name, field.type])),
1978
+ hasAccessorSlots: shapeHasAccessorSlots(rec),
1979
+ });
1884
1980
  // Canonical order is the shape's identity — enforce it.
1885
1981
  const sorted = [...rec.fields].map((f) => f.name).sort();
1886
1982
  if (rec.fields.some((f, i) => f.name !== sorted[i])) {
@@ -1933,7 +2029,7 @@ export function validateModule(mod) {
1933
2029
  for (const candidate of cases) {
1934
2030
  const arm = u.arms[candidate.tag];
1935
2031
  const record = arm?.kind === "record" ? recordsById.get(arm.shapeId) : undefined;
1936
- const member = record?.fields.find((entry) => entry.name === field);
2032
+ const member = record ? recordValidation.get(record.id)?.fields.get(field) : undefined;
1937
2033
  if (!Number.isInteger(candidate.tag) || candidate.tag < 0 || !member || tags.has(candidate.tag)) {
1938
2034
  errors.push({ message: `union ${u.id}: invalid discriminant tag ${candidate.tag}`, loc: noLoc });
1939
2035
  }
@@ -1946,8 +2042,8 @@ export function validateModule(mod) {
1946
2042
  errors.push({ message: `union ${u.id}: undefined discriminant value`, loc: noLoc });
1947
2043
  continue;
1948
2044
  }
1949
- const fieldTypes = member?.type.kind === "union"
1950
- ? unionsById.get(member.type.unionId)?.arms ?? [] : member ? [member.type] : [];
2045
+ const fieldTypes = member?.kind === "union"
2046
+ ? unionsById.get(member.unionId)?.arms ?? [] : member ? [member] : [];
1951
2047
  const valid = fieldTypes.some((type) => typeof value === "string" ? type.kind === "string"
1952
2048
  : typeof value === "boolean" ? type.kind === "bool"
1953
2049
  : typeof value === "number" && Number.isFinite(value) && type.kind === "f64");
@@ -2110,12 +2206,34 @@ export function validateModule(mod) {
2110
2206
  }
2111
2207
  }
2112
2208
  }
2209
+ // Class metadata is invariant across functions. Keep field lookup, hierarchy
2210
+ // membership, and virtual-call resolution local to this validation invocation.
2211
+ const classValidation = {
2212
+ fields: classFields,
2213
+ hierarchy: new Set(), implementations: new Map(), virtualCalls: new Map(),
2214
+ };
2215
+ for (const cls of classesByName.values()) {
2216
+ if (cls.base !== undefined) {
2217
+ classValidation.hierarchy.add(cls.name);
2218
+ classValidation.hierarchy.add(cls.base);
2219
+ }
2220
+ if (cls.name === RUNTIME_EMITTER_CLASS)
2221
+ classValidation.hierarchy.add(cls.name);
2222
+ for (const method of new Set(cls.methods ?? [])) {
2223
+ if (cls.abstractMethods?.includes(method))
2224
+ continue;
2225
+ let implementations = classValidation.implementations.get(method);
2226
+ if (!implementations)
2227
+ classValidation.implementations.set(method, (implementations = []));
2228
+ implementations.push(cls);
2229
+ }
2230
+ }
2113
2231
  for (const fn of mod.functions) {
2114
- validateFunction(fn, functionsByName, ffiByName, classesByName, recordsById, unionsById, globalsById, errors);
2232
+ validateFunction(fn, functionsByName, ffiByName, classesByName, recordsById, recordValidation, unionsById, globalsById, classValidation, errors);
2115
2233
  }
2116
2234
  return errors;
2117
2235
  }
2118
- function validateFunction(fn, functions, ffiByName, classes, records, unions, globals, errors) {
2236
+ function validateFunction(fn, functions, ffiByName, classes, records, recordValidation, unions, globals, classValidation, errors) {
2119
2237
  const locals = new Map(fn.locals.map((l) => [l.id, l]));
2120
2238
  const err = (message, loc) => errors.push({ message: `in ${fn.name}: ${message}`, loc });
2121
2239
  const asyncCaches = [
@@ -2158,17 +2276,41 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2158
2276
  }
2159
2277
  return false;
2160
2278
  };
2161
- const hierarchy = new Set();
2162
- for (const c of classes.values()) {
2163
- if (c.base !== undefined) {
2164
- hierarchy.add(c.name);
2165
- hierarchy.add(c.base);
2166
- }
2167
- // The runtime emitter class is ALWAYS a hierarchy member: ScrEmitter
2168
- // carries its vtable word even with no subclass in the program.
2169
- if (c.name === RUNTIME_EMITTER_CLASS)
2170
- hierarchy.add(c.name);
2171
- }
2279
+ const hierarchy = classValidation.hierarchy;
2280
+ const virtualCallInfo = (className, method) => {
2281
+ let methods = classValidation.virtualCalls.get(className);
2282
+ const cached = methods?.get(method);
2283
+ if (cached)
2284
+ return cached;
2285
+ if (!methods)
2286
+ classValidation.virtualCalls.set(className, (methods = new Map()));
2287
+ let declared = false;
2288
+ let implementation;
2289
+ for (let c = classes.get(className); c; c = c.base !== undefined ? classes.get(c.base) : undefined) {
2290
+ if (c.methods?.includes(method)) {
2291
+ declared = true;
2292
+ if (!c.abstractMethods?.includes(method)) {
2293
+ implementation = functions.get(`%${c.name}.${method}`);
2294
+ break;
2295
+ }
2296
+ }
2297
+ }
2298
+ let hasOverride = false;
2299
+ if (declared) {
2300
+ // Preserve class-table order when choosing an abstract slot's ABI.
2301
+ for (const c of classValidation.implementations.get(method) ?? []) {
2302
+ if (!isStrictSubclass(c.name, className))
2303
+ continue;
2304
+ hasOverride = true;
2305
+ implementation ??= functions.get(`%${c.name}.${method}`);
2306
+ if (implementation)
2307
+ break;
2308
+ }
2309
+ }
2310
+ const result = { declared, hasOverride, implementation };
2311
+ methods.set(method, result);
2312
+ return result;
2313
+ };
2172
2314
  // Unit kinds live only inside unions: a bare-unit local, param, or
2173
2315
  // return type is frontend breakage (mapType never produces them).
2174
2316
  for (const l of fn.locals) {
@@ -2594,15 +2736,15 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2594
2736
  // dyn field with fieldDyn set (validated numeric read-modify-write).
2595
2737
  checkExpr(e.obj);
2596
2738
  const cls = classes.get(e.className);
2597
- const field = cls?.fields.find((f) => f.name === e.field);
2739
+ const fieldType = classValidation.fields.get(e.className)?.get(e.field);
2598
2740
  if (!cls)
2599
2741
  err(`fieldIncDec on undeclared class "${e.className}"`, e.loc);
2600
- else if (!field)
2742
+ else if (!fieldType)
2601
2743
  err(`class ${e.className} has no field "${e.field}"`, e.loc);
2602
2744
  else {
2603
2745
  expectType(e.obj, { kind: "object", className: e.className }, "fieldIncDec receiver");
2604
- if (e.fieldDyn ? field.type.kind !== "dyn" : field.type.kind !== "f64") {
2605
- err(`fieldIncDec ${e.className}.${e.field} field/flag mismatch (${field.type.kind})`, e.loc);
2746
+ if (e.fieldDyn ? fieldType.kind !== "dyn" : fieldType.kind !== "f64") {
2747
+ err(`fieldIncDec ${e.className}.${e.field} field/flag mismatch (${fieldType.kind})`, e.loc);
2606
2748
  }
2607
2749
  }
2608
2750
  if (e.type.kind !== "f64")
@@ -3626,14 +3768,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3626
3768
  case "fieldGet": {
3627
3769
  checkExpr(e.obj);
3628
3770
  const cls = classes.get(e.className);
3629
- const field = cls?.fields.find((f) => f.name === e.field);
3771
+ const fieldType = classValidation.fields.get(e.className)?.get(e.field);
3630
3772
  if (!cls)
3631
3773
  err(`fieldGet on undeclared class "${e.className}"`, e.loc);
3632
- else if (!field)
3774
+ else if (!fieldType)
3633
3775
  err(`class ${e.className} has no field "${e.field}"`, e.loc);
3634
3776
  else {
3635
3777
  expectType(e.obj, { kind: "object", className: e.className }, "fieldGet receiver");
3636
- if (!typeEquals(e.type, field.type)) {
3778
+ if (!typeEquals(e.type, fieldType)) {
3637
3779
  err(`fieldGet ${e.className}.${e.field} type mismatch`, e.loc);
3638
3780
  }
3639
3781
  }
@@ -3807,30 +3949,15 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3807
3949
  // is then well-formed against any concrete override below — the
3808
3950
  // frontend's override-exactness rule makes every implementation
3809
3951
  // ABI-identical, so any one of them carries the slot's signature.
3810
- let declared = false;
3811
- let impl;
3812
- for (let c = classes.get(e.className); c; c = c.base !== undefined ? classes.get(c.base) : undefined) {
3813
- if (c.methods?.includes(e.method)) {
3814
- declared = true;
3815
- if (!c.abstractMethods?.includes(e.method)) {
3816
- impl = functions.get(`%${c.name}.${e.method}`);
3817
- break;
3818
- }
3819
- }
3820
- }
3821
- if (!declared) {
3952
+ const info = virtualCallInfo(e.className, e.method);
3953
+ if (!info.declared) {
3822
3954
  err(`virtualCall ${e.className}.${e.method}: no declaration on the base chain`, e.loc);
3823
3955
  break;
3824
3956
  }
3825
- const concreteBelow = [...classes.values()].filter((c) => c.methods?.includes(e.method) &&
3826
- !c.abstractMethods?.includes(e.method) &&
3827
- isStrictSubclass(c.name, e.className));
3828
- if (concreteBelow.length === 0) {
3957
+ if (!info.hasOverride) {
3829
3958
  err(`virtualCall ${e.className}.${e.method}: no concrete override below the static class`, e.loc);
3830
3959
  }
3831
- impl ??= concreteBelow
3832
- .map((c) => functions.get(`%${c.name}.${e.method}`))
3833
- .find((f) => f !== undefined);
3960
+ const impl = info.implementation;
3834
3961
  if (!impl) {
3835
3962
  err(`virtualCall ${e.className}.${e.method}: no implementation function exists`, e.loc);
3836
3963
  break;
@@ -3866,7 +3993,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3866
3993
  err(`recordLit of undeclared shape "${e.type.shapeId}"`, e.loc);
3867
3994
  break;
3868
3995
  }
3869
- const want = new Map(shape.fields.map((f) => [f.name, f.type]));
3996
+ const want = recordValidation.get(shape.id).initializationFields;
3870
3997
  const seen = new Set();
3871
3998
  for (const f of e.fields) {
3872
3999
  checkExpr(f.value);
@@ -3922,11 +4049,11 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3922
4049
  err(`recordClone of undeclared shape "${e.type.shapeId}"`, e.loc);
3923
4050
  break;
3924
4051
  }
3925
- if (shape.tuple || shape.indexValue || shapeHasAccessorSlots(shape)) {
4052
+ if (shape.tuple || shape.indexValue || recordValidation.get(shape.id).hasAccessorSlots) {
3926
4053
  err(`recordClone requires a plain declared-field shape, got ${shape.id}`, e.loc);
3927
4054
  }
3928
4055
  expectType(e.source, e.type, "recordClone source");
3929
- const want = new Map(shape.fields.map((f) => [f.name, f.type]));
4056
+ const want = recordValidation.get(shape.id).initializationFields;
3930
4057
  const seen = new Set();
3931
4058
  for (const f of e.overrides) {
3932
4059
  checkExpr(f.value);
@@ -3944,14 +4071,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3944
4071
  case "recordGet": {
3945
4072
  checkExpr(e.obj);
3946
4073
  const shape = records.get(e.shapeId);
3947
- const field = shape?.fields.find((f) => f.name === e.field);
4074
+ const field = recordValidation.get(e.shapeId)?.fields.get(e.field);
3948
4075
  if (!shape)
3949
4076
  err(`recordGet on undeclared shape "${e.shapeId}"`, e.loc);
3950
4077
  else if (!field)
3951
4078
  err(`shape ${e.shapeId} has no field "${e.field}"`, e.loc);
3952
4079
  else {
3953
4080
  expectType(e.obj, { kind: "record", shapeId: e.shapeId }, "recordGet receiver");
3954
- if (!typeEquals(e.type, field.type)) {
4081
+ if (!typeEquals(e.type, field)) {
3955
4082
  err(`recordGet ${e.shapeId}.${e.field} type mismatch`, e.loc);
3956
4083
  }
3957
4084
  }
@@ -4074,6 +4201,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4074
4201
  }
4075
4202
  case "dynCall": {
4076
4203
  checkExpr(e.callee);
4204
+ if (e.calleeNameValue !== undefined) {
4205
+ checkExpr(e.calleeNameValue);
4206
+ expectType(e.calleeNameValue, STRING, "dynCall callee name");
4207
+ }
4077
4208
  if (e.receiver !== undefined) {
4078
4209
  checkExpr(e.receiver);
4079
4210
  expectType(e.receiver, DYN, "dynCall receiver");
@@ -4105,6 +4236,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4105
4236
  }
4106
4237
  case "dynInvoke": {
4107
4238
  checkExpr(e.recv);
4239
+ if (e.calleeNameValue !== undefined) {
4240
+ checkExpr(e.calleeNameValue);
4241
+ expectType(e.calleeNameValue, STRING, "dynInvoke callee name");
4242
+ }
4108
4243
  expectType(e.recv, DYN, "dynInvoke receiver");
4109
4244
  if (e.type.kind !== "dyn")
4110
4245
  err(`dynInvoke must be dyn-typed, got ${e.type.kind}`, e.loc);
@@ -4315,9 +4450,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4315
4450
  }
4316
4451
  def.arms.forEach((arm, i) => {
4317
4452
  const fieldType = arm.kind === "record"
4318
- ? records.get(arm.shapeId)?.fields.find((f) => f.name === e.field)?.type
4453
+ ? recordValidation.get(arm.shapeId)?.fields.get(e.field)
4319
4454
  : arm.kind === "object"
4320
- ? classes.get(arm.className)?.fields.find((f) => f.name === e.field)?.type
4455
+ ? classValidation.fields.get(arm.className)?.get(e.field)
4321
4456
  : undefined;
4322
4457
  if (!fieldType) {
4323
4458
  err(`unionDisc: arm ${i} of ${e.unionId} has no field "${e.field}"`, e.loc);
@@ -4380,7 +4515,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4380
4515
  return;
4381
4516
  }
4382
4517
  const literal = e.key.kind === "strLit" ? e.key.value : null;
4383
- const declared = literal !== null ? shape.fields.find((f) => f.name === literal)?.type : undefined;
4518
+ const declared = literal !== null ? recordValidation.get(shape.id)?.fields.get(literal) : undefined;
4384
4519
  if (declared) {
4385
4520
  if (!surfaces(declared)) {
4386
4521
  err(`unionKeyGet: arm ${i} field "${literal}" of type ${declared.kind} cannot surface as the result`, e.loc);
@@ -4595,18 +4730,19 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4595
4730
  }
4596
4731
  }
4597
4732
  function checkLibValueCall(e) {
4598
- if (e.fn === "fileHandle.read" || e.fn === "fileHandle.writeBytes" || e.fn === "fileHandle.writeStr") {
4733
+ if (e.fn === "fileHandle.read" || e.fn === "fileHandle.writeBytes" || e.fn === "fileHandle.writeStr" || e.fn === "fileHandle.readv" || e.fn === "fileHandle.writev") {
4599
4734
  const inner = e.type.kind === "promise" ? e.type.inner : undefined;
4600
4735
  const shape = inner?.kind === "record" ? records.get(inner.shapeId) : undefined;
4601
- const countName = e.fn === "fileHandle.read" ? "bytesRead" : "bytesWritten";
4736
+ const countName = e.fn === "fileHandle.read" || e.fn === "fileHandle.readv" ? "bytesRead" : "bytesWritten";
4737
+ const payloadName = e.fn === "fileHandle.readv" || e.fn === "fileHandle.writev" ? "buffers" : "buffer";
4602
4738
  const payload = e.args[1]?.type;
4603
- const count = shape?.fields.find((f) => f.name === countName);
4604
- const buffer = shape?.fields.find((f) => f.name === "buffer");
4739
+ const count = shape ? recordValidation.get(shape.id)?.fields.get(countName) : undefined;
4740
+ const buffer = shape ? recordValidation.get(shape.id)?.fields.get(payloadName) : undefined;
4605
4741
  const ok = shape !== undefined && !shape.tuple && shape.indexValue === undefined && shape.fields.length === 2 &&
4606
- count?.type.kind === "f64" && payload !== undefined && buffer !== undefined &&
4607
- typeEquals(buffer.type, payload);
4742
+ count?.kind === "f64" && payload !== undefined && buffer !== undefined &&
4743
+ typeEquals(buffer, payload);
4608
4744
  if (!ok) {
4609
- err(`libCall ${e.fn} must return a promise of { ${countName}: number, buffer }`, e.loc);
4745
+ err(`libCall ${e.fn} must return a promise of { ${countName}: number, ${payloadName} }`, e.loc);
4610
4746
  }
4611
4747
  return true;
4612
4748
  }
@@ -5897,17 +6033,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
5897
6033
  break;
5898
6034
  }
5899
6035
  const rec = records.get(resultT.shapeId);
5900
- const doneF = rec?.fields.find((f) => f.name === "done");
5901
- const valueF = rec?.fields.find((f) => f.name === "value");
5902
- if (!rec || rec.fields.length !== 2 || doneF?.type.kind !== "bool" || valueF === undefined) {
6036
+ const doneF = rec ? recordValidation.get(rec.id)?.fields.get("done") : undefined;
6037
+ const valueF = rec ? recordValidation.get(rec.id)?.fields.get("value") : undefined;
6038
+ if (!rec || rec.fields.length !== 2 || doneF?.kind !== "bool" || valueF === undefined) {
5903
6039
  err(`genResume result record ${resultT.shapeId} is not { done: bool, value: V }`, e.loc);
5904
6040
  break;
5905
6041
  }
5906
- if (valueF.type.kind === "dyn")
6042
+ if (valueF.kind === "dyn")
5907
6043
  break;
5908
- const vdef = valueF.type.kind === "union" ? unions.get(valueF.type.unionId) : undefined;
6044
+ const vdef = valueF.kind === "union" ? unions.get(valueF.unionId) : undefined;
5909
6045
  if (!vdef || !vdef.arms.some((a) => a.kind === "undefinedT")) {
5910
- err(`genResume value slot ${typeKey(valueF.type)} is neither dyn nor an undefined-armed union`, e.loc);
6046
+ err(`genResume value slot ${typeKey(valueF)} is neither dyn nor an undefined-armed union`, e.loc);
5911
6047
  }
5912
6048
  break;
5913
6049
  }
@@ -5991,10 +6127,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
5991
6127
  break;
5992
6128
  }
5993
6129
  const shape = records.get(e.type.shapeId);
5994
- const fields = new Map(shape?.fields.map((f) => [f.name, f.type]) ?? []);
5995
- const prom = fields.get("promise");
5996
- const resolve = fields.get("resolve");
5997
- const reject = fields.get("reject");
6130
+ const fields = recordValidation.get(e.type.shapeId)?.initializationFields;
6131
+ const prom = fields?.get("promise");
6132
+ const resolve = fields?.get("resolve");
6133
+ const reject = fields?.get("reject");
5998
6134
  if (!shape || shape.fields.length !== 3 || !prom || !resolve || !reject) {
5999
6135
  err("promiseWithResolvers record must be { promise, resolve, reject }", e.loc);
6000
6136
  break;
@@ -6306,14 +6442,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
6306
6442
  checkExpr(s.obj);
6307
6443
  checkExpr(s.value);
6308
6444
  const cls = classes.get(s.className);
6309
- const field = cls?.fields.find((f) => f.name === s.field);
6445
+ const fieldType = classValidation.fields.get(s.className)?.get(s.field);
6310
6446
  if (!cls)
6311
6447
  err(`fieldSet on undeclared class "${s.className}"`, s.loc);
6312
- else if (!field)
6448
+ else if (!fieldType)
6313
6449
  err(`class ${s.className} has no field "${s.field}"`, s.loc);
6314
6450
  else {
6315
6451
  expectType(s.obj, { kind: "object", className: s.className }, "fieldSet receiver");
6316
- expectType(s.value, field.type, `fieldSet ${s.className}.${s.field}`);
6452
+ expectType(s.value, fieldType, `fieldSet ${s.className}.${s.field}`);
6317
6453
  }
6318
6454
  break;
6319
6455
  }
@@ -6321,14 +6457,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
6321
6457
  checkExpr(s.obj);
6322
6458
  checkExpr(s.value);
6323
6459
  const shape = records.get(s.shapeId);
6324
- const field = shape?.fields.find((f) => f.name === s.field);
6460
+ const field = recordValidation.get(s.shapeId)?.fields.get(s.field);
6325
6461
  if (!shape)
6326
6462
  err(`recordSet on undeclared shape "${s.shapeId}"`, s.loc);
6327
6463
  else if (!field)
6328
6464
  err(`shape ${s.shapeId} has no field "${s.field}"`, s.loc);
6329
6465
  else {
6330
6466
  expectType(s.obj, { kind: "record", shapeId: s.shapeId }, "recordSet receiver");
6331
- expectType(s.value, field.type, `recordSet ${s.shapeId}.${s.field}`);
6467
+ expectType(s.value, field, `recordSet ${s.shapeId}.${s.field}`);
6332
6468
  }
6333
6469
  break;
6334
6470
  }