@scriptc/compiler 0.1.4 → 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 (150) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +75 -11
  2. package/dist/backend/c/c-emitter.d.ts +5 -1
  3. package/dist/backend/c/c-emitter.js +22 -9
  4. package/dist/backend/c/c-emitter.js.map +1 -1
  5. package/dist/backend/c/exprs.d.ts +2 -2
  6. package/dist/backend/c/exprs.js +264 -21
  7. package/dist/backend/c/exprs.js.map +1 -1
  8. package/dist/backend/c/stmts.js +5 -3
  9. package/dist/backend/c/stmts.js.map +1 -1
  10. package/dist/backend/c/types.d.ts +2 -3
  11. package/dist/backend/c/types.js +8 -1
  12. package/dist/backend/c/types.js.map +1 -1
  13. package/dist/backend/c/walkers.js +1 -1
  14. package/dist/backend/c/walkers.js.map +1 -1
  15. package/dist/backend/link-plan.d.ts +1 -0
  16. package/dist/backend/link-plan.js +2 -1
  17. package/dist/backend/link-plan.js.map +1 -1
  18. package/dist/backend/llvm/dyn.js +1 -1
  19. package/dist/backend/llvm/dyn.js.map +1 -1
  20. package/dist/backend/llvm/emitter.js +25 -9
  21. package/dist/backend/llvm/emitter.js.map +1 -1
  22. package/dist/backend/llvm/expr-bytes.d.ts +1 -2
  23. package/dist/backend/llvm/expr-bytes.js +22 -17
  24. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  25. package/dist/backend/llvm/expr-containers.d.ts +1 -0
  26. package/dist/backend/llvm/expr-containers.js +32 -4
  27. package/dist/backend/llvm/expr-containers.js.map +1 -1
  28. package/dist/backend/llvm/expr-context.d.ts +6 -2
  29. package/dist/backend/llvm/expr-primitives.js +22 -7
  30. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  31. package/dist/backend/llvm/lib-filesystem.js +12 -0
  32. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  33. package/dist/backend/llvm/lib-network.js +53 -10
  34. package/dist/backend/llvm/lib-network.js.map +1 -1
  35. package/dist/backend/llvm/lib-shared.js +64 -0
  36. package/dist/backend/llvm/lib-shared.js.map +1 -1
  37. package/dist/backend/native-toolchain.d.ts +2 -0
  38. package/dist/backend/native-toolchain.js +2 -1
  39. package/dist/backend/native-toolchain.js.map +1 -1
  40. package/dist/backend/targets.d.ts +3 -0
  41. package/dist/backend/targets.js +13 -0
  42. package/dist/backend/targets.js.map +1 -1
  43. package/dist/coverage/surface-manifest.js +6 -4
  44. package/dist/coverage/surface-manifest.js.map +1 -1
  45. package/dist/executable/executable-cache.d.ts +2 -0
  46. package/dist/executable/executable-cache.js +3 -1
  47. package/dist/executable/executable-cache.js.map +1 -1
  48. package/dist/executable/executable-cache.test.js +3 -3
  49. package/dist/executable/executable-cache.test.js.map +1 -1
  50. package/dist/frontend/lowering/containers/bytes.d.ts +1 -1
  51. package/dist/frontend/lowering/containers/bytes.js +6 -5
  52. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  53. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +7 -6
  54. package/dist/frontend/lowering/containers/string-and-regexp.js +237 -28
  55. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  56. package/dist/frontend/lowering/expressions/object-literals.js +8 -0
  57. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  58. package/dist/frontend/lowering/lower-builtins.d.ts +4 -5
  59. package/dist/frontend/lowering/lower-builtins.js +18 -10
  60. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  61. package/dist/frontend/lowering/lower-calls.d.ts +3 -2
  62. package/dist/frontend/lowering/lower-calls.js +265 -88
  63. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  64. package/dist/frontend/lowering/lower-classes.js +2 -2
  65. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  66. package/dist/frontend/lowering/lower-containers.d.ts +7 -9
  67. package/dist/frontend/lowering/lower-containers.js +143 -51
  68. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  69. package/dist/frontend/lowering/lower-exprs.d.ts +12 -0
  70. package/dist/frontend/lowering/lower-exprs.js +128 -10
  71. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  72. package/dist/frontend/lowering/lower-island.js +17 -6
  73. package/dist/frontend/lowering/lower-island.js.map +1 -1
  74. package/dist/frontend/lowering/lower-server.d.ts +2 -4
  75. package/dist/frontend/lowering/lower-server.js +288 -32
  76. package/dist/frontend/lowering/lower-server.js.map +1 -1
  77. package/dist/frontend/lowering/lower-stmts.js +4 -4
  78. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  79. package/dist/frontend/lowering/lowerer.js +37 -2
  80. package/dist/frontend/lowering/lowerer.js.map +1 -1
  81. package/dist/frontend/lowering/optional-arguments.d.ts +9 -1
  82. package/dist/frontend/lowering/optional-arguments.js +67 -1
  83. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  84. package/dist/frontend/lowering/pairs-snapshot.d.ts +3 -1
  85. package/dist/frontend/lowering/pairs-snapshot.js +12 -4
  86. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  87. package/dist/frontend/lowering/surfaces.d.ts +8 -14
  88. package/dist/frontend/lowering/surfaces.js +37 -27
  89. package/dist/frontend/lowering/surfaces.js.map +1 -1
  90. package/dist/frontend/npm-static-prune.d.ts +6 -0
  91. package/dist/frontend/npm-static-prune.js +203 -0
  92. package/dist/frontend/npm-static-prune.js.map +1 -0
  93. package/dist/frontend/npm-static-prune.test.d.ts +1 -0
  94. package/dist/frontend/npm-static-prune.test.js +48 -0
  95. package/dist/frontend/npm-static-prune.test.js.map +1 -0
  96. package/dist/frontend/npm.js +7 -6
  97. package/dist/frontend/npm.js.map +1 -1
  98. package/dist/frontend/program.js +15 -4
  99. package/dist/frontend/program.js.map +1 -1
  100. package/dist/frontend/provenance.js +8 -3
  101. package/dist/frontend/provenance.js.map +1 -1
  102. package/dist/frontend/type-mapper.js +16 -5
  103. package/dist/frontend/type-mapper.js.map +1 -1
  104. package/dist/index.d.ts +3 -3
  105. package/dist/index.js +13 -41
  106. package/dist/index.js.map +1 -1
  107. package/dist/ir/analysis.d.ts +5 -3
  108. package/dist/ir/analysis.js +25 -11
  109. package/dist/ir/analysis.js.map +1 -1
  110. package/dist/ir/analysis.test.js +50 -2
  111. package/dist/ir/analysis.test.js.map +1 -1
  112. package/dist/ir/constant-tables.d.ts +17 -0
  113. package/dist/ir/constant-tables.js +99 -0
  114. package/dist/ir/constant-tables.js.map +1 -0
  115. package/dist/ir/constant-tables.test.d.ts +1 -0
  116. package/dist/ir/constant-tables.test.js +78 -0
  117. package/dist/ir/constant-tables.test.js.map +1 -0
  118. package/dist/ir/integer-ranges.d.ts +13 -0
  119. package/dist/ir/integer-ranges.js +122 -0
  120. package/dist/ir/integer-ranges.js.map +1 -0
  121. package/dist/ir/integer-ranges.test.d.ts +1 -0
  122. package/dist/ir/integer-ranges.test.js +63 -0
  123. package/dist/ir/integer-ranges.test.js.map +1 -0
  124. package/dist/ir/ir.d.ts +42 -34
  125. package/dist/ir/ir.js +7 -1
  126. package/dist/ir/ir.js.map +1 -1
  127. package/dist/ir/ir.test.js +6 -0
  128. package/dist/ir/ir.test.js.map +1 -1
  129. package/dist/ir/scalar-records.d.ts +8 -0
  130. package/dist/ir/scalar-records.js +216 -0
  131. package/dist/ir/scalar-records.js.map +1 -0
  132. package/dist/ir/scalar-records.test.d.ts +1 -0
  133. package/dist/ir/scalar-records.test.js +142 -0
  134. package/dist/ir/scalar-records.test.js.map +1 -0
  135. package/dist/ir/validate.js +92 -8
  136. package/dist/ir/validate.js.map +1 -1
  137. package/dist/ir/validate.test.d.ts +1 -0
  138. package/dist/ir/validate.test.js +31 -0
  139. package/dist/ir/validate.test.js.map +1 -0
  140. package/dist/library/cache-primitives.d.ts +1 -1
  141. package/dist/library/cache-primitives.js +3 -3
  142. package/dist/library/cache-primitives.js.map +1 -1
  143. package/dist/library/fence-eval.js +11 -4
  144. package/dist/library/fence-eval.js.map +1 -1
  145. package/dist/library/library-cache.js +0 -1
  146. package/dist/library/library-cache.js.map +1 -1
  147. package/dist/library/library-cache.test.js +3 -3
  148. package/dist/library/library-cache.test.js.map +1 -1
  149. package/package.json +17 -17
  150. package/surface-manifest.json +55 -42
@@ -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));
@@ -604,11 +604,36 @@ function emitLiteralExpr(emitter, e) {
604
604
  }
605
605
  }
606
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
+ }
607
626
  function emitOperatorExpr(emitter, e) {
608
627
  switch (e.kind) {
609
628
  case "bin": {
610
629
  const l = emitter.emitExpr(e.left);
611
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
+ }
612
637
  switch (e.op) {
613
638
  case "%":
614
639
  return emitter.newTemp(e.type, `fmod(${l.name}, ${r.name})`);
@@ -639,7 +664,8 @@ function emitOperatorExpr(emitter, e) {
639
664
  case "unary": {
640
665
  const v = emitter.emitExpr(e.operand);
641
666
  if (e.op === "~")
642
- 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})`);
643
669
  return emitter.newTemp(e.type, `${e.op}${v.name}`);
644
670
  }
645
671
  case "incDec": {
@@ -1233,9 +1259,13 @@ function emitStringExpr(emitter, e) {
1233
1259
  }
1234
1260
  return emitter.newTemp(e.type, `scr_str_includes(${r.name}, ${args[0].name})`);
1235
1261
  case "startsWith":
1236
- 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})`);
1237
1265
  case "endsWith":
1238
- 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})`);
1239
1269
  case "slice":
1240
1270
  return emitter.newTemp(e.type, `scr_str_slice(${r.name}, ${args[0]?.name ?? "0"}, ${args[1]?.name ?? "INFINITY"})`);
1241
1271
  case "substring":
@@ -1447,7 +1477,11 @@ function emitContainerExpr(emitter, e) {
1447
1477
  return emitter.newTemp(e.type, `scr_arr_state(${arr.name}, ${idx.name})`);
1448
1478
  }
1449
1479
  case "arrIntrinsic": {
1450
- 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);
1451
1485
  if (e.receiver.type.kind !== "array")
1452
1486
  throw new InternalCompilerError("emitter bug: arrIntrinsic on non-array");
1453
1487
  const acc = elemAccess(e.receiver.type.elem);
@@ -1455,6 +1489,11 @@ function emitContainerExpr(emitter, e) {
1455
1489
  switch (method) {
1456
1490
  case "length":
1457
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
+ }
1458
1497
  case "nextPresent": {
1459
1498
  const start = emitter.emitExpr(e.args[0]);
1460
1499
  return emitter.newTemp(e.type, `scr_arr_next_present(${r.name}, ${start.name})`);
@@ -1677,7 +1716,7 @@ function emitContainerExpr(emitter, e) {
1677
1716
  const method = e.method;
1678
1717
  const directElementAccess = method === "length" || method === "byteLength" || method === "get";
1679
1718
  const r = directElementAccess
1680
- ? emitBytesReceiver(emitter, e.receiver, e.args)
1719
+ ? emitStableReceiver(emitter, e.receiver, e.args)
1681
1720
  : emitter.emitExpr(e.receiver);
1682
1721
  const integerIndex = method === "get" ? emitter.integerLoopIndex(e.args[0]) : null;
1683
1722
  const args = integerIndex === null ? e.args.map((a) => emitter.emitExpr(a)) : [];
@@ -1688,7 +1727,7 @@ function emitContainerExpr(emitter, e) {
1688
1727
  if (e.receiver.type.kind !== "bytes") {
1689
1728
  throw new InternalCompilerError("emitter bug: bytesIntrinsic byteLength on non-bytes");
1690
1729
  }
1691
- 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"})`);
1692
1731
  case "get":
1693
1732
  // Any invalid index traps (the array runtime's discipline).
1694
1733
  if (e.receiver.type.kind !== "bytes") {
@@ -4764,6 +4803,8 @@ function emitPrimitiveLibCall(state) {
4764
4803
  return finish(`scr_math_max_arr(${arg(0)})`);
4765
4804
  case "math.minArr":
4766
4805
  return finish(`scr_math_min_arr(${arg(0)})`);
4806
+ case "math.hypotArr":
4807
+ return finish(`scr_math_hypot_arr(${arg(0)})`);
4767
4808
  // Math.floor/trunc/ceil — the C functions ARE the JS operations
4768
4809
  // (math.h is always included). Borrow nothing; no throw.
4769
4810
  case "math.floor":
@@ -4772,6 +4813,38 @@ function emitPrimitiveLibCall(state) {
4772
4813
  return finish(`trunc(${arg(0)})`);
4773
4814
  case "math.ceil":
4774
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)})`);
4775
4848
  // Math.abs — C fabs IS the JS operation. Math.round — the JS
4776
4849
  // half-toward-+Infinity rule (scr_lib.c; C round() differs on
4777
4850
  // halves and naive floor(x+0.5) drifts at the epsilon boundary).
@@ -5015,6 +5088,8 @@ function emitPrimitiveLibCall(state) {
5015
5088
  : `scr_str_from_char_code(${arg(0)})`);
5016
5089
  case "string.lastIndexOf":
5017
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)})`);
5018
5093
  case "string.raw":
5019
5094
  // Raw literals + pre-stringified substitutions; +1 string.
5020
5095
  return finish(`scr_str_raw(${arg(0)}, ${arg(1)})`);
@@ -5521,6 +5596,8 @@ function emitNetworkLibCall(state) {
5521
5596
  }
5522
5597
  case "net.serverPort":
5523
5598
  return finish(`scr_net_server_port(${arg(0)})`);
5599
+ case "net.serverListening":
5600
+ return finish(`scr_net_server_listening(${arg(0)})`);
5524
5601
  case "net.serverAddress": {
5525
5602
  // The AddressInfo record from the three runtime reads (the
5526
5603
  // dgram.address materialization; none of these throw).
@@ -5598,9 +5675,7 @@ function emitNetworkLibCall(state) {
5598
5675
  const cb = args[1];
5599
5676
  emitter.moveTemp(cb);
5600
5677
  const adapter = cbT.params.length === 0 ? "scr_net_conn_thunk0" : "scr_net_conn_thunk_sock";
5601
- const entry = e.fn === "net.serverOnConnection"
5602
- ? "scr_net_server_on_connection"
5603
- : "scr_net_server_on_secure_connection";
5678
+ const entry = e.fn === "net.serverOnConnection" ? "scr_net_server_on_connection" : "scr_net_server_on_secure_connection";
5604
5679
  emitter.line(`${entry}(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
5605
5680
  return { name: "", type: e.type };
5606
5681
  }
@@ -6058,10 +6133,22 @@ function emitHttpLibCall(state) {
6058
6133
  case "http.resSetHeader":
6059
6134
  emitter.line(`scr_http_res_set_header(${arg(0)}, ${arg(1)}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6060
6135
  return { name: "", type: e.type };
6136
+ case "http.validateHeaderName":
6137
+ emitter.line(`scr_http_validate_header_name(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6138
+ return { name: "", type: e.type };
6139
+ case "http.validateHeaderValue":
6140
+ emitter.line(`scr_http_validate_header_value(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6141
+ return { name: "", type: e.type };
6061
6142
  case "http.resWriteHead":
6062
6143
  return finish(`scr_http_res_write_head(${arg(0)}, ${arg(1)})`);
6063
6144
  case "http.resWriteHeadN":
6064
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)})`);
6065
6152
  case "http.resWrite":
6066
6153
  return finish(`scr_http_res_write_str(${arg(0)}, ${arg(1)})`);
6067
6154
  case "http.resWriteBytes":
@@ -6078,6 +6165,8 @@ function emitHttpLibCall(state) {
6078
6165
  return finish(`scr_http_res_end_dynv(${arg(0)}, ${arg(1)})`);
6079
6166
  case "http.resHeadersSent":
6080
6167
  return finish(`scr_http_res_headers_sent(${arg(0)})`);
6168
+ case "http.resWritableEnded":
6169
+ return finish(`scr_http_res_writable_ended(${arg(0)})`);
6081
6170
  case "http.resFlushHeaders":
6082
6171
  return finish(`scr_http_res_flush_headers(${arg(0)})`);
6083
6172
  case "http.resAddTrailers":
@@ -6245,6 +6334,32 @@ function emitHttpLibCall(state) {
6245
6334
  case "http.serverAllowMissingHostHeader":
6246
6335
  emitter.line(`scr_http_server_allow_missing_host_header(${arg(0)});${emitter.srcComment(e.loc)}`);
6247
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
+ }
6248
6363
  case "http.serverTimeoutGet":
6249
6364
  return finish(`scr_net_server_timeout_get(${arg(0)}, ${arg(1)})`);
6250
6365
  case "http.serverTimeoutSet":
@@ -6257,27 +6372,82 @@ function emitHttpLibCall(state) {
6257
6372
  case "http.resStatusSet":
6258
6373
  emitter.line(`scr_http_res_status_set(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6259
6374
  return { name: "", type: e.type };
6260
- case "http.resStatusMsgGet":
6261
- 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
+ }
6262
6388
  case "http.resStatusMsgSet":
6263
6389
  emitter.line(`scr_http_res_status_msg_set(${arg(0)}, ${arg(1)});${emitter.srcComment(e.loc)}`);
6264
6390
  return { name: "", type: e.type };
6265
- 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": {
6266
6429
  // string|undefined, exactly the http.reqHeader emission.
6267
6430
  if (e.type.kind !== "union")
6268
- 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`);
6269
6432
  const def = emitter.unionsById.get(e.type.unionId);
6270
6433
  const strTag = def ? def.arms.findIndex((a) => a.kind === "string") : -1;
6271
6434
  const undefTag = undefinedArmTag(e.type, emitter.unionsById);
6272
6435
  if (strTag < 0 || undefTag < 0) {
6273
6436
  throw new InternalCompilerError("emitter bug: http.resGetHeader union lacks its arms");
6274
6437
  }
6275
- 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)})`);
6276
6440
  emitter.moveTemp(s); // moves into the box when present; NULL otherwise
6277
6441
  const present = `scr_union_new_ref(${strTag}, ${s.name}, &scr_str_retain_v, &scr_str_release_v, NULL)`;
6278
6442
  const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
6279
6443
  return emitter.newTemp(e.type, `${s.name} ? ${present} : ${absent}`);
6280
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)})`);
6281
6451
  case "http.resHasHeader":
6282
6452
  return finish(`scr_http_res_has_header_named(${arg(0)}, ${arg(1)})`);
6283
6453
  case "http.resRemoveHeader":
@@ -6295,6 +6465,14 @@ function emitHttpLibCall(state) {
6295
6465
  return finish(`scr_http_res_write_head_dyn(${arg(0)}, ${arg(1)}, ${arg(2)})`);
6296
6466
  case "http.reqSetEncoding":
6297
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
+ }
6298
6476
  // node:http, the client slice (scr_http.c over the net client).
6299
6477
  case "http.request":
6300
6478
  case "http.requestCb": {
@@ -6464,6 +6642,18 @@ function emitHttpLibCall(state) {
6464
6642
  }
6465
6643
  case "http.clientWrite":
6466
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)})`);
6467
6657
  case "http.clientWriteBytes":
6468
6658
  return finish(`scr_http_client_write_bytes(${arg(0)}, ${arg(1)})`);
6469
6659
  case "http.clientEnd":
@@ -6487,9 +6677,48 @@ function emitHttpLibCall(state) {
6487
6677
  return finish(`scr_http_client_uncork(${arg(0)})`);
6488
6678
  case "http.clientWritableCorked":
6489
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)}`);
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()");
6490
6714
  case "http.clientDestroy":
6491
6715
  emitter.line(`scr_http_client_destroy(${arg(0)});${emitter.srcComment(e.loc)}`);
6492
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)})`);
6493
6722
  case "http.clientDestroyed":
6494
6723
  return finish(`scr_http_client_destroyed(${arg(0)})`);
6495
6724
  case "http.clientOnResponse": {
@@ -6502,6 +6731,16 @@ function emitHttpLibCall(state) {
6502
6731
  emitter.line(`scr_http_client_on_response(${arg(0)}, ${cb.name}, &${adapter}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6503
6732
  return { name: "", type: e.type };
6504
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
+ }
6505
6744
  case "http.clientOnError": {
6506
6745
  const cbT = e.args[1].type;
6507
6746
  if (cbT.kind !== "func")
@@ -6513,10 +6752,14 @@ function emitHttpLibCall(state) {
6513
6752
  return { name: "", type: e.type };
6514
6753
  }
6515
6754
  case "http.clientOnTimeout":
6516
- case "http.clientOnClose": {
6755
+ case "http.clientOnClose":
6756
+ case "http.clientOnFinish":
6757
+ case "http.clientOnAbort": {
6517
6758
  const cb = args[1];
6518
6759
  emitter.moveTemp(cb);
6519
- 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";
6520
6763
  emitter.line(`${fn}(${arg(0)}, ${cb.name}, ${arg(2)});${emitter.srcComment(e.loc)}`);
6521
6764
  return { name: "", type: e.type };
6522
6765
  }