@scriptc/compiler 0.1.3 → 0.1.5

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 (217) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +275 -62
  2. package/dist/backend/c/async.d.ts +25 -0
  3. package/dist/backend/c/async.js +167 -0
  4. package/dist/backend/c/async.js.map +1 -1
  5. package/dist/backend/c/c-emitter.d.ts +15 -1
  6. package/dist/backend/c/c-emitter.js +36 -11
  7. package/dist/backend/c/c-emitter.js.map +1 -1
  8. package/dist/backend/c/exprs.d.ts +2 -2
  9. package/dist/backend/c/exprs.js +556 -71
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/stmts.js +5 -3
  12. package/dist/backend/c/stmts.js.map +1 -1
  13. package/dist/backend/c/types.d.ts +2 -3
  14. package/dist/backend/c/types.js +10 -1
  15. package/dist/backend/c/types.js.map +1 -1
  16. package/dist/backend/c/walkers.js +1 -1
  17. package/dist/backend/c/walkers.js.map +1 -1
  18. package/dist/backend/link-plan.d.ts +3 -1
  19. package/dist/backend/link-plan.js +3 -1
  20. package/dist/backend/link-plan.js.map +1 -1
  21. package/dist/backend/llvm/dyn.js +1 -1
  22. package/dist/backend/llvm/dyn.js.map +1 -1
  23. package/dist/backend/llvm/emitter.js +42 -12
  24. package/dist/backend/llvm/emitter.js.map +1 -1
  25. package/dist/backend/llvm/expr-bytes.d.ts +1 -2
  26. package/dist/backend/llvm/expr-bytes.js +28 -23
  27. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  28. package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
  29. package/dist/backend/llvm/expr-callbacks.js +125 -0
  30. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  31. package/dist/backend/llvm/expr-containers.d.ts +1 -0
  32. package/dist/backend/llvm/expr-containers.js +32 -4
  33. package/dist/backend/llvm/expr-containers.js.map +1 -1
  34. package/dist/backend/llvm/expr-context.d.ts +19 -3
  35. package/dist/backend/llvm/expr-dispatch.js +1 -0
  36. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  37. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  38. package/dist/backend/llvm/expr-primitives.js +49 -13
  39. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  40. package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
  41. package/dist/backend/llvm/expr-primitives.test.js +38 -0
  42. package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
  43. package/dist/backend/llvm/expr-stream-callbacks.d.ts +3 -0
  44. package/dist/backend/llvm/expr-stream-callbacks.js +69 -0
  45. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  46. package/dist/backend/llvm/lib-filesystem.js +80 -10
  47. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  48. package/dist/backend/llvm/lib-network.js +69 -10
  49. package/dist/backend/llvm/lib-network.js.map +1 -1
  50. package/dist/backend/llvm/lib-process.js +156 -6
  51. package/dist/backend/llvm/lib-process.js.map +1 -1
  52. package/dist/backend/llvm/lib-shared.js +100 -0
  53. package/dist/backend/llvm/lib-shared.js.map +1 -1
  54. package/dist/backend/llvm/lib-stream.js +23 -0
  55. package/dist/backend/llvm/lib-stream.js.map +1 -1
  56. package/dist/backend/native-toolchain.d.ts +5 -0
  57. package/dist/backend/native-toolchain.js +4 -1
  58. package/dist/backend/native-toolchain.js.map +1 -1
  59. package/dist/backend/runtime-pack.test.js +28 -10
  60. package/dist/backend/runtime-pack.test.js.map +1 -1
  61. package/dist/backend/targets.d.ts +7 -0
  62. package/dist/backend/targets.js +26 -0
  63. package/dist/backend/targets.js.map +1 -1
  64. package/dist/backend/targets.test.js +8 -1
  65. package/dist/backend/targets.test.js.map +1 -1
  66. package/dist/coverage/surface-manifest.js +14 -4
  67. package/dist/coverage/surface-manifest.js.map +1 -1
  68. package/dist/diagnostics/diagnostic.js +1 -1
  69. package/dist/diagnostics/diagnostic.js.map +1 -1
  70. package/dist/executable/executable-cache.d.ts +4 -0
  71. package/dist/executable/executable-cache.js +6 -1
  72. package/dist/executable/executable-cache.js.map +1 -1
  73. package/dist/executable/executable-cache.test.js +3 -3
  74. package/dist/executable/executable-cache.test.js.map +1 -1
  75. package/dist/frontend/fork-target.d.ts +17 -0
  76. package/dist/frontend/fork-target.js +256 -0
  77. package/dist/frontend/fork-target.js.map +1 -0
  78. package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
  79. package/dist/frontend/lowering/abstract-equality.js +250 -0
  80. package/dist/frontend/lowering/abstract-equality.js.map +1 -0
  81. package/dist/frontend/lowering/containers/bytes.d.ts +1 -1
  82. package/dist/frontend/lowering/containers/bytes.js +6 -5
  83. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  84. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +7 -6
  85. package/dist/frontend/lowering/containers/string-and-regexp.js +237 -28
  86. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  87. package/dist/frontend/lowering/expressions/object-literals.js +8 -0
  88. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  89. package/dist/frontend/lowering/lower-assert.js +71 -2
  90. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  91. package/dist/frontend/lowering/lower-builtins.d.ts +54 -28
  92. package/dist/frontend/lowering/lower-builtins.js +957 -116
  93. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  94. package/dist/frontend/lowering/lower-calls.d.ts +32 -23
  95. package/dist/frontend/lowering/lower-calls.js +835 -206
  96. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  97. package/dist/frontend/lowering/lower-classes.js +41 -10
  98. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  99. package/dist/frontend/lowering/lower-containers.d.ts +7 -9
  100. package/dist/frontend/lowering/lower-containers.js +293 -51
  101. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  102. package/dist/frontend/lowering/lower-event-emitter.js +212 -21
  103. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  104. package/dist/frontend/lowering/lower-exprs.d.ts +12 -0
  105. package/dist/frontend/lowering/lower-exprs.js +263 -93
  106. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  107. package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
  108. package/dist/frontend/lowering/lower-inspect.js +1 -1
  109. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  110. package/dist/frontend/lowering/lower-island.d.ts +6 -3
  111. package/dist/frontend/lowering/lower-island.js +182 -12
  112. package/dist/frontend/lowering/lower-island.js.map +1 -1
  113. package/dist/frontend/lowering/lower-modules.d.ts +6 -0
  114. package/dist/frontend/lowering/lower-modules.js +184 -38
  115. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  116. package/dist/frontend/lowering/lower-namespaces.js +7 -0
  117. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  118. package/dist/frontend/lowering/lower-server.d.ts +3 -5
  119. package/dist/frontend/lowering/lower-server.js +413 -54
  120. package/dist/frontend/lowering/lower-server.js.map +1 -1
  121. package/dist/frontend/lowering/lower-stmts.js +122 -19
  122. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  123. package/dist/frontend/lowering/lower-stream.d.ts +3 -0
  124. package/dist/frontend/lowering/lower-stream.js +7 -0
  125. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  126. package/dist/frontend/lowering/lowerer.d.ts +86 -9
  127. package/dist/frontend/lowering/lowerer.js +449 -74
  128. package/dist/frontend/lowering/lowerer.js.map +1 -1
  129. package/dist/frontend/lowering/optional-arguments.d.ts +9 -1
  130. package/dist/frontend/lowering/optional-arguments.js +67 -1
  131. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  132. package/dist/frontend/lowering/pairs-snapshot.d.ts +3 -1
  133. package/dist/frontend/lowering/pairs-snapshot.js +12 -4
  134. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  135. package/dist/frontend/lowering/surfaces.d.ts +34 -14
  136. package/dist/frontend/lowering/surfaces.js +177 -104
  137. package/dist/frontend/lowering/surfaces.js.map +1 -1
  138. package/dist/frontend/npm-static-declarations.d.ts +4 -0
  139. package/dist/frontend/npm-static-declarations.js +56 -0
  140. package/dist/frontend/npm-static-declarations.js.map +1 -1
  141. package/dist/frontend/npm-static-declarations.test.js +23 -2
  142. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  143. package/dist/frontend/npm-static-prune.d.ts +6 -0
  144. package/dist/frontend/npm-static-prune.js +203 -0
  145. package/dist/frontend/npm-static-prune.js.map +1 -0
  146. package/dist/frontend/npm-static-prune.test.d.ts +1 -0
  147. package/dist/frontend/npm-static-prune.test.js +48 -0
  148. package/dist/frontend/npm-static-prune.test.js.map +1 -0
  149. package/dist/frontend/npm-static.js +6 -5
  150. package/dist/frontend/npm-static.js.map +1 -1
  151. package/dist/frontend/npm.d.ts +15 -3
  152. package/dist/frontend/npm.js +87 -14
  153. package/dist/frontend/npm.js.map +1 -1
  154. package/dist/frontend/npm.test.js +76 -9
  155. package/dist/frontend/npm.test.js.map +1 -1
  156. package/dist/frontend/program.js +107 -14
  157. package/dist/frontend/program.js.map +1 -1
  158. package/dist/frontend/provenance.js +8 -3
  159. package/dist/frontend/provenance.js.map +1 -1
  160. package/dist/frontend/resolve.d.ts +6 -0
  161. package/dist/frontend/resolve.js +7 -4
  162. package/dist/frontend/resolve.js.map +1 -1
  163. package/dist/frontend/type-mapper.d.ts +5 -0
  164. package/dist/frontend/type-mapper.js +80 -29
  165. package/dist/frontend/type-mapper.js.map +1 -1
  166. package/dist/index.d.ts +8 -3
  167. package/dist/index.js +34 -41
  168. package/dist/index.js.map +1 -1
  169. package/dist/ir/analysis.d.ts +5 -3
  170. package/dist/ir/analysis.js +25 -11
  171. package/dist/ir/analysis.js.map +1 -1
  172. package/dist/ir/analysis.test.js +50 -2
  173. package/dist/ir/analysis.test.js.map +1 -1
  174. package/dist/ir/constant-tables.d.ts +17 -0
  175. package/dist/ir/constant-tables.js +99 -0
  176. package/dist/ir/constant-tables.js.map +1 -0
  177. package/dist/ir/constant-tables.test.d.ts +1 -0
  178. package/dist/ir/constant-tables.test.js +78 -0
  179. package/dist/ir/constant-tables.test.js.map +1 -0
  180. package/dist/ir/integer-ranges.d.ts +13 -0
  181. package/dist/ir/integer-ranges.js +122 -0
  182. package/dist/ir/integer-ranges.js.map +1 -0
  183. package/dist/ir/integer-ranges.test.d.ts +1 -0
  184. package/dist/ir/integer-ranges.test.js +63 -0
  185. package/dist/ir/integer-ranges.test.js.map +1 -0
  186. package/dist/ir/ir.d.ts +130 -76
  187. package/dist/ir/ir.js +69 -4
  188. package/dist/ir/ir.js.map +1 -1
  189. package/dist/ir/ir.test.js +20 -1
  190. package/dist/ir/ir.test.js.map +1 -1
  191. package/dist/ir/scalar-records.d.ts +8 -0
  192. package/dist/ir/scalar-records.js +216 -0
  193. package/dist/ir/scalar-records.js.map +1 -0
  194. package/dist/ir/scalar-records.test.d.ts +1 -0
  195. package/dist/ir/scalar-records.test.js +142 -0
  196. package/dist/ir/scalar-records.test.js.map +1 -0
  197. package/dist/ir/serialize.d.ts +1 -1
  198. package/dist/ir/serialize.js +1 -1
  199. package/dist/ir/serialize.js.map +1 -1
  200. package/dist/ir/validate.js +256 -20
  201. package/dist/ir/validate.js.map +1 -1
  202. package/dist/ir/validate.test.d.ts +1 -0
  203. package/dist/ir/validate.test.js +31 -0
  204. package/dist/ir/validate.test.js.map +1 -0
  205. package/dist/library/cache-primitives.d.ts +1 -1
  206. package/dist/library/cache-primitives.js +3 -3
  207. package/dist/library/cache-primitives.js.map +1 -1
  208. package/dist/library/fence-eval.js +11 -4
  209. package/dist/library/fence-eval.js.map +1 -1
  210. package/dist/library/int-infer.test.js +4 -4
  211. package/dist/library/int-infer.test.js.map +1 -1
  212. package/dist/library/library-cache.js +0 -1
  213. package/dist/library/library-cache.js.map +1 -1
  214. package/dist/library/library-cache.test.js +8 -8
  215. package/dist/library/library-cache.test.js.map +1 -1
  216. package/package.json +17 -17
  217. package/surface-manifest.json +186 -79
@@ -1,12 +1,12 @@
1
1
  import { InternalCompilerError } from "../../errors.js";
2
- import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, CHILDWRITER_T, DYN, F64, islandPromisePayloadTag, isClassOwnEnumerableFieldName, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, RUNTIME_ERROR_CLASSES, STRING, typeEquals, typeKey } from "../../ir/ir.js";
2
+ import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, CHILDWRITER_T, DYN, F64, islandPromisePayloadTag, isClassOwnEnumerableFieldName, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, NETSOCKET_T, RUNTIME_ERROR_CLASSES, STRING, typeEquals, typeKey } from "../../ir/ir.js";
3
3
  import { boxAccess, BYTES_NUM_KIND_C, BYTES_NUM_VAR_C, bytesElemKindC, cDecl, cFnPtrCast, cNumberLiteral, cStringLiteral, cType, DV_GET_KIND_C, DV_SET_KIND_C, elemAccess, mapKeyAccess, mapKeyKindC, mapValKindC, releaseCallC, retainCallC, vAdapters } from "./types.js";
4
4
  import { mangleClassNew, mangleClassRetain, mangleClassStruct, mangleField, mangleFnClosure, mangleFunction, mangleGlobal, mangleLocal, mangleRecordClone, mangleRecordNew, mangleRecordStruct, mangleVtStruct } from "../mangle.js";
5
5
  import { OVERFLOW_MEMBER } from "./shapes.js";
6
6
  import { dynDestrCheckHelper, dynIterNHelper, dynKeyGetHelper } from "./walkers.js";
7
7
  import { collectFfiRetainedOps, parseFfiCallbackKey } from "../ffi-callbacks.js";
8
8
  import { genResultThunkFor } from "./async.js";
9
- import { isStableBytesOperand, matchStringSelfConcat, newValueMayThrow, streamTypedRefEligible, undefinedArmTag } from "../../ir/analysis.js";
9
+ import { isStableReceiverOperand, matchStringSelfConcat, newValueMayThrow, streamTypedRefEligible, undefinedArmTag } from "../../ir/analysis.js";
10
10
  function streamTypedRefCommitAdapter(emitter, t, snapshot, defs) {
11
11
  if (t.kind === "bytes") {
12
12
  const commit = `${snapshot}_commit`;
@@ -385,13 +385,13 @@ function dynPromiseAdapter(emitter, inner) {
385
385
  emitter.walkerDefs.push(`${sig} { /* checked-dynamic promise exit ${key} */`, ` ScrDyn *sc_d = (ScrDyn *)scr_promise_payload_ref(sc_src);`, ` ${cDecl(inner, "sc_v")} = ${emitter.dynCheckHelper(inner)}(sc_d, NULL);`, ` scr_dyn_release(sc_d);`, ` if (scr_exc_pending()) {`, ` scr_promise_reject_pending(sc_dst);`, ` return;`, ` }`, ` ${fulfill}`, `}`, ``);
386
386
  return sym;
387
387
  }
388
- /** Evaluate a bytes receiver as a borrow when it is a direct, unboxed
388
+ /** Evaluate a receiver as a borrow when it is a direct, unboxed
389
389
  * binding and all later operands are stable. The binding's scope/global
390
390
  * owner then keeps the value alive, avoiding retain/release traffic around
391
391
  * every indexed access. Any uncertain shape falls back to an owned temp. */
392
- export function emitBytesReceiver(emitter, receiver, following) {
392
+ export function emitStableReceiver(emitter, receiver, following) {
393
393
  if (receiver.kind === "varRef" &&
394
- following.every((operand) => isStableBytesOperand(operand, receiver.localId))) {
394
+ following.every((operand) => isStableReceiverOperand(operand, receiver.localId))) {
395
395
  const local = emitter.currentLocals.get(receiver.localId);
396
396
  if (local && !local.boxed) {
397
397
  return emitter.newBorrowedTemp(receiver.type, mangleLocal(receiver.localId));
@@ -547,6 +547,10 @@ function emitLiteralExpr(emitter, e) {
547
547
  const sym = emitter.internLiteral(e.value);
548
548
  return emitter.newTemp(e.type, retainCallC(e.type, `(ScrStr *)&${sym}`));
549
549
  }
550
+ case "moduleNsRef": {
551
+ const sym = emitter.internLiteral(`module:${e.moduleId}`);
552
+ return emitter.newTemp(e.type, retainCallC(e.type, `(ScrStr *)&${sym}`));
553
+ }
550
554
  case "unitLit":
551
555
  // unitLits are consumed inline by the unionWrap case (a unit arm is
552
556
  // tag-only); one reaching the generic dispatch escaped its wrap.
@@ -600,11 +604,36 @@ function emitLiteralExpr(emitter, e) {
600
604
  }
601
605
  }
602
606
  }
607
+ /** Unsigned operations avoid signed overflow and implementation-defined
608
+ * right shifts/conversions. Reinterpret the final bits numerically. */
609
+ function emitIntegerBits(emitter, e, left, right) {
610
+ const a = `sc_bits_${emitter.tempCounter++}`;
611
+ const out = `sc_bits_${emitter.tempCounter++}`;
612
+ emitter.line(`uint32_t ${a} = (uint32_t)(int64_t)${left};`);
613
+ let operation;
614
+ if (e.kind === "unary")
615
+ operation = `~${a}`;
616
+ else {
617
+ const b = `sc_bits_${emitter.tempCounter++}`;
618
+ const shift = e.op === "<<" || e.op === ">>" || e.op === ">>>";
619
+ emitter.line(`uint32_t ${b} = (uint32_t)(int64_t)${right}${shift ? " & 31u" : ""};`);
620
+ operation = e.op === ">>" ? `(${a} >> ${b}) | ((${a} & 0x80000000u) ? ~(UINT32_MAX >> ${b}) : 0u)`
621
+ : `${a} ${e.op === ">>>" ? ">>" : e.op} ${b}`;
622
+ }
623
+ emitter.line(`uint32_t ${out} = ${operation};`);
624
+ return emitter.newTemp(e.type, e.op === ">>>" ? `(double)${out}` : `(double)${out} - ((${out} & 0x80000000u) ? 4294967296.0 : 0.0)`);
625
+ }
603
626
  function emitOperatorExpr(emitter, e) {
604
627
  switch (e.kind) {
605
628
  case "bin": {
606
629
  const l = emitter.emitExpr(e.left);
607
630
  const r = emitter.emitExpr(e.right);
631
+ if ((e.op === "+" || e.op === "-") && emitter.integerRanges.get(e)) {
632
+ return emitter.newTemp(e.type, `(double)((int64_t)${l.name} ${e.op} (int64_t)${r.name})`);
633
+ }
634
+ if (["&", "|", "^", "<<", ">>", ">>>"].includes(e.op) && emitter.integerRanges.get(e.left) && emitter.integerRanges.get(e.right)) {
635
+ return emitIntegerBits(emitter, e, l.name, r.name);
636
+ }
608
637
  switch (e.op) {
609
638
  case "%":
610
639
  return emitter.newTemp(e.type, `fmod(${l.name}, ${r.name})`);
@@ -635,7 +664,8 @@ function emitOperatorExpr(emitter, e) {
635
664
  case "unary": {
636
665
  const v = emitter.emitExpr(e.operand);
637
666
  if (e.op === "~")
638
- return emitter.newTemp(e.type, `scr_bit_not(${v.name})`);
667
+ return emitter.integerRanges.get(e.operand)
668
+ ? emitIntegerBits(emitter, e, v.name) : emitter.newTemp(e.type, `scr_bit_not(${v.name})`);
639
669
  return emitter.newTemp(e.type, `${e.op}${v.name}`);
640
670
  }
641
671
  case "incDec": {
@@ -1229,9 +1259,13 @@ function emitStringExpr(emitter, e) {
1229
1259
  }
1230
1260
  return emitter.newTemp(e.type, `scr_str_includes(${r.name}, ${args[0].name})`);
1231
1261
  case "startsWith":
1232
- return emitter.newTemp(e.type, `scr_str_starts_with(${r.name}, ${args[0].name})`);
1262
+ return emitter.newTemp(e.type, args[1]
1263
+ ? `scr_str_starts_with_from(${r.name}, ${args[0].name}, ${args[1].name})`
1264
+ : `scr_str_starts_with(${r.name}, ${args[0].name})`);
1233
1265
  case "endsWith":
1234
- return emitter.newTemp(e.type, `scr_str_ends_with(${r.name}, ${args[0].name})`);
1266
+ return emitter.newTemp(e.type, args[1]
1267
+ ? `scr_str_ends_with_from(${r.name}, ${args[0].name}, ${args[1].name})`
1268
+ : `scr_str_ends_with(${r.name}, ${args[0].name})`);
1235
1269
  case "slice":
1236
1270
  return emitter.newTemp(e.type, `scr_str_slice(${r.name}, ${args[0]?.name ?? "0"}, ${args[1]?.name ?? "INFINITY"})`);
1237
1271
  case "substring":
@@ -1443,7 +1477,11 @@ function emitContainerExpr(emitter, e) {
1443
1477
  return emitter.newTemp(e.type, `scr_arr_state(${arr.name}, ${idx.name})`);
1444
1478
  }
1445
1479
  case "arrIntrinsic": {
1446
- const r = emitter.emitExpr(e.receiver);
1480
+ // getNumber copies out a scalar without invoking user code. A
1481
+ // stable binding can own its receiver until that lookup finishes.
1482
+ const r = e.method === "getNumber"
1483
+ ? emitStableReceiver(emitter, e.receiver, e.args)
1484
+ : emitter.emitExpr(e.receiver);
1447
1485
  if (e.receiver.type.kind !== "array")
1448
1486
  throw new InternalCompilerError("emitter bug: arrIntrinsic on non-array");
1449
1487
  const acc = elemAccess(e.receiver.type.elem);
@@ -1451,6 +1489,11 @@ function emitContainerExpr(emitter, e) {
1451
1489
  switch (method) {
1452
1490
  case "length":
1453
1491
  return emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1492
+ case "getNumber": {
1493
+ const index = emitter.emitExpr(e.args[0]);
1494
+ const table = e.receiver.kind === "varRef" ? emitter.constantNumericTables.get(e.receiver.localId) : undefined;
1495
+ return emitter.newTemp(e.type, `${table ? `${table.symbol}_get` : "scr_arr_get_number"}(${r.name}, ${index.name})`);
1496
+ }
1454
1497
  case "nextPresent": {
1455
1498
  const start = emitter.emitExpr(e.args[0]);
1456
1499
  return emitter.newTemp(e.type, `scr_arr_next_present(${r.name}, ${start.name})`);
@@ -1673,7 +1716,7 @@ function emitContainerExpr(emitter, e) {
1673
1716
  const method = e.method;
1674
1717
  const directElementAccess = method === "length" || method === "byteLength" || method === "get";
1675
1718
  const r = directElementAccess
1676
- ? emitBytesReceiver(emitter, e.receiver, e.args)
1719
+ ? emitStableReceiver(emitter, e.receiver, e.args)
1677
1720
  : emitter.emitExpr(e.receiver);
1678
1721
  const integerIndex = method === "get" ? emitter.integerLoopIndex(e.args[0]) : null;
1679
1722
  const args = integerIndex === null ? e.args.map((a) => emitter.emitExpr(a)) : [];
@@ -1684,7 +1727,7 @@ function emitContainerExpr(emitter, e) {
1684
1727
  if (e.receiver.type.kind !== "bytes") {
1685
1728
  throw new InternalCompilerError("emitter bug: bytesIntrinsic byteLength on non-bytes");
1686
1729
  }
1687
- return emitter.newTemp(e.type, `(double)(${r.name}->len * ${e.receiver.type.elem === "u8" ? "1" : "4"})`);
1730
+ return emitter.newTemp(e.type, `(double)(${r.name}->len * ${e.receiver.type.elem === "u8" ? "1" : e.receiver.type.elem === "f64" ? "8" : "4"})`);
1688
1731
  case "get":
1689
1732
  // Any invalid index traps (the array runtime's discipline).
1690
1733
  if (e.receiver.type.kind !== "bytes") {
@@ -4016,6 +4059,11 @@ function emitDynamicLibCall(state) {
4016
4059
  // +1 string or NULL with the exception pending (user
4017
4060
  // toString/valueOf throws propagate). Borrows the dyn.
4018
4061
  return finish(`scr_dyn_string_coerce_js(${arg(0)})`);
4062
+ case "dyn.toNumberCoerce":
4063
+ // JS ToNumber (number-hint valueOf/toString protocol). A
4064
+ // thrown hook leaves the exception pending; the may-throw
4065
+ // epilogue abandons the NaN dummy.
4066
+ return finish(`scr_dyn_number_coerce(${arg(0)})`);
4019
4067
  case "global.undefRead":
4020
4068
  // A declare-d const nothing defines: Node's catchable
4021
4069
  // ReferenceError at the access (always throws — the typed
@@ -4103,22 +4151,28 @@ function emitFilesystemLibCall(state) {
4103
4151
  return finish(`scr_fs_rmdir(${arg(0)})`);
4104
4152
  case "fs.readdirSync":
4105
4153
  return finish(`scr_fs_readdir(${arg(0)})`);
4106
- case "fs.readdirTypesSync": {
4154
+ case "fs.readdirTypesSync":
4155
+ case "fsp.readdirTypes": {
4107
4156
  // Dirent rows assembled inline from one scandir snapshot
4108
4157
  // (scr_lib.c) — the os.networkInterfaces pattern, flat. The
4109
4158
  // frontend/validator pinned the shape ({%dtype, name,
4110
- // parentPath}); lookups here only guard emitter bugs. The
4111
- // snapshot call throws Node's scandir error (may-throw seed
4112
- // set) and answers NULL then, so the pending check runs
4113
- // before any allocation.
4114
- if (e.type.kind !== "array" || e.type.elem.kind !== "record") {
4115
- throw new InternalCompilerError("emitter bug: readdirTypesSync result is not a record array");
4116
- }
4117
- const recT = e.type.elem;
4159
+ // parentPath}); lookups here only guard emitter bugs. The sync
4160
+ // form checks the snapshot's scandir error immediately. The
4161
+ // promise form lets NULL flow through the null-tolerant count/
4162
+ // free accessors, builds an empty dummy array, and moves it to
4163
+ // settled_ref: the pending exception becomes the rejection and
4164
+ // settled_ref releases that dummy.
4165
+ const promiseForm = e.fn === "fsp.readdirTypes";
4166
+ const arrayT = promiseForm && e.type.kind === "promise" ? e.type.inner : e.type;
4167
+ if (arrayT.kind !== "array" || arrayT.elem.kind !== "record") {
4168
+ throw new InternalCompilerError(`emitter bug: ${e.fn} result is not a Dirent record array`);
4169
+ }
4170
+ const recT = arrayT.elem;
4118
4171
  const snap = `sc_t${emitter.tempCounter++}`;
4119
4172
  emitter.line(`ScrScandir *${snap} = scr_fs_scandir(${arg(0)});${emitter.srcComment(e.loc)}`);
4120
- emitter.emitPendingCheck();
4121
- const out = emitter.newTemp(e.type, emitter.arrNewC(recT, `scr_fs_scandir_count(${snap})`));
4173
+ if (!promiseForm)
4174
+ emitter.emitPendingCheck();
4175
+ const out = emitter.newTemp(arrayT, emitter.arrNewC(recT, `scr_fs_scandir_count(${snap})`));
4122
4176
  const i = `sc_t${emitter.tempCounter++}`;
4123
4177
  const n = `sc_t${emitter.tempCounter++}`;
4124
4178
  emitter.line(`for (size_t ${i} = 0, ${n} = scr_fs_scandir_count(${snap}); ${i} < ${n}; ${i}++) {`);
@@ -4132,6 +4186,11 @@ function emitFilesystemLibCall(state) {
4132
4186
  emitter.indent--;
4133
4187
  emitter.line(`}`);
4134
4188
  emitter.line(`scr_fs_scandir_free(${snap});`);
4189
+ if (promiseForm) {
4190
+ const rc = vAdapters(arrayT);
4191
+ emitter.moveTemp(out); // promise fulfillment owns the result array
4192
+ return finish(`scr_promise_settled_ref(${out.name}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(arrayT)})`);
4193
+ }
4135
4194
  return out;
4136
4195
  }
4137
4196
  // Stats (scr_lib.c): statSync throws like the other sync fs
@@ -4140,6 +4199,16 @@ function emitFilesystemLibCall(state) {
4140
4199
  // Throws Node-shaped fs errors (may-throw seed set); the fd
4141
4200
  // comes back as f64.
4142
4201
  return finish(`scr_fs_open(${arg(0)}, ${arg(1)})`);
4202
+ case "fs.openNumericSync":
4203
+ return finish(`scr_fs_open_numeric(${arg(0)}, ${arg(1)}, ${arg(2)})`);
4204
+ case "fs.fstatSync":
4205
+ return finish(`scr_fs_fstat(${arg(0)})`);
4206
+ case "fs.fchmodSync":
4207
+ return finish(`scr_fs_fchmod(${arg(0)}, ${arg(1)})`);
4208
+ case "fs.fsyncSync":
4209
+ return finish(`scr_fs_fsync(${arg(0)})`);
4210
+ case "fs.linkSync":
4211
+ return finish(`scr_fs_link(${arg(0)}, ${arg(1)})`);
4143
4212
  case "fs.readSync":
4144
4213
  return finish(`scr_fs_read_sync(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)})`);
4145
4214
  case "fs.writeSync":
@@ -4182,12 +4251,18 @@ function emitFilesystemLibCall(state) {
4182
4251
  return finish(`scr_stats_atime_ms(${arg(0)})`);
4183
4252
  case "stats.mtimeMs":
4184
4253
  return finish(`scr_stats_mtime_ms(${arg(0)})`);
4254
+ case "stats.ctimeMs":
4255
+ return finish(`scr_stats_ctime_ms(${arg(0)})`);
4185
4256
  case "stats.isFile":
4186
4257
  return finish(`scr_stats_is_file(${arg(0)})`);
4187
4258
  case "stats.isDirectory":
4188
4259
  return finish(`scr_stats_is_dir(${arg(0)})`);
4189
4260
  case "stats.size":
4190
4261
  return finish(`scr_stats_size(${arg(0)})`);
4262
+ case "stats.dev":
4263
+ return finish(`scr_stats_dev(${arg(0)})`);
4264
+ case "stats.ino":
4265
+ return finish(`scr_stats_ino(${arg(0)})`);
4191
4266
  case "fs.toUnixTimestamp":
4192
4267
  return finish(`scr_fs_to_unix_timestamp(${arg(0)})`);
4193
4268
  // The fs argument-validation ladders: the always-throw Chk
@@ -4246,6 +4321,43 @@ function emitFilesystemLibCall(state) {
4246
4321
  return finish(`scr_zlib_deflate(${arg(0)})`);
4247
4322
  case "zlib.inflateSync":
4248
4323
  return finish(`scr_zlib_inflate(${arg(0)})`);
4324
+ case "zlib.deflateRawSync":
4325
+ return finish(`scr_zlib_deflate_mode(${arg(0)}, 1.0, -1.0)`);
4326
+ case "zlib.inflateRawSync":
4327
+ return finish(`scr_zlib_inflate_mode(${arg(0)}, 1.0)`);
4328
+ case "zlib.gzipSync":
4329
+ return finish(`scr_zlib_deflate_mode(${arg(0)}, 2.0, -1.0)`);
4330
+ case "zlib.gunzipSync":
4331
+ return finish(`scr_zlib_inflate_mode(${arg(0)}, 2.0)`);
4332
+ case "zlib.unzipSync":
4333
+ return finish(`scr_zlib_inflate_mode(${arg(0)}, 3.0)`);
4334
+ case "zlib.crc32":
4335
+ return finish(`scr_zlib_crc32(${arg(0)}, ${arg(1)})`);
4336
+ case "zlib.deflateCb":
4337
+ case "zlib.inflateCb":
4338
+ case "zlib.deflateRawCb":
4339
+ case "zlib.inflateRawCb":
4340
+ case "zlib.gzipCb":
4341
+ case "zlib.gunzipCb":
4342
+ case "zlib.unzipCb": {
4343
+ emitter.usesTimers = true;
4344
+ const cbT = e.args[1].type;
4345
+ if (cbT.kind !== "func")
4346
+ throw new InternalCompilerError("emitter bug: zlib callback not a func");
4347
+ const callback = args[1];
4348
+ emitter.moveTemp(callback);
4349
+ const adapter = emitter.zlibBytesThunkFor(cbT);
4350
+ const compressing = fn === "zlib.deflateCb" || fn === "zlib.deflateRawCb" || fn === "zlib.gzipCb";
4351
+ const mode = fn === "zlib.deflateRawCb" || fn === "zlib.inflateRawCb"
4352
+ ? 1
4353
+ : fn === "zlib.gzipCb" || fn === "zlib.gunzipCb"
4354
+ ? 2
4355
+ : fn === "zlib.unzipCb"
4356
+ ? 3
4357
+ : 0;
4358
+ emitter.line(`scr_zlib_codec_async(${arg(0)}, ${mode}.0, ${compressing ? "true" : "false"}, ${callback.name}, &${adapter});${emitter.srcComment(e.loc)}`);
4359
+ return { name: "", type: e.type };
4360
+ }
4249
4361
  case "fsp.readFile":
4250
4362
  return finish(`scr_fsp_read_file(${arg(0)})`);
4251
4363
  case "fsp.writeFile":
@@ -4272,6 +4384,10 @@ function emitFilesystemLibCall(state) {
4272
4384
  return finish(`scr_fsp_rm(${arg(0)})`);
4273
4385
  case "fsp.stat":
4274
4386
  return finish(`scr_fsp_stat(${arg(0)})`);
4387
+ case "fsp.realpath":
4388
+ return finish(`scr_fsp_realpath(${arg(0)})`);
4389
+ case "fsp.lstat":
4390
+ return finish(`scr_fsp_lstat(${arg(0)})`);
4275
4391
  case "fsp.open":
4276
4392
  return finish(`scr_fsp_open(${arg(0)}, ${arg(1)}, ${arg(2)})`);
4277
4393
  case "fileHandle.fd":
@@ -4535,10 +4651,18 @@ function emitPathUrlLibCall(state) {
4535
4651
  return finish(`scr_url_new(${arg(0)})`);
4536
4652
  case "url.protocol":
4537
4653
  return finish(`scr_url_protocol(${arg(0)})`);
4654
+ case "url.origin":
4655
+ return finish(`scr_url_origin(${arg(0)})`);
4656
+ case "url.username":
4657
+ return finish(`scr_url_username(${arg(0)})`);
4658
+ case "url.password":
4659
+ return finish(`scr_url_password(${arg(0)})`);
4538
4660
  case "url.host":
4539
4661
  return finish(`scr_url_host(${arg(0)})`);
4540
4662
  case "url.hostname":
4541
4663
  return finish(`scr_url_hostname(${arg(0)})`);
4664
+ case "url.port":
4665
+ return finish(`scr_url_port(${arg(0)})`);
4542
4666
  case "url.pathname":
4543
4667
  return finish(`scr_url_pathname(${arg(0)})`);
4544
4668
  case "url.href":
@@ -4572,6 +4696,8 @@ function emitPathUrlLibCall(state) {
4572
4696
  return finish(`scr_url_search_params(${arg(0)})`);
4573
4697
  case "url.search":
4574
4698
  return finish(`scr_url_search(${arg(0)})`);
4699
+ case "url.hash":
4700
+ return finish(`scr_url_hash(${arg(0)})`);
4575
4701
  case "sp.get": {
4576
4702
  // `string | null` — the sym.desc pattern with a null arm: the
4577
4703
  // runtime answers a +1 string or NULL.
@@ -4677,6 +4803,8 @@ function emitPrimitiveLibCall(state) {
4677
4803
  return finish(`scr_math_max_arr(${arg(0)})`);
4678
4804
  case "math.minArr":
4679
4805
  return finish(`scr_math_min_arr(${arg(0)})`);
4806
+ case "math.hypotArr":
4807
+ return finish(`scr_math_hypot_arr(${arg(0)})`);
4680
4808
  // Math.floor/trunc/ceil — the C functions ARE the JS operations
4681
4809
  // (math.h is always included). Borrow nothing; no throw.
4682
4810
  case "math.floor":
@@ -4685,6 +4813,38 @@ function emitPrimitiveLibCall(state) {
4685
4813
  return finish(`trunc(${arg(0)})`);
4686
4814
  case "math.ceil":
4687
4815
  return finish(`ceil(${arg(0)})`);
4816
+ case "math.sin":
4817
+ return finish(`sin(${arg(0)})`);
4818
+ case "math.cos":
4819
+ return finish(`cos(${arg(0)})`);
4820
+ case "math.tan":
4821
+ return finish(`tan(${arg(0)})`);
4822
+ case "math.asin":
4823
+ return finish(`asin(${arg(0)})`);
4824
+ case "math.acos":
4825
+ return finish(`acos(${arg(0)})`);
4826
+ case "math.atan":
4827
+ return finish(`atan(${arg(0)})`);
4828
+ case "math.cbrt":
4829
+ return finish(`cbrt(${arg(0)})`);
4830
+ case "math.sign":
4831
+ // Each argument was evaluated into a temp. Returning that temp
4832
+ // for unordered/zero inputs preserves NaN and the sign of zero.
4833
+ return finish(`(${arg(0)} > 0.0 ? 1.0 : (${arg(0)} < 0.0 ? -1.0 : ${arg(0)}))`);
4834
+ case "math.exp":
4835
+ return finish(`exp(${arg(0)})`);
4836
+ case "math.sqrt":
4837
+ return finish(`sqrt(${arg(0)})`);
4838
+ case "math.log":
4839
+ return finish(`log(${arg(0)})`);
4840
+ case "math.log2":
4841
+ return finish(`log2(${arg(0)})`);
4842
+ case "math.log10":
4843
+ return finish(`log10(${arg(0)})`);
4844
+ case "math.atan2":
4845
+ return finish(`atan2(${arg(0)}, ${arg(1)})`);
4846
+ case "math.pow":
4847
+ return finish(`scr_math_pow(${arg(0)}, ${arg(1)})`);
4688
4848
  // Math.abs — C fabs IS the JS operation. Math.round — the JS
4689
4849
  // half-toward-+Infinity rule (scr_lib.c; C round() differs on
4690
4850
  // halves and naive floor(x+0.5) drifts at the epsilon boundary).
@@ -4796,6 +4956,8 @@ function emitPrimitiveLibCall(state) {
4796
4956
  return finish(`scr_bigint_shr(${arg(0)}, ${arg(1)})`);
4797
4957
  case "bigint.eq":
4798
4958
  return finish(`scr_bigint_eq(${arg(0)}, ${arg(1)})`);
4959
+ case "bigint.eqString":
4960
+ return finish(`scr_bigint_eq_string(${arg(0)}, ${arg(1)})`);
4799
4961
  case "bigint.cmp":
4800
4962
  return finish(`scr_bigint_cmp_f64(${arg(0)}, ${arg(1)})`);
4801
4963
  case "bigint.cmpNumber":
@@ -4868,6 +5030,7 @@ function emitPrimitiveLibCall(state) {
4868
5030
  // +1 string, or Node's "Invalid time value" RangeError
4869
5031
  // (may-throw seed set).
4870
5032
  return finish(`scr_date_to_iso(${arg(0)})`);
5033
+ case "date.parse":
4871
5034
  case "date.parseGetTime":
4872
5035
  // The bounded date-string parse (X509 validity + ECMA format);
4873
5036
  // NaN elsewhere. Never throws.
@@ -4925,6 +5088,8 @@ function emitPrimitiveLibCall(state) {
4925
5088
  : `scr_str_from_char_code(${arg(0)})`);
4926
5089
  case "string.lastIndexOf":
4927
5090
  return finish(`scr_str_last_index_of(${arg(0)}, ${arg(1)})`);
5091
+ case "string.lastIndexOfFrom":
5092
+ return finish(`scr_str_last_index_of_from(${arg(0)}, ${arg(1)}, ${arg(2)})`);
4928
5093
  case "string.raw":
4929
5094
  // Raw literals + pre-stringified substitutions; +1 string.
4930
5095
  return finish(`scr_str_raw(${arg(0)}, ${arg(1)})`);
@@ -5244,20 +5409,37 @@ function emitChildProcessLibCall(state) {
5244
5409
  case "cp.spawn":
5245
5410
  emitter.usesTimers = true; // the loop must run to reap the child
5246
5411
  return finish(`scr_spawn(${arg(0)}, ${arg(1)})`);
5412
+ case "cp.fork":
5413
+ emitter.usesTimers = true;
5414
+ return finish(`scr_fork(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)}, ${arg(7)})`);
5247
5415
  case "cp.spawnOpts":
5248
5416
  // The options form: per-slot stdio (ignore/inherit/fd — the
5249
5417
  // fds dup2 into the child), detached (setsid), env
5250
5418
  // replacement, cwd. Same loop/reap story as cp.spawn.
5251
5419
  emitter.usesTimers = true;
5252
- return finish(`scr_spawn_opts(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)}, ${arg(7)}, ${arg(8)}, ${arg(9)}, ${arg(10)})`);
5253
- case "child.onExit": {
5420
+ return finish(`scr_spawn_opts(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)}, ${arg(7)}, ${arg(8)}, ${arg(9)}, ${arg(10)}, ${arg(11)})`);
5421
+ case "cp.execFile": {
5422
+ const callbackArg = e.args[2];
5423
+ const cb = args[2];
5424
+ if (!callbackArg || !cb)
5425
+ throw new InternalCompilerError("emitter bug: execFile callback missing");
5426
+ const cbT = callbackArg.type;
5427
+ if (cbT.kind !== "func")
5428
+ throw new InternalCompilerError("emitter bug: execFile callback not a func");
5429
+ emitter.moveTemp(cb);
5430
+ const adapter = emitter.execFileThunkFor(cbT);
5431
+ emitter.usesTimers = true;
5432
+ return finish(`scr_exec_file(${arg(0)}, ${arg(1)}, ${cb.name}, &${adapter})`);
5433
+ }
5434
+ case "child.onExit":
5435
+ case "child.onClose": {
5254
5436
  // The callback MOVES into the child's registry; the third
5255
5437
  // ingredient is the ADAPTER — emitted per callback shape,
5256
5438
  // because the `number | null` union's tags are program data
5257
5439
  // (a zero-param listener gets the runtime's ignoring thunk).
5258
5440
  const cbT = e.args[1].type;
5259
5441
  if (cbT.kind !== "func")
5260
- throw new InternalCompilerError("emitter bug: child.onExit callback not a func");
5442
+ throw new InternalCompilerError(`emitter bug: ${e.fn} callback not a func`);
5261
5443
  const cb = args[1];
5262
5444
  emitter.moveTemp(cb);
5263
5445
  const adapter = cbT.params.length === 0
@@ -5265,7 +5447,7 @@ function emitChildProcessLibCall(state) {
5265
5447
  : cbT.params.length === 1
5266
5448
  ? emitter.childExitThunkFor(cbT.params[0])
5267
5449
  : emitter.childExitSignalThunkFor(cbT.params[0], cbT.params[1]);
5268
- emitter.line(`scr_child_on_exit(${arg(0)}, ${cb.name}, &${adapter});${emitter.srcComment(e.loc)}`);
5450
+ emitter.line(`${e.fn === "child.onClose" ? "scr_child_on_close" : "scr_child_on_exit"}(${arg(0)}, ${cb.name}, &${adapter});${emitter.srcComment(e.loc)}`);
5269
5451
  return { name: "", type: e.type };
5270
5452
  }
5271
5453
  case "child.onError": {
@@ -5280,6 +5462,43 @@ function emitChildProcessLibCall(state) {
5280
5462
  emitter.line(`scr_child_on_error(${arg(0)}, ${cb.name}, &${adapter});${emitter.srcComment(e.loc)}`);
5281
5463
  return { name: "", type: e.type };
5282
5464
  }
5465
+ case "child.connected":
5466
+ return finish(`scr_child_ipc_connected(${arg(0)})`);
5467
+ case "child.send":
5468
+ emitter.usesTimers = true;
5469
+ return finish(`scr_child_ipc_send(${arg(0)}, ${arg(1)})`);
5470
+ case "child.sendCb": {
5471
+ const cbT = e.args[2].type;
5472
+ if (cbT.kind !== "func")
5473
+ throw new InternalCompilerError("emitter bug: child.send callback not a func");
5474
+ const cb = args[2];
5475
+ emitter.moveTemp(cb);
5476
+ emitter.usesTimers = true;
5477
+ return finish(`scr_child_ipc_send_cb(${arg(0)}, ${arg(1)}, ${cb.name}, &${emitter.ipcSendThunkFor(cbT)})`);
5478
+ }
5479
+ case "child.disconnect":
5480
+ emitter.usesTimers = true;
5481
+ return finish(`scr_child_ipc_disconnect(${arg(0)})`);
5482
+ case "child.onMessage": {
5483
+ const cbT = e.args[1].type;
5484
+ if (cbT.kind !== "func")
5485
+ throw new InternalCompilerError("emitter bug: child message listener not a func");
5486
+ const cb = args[1];
5487
+ emitter.moveTemp(cb);
5488
+ emitter.usesTimers = true;
5489
+ emitter.line(`scr_child_ipc_on_message(${arg(0)}, ${cb.name}, &${emitter.ipcMessageThunkFor(cbT)}, ${arg(2)});${emitter.srcComment(e.loc)}`);
5490
+ return { name: "", type: e.type };
5491
+ }
5492
+ case "child.onDisconnect": {
5493
+ const cbT = e.args[1].type;
5494
+ if (cbT.kind !== "func")
5495
+ throw new InternalCompilerError("emitter bug: child disconnect listener not a func");
5496
+ const cb = args[1];
5497
+ emitter.moveTemp(cb);
5498
+ emitter.usesTimers = true;
5499
+ emitter.line(`scr_child_ipc_on_disconnect(${arg(0)}, ${cb.name}, ${arg(2)});${emitter.srcComment(e.loc)}`);
5500
+ return { name: "", type: e.type };
5501
+ }
5283
5502
  default:
5284
5503
  throw new InternalCompilerError(`emitter bug: childProcess libCall dispatch for ${fn}`);
5285
5504
  }
@@ -5377,6 +5596,8 @@ function emitNetworkLibCall(state) {
5377
5596
  }
5378
5597
  case "net.serverPort":
5379
5598
  return finish(`scr_net_server_port(${arg(0)})`);
5599
+ case "net.serverListening":
5600
+ return finish(`scr_net_server_listening(${arg(0)})`);
5380
5601
  case "net.serverAddress": {
5381
5602
  // The AddressInfo record from the three runtime reads (the
5382
5603
  // dgram.address materialization; none of these throw).
@@ -5454,9 +5675,7 @@ function emitNetworkLibCall(state) {
5454
5675
  const cb = args[1];
5455
5676
  emitter.moveTemp(cb);
5456
5677
  const adapter = cbT.params.length === 0 ? "scr_net_conn_thunk0" : "scr_net_conn_thunk_sock";
5457
- const entry = e.fn === "net.serverOnConnection"
5458
- ? "scr_net_server_on_connection"
5459
- : "scr_net_server_on_secure_connection";
5678
+ const entry = e.fn === "net.serverOnConnection" ? "scr_net_server_on_connection" : "scr_net_server_on_secure_connection";
5460
5679
  emitter.line(`${entry}(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
5461
5680
  return { name: "", type: e.type };
5462
5681
  }
@@ -5857,7 +6076,8 @@ function emitHttpLibCall(state) {
5857
6076
  return finish(`scr_http_req_aborted_flag(${arg(0)})`);
5858
6077
  case "http.reqComplete":
5859
6078
  return finish(`scr_http_req_complete(${arg(0)})`);
5860
- case "http.reqHeader": {
6079
+ case "http.reqHeader":
6080
+ case "http.reqTrailer": {
5861
6081
  // string|undefined, type-directed exactly like process.envGet:
5862
6082
  // the runtime answers +1 or NULL; NULL takes the undefined arm.
5863
6083
  if (e.type.kind !== "union")
@@ -5868,12 +6088,29 @@ function emitHttpLibCall(state) {
5868
6088
  if (strTag < 0 || undefTag < 0) {
5869
6089
  throw new InternalCompilerError("emitter bug: http.reqHeader union lacks its arms");
5870
6090
  }
5871
- const s = emitter.newTemp(STRING, `scr_http_req_header(${arg(0)}, ${arg(1)})`);
6091
+ const entry = e.fn === "http.reqHeader" ? "scr_http_req_header" : "scr_http_req_trailer";
6092
+ const s = emitter.newTemp(STRING, `${entry}(${arg(0)}, ${arg(1)})`);
5872
6093
  emitter.moveTemp(s); // moves into the box when present; NULL otherwise
5873
6094
  const present = `scr_union_new_ref(${strTag}, ${s.name}, &scr_str_retain_v, &scr_str_release_v, NULL)`;
5874
6095
  const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
5875
6096
  return emitter.newTemp(e.type, `${s.name} ? ${present} : ${absent}`);
5876
6097
  }
6098
+ case "http.reqHeaderValues":
6099
+ case "http.reqTrailerValues": {
6100
+ if (e.type.kind !== "union")
6101
+ throw new InternalCompilerError("emitter bug: distinct header result is not a union");
6102
+ const def = emitter.unionsById.get(e.type.unionId);
6103
+ const arrTag = def ? def.arms.findIndex((a) => a.kind === "array") : -1;
6104
+ const undefTag = undefinedArmTag(e.type, emitter.unionsById);
6105
+ if (arrTag < 0 || undefTag < 0)
6106
+ throw new InternalCompilerError("emitter bug: distinct header union lacks its arms");
6107
+ const entry = e.fn === "http.reqHeaderValues" ? "scr_http_req_header_values" : "scr_http_req_trailer_values";
6108
+ const values = emitter.newTemp(arrayOf(STRING), `${entry}(${arg(0)}, ${arg(1)})`);
6109
+ emitter.moveTemp(values);
6110
+ const present = `scr_union_new_ref(${arrTag}, ${values.name}, &scr_arr_retain_v, &scr_arr_release_v, NULL)`;
6111
+ const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
6112
+ return emitter.newTemp(e.type, `${values.name} ? ${present} : ${absent}`);
6113
+ }
5877
6114
  case "http.reqOnData": {
5878
6115
  const cbT = e.args[1].type;
5879
6116
  if (cbT.kind !== "func")
@@ -5896,35 +6133,51 @@ function emitHttpLibCall(state) {
5896
6133
  case "http.resSetHeader":
5897
6134
  emitter.line(`scr_http_res_set_header(${arg(0)}, ${arg(1)}, ${arg(2)});${emitter.srcComment(e.loc)}`);
5898
6135
  return { name: "", type: e.type };
5899
- case "http.resWriteHead":
5900
- emitter.line(`scr_http_res_write_head(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6136
+ case "http.validateHeaderName":
6137
+ emitter.line(`scr_http_validate_header_name(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5901
6138
  return { name: "", type: e.type };
5902
- case "http.resWriteHeadN":
5903
- emitter.line(`scr_http_res_write_head_n(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)});${emitter.srcComment(e.loc)}`);
6139
+ case "http.validateHeaderValue":
6140
+ emitter.line(`scr_http_validate_header_value(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5904
6141
  return { name: "", type: e.type };
6142
+ case "http.resWriteHead":
6143
+ return finish(`scr_http_res_write_head(${arg(0)}, ${arg(1)})`);
6144
+ case "http.resWriteHeadN":
6145
+ return finish(`scr_http_res_write_head_n(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)})`);
6146
+ case "http.resWriteContinue":
6147
+ return finish(`scr_http_res_write_continue(${arg(0)})`);
6148
+ case "http.resWriteProcessing":
6149
+ return finish(`scr_http_res_write_processing(${arg(0)})`);
6150
+ case "http.resWriteEarlyHints":
6151
+ return finish(`scr_http_res_write_early_hints(${arg(0)}, ${arg(1)})`);
5905
6152
  case "http.resWrite":
5906
- emitter.line(`scr_http_res_write_str(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5907
- return { name: "", type: e.type };
6153
+ return finish(`scr_http_res_write_str(${arg(0)}, ${arg(1)})`);
5908
6154
  case "http.resWriteBytes":
5909
- emitter.line(`scr_http_res_write_bytes(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5910
- return { name: "", type: e.type };
6155
+ return finish(`scr_http_res_write_bytes(${arg(0)}, ${arg(1)})`);
5911
6156
  case "http.resEnd":
5912
- emitter.line(`scr_http_res_end(${arg(0)});${emitter.srcComment(e.loc)}`);
5913
- return { name: "", type: e.type };
6157
+ return finish(`scr_http_res_end(${arg(0)})`);
5914
6158
  case "http.resEndStr":
5915
- emitter.line(`scr_http_res_end_str(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5916
- return { name: "", type: e.type };
6159
+ return finish(`scr_http_res_end_str(${arg(0)}, ${arg(1)})`);
5917
6160
  case "http.resEndBytes":
5918
- emitter.line(`scr_http_res_end_bytes(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5919
- return { name: "", type: e.type };
6161
+ return finish(`scr_http_res_end_bytes(${arg(0)}, ${arg(1)})`);
5920
6162
  case "http.resWriteDyn":
5921
- emitter.line(`scr_http_res_write_dynv(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5922
- return { name: "", type: e.type };
6163
+ return finish(`scr_http_res_write_dynv(${arg(0)}, ${arg(1)})`);
5923
6164
  case "http.resEndDyn":
5924
- emitter.line(`scr_http_res_end_dynv(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
5925
- return { name: "", type: e.type };
6165
+ return finish(`scr_http_res_end_dynv(${arg(0)}, ${arg(1)})`);
5926
6166
  case "http.resHeadersSent":
5927
6167
  return finish(`scr_http_res_headers_sent(${arg(0)})`);
6168
+ case "http.resWritableEnded":
6169
+ return finish(`scr_http_res_writable_ended(${arg(0)})`);
6170
+ case "http.resFlushHeaders":
6171
+ return finish(`scr_http_res_flush_headers(${arg(0)})`);
6172
+ case "http.resAddTrailers":
6173
+ return finish(`scr_http_res_add_trailers(${arg(0)}, ${arg(1)})`);
6174
+ case "http.resCork":
6175
+ emitter.line(`scr_http_res_cork(${arg(0)});${emitter.srcComment(e.loc)}`);
6176
+ return { name: "", type: e.type };
6177
+ case "http.resUncork":
6178
+ return finish(`scr_http_res_uncork(${arg(0)})`);
6179
+ case "http.resWritableCorked":
6180
+ return finish(`scr_http_res_writable_corked(${arg(0)})`);
5928
6181
  // The server-surface member follow-ups.
5929
6182
  case "http.reqStatusCode": {
5930
6183
  // number | undefined, type-directed like process.columns: the
@@ -5961,8 +6214,12 @@ function emitHttpLibCall(state) {
5961
6214
  return finish(`scr_http_req_h2_stream_or_throw(${arg(0)}, ${arg(1)})`);
5962
6215
  case "http.reqRawHeaders":
5963
6216
  return finish(`scr_http_req_raw_headers(${arg(0)})`);
6217
+ case "http.reqRawTrailers":
6218
+ return finish(`scr_http_req_raw_trailers(${arg(0)})`);
5964
6219
  case "http.reqHeaderPairs":
5965
6220
  return finish(`scr_http_req_header_pairs(${arg(0)})`);
6221
+ case "http.reqTrailerPairs":
6222
+ return finish(`scr_http_req_trailer_pairs(${arg(0)})`);
5966
6223
  case "http.reqStatusMessage": {
5967
6224
  // string | undefined: a reason phrase on client responses,
5968
6225
  // NULL (the undefined arm) on server requests — the
@@ -6074,6 +6331,35 @@ function emitHttpLibCall(state) {
6074
6331
  case "http.serverJoinDupHeaders":
6075
6332
  emitter.line(`scr_http_server_join_duplicate_headers(${arg(0)});${emitter.srcComment(e.loc)}`);
6076
6333
  return { name: "", type: e.type };
6334
+ case "http.serverAllowMissingHostHeader":
6335
+ emitter.line(`scr_http_server_allow_missing_host_header(${arg(0)});${emitter.srcComment(e.loc)}`);
6336
+ return { name: "", type: e.type };
6337
+ case "http.serverSetTimeout":
6338
+ emitter.line(`scr_net_server_set_timeout_plain(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6339
+ return { name: "", type: e.type };
6340
+ case "http.serverCloseAllConnections":
6341
+ case "http.serverCloseIdleConnections": {
6342
+ const entry = e.fn === "http.serverCloseAllConnections"
6343
+ ? "scr_net_server_close_all_connections" : "scr_net_server_close_idle_connections";
6344
+ emitter.line(`${entry}(${arg(0)});${emitter.srcComment(e.loc)}`);
6345
+ return { name: "", type: e.type };
6346
+ }
6347
+ case "http.serverOnTimeout":
6348
+ case "http.serverSetTimeoutCb": {
6349
+ const cbIndex = e.fn === "http.serverSetTimeoutCb" ? 2 : 1;
6350
+ const cbT = e.args[cbIndex].type;
6351
+ if (cbT.kind !== "func")
6352
+ throw new InternalCompilerError(`emitter bug: ${e.fn} callback not a func`);
6353
+ const cb = args[cbIndex];
6354
+ emitter.moveTemp(cb);
6355
+ const adapter = cbT.params.length === 0 ? "scr_net_conn_thunk0" : "scr_net_conn_thunk_sock";
6356
+ const entry = e.fn === "http.serverOnTimeout" ? "scr_net_server_on_timeout" : "scr_net_server_set_timeout_cb";
6357
+ const callArgs = e.fn === "http.serverOnTimeout"
6358
+ ? `${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)}`
6359
+ : `${arg(0)}, ${arg(1)}, ${cb.name}, &${adapter}`;
6360
+ emitter.line(`${entry}(${callArgs});${emitter.srcComment(e.loc)}`);
6361
+ return { name: "", type: e.type };
6362
+ }
6077
6363
  case "http.serverTimeoutGet":
6078
6364
  return finish(`scr_net_server_timeout_get(${arg(0)}, ${arg(1)})`);
6079
6365
  case "http.serverTimeoutSet":
@@ -6086,27 +6372,82 @@ function emitHttpLibCall(state) {
6086
6372
  case "http.resStatusSet":
6087
6373
  emitter.line(`scr_http_res_status_set(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6088
6374
  return { name: "", type: e.type };
6089
- case "http.resStatusMsgGet":
6090
- return finish(`scr_http_res_status_msg_get(${arg(0)})`);
6375
+ case "http.resStatusMsgGet": {
6376
+ if (e.type.kind !== "union")
6377
+ throw new InternalCompilerError("emitter bug: http.resStatusMsgGet result is not a union");
6378
+ const def = emitter.unionsById.get(e.type.unionId);
6379
+ const strTag = def ? def.arms.findIndex((a) => a.kind === "string") : -1;
6380
+ const undefTag = undefinedArmTag(e.type, emitter.unionsById);
6381
+ if (strTag < 0 || undefTag < 0)
6382
+ throw new InternalCompilerError("emitter bug: http.resStatusMsgGet union lacks its arms");
6383
+ const msg = emitter.newTemp(STRING, `scr_http_res_status_msg_get(${arg(0)})`);
6384
+ emitter.moveTemp(msg);
6385
+ const present = `scr_union_new_ref(${strTag}, ${msg.name}, &scr_str_retain_v, &scr_str_release_v, NULL)`;
6386
+ return emitter.newTemp(e.type, `${msg.name} ? ${present} : ${emitter.unitInstanceRef(e.type.unionId, undefTag)}`);
6387
+ }
6091
6388
  case "http.resStatusMsgSet":
6092
6389
  emitter.line(`scr_http_res_status_msg_set(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6093
6390
  return { name: "", type: e.type };
6094
- case "http.resGetHeader": {
6391
+ case "http.resRequest":
6392
+ return finish(`scr_http_res_request(${arg(0)})`);
6393
+ case "http.resSocket": {
6394
+ if (e.type.kind !== "union")
6395
+ throw new InternalCompilerError("emitter bug: http.resSocket result is not a union");
6396
+ const def = emitter.unionsById.get(e.type.unionId);
6397
+ const socketTag = def ? def.arms.findIndex((a) => a.kind === "netSocket") : -1;
6398
+ const nullTag = def ? def.arms.findIndex((a) => a.kind === "nullT") : -1;
6399
+ if (socketTag < 0 || nullTag < 0)
6400
+ throw new InternalCompilerError("emitter bug: http.resSocket union lacks its arms");
6401
+ const sock = emitter.newTemp(NETSOCKET_T, `scr_http_res_socket(${arg(0)})`);
6402
+ emitter.moveTemp(sock);
6403
+ const present = `scr_union_new_ref(${socketTag}, ${sock.name}, &scr_net_sock_retain_v, &scr_net_sock_release_v, NULL)`;
6404
+ return emitter.newTemp(e.type, `${sock.name} ? ${present} : ${emitter.unitInstanceRef(e.type.unionId, nullTag)}`);
6405
+ }
6406
+ case "http.resWritableFinished":
6407
+ return finish(`scr_http_res_writable_finished(${arg(0)})`);
6408
+ case "http.resSendDateGet":
6409
+ return finish(`scr_http_res_send_date(${arg(0)})`);
6410
+ case "http.resSendDateSet":
6411
+ emitter.line(`scr_http_res_set_send_date(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6412
+ return { name: "", type: e.type };
6413
+ case "http.resStrictContentLengthGet":
6414
+ return finish(`scr_http_res_strict_content_length(${arg(0)})`);
6415
+ case "http.resStrictContentLengthSet":
6416
+ emitter.line(`scr_http_res_set_strict_content_length(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6417
+ return { name: "", type: e.type };
6418
+ case "http.resSetTimeout":
6419
+ emitter.line(`scr_http_res_set_timeout_plain(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6420
+ return { name: "", type: e.type };
6421
+ case "http.resSetTimeoutCb": {
6422
+ const cb = args[2];
6423
+ emitter.moveTemp(cb);
6424
+ emitter.line(`scr_http_res_set_timeout(${arg(0)}, ${arg(1)}, ${cb.name});${emitter.srcComment(e.loc)}`);
6425
+ return { name: "", type: e.type };
6426
+ }
6427
+ case "http.resGetHeader":
6428
+ case "http.clientGetHeader": {
6095
6429
  // string|undefined, exactly the http.reqHeader emission.
6096
6430
  if (e.type.kind !== "union")
6097
- throw new InternalCompilerError("emitter bug: http.resGetHeader result is not a union");
6431
+ throw new InternalCompilerError(`emitter bug: ${e.fn} result is not a union`);
6098
6432
  const def = emitter.unionsById.get(e.type.unionId);
6099
6433
  const strTag = def ? def.arms.findIndex((a) => a.kind === "string") : -1;
6100
6434
  const undefTag = undefinedArmTag(e.type, emitter.unionsById);
6101
6435
  if (strTag < 0 || undefTag < 0) {
6102
6436
  throw new InternalCompilerError("emitter bug: http.resGetHeader union lacks its arms");
6103
6437
  }
6104
- const s = emitter.newTemp(STRING, `scr_http_res_get_header(${arg(0)}, ${arg(1)})`);
6438
+ const entry = e.fn === "http.resGetHeader" ? "scr_http_res_get_header" : "scr_http_client_get_header";
6439
+ const s = emitter.newTemp(STRING, `${entry}(${arg(0)}, ${arg(1)})`);
6105
6440
  emitter.moveTemp(s); // moves into the box when present; NULL otherwise
6106
6441
  const present = `scr_union_new_ref(${strTag}, ${s.name}, &scr_str_retain_v, &scr_str_release_v, NULL)`;
6107
6442
  const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
6108
6443
  return emitter.newTemp(e.type, `${s.name} ? ${present} : ${absent}`);
6109
6444
  }
6445
+ case "http.resGetHeaderNames":
6446
+ return finish(`scr_http_res_get_header_names(${arg(0)})`);
6447
+ case "http.resGetRawHeaderNames":
6448
+ return finish(`scr_http_res_get_raw_header_names(${arg(0)})`);
6449
+ case "http.resGetHeaders":
6450
+ return finish(`scr_http_res_get_headers(${arg(0)})`);
6110
6451
  case "http.resHasHeader":
6111
6452
  return finish(`scr_http_res_has_header_named(${arg(0)}, ${arg(1)})`);
6112
6453
  case "http.resRemoveHeader":
@@ -6119,12 +6460,19 @@ function emitHttpLibCall(state) {
6119
6460
  return { name: "", type: e.type };
6120
6461
  }
6121
6462
  case "http.resWriteHeadPairs":
6122
- emitter.line(`scr_http_res_write_head_pairs(${arg(0)}, ${arg(1)}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6123
- return { name: "", type: e.type };
6463
+ return finish(`scr_http_res_write_head_pairs(${arg(0)}, ${arg(1)}, ${arg(2)})`);
6124
6464
  case "http.resWriteHeadDyn":
6125
6465
  return finish(`scr_http_res_write_head_dyn(${arg(0)}, ${arg(1)}, ${arg(2)})`);
6126
6466
  case "http.reqSetEncoding":
6127
6467
  return finish(`scr_http_req_set_encoding(${arg(0)}, ${arg(1)})`);
6468
+ case "http.reqSetTimeout":
6469
+ return finish(`scr_http_req_set_timeout_plain(${arg(0)}, ${arg(1)})`);
6470
+ case "http.reqSetTimeoutCb": {
6471
+ const cb = args[2];
6472
+ emitter.moveTemp(cb);
6473
+ emitter.line(`scr_http_req_set_timeout(${arg(0)}, ${arg(1)}, ${cb.name});${emitter.srcComment(e.loc)}`);
6474
+ return { name: "", type: e.type };
6475
+ }
6128
6476
  // node:http, the client slice (scr_http.c over the net client).
6129
6477
  case "http.request":
6130
6478
  case "http.requestCb": {
@@ -6293,29 +6641,84 @@ function emitHttpLibCall(state) {
6293
6641
  return finish(`(${arg(0)} ? scr_https_request(${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)}, ${arg(7)}, ${arg(8)}, (const char *)${arg(9)}->data, ${arg(9)}->len, ${cbExpr}, ${adapter}) : scr_http_request_ex(${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)}, ${arg(7)}, ${cbExpr}, ${adapter}, 80, NULL, NULL))`);
6294
6642
  }
6295
6643
  case "http.clientWrite":
6296
- emitter.line(`scr_http_client_write_str(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6297
- return { name: "", type: e.type };
6644
+ return finish(`scr_http_client_write_str(${arg(0)}, ${arg(1)})`);
6645
+ case "http.clientSetHeader":
6646
+ return finish(`scr_http_client_set_header(${arg(0)}, ${arg(1)}, ${arg(2)})`);
6647
+ case "http.clientHasHeader":
6648
+ return finish(`scr_http_client_has_header_named(${arg(0)}, ${arg(1)})`);
6649
+ case "http.clientRemoveHeader":
6650
+ return finish(`scr_http_client_remove_header(${arg(0)}, ${arg(1)})`);
6651
+ case "http.clientGetHeaderNames":
6652
+ return finish(`scr_http_client_get_header_names(${arg(0)})`);
6653
+ case "http.clientGetRawHeaderNames":
6654
+ return finish(`scr_http_client_get_raw_header_names(${arg(0)})`);
6655
+ case "http.clientGetHeaders":
6656
+ return finish(`scr_http_client_get_headers(${arg(0)})`);
6298
6657
  case "http.clientWriteBytes":
6299
- emitter.line(`scr_http_client_write_bytes(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6300
- return { name: "", type: e.type };
6658
+ return finish(`scr_http_client_write_bytes(${arg(0)}, ${arg(1)})`);
6301
6659
  case "http.clientEnd":
6302
- emitter.line(`scr_http_client_end(${arg(0)});${emitter.srcComment(e.loc)}`);
6303
- return { name: "", type: e.type };
6660
+ return finish(`scr_http_client_end(${arg(0)})`);
6304
6661
  case "http.clientEndStr":
6305
- emitter.line(`scr_http_client_end_str(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6306
- return { name: "", type: e.type };
6662
+ return finish(`scr_http_client_end_str(${arg(0)}, ${arg(1)})`);
6307
6663
  case "http.clientEndBytes":
6308
- emitter.line(`scr_http_client_end_bytes(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6309
- return { name: "", type: e.type };
6664
+ return finish(`scr_http_client_end_bytes(${arg(0)}, ${arg(1)})`);
6310
6665
  case "http.clientWriteDyn":
6311
- emitter.line(`scr_http_client_write_dynv(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6312
- return { name: "", type: e.type };
6666
+ return finish(`scr_http_client_write_dynv(${arg(0)}, ${arg(1)})`);
6313
6667
  case "http.clientEndDyn":
6314
- emitter.line(`scr_http_client_end_dynv(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6668
+ return finish(`scr_http_client_end_dynv(${arg(0)}, ${arg(1)})`);
6669
+ case "http.clientFlushHeaders":
6670
+ return finish(`scr_http_client_flush_headers(${arg(0)})`);
6671
+ case "http.clientAddTrailers":
6672
+ return finish(`scr_http_client_add_trailers(${arg(0)}, ${arg(1)})`);
6673
+ case "http.clientCork":
6674
+ emitter.line(`scr_http_client_cork(${arg(0)});${emitter.srcComment(e.loc)}`);
6675
+ return { name: "", type: e.type };
6676
+ case "http.clientUncork":
6677
+ return finish(`scr_http_client_uncork(${arg(0)})`);
6678
+ case "http.clientWritableCorked":
6679
+ return finish(`scr_http_client_writable_corked(${arg(0)})`);
6680
+ case "http.clientMethod":
6681
+ return finish(`scr_http_client_method(${arg(0)})`);
6682
+ case "http.clientPath":
6683
+ return finish(`scr_http_client_path(${arg(0)})`);
6684
+ case "http.clientHost":
6685
+ return finish(`scr_http_client_host(${arg(0)})`);
6686
+ case "http.clientProtocol":
6687
+ return finish(`scr_http_client_protocol(${arg(0)})`);
6688
+ case "http.clientHeadersSent":
6689
+ return finish(`scr_http_client_headers_sent(${arg(0)})`);
6690
+ case "http.clientWritableEnded":
6691
+ return finish(`scr_http_client_writable_ended(${arg(0)})`);
6692
+ case "http.clientWritableFinished":
6693
+ return finish(`scr_http_client_writable_finished(${arg(0)})`);
6694
+ case "http.clientSocket":
6695
+ return finish(`scr_http_client_socket(${arg(0)})`);
6696
+ case "http.clientReusedSocket":
6697
+ return finish(`scr_http_client_reused_socket(${arg(0)})`);
6698
+ case "http.clientSetNoDelay":
6699
+ return finish(`scr_http_client_set_nodelay(${arg(0)}, ${arg(1)})`);
6700
+ case "http.clientSetSocketKeepAlive":
6701
+ return finish(`scr_http_client_set_socket_keepalive(${arg(0)}, ${arg(1)}, ${arg(2)})`);
6702
+ case "http.clientSetTimeout":
6703
+ return finish(`scr_http_client_set_timeout(${arg(0)}, ${arg(1)})`);
6704
+ case "http.clientSetTimeoutCb": {
6705
+ const cb = args[2];
6706
+ emitter.moveTemp(cb);
6707
+ emitter.line(`scr_http_client_set_timeout_cb(${arg(0)}, ${arg(1)}, ${cb.name});${emitter.srcComment(e.loc)}`);
6315
6708
  return { name: "", type: e.type };
6709
+ }
6710
+ case "http.statusCodes":
6711
+ return finish("scr_http_status_codes()");
6712
+ case "http.methods":
6713
+ return finish("scr_http_methods()");
6316
6714
  case "http.clientDestroy":
6317
6715
  emitter.line(`scr_http_client_destroy(${arg(0)});${emitter.srcComment(e.loc)}`);
6318
6716
  return { name: "", type: e.type };
6717
+ case "http.clientAbort":
6718
+ emitter.line(`scr_http_client_abort(${arg(0)});${emitter.srcComment(e.loc)}`);
6719
+ return { name: "", type: e.type };
6720
+ case "http.clientAborted":
6721
+ return finish(`scr_http_client_aborted(${arg(0)})`);
6319
6722
  case "http.clientDestroyed":
6320
6723
  return finish(`scr_http_client_destroyed(${arg(0)})`);
6321
6724
  case "http.clientOnResponse": {
@@ -6328,6 +6731,16 @@ function emitHttpLibCall(state) {
6328
6731
  emitter.line(`scr_http_client_on_response(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6329
6732
  return { name: "", type: e.type };
6330
6733
  }
6734
+ case "http.clientOnSocket": {
6735
+ const cbT = e.args[1].type;
6736
+ if (cbT.kind !== "func")
6737
+ throw new InternalCompilerError("emitter bug: http.clientOnSocket callback not a func");
6738
+ const cb = args[1];
6739
+ emitter.moveTemp(cb);
6740
+ const adapter = cbT.params.length === 0 ? "scr_net_conn_thunk0" : "scr_net_conn_thunk_sock";
6741
+ emitter.line(`scr_http_client_on_socket(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6742
+ return { name: "", type: e.type };
6743
+ }
6331
6744
  case "http.clientOnError": {
6332
6745
  const cbT = e.args[1].type;
6333
6746
  if (cbT.kind !== "func")
@@ -6339,10 +6752,14 @@ function emitHttpLibCall(state) {
6339
6752
  return { name: "", type: e.type };
6340
6753
  }
6341
6754
  case "http.clientOnTimeout":
6342
- case "http.clientOnClose": {
6755
+ case "http.clientOnClose":
6756
+ case "http.clientOnFinish":
6757
+ case "http.clientOnAbort": {
6343
6758
  const cb = args[1];
6344
6759
  emitter.moveTemp(cb);
6345
- const fn = e.fn === "http.clientOnTimeout" ? "scr_http_client_on_timeout" : "scr_http_client_on_close";
6760
+ const fn = e.fn === "http.clientOnTimeout" ? "scr_http_client_on_timeout"
6761
+ : e.fn === "http.clientOnClose" ? "scr_http_client_on_close"
6762
+ : e.fn === "http.clientOnAbort" ? "scr_http_client_on_abort" : "scr_http_client_on_finish";
6346
6763
  emitter.line(`${fn}(${arg(0)}, ${cb.name}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6347
6764
  return { name: "", type: e.type };
6348
6765
  }
@@ -7126,6 +7543,45 @@ function emitProcessLibCall(state) {
7126
7543
  return finish(`scr_process_getgid()`);
7127
7544
  case "process.execPath":
7128
7545
  return finish(`scr_process_exec_path()`);
7546
+ case "process.forkTarget":
7547
+ return finish(`scr_process_fork_target(${arg(0)})`);
7548
+ case "process.connected":
7549
+ return finish(`scr_process_ipc_connected()`);
7550
+ case "process.send":
7551
+ emitter.usesTimers = true;
7552
+ return finish(`scr_process_ipc_send(${arg(0)})`);
7553
+ case "process.sendCb": {
7554
+ const cbT = e.args[1].type;
7555
+ if (cbT.kind !== "func")
7556
+ throw new InternalCompilerError("emitter bug: process.send callback not a func");
7557
+ const cb = args[1];
7558
+ emitter.moveTemp(cb);
7559
+ emitter.usesTimers = true;
7560
+ return finish(`scr_process_ipc_send_cb(${arg(0)}, ${cb.name}, &${emitter.ipcSendThunkFor(cbT)})`);
7561
+ }
7562
+ case "process.disconnect":
7563
+ emitter.usesTimers = true;
7564
+ return finish(`scr_process_ipc_disconnect()`);
7565
+ case "process.onMessage": {
7566
+ const cbT = e.args[0].type;
7567
+ if (cbT.kind !== "func")
7568
+ throw new InternalCompilerError("emitter bug: process message listener not a func");
7569
+ const cb = args[0];
7570
+ emitter.moveTemp(cb);
7571
+ emitter.usesTimers = true;
7572
+ emitter.line(`scr_process_ipc_on_message(${cb.name}, &${emitter.ipcMessageThunkFor(cbT)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
7573
+ return { name: "", type: e.type };
7574
+ }
7575
+ case "process.onDisconnect": {
7576
+ const cbT = e.args[0].type;
7577
+ if (cbT.kind !== "func")
7578
+ throw new InternalCompilerError("emitter bug: process disconnect listener not a func");
7579
+ const cb = args[0];
7580
+ emitter.moveTemp(cb);
7581
+ emitter.usesTimers = true;
7582
+ emitter.line(`scr_process_ipc_on_disconnect(${cb.name}, ${arg(1)});${emitter.srcComment(e.loc)}`);
7583
+ return { name: "", type: e.type };
7584
+ }
7129
7585
  case "process.arch":
7130
7586
  return finish(`scr_process_arch()`);
7131
7587
  case "process.versionsNode":
@@ -7149,6 +7605,10 @@ function emitProcessLibCall(state) {
7149
7605
  // Flushes stdout and _Exit()s — never returns (exit handlers,
7150
7606
  // including the RC audit, deliberately do not run).
7151
7607
  return finish(`scr_process_exit(${arg(0)})`);
7608
+ case "process.setExitCode":
7609
+ return finish(`scr_process_set_exit_code(${arg(0)})`);
7610
+ case "process.currentExitCode":
7611
+ return finish(`scr_process_exit_code_or_zero()`);
7152
7612
  case "process.nextTick": {
7153
7613
  // The tick queue owns the callback until the drain fires it;
7154
7614
  // ticks run before promise jobs at every loop checkpoint and
@@ -7362,6 +7822,8 @@ function emitErrorsEventsLibCall(state) {
7362
7822
  const dynThunk = emitter.emitterInvokeThunkFor(adT);
7363
7823
  return finish(`(${cType(e.type).trim()})scr_emitter_on_dyn((ScrEmitter *)${arg(0)}, ${arg(1)}, ${arg(2)}, ${adapter.name}, &${dynThunk}, ${arg(4)}, ${arg(5)})`);
7364
7824
  }
7825
+ case "emitter.onFlex":
7826
+ return finish(`(${cType(e.type).trim()})scr_emitter_on_flex((ScrEmitter *)${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)})`);
7365
7827
  case "emitter.onData": {
7366
7828
  // The stream-'data' registration: same runtime entry as
7367
7829
  // emitter.on, but the DATA invoke thunk (the two-slot payload
@@ -7401,6 +7863,13 @@ function emitErrorsEventsLibCall(state) {
7401
7863
  // C variadic tail, every argument borrowed (the invoke
7402
7864
  // adapters retain each callee's +1). May-throw (listeners).
7403
7865
  return finish(`scr_emitter_emit((ScrEmitter *)${arg(0)}, ${arg(1)}${e.args.slice(2).map((_, i) => `, ${arg(i + 2)}`).join("")})`);
7866
+ case "emitter.emitFlex": {
7867
+ const count = e.args.length - 2;
7868
+ const payload = count === 0
7869
+ ? "NULL"
7870
+ : `(ScrDyn *const[]){${e.args.slice(2).map((_, i) => arg(i + 2)).join(", ")}}`;
7871
+ return finish(`scr_emitter_emit_flex((ScrEmitter *)${arg(0)}, ${arg(1)}, ${payload}, ${count})`);
7872
+ }
7404
7873
  case "emitter.emitError":
7405
7874
  // emit('error', err): unhandled ⇒ the runtime throws the
7406
7875
  // payload through the exception cell (may-throw seed).
@@ -7479,12 +7948,25 @@ function emitStreamLibCall(state) {
7479
7948
  emitter.line(`scr_child_stream_on_data(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
7480
7949
  return { name: "", type: e.type };
7481
7950
  }
7951
+ case "stream.onDataStr": {
7952
+ emitter.usesTimers = true;
7953
+ const cbT = e.args[1].type;
7954
+ if (cbT.kind !== "func" || cbT.params[0]?.kind !== "string") {
7955
+ throw new InternalCompilerError("emitter bug: stream.onDataStr callback not a string func");
7956
+ }
7957
+ const cb = args[1];
7958
+ emitter.moveTemp(cb);
7959
+ emitter.line(`scr_child_stream_on_data_str(${arg(0)}, ${cb.name}, &scr_child_stream_thunk_str, ${arg(2)});${emitter.srcComment(e.loc)}`);
7960
+ return { name: "", type: e.type };
7961
+ }
7482
7962
  case "stream.onEnd": {
7483
7963
  const cb = args[1];
7484
7964
  emitter.moveTemp(cb);
7485
7965
  emitter.line(`scr_child_stream_on_end(${arg(0)}, ${cb.name}, ${arg(2)});${emitter.srcComment(e.loc)}`);
7486
7966
  return { name: "", type: e.type };
7487
7967
  }
7968
+ case "stream.childSetEncoding":
7969
+ return finish(`scr_child_stream_set_encoding(${arg(0)}, ${arg(1)})`);
7488
7970
  // node:stream (scr_stream.c — linked exactly when these appear,
7489
7971
  // moduleUsesStream). Receivers reinterpret to the shared
7490
7972
  // ScrStream layout (the ScrEmitter prefix plus the stream-state
@@ -7895,6 +8377,8 @@ function emitAssertInspectLibCall(state) {
7895
8377
  // The quartet over checked-dynamic operands: SameValue /
7896
8378
  // dyn-walk deep equality, assertion_error.js messages.
7897
8379
  return finish(`scr_assert_eq_dyn(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)})`);
8380
+ case "assert.looseResult":
8381
+ return finish(`scr_assert_loose_result(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)})`);
7898
8382
  case "assert.deepResult":
7899
8383
  return finish(`scr_assert_deep_result(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)})`);
7900
8384
  case "assert.deqEnter":
@@ -8175,6 +8659,7 @@ export function emitExpr(emitter, e) {
8175
8659
  case "numLit":
8176
8660
  case "boolLit":
8177
8661
  case "strLit":
8662
+ case "moduleNsRef":
8178
8663
  case "unitLit":
8179
8664
  case "varRef":
8180
8665
  return emitLiteralExpr(emitter, e);