@scriptc/compiler 0.2.0 → 0.2.2

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 (284) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +84 -19
  2. package/dist/backend/cycle-analysis.js +1 -0
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/llvm/classes.js +21 -5
  5. package/dist/backend/llvm/classes.js.map +1 -1
  6. package/dist/backend/llvm/dyn.d.ts +8 -0
  7. package/dist/backend/llvm/dyn.js +247 -108
  8. package/dist/backend/llvm/dyn.js.map +1 -1
  9. package/dist/backend/llvm/emitter.d.ts +6 -3
  10. package/dist/backend/llvm/emitter.js +99 -25
  11. package/dist/backend/llvm/emitter.js.map +1 -1
  12. package/dist/backend/llvm/emitter.test.js +9 -1
  13. package/dist/backend/llvm/emitter.test.js.map +1 -1
  14. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  15. package/dist/backend/llvm/expr-bytes.js +28 -17
  16. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  17. package/dist/backend/llvm/expr-containers.js +5 -0
  18. package/dist/backend/llvm/expr-containers.js.map +1 -1
  19. package/dist/backend/llvm/expr-control.js +1 -1
  20. package/dist/backend/llvm/expr-control.js.map +1 -1
  21. package/dist/backend/llvm/expr-dynamic.js +47 -13
  22. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  23. package/dist/backend/llvm/expr-primitives.js +11 -1
  24. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  25. package/dist/backend/llvm/expr-records.js +11 -3
  26. package/dist/backend/llvm/expr-records.js.map +1 -1
  27. package/dist/backend/llvm/expr-stream-bridges.js +187 -18
  28. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  29. package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
  30. package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
  31. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  32. package/dist/backend/llvm/lib-dispatch.js +41 -3
  33. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  34. package/dist/backend/llvm/lib-filesystem.js +12 -9
  35. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  36. package/dist/backend/llvm/lib-process.js +23 -3
  37. package/dist/backend/llvm/lib-process.js.map +1 -1
  38. package/dist/backend/llvm/lib-shared.js +80 -3
  39. package/dist/backend/llvm/lib-shared.js.map +1 -1
  40. package/dist/backend/llvm/shapes.js +8 -2
  41. package/dist/backend/llvm/shapes.js.map +1 -1
  42. package/dist/backend/may-throw.js +4 -0
  43. package/dist/backend/may-throw.js.map +1 -1
  44. package/dist/backend/native-codegen.d.ts +1 -1
  45. package/dist/backend/native-codegen.js +4 -3
  46. package/dist/backend/native-codegen.js.map +1 -1
  47. package/dist/backend/native-codegen.test.js +11 -0
  48. package/dist/backend/native-codegen.test.js.map +1 -1
  49. package/dist/backend/native-toolchain.d.ts +3 -6
  50. package/dist/backend/native-toolchain.js +53 -23
  51. package/dist/backend/native-toolchain.js.map +1 -1
  52. package/dist/backend/native-toolchain.test.js +72 -0
  53. package/dist/backend/native-toolchain.test.js.map +1 -1
  54. package/dist/backend/runtime-abi.d.ts +2 -2
  55. package/dist/backend/runtime-abi.js +2 -2
  56. package/dist/backend/runtime-pack-native.js +4 -1
  57. package/dist/backend/runtime-pack-native.js.map +1 -1
  58. package/dist/backend/runtime-pack-targets.test.js +1 -1
  59. package/dist/backend/runtime-pack.test.js +1 -1
  60. package/dist/backend/target-diagnostics.d.ts +5 -0
  61. package/dist/backend/target-diagnostics.js +72 -1
  62. package/dist/backend/target-diagnostics.js.map +1 -1
  63. package/dist/backend/target-diagnostics.test.d.ts +1 -0
  64. package/dist/backend/target-diagnostics.test.js +68 -0
  65. package/dist/backend/target-diagnostics.test.js.map +1 -0
  66. package/dist/backend/targets.js +10 -6
  67. package/dist/backend/targets.js.map +1 -1
  68. package/dist/backend/targets.test.js +7 -0
  69. package/dist/backend/targets.test.js.map +1 -1
  70. package/dist/compat/fetch-profile.js +34 -4
  71. package/dist/compat/fetch-profile.js.map +1 -1
  72. package/dist/coverage/surface-manifest.js +5 -3
  73. package/dist/coverage/surface-manifest.js.map +1 -1
  74. package/dist/diagnostics/diagnostic.js +2 -7
  75. package/dist/diagnostics/diagnostic.js.map +1 -1
  76. package/dist/executable/executable-cache.d.ts +7 -3
  77. package/dist/executable/executable-cache.js +47 -11
  78. package/dist/executable/executable-cache.js.map +1 -1
  79. package/dist/executable/executable-cache.test.js +109 -2
  80. package/dist/executable/executable-cache.test.js.map +1 -1
  81. package/dist/executable/prepare.js +2 -1
  82. package/dist/executable/prepare.js.map +1 -1
  83. package/dist/frontend/builtin-modules.d.ts +1 -1
  84. package/dist/frontend/builtin-modules.js +1 -1
  85. package/dist/frontend/builtin-modules.js.map +1 -1
  86. package/dist/frontend/function-completion.d.ts +6 -0
  87. package/dist/frontend/function-completion.js +50 -0
  88. package/dist/frontend/function-completion.js.map +1 -0
  89. package/dist/frontend/lowering/abstract-equality.js +5 -1
  90. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  91. package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
  92. package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
  93. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
  94. package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
  95. package/dist/frontend/lowering/checked-promise-all.js +31 -0
  96. package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
  97. package/dist/frontend/lowering/class-callbacks.d.ts +4 -4
  98. package/dist/frontend/lowering/class-callbacks.js +29 -17
  99. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  100. package/dist/frontend/lowering/class-construction.d.ts +14 -0
  101. package/dist/frontend/lowering/class-construction.js +185 -0
  102. package/dist/frontend/lowering/class-construction.js.map +1 -0
  103. package/dist/frontend/lowering/class-descriptors.d.ts +2 -1
  104. package/dist/frontend/lowering/class-descriptors.js +58 -10
  105. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  106. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +36 -1
  107. package/dist/frontend/lowering/class-dynamic-dispatch.js +965 -91
  108. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  109. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +66 -3
  110. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  111. package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
  112. package/dist/frontend/lowering/class-instance-constructor.js +15 -42
  113. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  114. package/dist/frontend/lowering/class-method-values.d.ts +20 -1
  115. package/dist/frontend/lowering/class-method-values.js +120 -24
  116. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  117. package/dist/frontend/lowering/class-prototypes.d.ts +10 -3
  118. package/dist/frontend/lowering/class-prototypes.js +188 -21
  119. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  120. package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
  121. package/dist/frontend/lowering/class-runtime-statics.js +84 -0
  122. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
  123. package/dist/frontend/lowering/class-static-data.d.ts +1 -0
  124. package/dist/frontend/lowering/class-static-data.js +6 -4
  125. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  126. package/dist/frontend/lowering/containers/bytes.js +66 -17
  127. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  128. package/dist/frontend/lowering/containers/string-and-regexp.js +24 -47
  129. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  130. package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
  131. package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
  132. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
  133. package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
  134. package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
  135. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
  136. package/dist/frontend/lowering/error-methods.d.ts +4 -1
  137. package/dist/frontend/lowering/error-methods.js +100 -1
  138. package/dist/frontend/lowering/error-methods.js.map +1 -1
  139. package/dist/frontend/lowering/expressions/native-proxy.js +3 -1
  140. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  141. package/dist/frontend/lowering/expressions/nullish-assignment.js +19 -11
  142. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  143. package/dist/frontend/lowering/expressions/object-literals.js +68 -7
  144. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  145. package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
  146. package/dist/frontend/lowering/expressions/optional-chains.js +72 -20
  147. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  148. package/dist/frontend/lowering/function-context.d.ts +11 -3
  149. package/dist/frontend/lowering/function-context.js +11 -5
  150. package/dist/frontend/lowering/function-context.js.map +1 -1
  151. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -0
  152. package/dist/frontend/lowering/generator-dynamic-dispatch.js +39 -1
  153. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
  154. package/dist/frontend/lowering/lib-boundary.d.ts +2 -0
  155. package/dist/frontend/lowering/lib-boundary.js +54 -1
  156. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  157. package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -1
  158. package/dist/frontend/lowering/lower-builtin-values.js +113 -3
  159. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  160. package/dist/frontend/lowering/lower-builtins.d.ts +10 -14
  161. package/dist/frontend/lowering/lower-builtins.js +443 -88
  162. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  163. package/dist/frontend/lowering/lower-calls.d.ts +8 -5
  164. package/dist/frontend/lowering/lower-calls.js +717 -142
  165. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  166. package/dist/frontend/lowering/lower-classes.d.ts +18 -13
  167. package/dist/frontend/lowering/lower-classes.js +1076 -188
  168. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  169. package/dist/frontend/lowering/lower-containers.d.ts +9 -0
  170. package/dist/frontend/lowering/lower-containers.js +172 -51
  171. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  172. package/dist/frontend/lowering/lower-dgram.js +3 -2
  173. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  174. package/dist/frontend/lowering/lower-exprs.d.ts +12 -8
  175. package/dist/frontend/lowering/lower-exprs.js +802 -232
  176. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  177. package/dist/frontend/lowering/lower-generators.js +17 -2
  178. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  179. package/dist/frontend/lowering/lower-inspect.js +15 -1
  180. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  181. package/dist/frontend/lowering/lower-island.d.ts +2 -0
  182. package/dist/frontend/lowering/lower-island.js +36 -10
  183. package/dist/frontend/lowering/lower-island.js.map +1 -1
  184. package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
  185. package/dist/frontend/lowering/lower-island.test.js +51 -0
  186. package/dist/frontend/lowering/lower-island.test.js.map +1 -0
  187. package/dist/frontend/lowering/lower-modules.d.ts +1 -3
  188. package/dist/frontend/lowering/lower-modules.js +380 -73
  189. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  190. package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
  191. package/dist/frontend/lowering/lower-modules.test.js +107 -0
  192. package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
  193. package/dist/frontend/lowering/lower-stmts.d.ts +7 -3
  194. package/dist/frontend/lowering/lower-stmts.js +221 -47
  195. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  196. package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
  197. package/dist/frontend/lowering/lower-stmts.test.js +77 -0
  198. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
  199. package/dist/frontend/lowering/lower-stream.js +3 -1
  200. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  201. package/dist/frontend/lowering/lower-url.d.ts +2 -1
  202. package/dist/frontend/lowering/lower-url.js +32 -9
  203. package/dist/frontend/lowering/lower-url.js.map +1 -1
  204. package/dist/frontend/lowering/lowerer.d.ts +53 -10
  205. package/dist/frontend/lowering/lowerer.js +390 -77
  206. package/dist/frontend/lowering/lowerer.js.map +1 -1
  207. package/dist/frontend/lowering/lowerer.test.js +187 -3
  208. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  209. package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
  210. package/dist/frontend/lowering/module-namespace-elements.js +54 -0
  211. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
  212. package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
  213. package/dist/frontend/lowering/object-factory-new.js +27 -14
  214. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  215. package/dist/frontend/lowering/surfaces.d.ts +3 -0
  216. package/dist/frontend/lowering/surfaces.js +48 -19
  217. package/dist/frontend/lowering/surfaces.js.map +1 -1
  218. package/dist/frontend/lowering/text-decoder-encoding.d.ts +2 -0
  219. package/dist/frontend/lowering/text-decoder-encoding.js +8 -0
  220. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  221. package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
  222. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  223. package/dist/frontend/lowering/unregistered-class-types.test.js +3 -3
  224. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
  225. package/dist/frontend/npm-static-prune.js +116 -34
  226. package/dist/frontend/npm-static-prune.js.map +1 -1
  227. package/dist/frontend/npm-static-prune.test.js +8 -0
  228. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  229. package/dist/frontend/program.d.ts +1 -1
  230. package/dist/frontend/program.js +57 -26
  231. package/dist/frontend/program.js.map +1 -1
  232. package/dist/frontend/program.test.js +18 -0
  233. package/dist/frontend/program.test.js.map +1 -1
  234. package/dist/frontend/ts7/ast.js +4 -3
  235. package/dist/frontend/ts7/ast.js.map +1 -1
  236. package/dist/frontend/ts7/semantic-json.js +5 -10
  237. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  238. package/dist/frontend/type-mapper.d.ts +9 -1
  239. package/dist/frontend/type-mapper.js +169 -23
  240. package/dist/frontend/type-mapper.js.map +1 -1
  241. package/dist/frontend/type-mapper.test.js +23 -0
  242. package/dist/frontend/type-mapper.test.js.map +1 -1
  243. package/dist/frontend/union-discriminants.d.ts +1 -1
  244. package/dist/frontend/union-discriminants.js +24 -9
  245. package/dist/frontend/union-discriminants.js.map +1 -1
  246. package/dist/index.js +16 -10
  247. package/dist/index.js.map +1 -1
  248. package/dist/ir/analysis.js +2 -0
  249. package/dist/ir/analysis.js.map +1 -1
  250. package/dist/ir/ir.d.ts +74 -41
  251. package/dist/ir/ir.js +167 -43
  252. package/dist/ir/ir.js.map +1 -1
  253. package/dist/ir/ir.test.js +35 -0
  254. package/dist/ir/ir.test.js.map +1 -1
  255. package/dist/ir/serialize.js +35 -3
  256. package/dist/ir/serialize.js.map +1 -1
  257. package/dist/ir/serialize.test.js +26 -1
  258. package/dist/ir/serialize.test.js.map +1 -1
  259. package/dist/ir/traverse.d.ts +0 -3
  260. package/dist/ir/traverse.js +33 -20
  261. package/dist/ir/traverse.js.map +1 -1
  262. package/dist/ir/validate.js +136 -16
  263. package/dist/ir/validate.js.map +1 -1
  264. package/dist/ir/validate.test.js +77 -1
  265. package/dist/ir/validate.test.js.map +1 -1
  266. package/dist/library/compiler-self-identity.js +1 -1
  267. package/dist/library/compiler-self-identity.test.js +2 -2
  268. package/dist/library/compiler-self-identity.test.js.map +1 -1
  269. package/dist/library/int-infer.d.ts +2 -2
  270. package/dist/library/int-infer.js +10 -7
  271. package/dist/library/int-infer.js.map +1 -1
  272. package/dist/library/int-infer.test.js +44 -0
  273. package/dist/library/int-infer.test.js.map +1 -1
  274. package/dist/library/prepare.js +2 -1
  275. package/dist/library/prepare.js.map +1 -1
  276. package/dist/native/sanitizer.js +3 -1
  277. package/dist/native/sanitizer.js.map +1 -1
  278. package/dist/native/toolchain.d.ts +1 -1
  279. package/dist/native/toolchain.js +26 -6
  280. package/dist/native/toolchain.js.map +1 -1
  281. package/dist/native/toolchain.test.js +53 -1
  282. package/dist/native/toolchain.test.js.map +1 -1
  283. package/package.json +20 -20
  284. package/surface-manifest.json +170 -93
@@ -2,7 +2,7 @@ import { typedRefConstructor } from "./shapes.js";
2
2
  import { BYTES_ELEM_NUM, f64Lit } from "./common.js";
3
3
  import { InternalCompilerError } from "../../errors.js";
4
4
  import { DYN_HANDLE_KINDS, isDynTypedRefType, isRefCounted, typeKey } from "../../ir/ir.js";
5
- import { dynDesc, undefinedArmTag } from "../../ir/analysis.js";
5
+ import { dynDesc, streamTypedRefEligible } from "../../ir/analysis.js";
6
6
  import { mangleRecordNew, mangleRecordStruct } from "../mangle.js";
7
7
  import { BlockBuilder } from "./blocks.js";
8
8
  import { llvmCommentText } from "./common.js";
@@ -49,6 +49,7 @@ export class LlDyn {
49
49
  dynFuncBoxes = new Map();
50
50
  dynFuncAdapters = new Map();
51
51
  promiseDynAdapters = new Map();
52
+ mapDynOps = new Map();
52
53
  dynToStrFn = null;
53
54
  caughtToDynFn = null;
54
55
  helperMemo = new Map();
@@ -92,7 +93,45 @@ export class LlDyn {
92
93
  }
93
94
  /** The value LLVM type of a dynCheck result / toDyn operand for `t`. */
94
95
  valTy(t) {
95
- return t.kind === "f64" ? "double" : t.kind === "bool" ? "i1" : "ptr";
96
+ return t.kind === "f64" || t.kind === "date" ? "double" : t.kind === "bool" ? "i1" : "ptr";
97
+ }
98
+ collectionDynOps(t) {
99
+ const key = typeKey(t);
100
+ const prior = this.mapDynOps.get(key);
101
+ if (prior)
102
+ return prior;
103
+ const name = `sc_map_dyn_${this.mapDynOps.size}`;
104
+ this.mapDynOps.set(key, name);
105
+ const keyType = t.kind === "map" ? t.key : t.elem;
106
+ const valueType = t.kind === "map" ? t.value : { kind: "f64" };
107
+ const emitSlot = (type, role) => {
108
+ const ty = this.valTy(type);
109
+ const unpack = ty === "double" ? "bitcast i64 %slot to double" : ty === "i1" ? "trunc i64 %slot to i1" : "inttoptr i64 %slot to ptr";
110
+ const pack = ty === "double" ? "bitcast double %value to i64" : ty === "i1" ? "zext i1 %value to i64" : "ptrtoint ptr %value to i64";
111
+ // Collection reads expose the original mutable element, including
112
+ // records/arrays inside unions, rather than a detached dyn snapshot.
113
+ const B = new BlockBuilder();
114
+ B.line(`%value = ${unpack}`);
115
+ if (type.kind === "union" && this.host.unionsById.get(type.unionId)?.arms.some(streamTypedRefEligible)) {
116
+ B.line(`%result = call ptr @${this.host.liveDynUnionRefAdapter(type)}(ptr %value)`);
117
+ }
118
+ else if (type.kind === "record" || type.kind === "array") {
119
+ const adapter = this.host.liveDynRefAdapter(type);
120
+ const rc = vAdapters(this.host, type);
121
+ const typeId = typeKey(type);
122
+ B.line(`%result = call ptr ${typedRefConstructor(this.host, type)}(ptr %value, ptr ${rc.retain}, ptr ${rc.release}, ptr ${this.host.cstr(typeId)}, ${this.S} ${Buffer.byteLength(typeId, "utf8")}, ptr @${adapter.snapshot}, ptr ${adapter.commit})`);
123
+ }
124
+ else {
125
+ B.line(`%result = call ptr @${this.toDynHelper(type)}(${ty} %value)`);
126
+ }
127
+ B.terminate("ret ptr %result");
128
+ const unbox = this.dynCheckHelper(type);
129
+ this.defs.push(`define internal ptr @${name}_${role}_box(i64 %slot) ${FN_ATTRS} {`, B.render(), `}`, "", `define internal i64 @${name}_${role}_unbox(ptr %d) ${FN_ATTRS} {`, ` %value = call ${ty === "i1" ? "zeroext i1" : ty} @${unbox}(ptr %d, ptr null)`, ` %result = ${pack}`, ` ret i64 %result`, `}`, "");
130
+ };
131
+ emitSlot(keyType, "key");
132
+ emitSlot(valueType, "value");
133
+ this.defs.push(`@${name} = internal constant { ptr, ptr, ptr, ptr, ptr, ptr } { ptr ${this.host.cstr(key)}, ptr @${name}_key_box, ptr @${name}_key_unbox, ptr @${this.dynMatchHelper(keyType)}, ptr @${name}_value_box, ptr @${name}_value_unbox }`, "");
134
+ return name;
96
135
  }
97
136
  /* ── dyn node plumbing ─────────────────────────────────────────────── */
98
137
  /** Loads a dyn node's kind tag (after the size_t rc word). */
@@ -197,6 +236,13 @@ export class LlDyn {
197
236
  B.line(`${t} = call ptr @scr_dyn_obj_get(ptr ${d}, ptr ${this.host.cstr(key)}, ${this.S} ${len}) ; .${llvmCommentText(key)}`);
198
237
  return t;
199
238
  }
239
+ /** Ordinary property lookup, including inherited data and accessors (+1). */
240
+ objReadLit(B, d, key) {
241
+ this.host.declare(`declare ptr @scr_dyn_obj_read(ptr, ptr, ${this.S})`);
242
+ const value = B.tmp();
243
+ B.line(`${value} = call ptr @scr_dyn_obj_read(ptr ${d}, ptr ${this.host.cstr(key)}, ${this.S} ${Buffer.byteLength(key, "utf8")})`);
244
+ return value;
245
+ }
200
246
  /** Appends an ScrStr's bytes into a ScrJsonBuf (walkers' putScrStr). */
201
247
  putScrStr(B, buf, s) {
202
248
  this.host.declare(`declare void @scr_jb_putc(ptr, i8)`);
@@ -338,10 +384,19 @@ export class LlDyn {
338
384
  B.terminate(`ret i1 ${r}`);
339
385
  };
340
386
  switch (t.kind) {
341
- case "url": {
342
- this.host.declare(`declare zeroext i1 @scr_dyn_native_url_is(ptr)`);
387
+ case "date": {
388
+ this.host.declare(`declare zeroext i1 @scr_dyn_native_date_is(ptr)`);
389
+ const r = B.tmp();
390
+ B.line(`${r} = call zeroext i1 @scr_dyn_native_date_is(ptr %d)`);
391
+ B.terminate(`ret i1 ${r}`);
392
+ break;
393
+ }
394
+ case "url":
395
+ case "searchParams": {
396
+ const native = t.kind === "url" ? "url" : "search_params";
397
+ this.host.declare(`declare zeroext i1 @scr_dyn_native_${native}_is(ptr)`);
343
398
  const r = B.tmp();
344
- B.line(`${r} = call zeroext i1 @scr_dyn_native_url_is(ptr %d)`);
399
+ B.line(`${r} = call zeroext i1 @scr_dyn_native_${native}_is(ptr %d)`);
345
400
  B.terminate(`ret i1 ${r}`);
346
401
  break;
347
402
  }
@@ -354,15 +409,19 @@ export class LlDyn {
354
409
  }
355
410
  case "map":
356
411
  case "set": {
357
- this.host.declare(`declare zeroext i1 @scr_dyn_native_${t.kind}_is(ptr)`);
412
+ this.host.declare(`declare zeroext i1 @scr_dyn_native_collection_is(ptr, i32, ptr)`);
358
413
  const r = B.tmp();
359
- B.line(`${r} = call zeroext i1 @scr_dyn_native_${t.kind}_is(ptr %d)`);
414
+ const typed = t.kind === "map" ? t.key.kind !== "dyn" || t.value.kind !== "dyn" : t.elem.kind !== "dyn";
415
+ B.line(`${r} = call zeroext i1 @scr_dyn_native_collection_is(ptr %d, i32 ${t.kind === "map" ? 1 : 0}, ptr ${typed ? this.host.cstr(typeKey(t)) : "null"})`);
360
416
  B.terminate(`ret i1 ${r}`);
361
417
  break;
362
418
  }
363
419
  case "bigint":
364
420
  kindIs(DYN_KIND.BIGINT);
365
421
  break;
422
+ case "promise":
423
+ kindIs(DYN_KIND.PROMISE);
424
+ break;
366
425
  case "symbol":
367
426
  kindIs(DYN_KIND.SYMBOL);
368
427
  break;
@@ -393,7 +452,12 @@ export class LlDyn {
393
452
  break;
394
453
  }
395
454
  case "func":
396
- kindIs(DYN_KIND.FUNC);
455
+ this.host.declare(`declare zeroext i1 @scr_dyn_is_callable(ptr)`);
456
+ {
457
+ const matched = B.tmp();
458
+ B.line(`${matched} = call zeroext i1 @scr_dyn_is_callable(ptr %d)`);
459
+ B.terminate(`ret i1 ${matched}`);
460
+ }
397
461
  break;
398
462
  case "classval": {
399
463
  this.host.declare(`declare zeroext i1 @scr_dyn_class_is(ptr, ptr)`);
@@ -465,28 +529,26 @@ export class LlDyn {
465
529
  const isObj = B.tmp();
466
530
  B.line(`${isObj} = icmp eq i32 ${kd}, ${DYN_KIND.OBJ}`);
467
531
  const l0 = B.newLabel("dm.o");
468
- B.condBr(isObj, l0, fail);
532
+ let readable = isObj;
533
+ if (!shape.indexValue) {
534
+ const proxy = B.tmp();
535
+ readable = B.tmp();
536
+ B.line(`${proxy} = icmp eq i32 ${kd}, ${DYN_KIND.PROXY}`);
537
+ B.line(`${readable} = or i1 ${isObj}, ${proxy}`);
538
+ }
539
+ B.condBr(readable, l0, fail);
469
540
  B.startBlock(l0);
470
541
  // dyn ('unknown') fields match ANY value, present or missing.
471
542
  for (const f of shape.fields) {
472
543
  if (f.type.kind === "dyn")
473
544
  continue;
474
- const m = this.objGetLit(B, "%d", f.name);
475
- const has = B.tmp();
476
- B.line(`${has} = icmp ne ptr ${m}, null`);
477
- const lTest = B.newLabel("dm.t");
545
+ const m = this.objReadLit(B, "%d", f.name);
478
546
  const lNext = B.newLabel("dm.n");
479
- if (undefinedArmTag(f.type, this.host.unionsById) >= 0) {
480
- // Optional-flavored field: a MISSING key is the undefined arm
481
- // (a match); a PRESENT key must fit the union as usual.
482
- B.condBr(has, lTest, lNext);
483
- }
484
- else {
485
- B.condBr(has, lTest, fail);
486
- }
487
- B.startBlock(lTest);
547
+ this.host.declare(`declare void @scr_dyn_release(ptr)`);
548
+ this.pendingBail(B, "dm.read", () => B.line(`call void @scr_dyn_release(ptr ${m})`), "i1 false");
488
549
  const ok = B.tmp();
489
550
  B.line(`${ok} = call zeroext i1 @${this.dynMatchHelper(f.type)}(ptr ${m})`);
551
+ B.line(`call void @scr_dyn_release(ptr ${m})`);
490
552
  B.condBr(ok, lNext, fail);
491
553
  B.startBlock(lNext);
492
554
  }
@@ -543,7 +605,16 @@ export class LlDyn {
543
605
  B.startBlock(l0);
544
606
  const n = this.lenOf(B, "%d");
545
607
  const items = this.itemsOf(B, "%d");
546
- this.i64Loop(B, "dm.el", n, (i) => {
608
+ this.i64Loop(B, "dm.el", n, (i, brNext) => {
609
+ this.host.declare(`declare zeroext i1 @scr_dyn_arr_has_index(ptr, ${this.S})`);
610
+ const present = B.tmp();
611
+ B.line(`${present} = call zeroext i1 @scr_dyn_arr_has_index(ptr %d, ${this.S} ${i})`);
612
+ const valueLabel = B.newLabel("dm.present");
613
+ const holeLabel = B.newLabel("dm.hole");
614
+ B.condBr(present, valueLabel, holeLabel);
615
+ B.startBlock(holeLabel);
616
+ brNext();
617
+ B.startBlock(valueLabel);
547
618
  const e = this.itemAt(B, items, i);
548
619
  const ok = B.tmp();
549
620
  B.line(`${ok} = call zeroext i1 @${m}(ptr ${e})`);
@@ -625,6 +696,17 @@ export class LlDyn {
625
696
  }
626
697
  if (isRefCounted(t) && t.kind !== "dyn") {
627
698
  host.declare(`declare ptr @scr_dyn_typed_ref_unbox(ptr)`);
699
+ if (t.kind === "object" && t.className === "%Error") {
700
+ host.declare(`declare ptr @scr_errdyn_err_of(ptr)`);
701
+ const error = B.tmp(), found = B.tmp();
702
+ B.line(`${error} = call ptr @scr_errdyn_err_of(ptr %d)`);
703
+ B.line(`${found} = icmp ne ptr ${error}, null`);
704
+ const yes = B.newLabel("dc.error"), next = B.newLabel("dc.noterror");
705
+ B.condBr(found, yes, next);
706
+ B.startBlock(yes);
707
+ B.terminate(`ret ptr ${error}`);
708
+ B.startBlock(next);
709
+ }
628
710
  const matched = this.typedRefMatches(B, t);
629
711
  const lRef = B.newLabel("dc.tr");
630
712
  const lNext = B.newLabel("dc.nt");
@@ -637,7 +719,7 @@ export class LlDyn {
637
719
  if (t.kind !== "union") {
638
720
  host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
639
721
  host.declare(`declare ptr @scr_dyn_typed_ref_cached_cast(ptr, ptr, ${host.sizeType})`);
640
- host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, ${host.sizeType}, ptr, ptr, ptr)`);
722
+ host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, ${host.sizeType}, ptr, ptr, ptr, i1)`);
641
723
  host.declare(`declare void @scr_dyn_release_v(ptr)`);
642
724
  const rc = vAdapters(host, t);
643
725
  const kind = this.kindOf(B, "%d");
@@ -735,7 +817,7 @@ export class LlDyn {
735
817
  B.line(`call void ${releaseSym(host, t)}(ptr ${checked})`);
736
818
  B.terminate(`ret ptr ${cached}`);
737
819
  B.startBlock(lCache);
738
- B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
820
+ B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release}, i1 ${traceAdapter(host, t) !== null ? "true" : "false"})`);
739
821
  B.terminate(`ret ptr ${checked}`);
740
822
  }
741
823
  else {
@@ -743,7 +825,7 @@ export class LlDyn {
743
825
  const lReturn = B.newLabel("dc.tr.ret");
744
826
  B.condBr(ok, lCache, lReturn);
745
827
  B.startBlock(lCache);
746
- B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
828
+ B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release}, i1 ${traceAdapter(host, t) !== null ? "true" : "false"})`);
747
829
  B.br(lReturn);
748
830
  B.startBlock(lReturn);
749
831
  B.terminate(`ret ptr ${checked}`);
@@ -765,10 +847,19 @@ export class LlDyn {
765
847
  B.startBlock(lo);
766
848
  };
767
849
  switch (t.kind) {
768
- case "url": {
769
- host.declare(`declare ptr @scr_dyn_native_url_check(ptr, ptr)`);
850
+ case "date": {
851
+ host.declare(`declare double @scr_dyn_native_date_value(ptr)`);
770
852
  const r = B.tmp();
771
- B.line(`${r} = call ptr @scr_dyn_native_url_check(ptr %d, ptr %path)`);
853
+ B.line(`${r} = call double @scr_dyn_native_date_value(ptr %d)`);
854
+ B.terminate(`ret double ${r}`);
855
+ break;
856
+ }
857
+ case "url":
858
+ case "searchParams": {
859
+ const native = t.kind === "url" ? "url" : "search_params";
860
+ host.declare(`declare ptr @scr_dyn_native_${native}_check(ptr, ptr)`);
861
+ const r = B.tmp();
862
+ B.line(`${r} = call ptr @scr_dyn_native_${native}_check(ptr %d, ptr %path)`);
772
863
  B.terminate(`ret ptr ${r}`);
773
864
  break;
774
865
  }
@@ -781,9 +872,10 @@ export class LlDyn {
781
872
  }
782
873
  case "map":
783
874
  case "set": {
784
- host.declare(`declare ptr @scr_dyn_native_${t.kind}_check(ptr, ptr)`);
875
+ host.declare(`declare ptr @scr_dyn_native_collection_check(ptr, i32, ptr, ptr)`);
785
876
  const r = B.tmp();
786
- B.line(`${r} = call ptr @scr_dyn_native_${t.kind}_check(ptr %d, ptr %path)`);
877
+ const typed = t.kind === "map" ? t.key.kind !== "dyn" || t.value.kind !== "dyn" : t.elem.kind !== "dyn";
878
+ B.line(`${r} = call ptr @scr_dyn_native_collection_check(ptr %d, i32 ${t.kind === "map" ? 1 : 0}, ptr ${typed ? host.cstr(typeKey(t)) : "null"}, ptr %path)`);
787
879
  B.terminate(`ret ptr ${r}`);
788
880
  break;
789
881
  }
@@ -855,6 +947,24 @@ export class LlDyn {
855
947
  B.line(`call void @scr_dyn_check_fail(ptr %path, ptr ${want}, ptr %d)`);
856
948
  B.terminate(`ret ptr null`);
857
949
  break;
950
+ case "promise": {
951
+ requireKind(DYN_KIND.PROMISE, "dc");
952
+ host.declare(`declare ptr @scr_promise_retain(ptr)`);
953
+ const promise = this.payloadOf(B, "%d", "ptr"), retained = B.tmp();
954
+ if (t.inner.kind !== "dyn") {
955
+ host.declare(`declare ptr @scr_promise_new()`);
956
+ host.declare(`declare void @scr_promise_race_add(ptr, ptr, ptr)`);
957
+ B.line(`${retained} = call ptr @scr_promise_new()`);
958
+ host.declare(`declare void @scr_promise_share_identity(ptr, ptr)`);
959
+ B.line(`call void @scr_promise_share_identity(ptr ${retained}, ptr ${promise})`);
960
+ B.line(`call void @scr_promise_race_add(ptr ${retained}, ptr ${promise}, ptr @${host.dynPromiseAdapter(t.inner)})`);
961
+ B.terminate(`ret ptr ${retained}`);
962
+ break;
963
+ }
964
+ B.line(`${retained} = call ptr @scr_promise_retain(ptr ${promise})`);
965
+ B.terminate(`ret ptr ${retained}`);
966
+ break;
967
+ }
858
968
  case "object": {
859
969
  // The %Error extraction (an instanceof-Error narrow on unknown):
860
970
  // validate the checked-dynamic tree's error encoding — the reserved "%error" marker
@@ -969,7 +1079,20 @@ export class LlDyn {
969
1079
  B.terminate(`ret ptr %r0`);
970
1080
  break;
971
1081
  }
972
- requireKind(DYN_KIND.OBJ, "dcr");
1082
+ if (shape.indexValue)
1083
+ requireKind(DYN_KIND.OBJ, "dcr");
1084
+ else {
1085
+ const kind = this.kindOf(B, "%d"), object = B.tmp(), proxy = B.tmp(), readable = B.tmp();
1086
+ B.line(`${object} = icmp eq i32 ${kind}, ${DYN_KIND.OBJ}`);
1087
+ B.line(`${proxy} = icmp eq i32 ${kind}, ${DYN_KIND.PROXY}`);
1088
+ B.line(`${readable} = or i1 ${object}, ${proxy}`);
1089
+ const ok = B.newLabel("dcr.object"), fail = B.newLabel("dcr.fail");
1090
+ B.condBr(readable, ok, fail);
1091
+ B.startBlock(fail);
1092
+ B.line(`call void @scr_dyn_check_fail(ptr %path, ptr ${want}, ptr %d)`);
1093
+ B.terminate(`ret ptr null`);
1094
+ B.startBlock(ok);
1095
+ }
973
1096
  if (shape.fields.length === 0 && !shape.indexValue) {
974
1097
  const sourceAccessor = `${this.toDynHelper(t)}_source_access`;
975
1098
  const rc = vAdapters(host, t);
@@ -987,61 +1110,15 @@ export class LlDyn {
987
1110
  }
988
1111
  B.line(`%r0 = call ptr @${mangleRecordNew(t.shapeId)}()`);
989
1112
  for (const f of shape.fields) {
990
- const fieldWant = host.cstr(dynDesc(f.type, this.host.recordsById, this.host.unionsById));
991
- const utag = f.type.kind === "union" ? undefinedArmTag(f.type, host.unionsById) : -1;
992
- const m = this.objGetLit(B, "%d", f.name);
993
- if (f.type.kind === "dyn") {
994
- // An `unknown` field: a present key passes through, a missing
995
- // one IS the undefined dyn value. Go through the dyn builder so
996
- // a Web-stream typed-ref capsule cannot escape inside a checked
997
- // record field.
998
- const has = B.tmp();
999
- B.line(`${has} = icmp ne ptr ${m}, null`);
1000
- const sel = B.tmp();
1001
- const u = this.undef(B);
1002
- B.line(`${sel} = select i1 ${has}, ptr ${m}, ptr ${u}`);
1003
- const value = B.tmp();
1004
- B.line(`${value} = call ptr @${this.dynCheckHelper(f.type)}(ptr ${sel}, ptr ${pathSlot})`);
1005
- storeInto(f.name, f.type, value);
1006
- }
1007
- else if (utag >= 0 && f.type.kind === "union") {
1008
- const unit = host.unitInstanceRef(f.type.unionId, utag);
1009
- const has = B.tmp();
1010
- B.line(`${has} = icmp ne ptr ${m}, null`);
1011
- const lp = B.newLabel("dcr.p");
1012
- const la = B.newLabel("dcr.a");
1013
- const lj = B.newLabel("dcr.j");
1014
- B.condBr(has, lp, la);
1015
- B.startBlock(la);
1016
- storeInto(f.name, f.type, unit); // absent key -> the undefined arm
1017
- B.br(lj);
1018
- B.startBlock(lp);
1019
- setPath(f.name, "0");
1020
- const v = B.tmp();
1021
- B.line(`${v} = call ptr @${this.dynCheckHelper(f.type)}(ptr ${m}, ptr ${pathSlot})`);
1022
- storeInto(f.name, f.type, v);
1023
- this.pendingBail(B, "dcr", releaseR, "ptr null");
1024
- B.br(lj);
1025
- B.startBlock(lj);
1026
- }
1027
- else {
1028
- const has = B.tmp();
1029
- B.line(`${has} = icmp ne ptr ${m}, null`);
1030
- const lp = B.newLabel("dcr.p");
1031
- const la = B.newLabel("dcr.a");
1032
- B.condBr(has, lp, la);
1033
- B.startBlock(la);
1034
- setPath(f.name, "0");
1035
- B.line(`call void @scr_dyn_check_fail(ptr ${pathSlot}, ptr ${fieldWant}, ptr null)`);
1036
- releaseR();
1037
- B.terminate(`ret ptr null`);
1038
- B.startBlock(lp);
1039
- setPath(f.name, "0");
1040
- const v = B.tmp();
1041
- B.line(`${v} = call ${this.valTy(f.type)} @${this.dynCheckHelper(f.type)}(ptr ${m}, ptr ${pathSlot})`);
1042
- storeInto(f.name, f.type, v);
1043
- this.pendingBail(B, "dcr", releaseR, "ptr null");
1044
- }
1113
+ const m = this.objReadLit(B, "%d", f.name);
1114
+ host.declare(`declare void @scr_dyn_release(ptr)`);
1115
+ this.pendingBail(B, "dcr.read", () => { B.line(`call void @scr_dyn_release(ptr ${m})`); releaseR(); }, "ptr null");
1116
+ setPath(f.name, "0");
1117
+ const value = B.tmp();
1118
+ B.line(`${value} = call ${this.valTy(f.type)} @${this.dynCheckHelper(f.type)}(ptr ${m}, ptr ${pathSlot})`);
1119
+ B.line(`call void @scr_dyn_release(ptr ${m})`);
1120
+ storeInto(f.name, f.type, value);
1121
+ this.pendingBail(B, "dcr", releaseR, "ptr null");
1045
1122
  }
1046
1123
  // Index-signature shapes CAPTURE undeclared keys into the
1047
1124
  // overflow map.
@@ -1123,6 +1200,22 @@ export class LlDyn {
1123
1200
  const accTy = acc === "f64" ? "double" : acc === "bool" ? "i1" : "ptr";
1124
1201
  host.declare(`declare double @scr_arr_push_${acc}(ptr, ${acc === "bool" ? "i1 zeroext" : accTy})`);
1125
1202
  this.i64Loop(B, "dca", n, (i) => {
1203
+ host.declare(`declare zeroext i1 @scr_dyn_arr_has_index(ptr, ${this.S})`);
1204
+ const present = B.tmp();
1205
+ B.line(`${present} = call zeroext i1 @scr_dyn_arr_has_index(ptr %d, ${this.S} ${i})`);
1206
+ const valueLabel = B.newLabel("dca.present");
1207
+ const holeLabel = B.newLabel("dca.hole");
1208
+ const doneLabel = B.newLabel("dca.done");
1209
+ B.condBr(present, valueLabel, holeLabel);
1210
+ B.startBlock(holeLabel);
1211
+ host.declare(`declare void @scr_arr_set_len(ptr, double)`);
1212
+ const index = B.tmp();
1213
+ const length = B.tmp();
1214
+ B.line(`${index} = uitofp ${this.S} ${i} to double`);
1215
+ B.line(`${length} = fadd double ${index}, 1.0`);
1216
+ B.line(`call void @scr_arr_set_len(ptr ${a}, double ${length})`);
1217
+ B.br(doneLabel);
1218
+ B.startBlock(valueLabel);
1126
1219
  const pp = B.tmp();
1127
1220
  const kp = B.tmp();
1128
1221
  const ip = B.tmp();
@@ -1141,6 +1234,8 @@ export class LlDyn {
1141
1234
  }, "ptr null");
1142
1235
  const pushed = B.tmp();
1143
1236
  B.line(`${pushed} = call double @scr_arr_push_${acc}(ptr ${a}, ${accTy} ${v})`);
1237
+ B.br(doneLabel);
1238
+ B.startBlock(doneLabel);
1144
1239
  });
1145
1240
  B.terminate(`ret ptr ${a}`);
1146
1241
  break;
@@ -1194,7 +1289,7 @@ export class LlDyn {
1194
1289
  // live narrowed alias).
1195
1290
  host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
1196
1291
  host.declare(`declare ptr @scr_dyn_typed_ref_cached_cast(ptr, ptr, ${host.sizeType})`);
1197
- host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, ${host.sizeType}, ptr, ptr, ptr)`);
1292
+ host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, ${host.sizeType}, ptr, ptr, ptr, i1)`);
1198
1293
  host.declare(`declare void @scr_dyn_release_v(ptr)`);
1199
1294
  host.declare(`declare void @scr_union_release(ptr)`);
1200
1295
  const rc = vAdapters(host, t);
@@ -1255,7 +1350,7 @@ export class LlDyn {
1255
1350
  B.line(`call void @scr_union_release(ptr ${checked})`);
1256
1351
  B.terminate(`ret ptr ${cached}`);
1257
1352
  B.startBlock(lCache);
1258
- B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
1353
+ B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, ${host.sizeType} ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release}, i1 ${traceAdapter(host, t) !== null ? "true" : "false"})`);
1259
1354
  B.terminate(`ret ptr ${checked}`);
1260
1355
  B.startBlock(lFail);
1261
1356
  B.line(`call void @scr_dyn_check_fail(ptr %path, ptr ${want}, ptr %d)`);
@@ -1269,7 +1364,22 @@ export class LlDyn {
1269
1364
  // caps[0] obj-box owns the dyn value (untraced).
1270
1365
  const adapter = this.dynFuncAdapterHelper(t);
1271
1366
  const sigLit = host.cstr(key);
1272
- requireKind(DYN_KIND.FUNC, "dcf");
1367
+ const lWrap = B.newLabel("dcf.w");
1368
+ host.declare(`declare zeroext i1 @scr_dyn_is_callable(ptr)`);
1369
+ const callable = B.tmp();
1370
+ const valid = B.newLabel("dcf.k");
1371
+ const invalid = B.newLabel("dcf.f");
1372
+ B.line(`${callable} = call zeroext i1 @scr_dyn_is_callable(ptr %d)`);
1373
+ B.condBr(callable, valid, invalid);
1374
+ B.startBlock(invalid);
1375
+ B.line(`call void @scr_dyn_check_fail(ptr %path, ptr ${want}, ptr %d)`);
1376
+ B.terminate(`ret ${dummy}`);
1377
+ B.startBlock(valid);
1378
+ const direct = B.tmp();
1379
+ const lSignature = B.newLabel("dcf.signature");
1380
+ B.line(`${direct} = icmp eq i32 ${this.kindOf(B, "%d")}, ${DYN_KIND.FUNC}`);
1381
+ B.condBr(direct, lSignature, lWrap);
1382
+ B.startBlock(lSignature);
1273
1383
  host.declare(`declare i32 @strcmp(ptr, ptr)`);
1274
1384
  const sigp = B.tmp();
1275
1385
  const sig = B.tmp();
@@ -1280,7 +1390,6 @@ export class LlDyn {
1280
1390
  B.line(`${cmp} = call i32 @strcmp(ptr ${sig}, ptr ${sigLit})`);
1281
1391
  B.line(`${same} = icmp eq i32 ${cmp}, 0`);
1282
1392
  const lSame = B.newLabel("dcf.s");
1283
- const lWrap = B.newLabel("dcf.w");
1284
1393
  B.condBr(same, lSame, lWrap);
1285
1394
  B.startBlock(lSame);
1286
1395
  host.declare(`declare ptr @scr_closure_retain_v(ptr)`);
@@ -1300,14 +1409,14 @@ export class LlDyn {
1300
1409
  host.declare(`declare void @scr_dyn_release_v(ptr)`);
1301
1410
  const a = B.tmp();
1302
1411
  B.line(`${a} = call ptr @scr_closure_new(ptr @${adapter}, ${host.sizeType} 1)`);
1303
- const sourceClosure = this.payloadOf(B, "%d", "ptr");
1304
- const sourceKind = B.tmp();
1412
+ host.declare(`declare i32 @scr_dyn_function_kind(ptr)`);
1305
1413
  const functionKind = B.tmp();
1306
1414
  const targetKind = B.tmp();
1307
- B.line(`${sourceKind} = getelementptr inbounds %ScrClosure, ptr ${sourceClosure}, i64 0, i32 4`);
1308
- B.line(`${functionKind} = load i32, ptr ${sourceKind}`);
1415
+ B.line(`${functionKind} = call i32 @scr_dyn_function_kind(ptr %d)`);
1309
1416
  B.line(`${targetKind} = getelementptr inbounds %ScrClosure, ptr ${a}, i64 0, i32 4`);
1310
- B.line(`store i32 ${functionKind}, ptr ${targetKind}`);
1417
+ const adapterKind = B.tmp();
1418
+ B.line(`${adapterKind} = or i32 ${functionKind}, 8 ; preserves the checked callable in caps[0]`);
1419
+ B.line(`store i32 ${adapterKind}, ptr ${targetKind}`);
1311
1420
  const box = B.tmp();
1312
1421
  B.line(`${box} = call ptr @scr_box_new_obj(ptr @scr_dyn_retain_v, ptr @scr_dyn_release_v, ptr @scr_dyn_trace_v)`);
1313
1422
  const capp = B.tmp();
@@ -1351,10 +1460,12 @@ export class LlDyn {
1351
1460
  const B = new BlockBuilder();
1352
1461
  let sourceAccessor = null;
1353
1462
  switch (t.kind) {
1354
- case "url": {
1355
- host.declare(`declare ptr @scr_dyn_native_url(ptr)`);
1463
+ case "url":
1464
+ case "searchParams": {
1465
+ const native = t.kind === "url" ? "url" : "search_params";
1466
+ host.declare(`declare ptr @scr_dyn_native_${native}(ptr)`);
1356
1467
  const r = B.tmp();
1357
- B.line(`${r} = call ptr @scr_dyn_native_url(ptr %v)`);
1468
+ B.line(`${r} = call ptr @scr_dyn_native_${native}(ptr %v)`);
1358
1469
  B.terminate(`ret ptr ${r}`);
1359
1470
  break;
1360
1471
  }
@@ -1368,6 +1479,10 @@ export class LlDyn {
1368
1479
  case "map":
1369
1480
  case "set": {
1370
1481
  host.declare(`declare ptr @scr_dyn_native_${t.kind}(ptr)`);
1482
+ if (t.kind === "map" ? t.key.kind !== "dyn" || t.value.kind !== "dyn" : t.elem.kind !== "dyn") {
1483
+ host.declare(`declare void @scr_map_dyn_attach(ptr, ptr)`);
1484
+ B.line(`call void @scr_map_dyn_attach(ptr %v, ptr @${this.collectionDynOps(t)})`);
1485
+ }
1371
1486
  const r = B.tmp();
1372
1487
  B.line(`${r} = call ptr @scr_dyn_native_${t.kind}(ptr %v)`);
1373
1488
  B.terminate(`ret ptr ${r}`);
@@ -1637,9 +1752,19 @@ export class LlDyn {
1637
1752
  const state = B.tmp();
1638
1753
  const undefinedState = B.tmp();
1639
1754
  const undefinedLabel = B.newLabel("tda.undefined");
1755
+ const holeLabel = B.newLabel("tda.hole");
1756
+ const presentLabel = B.newLabel("tda.present");
1640
1757
  const valueLabel = B.newLabel("tda.value");
1641
1758
  const doneLabel = B.newLabel("tda.done");
1642
1759
  B.line(`${state} = call double @scr_arr_state(ptr %v, double ${i})`);
1760
+ const hole = B.tmp();
1761
+ B.line(`${hole} = fcmp oeq double ${state}, 0.0`); // SCR_ARR_HOLE
1762
+ B.condBr(hole, holeLabel, presentLabel);
1763
+ B.startBlock(holeLabel);
1764
+ host.declare(`declare void @scr_dyn_arr_push_hole(ptr)`);
1765
+ B.line(`call void @scr_dyn_arr_push_hole(ptr ${d})`);
1766
+ B.br(doneLabel);
1767
+ B.startBlock(presentLabel);
1643
1768
  B.line(`${undefinedState} = fcmp oeq double ${state}, 2.0`); // SCR_ARR_UNDEFINED
1644
1769
  B.terminate(`br i1 ${undefinedState}, label %${undefinedLabel}, label %${valueLabel}`);
1645
1770
  B.startBlock(undefinedLabel);
@@ -1676,6 +1801,8 @@ export class LlDyn {
1676
1801
  B.terminate(`br label %${doneLabel}`);
1677
1802
  B.startBlock(doneLabel);
1678
1803
  });
1804
+ host.declare(`declare void @scr_arr_copy_metadata(ptr, ptr)`);
1805
+ B.line(`call void @scr_arr_copy_metadata(ptr %v, ptr ${d})`);
1679
1806
  if (cyclicArr)
1680
1807
  B.line(`call void @scr_dyn_from_leave()`);
1681
1808
  host.declare(`declare ptr @scr_dyn_mark_snapshot(ptr)`);
@@ -2818,14 +2945,13 @@ export class LlDyn {
2818
2945
  const materialized = B.tmp();
2819
2946
  const out = B.tmp();
2820
2947
  B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
2821
- B.line(`${out} = call ptr @${name}(ptr ${materialized}, ${host.sizeType} %n)`);
2948
+ B.line(`${out} = call ptr @${name}(ptr ${materialized}, ${host.sizeType} %n, ptr %spelling)`);
2822
2949
  B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
2823
2950
  B.terminate(`ret ptr ${out}`);
2824
2951
  B.startBlock(lNext);
2825
2952
  }
2826
- // ISLAND-held sources: an engine array IS iterable — the not-iterable
2827
- // TypeError below would be a wrong claim. Loud fence (lane
2828
- // dyn-routing-ops).
2953
+ // Island-held sources keep the engine's iterator and IteratorClose
2954
+ // behavior while returning checked values for the destructuring slots.
2829
2955
  {
2830
2956
  const isJv = B.tmp();
2831
2957
  B.line(`${isJv} = icmp eq i32 ${kd}, ${DYN_KIND.JSVAL}`);
@@ -2833,10 +2959,12 @@ export class LlDyn {
2833
2959
  const lNotJv = B.newLabel("din.njv");
2834
2960
  B.condBr(isJv, lJv, lNotJv);
2835
2961
  B.startBlock(lJv);
2836
- host.declare(`declare zeroext i1 @scr_dyn_isl_fence(ptr, ptr)`);
2837
- const f = B.tmp();
2838
- B.line(`${f} = call zeroext i1 @scr_dyn_isl_fence(ptr %d, ptr ${host.cstr("iteration")})`);
2839
- B.terminate(`ret ptr null`);
2962
+ host.declare(`declare ptr @scr_dyn_jsval_iter_n(ptr, double)`);
2963
+ const count = B.tmp();
2964
+ const out = B.tmp();
2965
+ B.line(`${count} = uitofp ${host.sizeType} %n to double`);
2966
+ B.line(`${out} = call ptr @scr_dyn_jsval_iter_n(ptr %d, double ${count})`);
2967
+ B.terminate(`ret ptr ${out}`);
2840
2968
  B.startBlock(lNotJv);
2841
2969
  }
2842
2970
  const okA = B.tmp();
@@ -2857,6 +2985,17 @@ export class LlDyn {
2857
2985
  const buf = "%dib";
2858
2986
  B.entryAllocas.push(`${buf} = alloca %ScrJsonBuf`);
2859
2987
  B.line(`call void @scr_jb_init(ptr ${buf})`);
2988
+ const hasSpelling = B.tmp();
2989
+ B.line(`${hasSpelling} = icmp ne ptr %spelling, null`);
2990
+ const named = B.newLabel("din.named"), unnamed = B.newLabel("din.unnamed");
2991
+ B.condBr(hasSpelling, named, unnamed);
2992
+ B.startBlock(named);
2993
+ B.line(`call void @scr_jb_puts(ptr ${buf}, ptr %spelling)`);
2994
+ const namedMessage = B.tmp();
2995
+ B.line(`${namedMessage} = call ptr @scr_jb_finish(ptr ${buf})`);
2996
+ B.line(`call void @scr_throw_error(i32 1, ptr ${namedMessage})`);
2997
+ B.terminate(`ret ptr null`);
2998
+ B.startBlock(unnamed);
2860
2999
  const lU = B.newLabel("din.u");
2861
3000
  const lN = B.newLabel("din.n");
2862
3001
  const lB2 = B.newLabel("din.b");
@@ -3036,7 +3175,7 @@ export class LlDyn {
3036
3175
  B.line(`call void @scr_dyn_arr_push(ptr ${out}, ptr ${item}) ; push takes ownership`);
3037
3176
  });
3038
3177
  B.terminate(`ret ptr ${out}`);
3039
- this.defs.push(`define internal ptr @${name}(ptr %d, ${host.sizeType} %n) ${FN_ATTRS} { ; destructuring GetIterator + N steps`, B.render(), `}`, ``);
3178
+ this.defs.push(`define internal ptr @${name}(ptr %d, ${host.sizeType} %n, ptr %spelling) ${FN_ATTRS} { ; destructuring GetIterator + N steps`, B.render(), `}`, ``);
3040
3179
  return name;
3041
3180
  }
3042
3181
  /* ── the checked-dynamic function boundary (ported) ────────────────── */