@scriptc/compiler 0.2.0 → 0.2.1

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 (194) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +25 -15
  2. package/dist/backend/cycle-analysis.js +1 -0
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/llvm/classes.js +21 -5
  5. package/dist/backend/llvm/classes.js.map +1 -1
  6. package/dist/backend/llvm/dyn.d.ts +5 -0
  7. package/dist/backend/llvm/dyn.js +166 -99
  8. package/dist/backend/llvm/dyn.js.map +1 -1
  9. package/dist/backend/llvm/emitter.d.ts +2 -2
  10. package/dist/backend/llvm/emitter.js +79 -20
  11. package/dist/backend/llvm/emitter.js.map +1 -1
  12. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  13. package/dist/backend/llvm/expr-bytes.js +28 -17
  14. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  15. package/dist/backend/llvm/expr-control.js +1 -1
  16. package/dist/backend/llvm/expr-control.js.map +1 -1
  17. package/dist/backend/llvm/expr-dynamic.js +18 -9
  18. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  19. package/dist/backend/llvm/expr-primitives.js +11 -1
  20. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  21. package/dist/backend/llvm/expr-records.js +11 -3
  22. package/dist/backend/llvm/expr-records.js.map +1 -1
  23. package/dist/backend/llvm/expr-stream-bridges.js +125 -17
  24. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  25. package/dist/backend/llvm/lib-process.js +23 -3
  26. package/dist/backend/llvm/lib-process.js.map +1 -1
  27. package/dist/backend/llvm/lib-shared.js +45 -2
  28. package/dist/backend/llvm/lib-shared.js.map +1 -1
  29. package/dist/backend/llvm/shapes.js +8 -2
  30. package/dist/backend/llvm/shapes.js.map +1 -1
  31. package/dist/backend/native-toolchain.d.ts +3 -6
  32. package/dist/backend/native-toolchain.js +53 -23
  33. package/dist/backend/native-toolchain.js.map +1 -1
  34. package/dist/backend/native-toolchain.test.js +72 -0
  35. package/dist/backend/native-toolchain.test.js.map +1 -1
  36. package/dist/backend/runtime-abi.d.ts +2 -2
  37. package/dist/backend/runtime-abi.js +2 -2
  38. package/dist/backend/runtime-pack-native.js +4 -1
  39. package/dist/backend/runtime-pack-native.js.map +1 -1
  40. package/dist/backend/runtime-pack-targets.test.js +1 -1
  41. package/dist/backend/runtime-pack.test.js +1 -1
  42. package/dist/backend/targets.js +10 -6
  43. package/dist/backend/targets.js.map +1 -1
  44. package/dist/backend/targets.test.js +7 -0
  45. package/dist/backend/targets.test.js.map +1 -1
  46. package/dist/compat/fetch-profile.js +34 -4
  47. package/dist/compat/fetch-profile.js.map +1 -1
  48. package/dist/diagnostics/diagnostic.js +2 -7
  49. package/dist/diagnostics/diagnostic.js.map +1 -1
  50. package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
  51. package/dist/frontend/lowering/class-callbacks.js +26 -15
  52. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  53. package/dist/frontend/lowering/class-construction.d.ts +12 -0
  54. package/dist/frontend/lowering/class-construction.js +156 -0
  55. package/dist/frontend/lowering/class-construction.js.map +1 -0
  56. package/dist/frontend/lowering/class-descriptors.d.ts +1 -0
  57. package/dist/frontend/lowering/class-descriptors.js +46 -5
  58. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  59. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +11 -1
  60. package/dist/frontend/lowering/class-dynamic-dispatch.js +403 -48
  61. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  62. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +2 -1
  63. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  64. package/dist/frontend/lowering/class-instance-constructor.js +4 -1
  65. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  66. package/dist/frontend/lowering/class-method-values.d.ts +4 -1
  67. package/dist/frontend/lowering/class-method-values.js +72 -7
  68. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  69. package/dist/frontend/lowering/class-prototypes.d.ts +5 -2
  70. package/dist/frontend/lowering/class-prototypes.js +121 -13
  71. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  72. package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
  73. package/dist/frontend/lowering/class-runtime-statics.js +66 -0
  74. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
  75. package/dist/frontend/lowering/class-static-data.js +2 -2
  76. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  77. package/dist/frontend/lowering/containers/bytes.js +49 -13
  78. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  79. package/dist/frontend/lowering/containers/string-and-regexp.js +19 -47
  80. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  81. package/dist/frontend/lowering/error-methods.d.ts +4 -1
  82. package/dist/frontend/lowering/error-methods.js +100 -1
  83. package/dist/frontend/lowering/error-methods.js.map +1 -1
  84. package/dist/frontend/lowering/expressions/native-proxy.js +3 -1
  85. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  86. package/dist/frontend/lowering/expressions/nullish-assignment.js +19 -11
  87. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  88. package/dist/frontend/lowering/expressions/object-literals.js +38 -7
  89. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  90. package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
  91. package/dist/frontend/lowering/expressions/optional-chains.js +69 -17
  92. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  93. package/dist/frontend/lowering/function-context.d.ts +11 -3
  94. package/dist/frontend/lowering/function-context.js +11 -5
  95. package/dist/frontend/lowering/function-context.js.map +1 -1
  96. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -0
  97. package/dist/frontend/lowering/generator-dynamic-dispatch.js +39 -1
  98. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
  99. package/dist/frontend/lowering/lib-boundary.d.ts +2 -0
  100. package/dist/frontend/lowering/lib-boundary.js +54 -1
  101. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  102. package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -1
  103. package/dist/frontend/lowering/lower-builtin-values.js +113 -3
  104. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  105. package/dist/frontend/lowering/lower-builtins.d.ts +6 -5
  106. package/dist/frontend/lowering/lower-builtins.js +156 -41
  107. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  108. package/dist/frontend/lowering/lower-calls.d.ts +8 -5
  109. package/dist/frontend/lowering/lower-calls.js +448 -83
  110. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  111. package/dist/frontend/lowering/lower-classes.d.ts +13 -13
  112. package/dist/frontend/lowering/lower-classes.js +650 -176
  113. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  114. package/dist/frontend/lowering/lower-containers.d.ts +9 -0
  115. package/dist/frontend/lowering/lower-containers.js +135 -36
  116. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  117. package/dist/frontend/lowering/lower-dgram.js +3 -2
  118. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  119. package/dist/frontend/lowering/lower-exprs.d.ts +2 -2
  120. package/dist/frontend/lowering/lower-exprs.js +531 -126
  121. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  122. package/dist/frontend/lowering/lower-generators.js +12 -1
  123. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  124. package/dist/frontend/lowering/lower-island.d.ts +2 -0
  125. package/dist/frontend/lowering/lower-island.js +32 -10
  126. package/dist/frontend/lowering/lower-island.js.map +1 -1
  127. package/dist/frontend/lowering/lower-modules.js +220 -17
  128. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  129. package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
  130. package/dist/frontend/lowering/lower-modules.test.js +39 -0
  131. package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
  132. package/dist/frontend/lowering/lower-stmts.d.ts +7 -3
  133. package/dist/frontend/lowering/lower-stmts.js +135 -26
  134. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  135. package/dist/frontend/lowering/lower-stream.js +1 -1
  136. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  137. package/dist/frontend/lowering/lowerer.d.ts +27 -1
  138. package/dist/frontend/lowering/lowerer.js +172 -50
  139. package/dist/frontend/lowering/lowerer.js.map +1 -1
  140. package/dist/frontend/lowering/lowerer.test.js +149 -3
  141. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  142. package/dist/frontend/lowering/surfaces.d.ts +2 -0
  143. package/dist/frontend/lowering/surfaces.js +25 -8
  144. package/dist/frontend/lowering/surfaces.js.map +1 -1
  145. package/dist/frontend/lowering/text-decoder-encoding.d.ts +2 -0
  146. package/dist/frontend/lowering/text-decoder-encoding.js +5 -0
  147. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  148. package/dist/frontend/lowering/unregistered-class-types.test.js +3 -3
  149. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
  150. package/dist/frontend/npm-static-prune.js +116 -34
  151. package/dist/frontend/npm-static-prune.js.map +1 -1
  152. package/dist/frontend/npm-static-prune.test.js +8 -0
  153. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  154. package/dist/frontend/program.d.ts +1 -1
  155. package/dist/frontend/program.js +53 -24
  156. package/dist/frontend/program.js.map +1 -1
  157. package/dist/frontend/program.test.js +18 -0
  158. package/dist/frontend/program.test.js.map +1 -1
  159. package/dist/frontend/ts7/ast.js +4 -3
  160. package/dist/frontend/ts7/ast.js.map +1 -1
  161. package/dist/frontend/ts7/semantic-json.js +5 -10
  162. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  163. package/dist/frontend/type-mapper.d.ts +9 -1
  164. package/dist/frontend/type-mapper.js +90 -13
  165. package/dist/frontend/type-mapper.js.map +1 -1
  166. package/dist/frontend/type-mapper.test.js +23 -0
  167. package/dist/frontend/type-mapper.test.js.map +1 -1
  168. package/dist/frontend/union-discriminants.d.ts +1 -1
  169. package/dist/frontend/union-discriminants.js +2 -2
  170. package/dist/frontend/union-discriminants.js.map +1 -1
  171. package/dist/ir/analysis.js +2 -0
  172. package/dist/ir/analysis.js.map +1 -1
  173. package/dist/ir/ir.d.ts +52 -33
  174. package/dist/ir/ir.js +142 -42
  175. package/dist/ir/ir.js.map +1 -1
  176. package/dist/ir/ir.test.js +35 -0
  177. package/dist/ir/ir.test.js.map +1 -1
  178. package/dist/ir/serialize.js +15 -3
  179. package/dist/ir/serialize.js.map +1 -1
  180. package/dist/ir/serialize.test.js +5 -1
  181. package/dist/ir/serialize.test.js.map +1 -1
  182. package/dist/ir/validate.js +80 -11
  183. package/dist/ir/validate.js.map +1 -1
  184. package/dist/ir/validate.test.js +61 -1
  185. package/dist/ir/validate.test.js.map +1 -1
  186. package/dist/native/sanitizer.js +3 -1
  187. package/dist/native/sanitizer.js.map +1 -1
  188. package/dist/native/toolchain.d.ts +1 -1
  189. package/dist/native/toolchain.js +26 -6
  190. package/dist/native/toolchain.js.map +1 -1
  191. package/dist/native/toolchain.test.js +53 -1
  192. package/dist/native/toolchain.test.js.map +1 -1
  193. package/package.json +20 -20
  194. package/surface-manifest.json +56 -81
@@ -7,6 +7,7 @@ import { InternalCompilerError } from "../../errors.js";
7
7
  import { builtinModules } from "node:module";
8
8
  import { dirname, isAbsolute, resolve } from "node:path";
9
9
  import * as ts from "../ts7/adapter.js";
10
+ import { lowerCheckedPredicateValue } from "./lower-builtin-values.js";
10
11
  import { PoisonError, dynUndefinedExpr, ladderFenceExpr, nodeThrowExpr, own } from "./lowerer.js";
11
12
  import { canonicalBuiltinModule, isCreateRequireBinding7, isJsSourceFile, isNodeEsmFile, locOf, npmStaticDepSf7, requireSpecOf, resolveImport } from "../program.js";
12
13
  import { isRelativeSpecifier } from "../workspace-registry.js";
@@ -480,7 +481,7 @@ export function createRequireProgramModuleOf(lowerer, expr) {
480
481
  const cr = createRequireSpecOf(lowerer, call);
481
482
  if (cr === null || cr.spec === null || canonicalBuiltinModule(cr.spec) !== null)
482
483
  return null;
483
- const dep = resolveImport(lowerer.program, cr.baseFile, cr.spec) ??
484
+ const dep = resolveImport(lowerer.program, cr.baseFile, cr.spec, "require") ??
484
485
  npmStaticDepSf7(lowerer.program, cr.baseFile, cr.spec, "require");
485
486
  if (dep === null || dep.fileName.endsWith(".json"))
486
487
  return null;
@@ -1161,6 +1162,9 @@ export function lowerFsToUnixTimestampCall(lowerer, expr, bi, loc) {
1161
1162
  * after every validation passes, exactly Node's order. Null when this
1162
1163
  * is not a claimed member/shape (the table or fence path stands). */
1163
1164
  export function lowerFsLadderCall(lowerer, expr, bi, loc) {
1165
+ if (bi.module === "fs" && bi.member !== "rename" && builtinModuleFnOf(lowerer, bi.module, bi.member)?.fn === "fs.callbackCall") {
1166
+ return lowerer.lowerBuiltinModuleCall(expr, bi, { fn: "fs.callbackCall", params: [], result: DYN }, loc);
1167
+ }
1164
1168
  if (bi.module !== "fs" && bi.module !== "fs/promises")
1165
1169
  return null;
1166
1170
  if (!isJsSourceFile(expr.getSourceFile()))
@@ -1410,6 +1414,12 @@ function lowerZlibModuleCall(lowerer, expr, bi, loc) {
1410
1414
  }
1411
1415
  export function lowerBuiltinModuleCall(lowerer, expr, bi, fn, loc) {
1412
1416
  const name = expr.expression.getText();
1417
+ if (fn.fn === "fs.callbackCall" && bi.member !== "rename") {
1418
+ if (expr.arguments.some(ts.isSpreadElement))
1419
+ lowerer.noLowering("filesystem callback call with spread arguments", expr);
1420
+ const args = { kind: "dynArrLit", elems: expr.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
1421
+ return { kind: "libCall", fn: "fs.callbackCall", args: [{ kind: "strLit", value: bi.member, type: STRING, loc }, args], type: DYN, loc };
1422
+ }
1413
1423
  // Numeric open flags are interpreted symbolically at the call site. The
1414
1424
  // O_* bit values differ between Darwin and Linux, so emit a stable mask
1415
1425
  // and let the target runtime select its own native constants.
@@ -2318,15 +2328,20 @@ export function lowerBuiltinModuleCall(lowerer, expr, bi, fn, loc) {
2318
2328
  }
2319
2329
  return { kind: "libCall", fn: fn.fn, args, type: fn.result, loc };
2320
2330
  }
2321
- /** Reflect.apply(target, thisArg, argsList) where the TARGET is a builtin
2331
+ /** Reflect.ownKeys uses native computed-key reflection. Reflect.apply(target,
2332
+ * thisArg, argsList) where the TARGET is a builtin
2322
2333
  * rest-parameter table fn (path.join / path.resolve — test/common
2323
2334
  * fixtures.js's fixturesPath forwards its rest args exactly this way):
2324
2335
  * the packed libCall over a validated string[] extraction of argsList.
2325
2336
  * The builtins ignore the receiver, so thisArg must be an effect-free
2326
2337
  * spelling (`this`, an identifier, a unit literal) whose dropped
2327
2338
  * evaluation is unobservable; every other Reflect.apply keeps the
2328
- * fence. Null when this isn't a Reflect.apply call. */
2329
- export function lowerReflectApplyCall(lowerer, call, access) {
2339
+ * fence. Null when this isn't a supported Reflect call. */
2340
+ export function lowerReflectCall(lowerer, call, access) {
2341
+ if (!call.questionDotToken && !access.questionDotToken && lowerer.stdlibGlobalMember(access, "Reflect") === "ownKeys" &&
2342
+ call.arguments.length === 1 && !ts.isSpreadElement(call.arguments[0])) {
2343
+ return { kind: "libCall", fn: "dyn.ownKeys", args: [lowerer.lowerExprExpecting(call.arguments[0], DYN)], type: DYN, loc: locOf(call) };
2344
+ }
2330
2345
  if (call.questionDotToken)
2331
2346
  return null;
2332
2347
  if (lowerer.stdlibGlobalMember(access, "Reflect") !== "apply")
@@ -2340,7 +2355,10 @@ export function lowerReflectApplyCall(lowerer, call, access) {
2340
2355
  const bi = ts.isPropertyAccessExpression(targetNode) ? lowerer.builtinMemberOf(targetNode) : null;
2341
2356
  const fn = bi ? builtinModuleFnOf(lowerer, bi.module, bi.member) : null;
2342
2357
  if (!fn || fn.variadicPack !== true) {
2343
- lowerer.noLowering(`Reflect.apply of '${targetNode.getText()}'`, targetNode, fenceHint);
2358
+ const target = lowerer.lowerExprExpecting(targetNode, DYN);
2359
+ const receiver = lowerer.lowerExprExpecting(call.arguments[1], DYN);
2360
+ const argumentsList = lowerer.lowerExprExpecting(call.arguments[2], DYN);
2361
+ return { kind: "libCall", fn: "dyn.reflectApply", args: [target, receiver, argumentsList], type: DYN, loc };
2344
2362
  }
2345
2363
  const thisNode = call.arguments[1];
2346
2364
  const effectFree = thisNode.kind === ts.SyntaxKind.ThisKeyword ||
@@ -2524,8 +2542,8 @@ export function lowerSpawnSyncCall(lowerer, expr, loc) {
2524
2542
  };
2525
2543
  }
2526
2544
  /** `spawn(command, args?, options)` → one cp.spawn / cp.spawnOpts
2527
- * libCall. The options argument, when present, must be an object
2528
- * LITERAL. Stdio accepts "ignore", "inherit", or "pipe" as the scalar,
2545
+ * libCall. Computed options use native runtime normalization. Inline
2546
+ * stdio accepts "ignore", "inherit", or "pipe" as the scalar,
2529
2547
  * or the 3-tuple whose stdin pipe becomes child.stdin, stdout/stderr
2530
2548
  * pipes become child.stdout/child.stderr, and output slots may also be
2531
2549
  * number fds. Omitting stdio uses Node's default: all three piped. The
@@ -2559,7 +2577,11 @@ export function lowerSpawnCall(lowerer, expr, loc) {
2559
2577
  optsNode = second;
2560
2578
  }
2561
2579
  if (optsNode !== undefined && !ts.isObjectLiteralExpression(optsNode)) {
2562
- lowerer.noLowering("spawn with a non-literal options argument", optsNode, "pass stdio, detached, env, cwd, windowsHide, and shell in an inline object literal");
2580
+ return {
2581
+ kind: "libCall", fn: "cp.spawnDynamic",
2582
+ args: [cmd, lowerer.lowerChildArgsArg(argsNode, loc), lowerer.lowerExprExpecting(optsNode, DYN)],
2583
+ type: CHILD_T, loc,
2584
+ };
2563
2585
  }
2564
2586
  const emptyStr = { kind: "strLit", value: "", type: STRING, loc };
2565
2587
  // Per-slot stdio modes (scr_child.c: 0 ignore, 1 inherit, 2 fd) and
@@ -4312,6 +4334,18 @@ export function lowerJsonMethodCall(lowerer, call, access) {
4312
4334
  return { kind: "libCall", fn: "json.parseReviver", args: [text, callback], type: DYN, loc };
4313
4335
  }
4314
4336
  if (member === "stringify") {
4337
+ const replacerNode = call.arguments[1];
4338
+ const spaceNode = call.arguments[2];
4339
+ const runtimeOptions = replacerNode && !jsonNullishArgument(lowerer, replacerNode) &&
4340
+ lowerer.mapTypeOf(lowerer.typeOf(replacerNode))?.kind === "dyn" ||
4341
+ spaceNode && !jsonNullishArgument(lowerer, spaceNode) &&
4342
+ !ts.isNumericLiteral(spaceNode) && !ts.isStringLiteral(spaceNode) && !ts.isNoSubstitutionTemplateLiteral(spaceNode) &&
4343
+ !(ts.isPrefixUnaryExpression(spaceNode) && ts.isNumericLiteral(spaceNode.operand));
4344
+ if (runtimeOptions && call.arguments[0]) {
4345
+ const args = [0, 1, 2].map((index) => call.arguments[index]
4346
+ ? lowerer.lowerExprExpecting(call.arguments[index], DYN) : dynUndefinedExpr(loc));
4347
+ return { kind: "libCall", fn: "json.stringifyValue", args, type: DYN, loc };
4348
+ }
4315
4349
  const indent = stringifySpaceIndent(lowerer, call);
4316
4350
  if (call.arguments.length === 0) {
4317
4351
  return lowerer.wrappedUndefined(lowerer.withUndefinedArm(STRING), loc);
@@ -4516,6 +4550,12 @@ function jsonNullishArgument(lowerer, node) {
4516
4550
  * refuse signatures that request one until that protocol is implemented. */
4517
4551
  function lowerJsonCallback(lowerer, node, role) {
4518
4552
  const callback = lowerer.lowerExpr(node);
4553
+ if (callback.type.kind === "dyn")
4554
+ return callback;
4555
+ if (callback.type.kind === "union" && lowerer.dynConvertible(callback.type) &&
4556
+ lowerer.unions.get(callback.type.unionId)?.arms.every((arm) => isUnitType(arm) || arm.kind === "func" &&
4557
+ arm.params.length <= 2 && (role !== "reviver" || (!arm.rest && !arm.argumentsAll))))
4558
+ return lowerer.coerceToExpected(callback, DYN);
4519
4559
  if (callback.type.kind === "func" && callback.type.params.length <= 2 &&
4520
4560
  (role !== "reviver" || (!callback.type.rest && !callback.type.argumentsAll)) &&
4521
4561
  canBoxFuncIntoDyn(callback.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
@@ -4959,6 +4999,9 @@ export function lowerSearchParamsNew(lowerer, expr, loc) {
4959
4999
  return acc;
4960
5000
  }
4961
5001
  const init = lowerer.lowerExpr(arg);
5002
+ if (init.type.kind === "dyn") {
5003
+ return { kind: "libCall", fn: "sp.newChecked", args: [init], type: SEARCH_PARAMS_T, loc };
5004
+ }
4962
5005
  if (init.type.kind === "string") {
4963
5006
  return { kind: "libCall", fn: "sp.parse", args: [init], type: SEARCH_PARAMS_T, loc };
4964
5007
  }
@@ -5817,7 +5860,7 @@ export function lowerChildMethodCall(lowerer, call, access) {
5817
5860
  if ((name === "on" || name === "once") && call.arguments.length === 2) {
5818
5861
  const evT = lowerer.typeOf(call.arguments[0]);
5819
5862
  const event = evT.isStringLiteralType() ? evT.value : null;
5820
- if (event !== "exit" && event !== "close" && event !== "error" && event !== "message" && event !== "disconnect") {
5863
+ if (event !== "spawn" && event !== "exit" && event !== "close" && event !== "error" && event !== "message" && event !== "disconnect") {
5821
5864
  lowerer.noLowering(`child.${name}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, call.arguments[0], '"exit", "close", "error", "message", and "disconnect" are the supported child events (as literals)');
5822
5865
  }
5823
5866
  if (!ts.isExpressionStatement(call.parent)) {
@@ -5843,7 +5886,33 @@ export function lowerChildMethodCall(lowerer, call, access) {
5843
5886
  loc,
5844
5887
  };
5845
5888
  }
5889
+ const listenerNode = stripTypeCasts(call.arguments[1]);
5890
+ if (isJsSourceFile(listenerNode.getSourceFile()) &&
5891
+ (ts.isArrowFunction(listenerNode) || ts.isFunctionExpression(listenerNode)) &&
5892
+ listenerNode.parameters.some((param) => param.dotDotDotToken) &&
5893
+ listenerNode.parameters.every((param) => !param.type) &&
5894
+ !/@(?:param|type)\b/.test(listenerNode.getSourceFile().text.slice(listenerNode.pos, listenerNode.getStart()))) {
5895
+ for (const param of listenerNode.parameters)
5896
+ lowerer.checkedCallbackParams.add(param);
5897
+ }
5846
5898
  const cb = lowerer.lowerExpr(call.arguments[1]);
5899
+ if (cb.type.kind === "func" && cb.type.rest) {
5900
+ if (!canBoxFuncIntoDyn(cb.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
5901
+ lowerer.noLowering("child event rest listeners with non-representable parameters", call.arguments[1]);
5902
+ }
5903
+ return {
5904
+ kind: "libCall", fn: "child.onDyn",
5905
+ args: [receiver, { kind: "strLit", value: event, type: STRING, loc },
5906
+ { kind: "dynFrom", value: cb, type: DYN, loc }],
5907
+ type: VOID, loc,
5908
+ };
5909
+ }
5910
+ if (event === "spawn") {
5911
+ if (cb.type.kind !== "func" || cb.type.params.length !== 0 || cb.type.ret.kind !== "void") {
5912
+ lowerer.noLowering("spawn event listeners with parameters or a returned value", call.arguments[1]);
5913
+ }
5914
+ return { kind: "libCall", fn: "child.onSpawn", args: [receiver, cb], type: VOID, loc };
5915
+ }
5847
5916
  if (cb.type.kind !== "func" || cb.type.params.length > (event === "error" ? 1 : 2)) {
5848
5917
  lowerer.unsupported("SC1090", call.arguments[1], event !== "error"
5849
5918
  ? `${event} listeners with more than two parameters (use (code, signal), (code), or ())`
@@ -5918,9 +5987,9 @@ export function lowerChildMethodCall(lowerer, call, access) {
5918
5987
  // child.unref(): drops the child from the event loop's keep-alive set
5919
5988
  // (the process may exit while the child runs — Node's semantics; the
5920
5989
  // child is still reaped while the loop runs for other reasons).
5921
- if (name === "unref" && call.arguments.length === 0) {
5990
+ if ((name === "unref" || name === "ref") && call.arguments.length === 0) {
5922
5991
  const receiver = lowerer.lowerExpr(access.expression);
5923
- return { kind: "libCall", fn: "child.unref", args: [receiver], type: VOID, loc };
5992
+ return { kind: "libCall", fn: name === "ref" ? "child.ref" : "child.unref", args: [receiver], type: VOID, loc };
5924
5993
  }
5925
5994
  lowerer.noLowering(`ChildProcess.${name}`, call, "send(), connected, disconnect(), on/once(\"message\" | \"disconnect\" | \"exit\" | \"close\" | \"error\", cb), pid, exitCode, killed, kill(signal?), and unref() are supported", lowerer.checker.getSymbolAtLocation(access.name));
5926
5995
  }
@@ -6259,10 +6328,10 @@ export function lowerFsConstantsProperty(lowerer, expr) {
6259
6328
  const bi = lowerer.builtinImportOf(expr.expression);
6260
6329
  if (!bi || bi.module !== "fs" || bi.member !== "constants")
6261
6330
  return null;
6262
- const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4 };
6331
+ const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4, COPYFILE_EXCL: 1, COPYFILE_FICLONE: 2, COPYFILE_FICLONE_FORCE: 4 };
6263
6332
  const value = own(MODES, expr.name.text);
6264
6333
  if (value === undefined) {
6265
- lowerer.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, and X_OK are the lowered constants");
6334
+ lowerer.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, X_OK, and COPYFILE_* are the lowered constants");
6266
6335
  }
6267
6336
  return { kind: "numLit", value, type: F64, loc: locOf(expr) };
6268
6337
  }
@@ -7777,7 +7846,7 @@ export function lowerDateCall(lowerer, call, access) {
7777
7846
  export function lowerTextCodecNew(lowerer, ctor, cls) {
7778
7847
  const args = ctor.arguments ?? [];
7779
7848
  const loc = locOf(ctor);
7780
- let encoding = -1;
7849
+ let encoding = { kind: "numLit", value: -1, type: F64, loc };
7781
7850
  let label = null;
7782
7851
  if (cls === "TextEncoder") {
7783
7852
  if (args.length !== 0)
@@ -7786,17 +7855,39 @@ export function lowerTextCodecNew(lowerer, ctor, cls) {
7786
7855
  else if (args.length !== 0) {
7787
7856
  const labelT = lowerer.typeOf(args[0]);
7788
7857
  const parsed = labelT.isStringLiteralType() ? staticTextDecoderEncoding(labelT.value) : null;
7789
- if (args.length !== 1 || parsed === null) {
7790
- lowerer.noLowering("new TextDecoder with runtime-valued options or an unknown label", ctor, "a recognized literal WHATWG label with default options compiles");
7858
+ if (args.length > 2)
7859
+ lowerer.noLowering("new TextDecoder with extra arguments", ctor);
7860
+ if (parsed === null) {
7861
+ encoding = { kind: "libCall", fn: "text.decoderEncoding", args: [lowerer.lowerExprExpecting(args[0], DYN)], type: F64, loc };
7862
+ }
7863
+ else {
7864
+ encoding = { kind: "numLit", value: parsed.kind === "utf8" ? -1 : parsed.id, type: F64, loc };
7865
+ label = lowerer.lowerExprExpecting(args[0], STRING);
7866
+ }
7867
+ }
7868
+ const options = args[1] ? stripTypeCasts(args[1]) : null;
7869
+ const flags = new Map();
7870
+ for (const name of ["fatal", "ignoreBOM"])
7871
+ flags.set(name, { kind: "boolLit", value: false, type: BOOL, loc });
7872
+ if (options) {
7873
+ if (!ts.isObjectLiteralExpression(options))
7874
+ lowerer.noLowering("TextDecoder options outside an object literal", options);
7875
+ for (const property of options.properties) {
7876
+ if ((!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property)) ||
7877
+ !ts.isIdentifier(property.name) || !flags.has(property.name.text))
7878
+ lowerer.noLowering("unknown TextDecoder option", property);
7879
+ const value = ts.isPropertyAssignment(property) ? property.initializer : property.name;
7880
+ flags.set(property.name.text, lowerer.lowerExprExpecting(value, BOOL));
7791
7881
  }
7792
- encoding = parsed.kind === "utf8" ? -1 : parsed.id;
7793
- label = lowerer.lowerExprExpecting(args[0], STRING);
7794
7882
  }
7795
7883
  const type = lowerer.mapTypeOf(lowerer.typeOf(ctor));
7796
7884
  if (type?.kind !== "record")
7797
7885
  lowerer.badType(ctor, lowerer.typeOf(ctor));
7798
7886
  const result = {
7799
- kind: "recordLit", fields: [{ name: `%${cls}`, value: { kind: "numLit", value: encoding, type: F64, loc } }], type, loc,
7887
+ kind: "recordLit", fields: [{ name: `%${cls}`, value: encoding }, ...(cls === "TextDecoder" ? [
7888
+ ...[...flags].map(([name, value]) => ({ name: `%${name}`, value })),
7889
+ { name: "%state", value: { kind: "dynObjLit", fields: [], type: DYN, loc } },
7890
+ ] : [])], type, loc,
7800
7891
  };
7801
7892
  return label === null || label.kind === "strLit" ? result : {
7802
7893
  kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: label, loc }], result, type, loc,
@@ -7814,17 +7905,32 @@ function lowerStoredTextCodecCall(lowerer, call, access) {
7814
7905
  return null;
7815
7906
  if (access.name.text !== (cls === "TextEncoder" ? "encode" : "decode"))
7816
7907
  return null;
7817
- if (call.arguments.length > 1) {
7818
- lowerer.noLowering(cls === "TextDecoder" ? "decode with a stream option" : "TextEncoder.encode with extra arguments", call);
7908
+ if (call.arguments.length > (cls === "TextDecoder" ? 2 : 1)) {
7909
+ lowerer.noLowering(`${cls}.${access.name.text} with extra arguments`, call);
7819
7910
  }
7820
7911
  const loc = locOf(call);
7912
+ let stream = { kind: "boolLit", value: false, type: BOOL, loc };
7913
+ if (cls === "TextDecoder" && call.arguments[1]) {
7914
+ const options = stripTypeCasts(call.arguments[1]);
7915
+ if (!ts.isObjectLiteralExpression(options))
7916
+ lowerer.noLowering("TextDecoder.decode options outside an object literal", options);
7917
+ for (const property of options.properties) {
7918
+ if ((!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property)) ||
7919
+ !ts.isIdentifier(property.name) || property.name.text !== "stream")
7920
+ lowerer.noLowering("unknown TextDecoder.decode option", property);
7921
+ stream = lowerer.lowerExprExpecting(ts.isPropertyAssignment(property) ? property.initializer : property.name, BOOL);
7922
+ }
7923
+ }
7821
7924
  const receiver = lowerer.lowerExpr(access.expression);
7822
7925
  if (receiver.type.kind !== "record")
7823
7926
  lowerer.badType(access.expression, lowerer.typeOf(access.expression));
7824
- const arg = call.arguments.length === 0
7927
+ let arg = call.arguments.length === 0
7825
7928
  ? cls === "TextEncoder" ? strLit("", loc)
7826
7929
  : { kind: "bytesNew", source: null, type: BYTES_U8, loc }
7827
7930
  : cls === "TextEncoder" ? lowerer.lowerExprExpecting(call.arguments[0], STRING) : lowerer.lowerExpr(call.arguments[0]);
7931
+ if (cls === "TextDecoder" && (arg.type.kind === "dyn" || arg.type.kind === "bytes" && arg.type.elem !== "u8")) {
7932
+ arg = { kind: "libCall", fn: "bytes.bufferSource", args: [lowerer.coerceInto(call.arguments[0], arg, DYN)], type: BYTES_U8, loc };
7933
+ }
7828
7934
  if (cls === "TextDecoder" && !(arg.type.kind === "bytes" && arg.type.elem === "u8")) {
7829
7935
  lowerer.noLowering(`TextDecoder.decode of '${lowerer.fmt(arg.type)}' values`, call, "Uint8Array/Buffer input decodes (ArrayBuffer values have no representation)");
7830
7936
  }
@@ -7837,22 +7943,22 @@ function lowerStoredTextCodecCall(lowerer, call, access) {
7837
7943
  const input = varRef("input.0", arg.type, loc);
7838
7944
  const result = cls === "TextEncoder"
7839
7945
  ? { kind: "libCall", fn: "buffer.fromStr", args: [input, { kind: "strLit", value: "utf8", type: STRING, loc }], type: BYTES_U8, loc }
7840
- : {
7841
- kind: "ternary",
7842
- cond: { kind: "bin", op: "<", left: { kind: "recordGet", obj: varRef("codec.0", recT, loc), shapeId: recT.shapeId, field: "%TextDecoder", type: F64, loc }, right: { kind: "numLit", value: 0, type: F64, loc }, type: BOOL, loc },
7843
- then: { kind: "libCall", fn: "text.decode", args: [input], type: STRING, loc },
7844
- else_: { kind: "libCall", fn: "text.decodeLegacy", args: [input, { kind: "recordGet", obj: varRef("codec.0", recT, loc), shapeId: recT.shapeId, field: "%TextDecoder", type: F64, loc }], type: STRING, loc },
7845
- type: STRING, loc,
7846
- };
7946
+ : { kind: "libCall", fn: "text.decodeStream", args: [
7947
+ { kind: "recordGet", obj: varRef("codec.0", recT, loc), shapeId: recT.shapeId, field: "%state", type: DYN, loc },
7948
+ input,
7949
+ { kind: "recordGet", obj: varRef("codec.0", recT, loc), shapeId: recT.shapeId, field: "%TextDecoder", type: F64, loc },
7950
+ ...["%fatal", "%ignoreBOM"].map((field) => ({ kind: "recordGet", obj: varRef("codec.0", recT, loc), shapeId: recT.shapeId, field, type: BOOL, loc })),
7951
+ varRef("stream.0", BOOL, loc),
7952
+ ], type: STRING, loc };
7847
7953
  lowerer.liftedFns.push({
7848
7954
  name,
7849
- params: [{ localId: "codec.0", name: "codec", type: recT }, { localId: "input.0", name: "input", type: arg.type }],
7955
+ params: [{ localId: "codec.0", name: "codec", type: recT }, { localId: "input.0", name: "input", type: arg.type }, { localId: "stream.0", name: "stream", type: BOOL }],
7850
7956
  returnType: result.type,
7851
- locals: [{ id: "codec.0", name: "codec", type: recT, mutable: false }, { id: "input.0", name: "input", type: arg.type, mutable: false }],
7957
+ locals: [{ id: "codec.0", name: "codec", type: recT, mutable: false }, { id: "input.0", name: "input", type: arg.type, mutable: false }, { id: "stream.0", name: "stream", type: BOOL, mutable: false }],
7852
7958
  body: [{ kind: "return", value: result, loc }], loc,
7853
7959
  });
7854
7960
  }
7855
- return { kind: "call", callee: name, args: [receiver, arg], type: cls === "TextEncoder" ? BYTES_U8 : STRING, loc };
7961
+ return { kind: "call", callee: name, args: [receiver, arg, stream], type: cls === "TextEncoder" ? BYTES_U8 : STRING, loc };
7856
7962
  }
7857
7963
  /** A direct construction of THE stdlib TextEncoder/TextDecoder, through
7858
7964
  * type-only wrappers. Name alone is never enough: a user class with the
@@ -7893,6 +7999,8 @@ export function lowerTextCodecCall(lowerer, call, access) {
7893
7999
  if (!lowerer.isStdlibMember(access))
7894
8000
  return null;
7895
8001
  const { cls, ctor: recv } = info;
8002
+ if (cls === "TextDecoder" && ((recv.arguments?.length ?? 0) > 1 || call.arguments.length > 1))
8003
+ return lowerStoredTextCodecCall(lowerer, call, access);
7896
8004
  if (!(cls === "TextDecoder" && member === "decode") && !(cls === "TextEncoder" && member === "encode")) {
7897
8005
  return null;
7898
8006
  }
@@ -7909,7 +8017,7 @@ export function lowerTextCodecCall(lowerer, call, access) {
7909
8017
  ? staticTextDecoderEncoding(labelT.value)
7910
8018
  : null;
7911
8019
  if (ctorArgs.length > 1 || encoding === null) {
7912
- lowerer.noLowering("new TextDecoder with runtime-valued options or an unknown label", recv, "a recognized literal WHATWG label with default options compiles");
8020
+ return lowerStoredTextCodecCall(lowerer, call, access);
7913
8021
  }
7914
8022
  const labelEffect = ctorArgs.length === 1
7915
8023
  ? lowerer.lowerExprExpecting(ctorArgs[0], STRING)
@@ -7931,7 +8039,10 @@ export function lowerTextCodecCall(lowerer, call, access) {
7931
8039
  lowerer.noLowering("decode with a stream option", call, "streaming decode has no lowering — decode whole buffers");
7932
8040
  }
7933
8041
  const argNode = call.arguments[0];
7934
- const arg = lowerer.lowerExpr(argNode);
8042
+ let arg = lowerer.lowerExpr(argNode);
8043
+ if (arg.type.kind === "dyn" || arg.type.kind === "bytes" && arg.type.elem !== "u8") {
8044
+ arg = { kind: "libCall", fn: "bytes.bufferSource", args: [lowerer.coerceInto(argNode, arg, DYN)], type: BYTES_U8, loc };
8045
+ }
7935
8046
  if (!(arg.type.kind === "bytes" && arg.type.elem === "u8")) {
7936
8047
  lowerer.noLowering(`TextDecoder.decode of '${lowerer.fmt(arg.type)}' values`, argNode, "Uint8Array/Buffer input decodes (ArrayBuffer values have no representation)");
7937
8048
  }
@@ -8159,7 +8270,7 @@ export function lowerPromiseStaticCall(lowerer, call, access) {
8159
8270
  // reads are the routed keyed ops). All-static tuples keep the
8160
8271
  // typed fence hint below. --dynamic only by construction: jsval
8161
8272
  // entries exist only there.
8162
- if (elems.some((e) => e.type.kind === "jsval")) {
8273
+ if (lowerer.dynamic && elems.some((e) => e.type.kind === "jsval" || e.type.kind === "dyn")) {
8163
8274
  const diagsBefore = lowerer.diags.length;
8164
8275
  try {
8165
8276
  const marshaled = argNode.elements.map((el, i) => lowerer.jsvalIn(elems[i], el));
@@ -8192,7 +8303,7 @@ export function lowerPromiseStaticCall(lowerer, call, access) {
8192
8303
  // marshaled array (an 'any' value passes through; an `any[]` value
8193
8304
  // lifts per element by reference), the result staying an island
8194
8305
  // value the static side awaits through the island→static bridge.
8195
- if (entries.type.kind === "jsval" ||
8306
+ if (entries.type.kind === "jsval" || lowerer.dynamic && entries.type.kind === "dyn" ||
8196
8307
  (entries.type.kind === "array" && entries.type.elem.kind === "jsval")) {
8197
8308
  const diagsBefore = lowerer.diags.length;
8198
8309
  try {
@@ -8368,11 +8479,12 @@ export function lowerPromiseStaticCall(lowerer, call, access) {
8368
8479
  return { kind: "intrinsic", name: "promise.resolve", args: [], type: { kind: "promise", inner: VOID }, loc };
8369
8480
  }
8370
8481
  if (resultT.inner.kind === "void") {
8371
- // Promise.resolve(expr) at a void-promise type: the argument's
8372
- // effects must still run — no statement slot exists here for
8373
- // them, so only effect-free spellings could drop it honestly;
8374
- // fence rather than model that corner.
8375
- lowerer.noLowering("Promise.resolve with an argument at a void-promise type", call);
8482
+ return {
8483
+ kind: "seqExpr",
8484
+ stmts: [lowerer.lowerExprStatement(argNode)],
8485
+ result: { kind: "intrinsic", name: "promise.resolve", args: [], type: resultT, loc },
8486
+ type: resultT, loc,
8487
+ };
8376
8488
  }
8377
8489
  if (isUnitType(resultT.inner)) {
8378
8490
  // A unit payload (Promise<undefined>/Promise<null>) has no
@@ -8392,6 +8504,9 @@ export function lowerNumberStaticProperty(lowerer, expr) {
8392
8504
  const member = lowerer.stdlibGlobalMember(expr, "Number");
8393
8505
  if (member === null)
8394
8506
  return null;
8507
+ const predicate = own(NUMBER_STATIC_PREDICATES, member);
8508
+ if (predicate)
8509
+ return lowerCheckedPredicateValue(lowerer, `Number.${member}`, "number", locOf(expr), predicate);
8395
8510
  const value = own(NUMBER_CONSTANTS, member);
8396
8511
  if (value === undefined)
8397
8512
  return null;