@scriptc/compiler 0.0.22 → 0.0.24

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 (93) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +139 -14
  2. package/dist/backend/cc.d.ts +13 -0
  3. package/dist/backend/cc.js +11 -0
  4. package/dist/backend/cc.js.map +1 -1
  5. package/dist/backend/emission/emit-async.d.ts +4 -0
  6. package/dist/backend/emission/emit-async.js +34 -2
  7. package/dist/backend/emission/emit-async.js.map +1 -1
  8. package/dist/backend/emission/emit-exprs.d.ts +10 -0
  9. package/dist/backend/emission/emit-exprs.js +272 -22
  10. package/dist/backend/emission/emit-exprs.js.map +1 -1
  11. package/dist/backend/emission/emit-shapes.js +1 -0
  12. package/dist/backend/emission/emit-shapes.js.map +1 -1
  13. package/dist/backend/emission/emit-stmts.js +36 -9
  14. package/dist/backend/emission/emit-stmts.js.map +1 -1
  15. package/dist/backend/emission/emit-types.js +14 -1
  16. package/dist/backend/emission/emit-types.js.map +1 -1
  17. package/dist/backend/emission/emitter.d.ts +19 -1
  18. package/dist/backend/emission/emitter.js +81 -2
  19. package/dist/backend/emission/emitter.js.map +1 -1
  20. package/dist/backend/llvm/emitter.js +578 -36
  21. package/dist/backend/llvm/emitter.js.map +1 -1
  22. package/dist/backend/llvm/shapes.js +12 -3
  23. package/dist/backend/llvm/shapes.js.map +1 -1
  24. package/dist/backend/mangle.d.ts +3 -0
  25. package/dist/backend/mangle.js +5 -0
  26. package/dist/backend/mangle.js.map +1 -1
  27. package/dist/compat/fetch-profile.d.ts +10 -0
  28. package/dist/compat/fetch-profile.js +55 -6
  29. package/dist/compat/fetch-profile.js.map +1 -1
  30. package/dist/coverage/surface-manifest.js +16 -1
  31. package/dist/coverage/surface-manifest.js.map +1 -1
  32. package/dist/diagnostics/diagnostic.d.ts +10 -0
  33. package/dist/diagnostics/diagnostic.js +27 -1
  34. package/dist/diagnostics/diagnostic.js.map +1 -1
  35. package/dist/frontend/lowering/lower-builtins.d.ts +17 -16
  36. package/dist/frontend/lowering/lower-builtins.js +817 -117
  37. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  38. package/dist/frontend/lowering/lower-calls.js +3 -1
  39. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  40. package/dist/frontend/lowering/lower-classes.js +28 -8
  41. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  42. package/dist/frontend/lowering/lower-containers.d.ts +2 -1
  43. package/dist/frontend/lowering/lower-containers.js +99 -32
  44. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  45. package/dist/frontend/lowering/lower-exprs.d.ts +1 -1
  46. package/dist/frontend/lowering/lower-exprs.js +78 -6
  47. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  48. package/dist/frontend/lowering/lower-generators.js +7 -1
  49. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  50. package/dist/frontend/lowering/lower-inspect.js +59 -1
  51. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  52. package/dist/frontend/lowering/lower-island.d.ts +21 -0
  53. package/dist/frontend/lowering/lower-island.js +284 -10
  54. package/dist/frontend/lowering/lower-island.js.map +1 -1
  55. package/dist/frontend/lowering/lower-server.d.ts +5 -0
  56. package/dist/frontend/lowering/lower-server.js +1 -1
  57. package/dist/frontend/lowering/lower-server.js.map +1 -1
  58. package/dist/frontend/lowering/lower-stmts.d.ts +6 -2
  59. package/dist/frontend/lowering/lower-stmts.js +53 -14
  60. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  61. package/dist/frontend/lowering/lowerer.d.ts +3 -2
  62. package/dist/frontend/lowering/lowerer.js +17 -8
  63. package/dist/frontend/lowering/lowerer.js.map +1 -1
  64. package/dist/frontend/lowering/surfaces.js +108 -25
  65. package/dist/frontend/lowering/surfaces.js.map +1 -1
  66. package/dist/frontend/program.d.ts +4 -4
  67. package/dist/frontend/program.js +264 -46
  68. package/dist/frontend/program.js.map +1 -1
  69. package/dist/frontend/resolve.d.ts +10 -0
  70. package/dist/frontend/resolve.js +37 -0
  71. package/dist/frontend/resolve.js.map +1 -1
  72. package/dist/frontend/ts7/enums.d.ts +9 -0
  73. package/dist/frontend/ts7/enums.js +8 -6
  74. package/dist/frontend/ts7/enums.js.map +1 -1
  75. package/dist/frontend/ts7/program.js +4 -1
  76. package/dist/frontend/ts7/program.js.map +1 -1
  77. package/dist/frontend/types.d.ts +7 -4
  78. package/dist/frontend/types.js +103 -8
  79. package/dist/frontend/types.js.map +1 -1
  80. package/dist/index.js +8 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/ir/integer-loops.d.ts +23 -0
  83. package/dist/ir/integer-loops.js +82 -0
  84. package/dist/ir/integer-loops.js.map +1 -0
  85. package/dist/ir/nodes.d.ts +104 -28
  86. package/dist/ir/nodes.js +89 -1
  87. package/dist/ir/nodes.js.map +1 -1
  88. package/dist/ir/validate.js +136 -25
  89. package/dist/ir/validate.js.map +1 -1
  90. package/dist/library/fence-eval.js +4 -3
  91. package/dist/library/fence-eval.js.map +1 -1
  92. package/package.json +2 -2
  93. package/surface-manifest.json +186 -29
@@ -1,4 +1,4 @@
1
- import { arrayOf, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isJsonSafeType, isRefCounted, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey, unionFuncSetArmsOk, URL_T, VOID } from "./nodes.js";
1
+ import { arrayOf, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, DATE_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, FILEHANDLE_T, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isJsonSafeType, isRefCounted, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey, unionFuncSetArmsOk, URL_T, VOID } from "./nodes.js";
2
2
  /** Per-method signature for strIntrinsic: `argTypes` lists every argument
3
3
  * position (optional ones included); `minArgs` is how many may be omitted
4
4
  * from the end (backends fill the documented defaults). Exported for the
@@ -18,7 +18,7 @@ export const STR_INTRINSIC_SIGS = {
18
18
  trim: { argTypes: [], minArgs: 0, result: STRING },
19
19
  trimStart: { argTypes: [], minArgs: 0, result: STRING },
20
20
  trimEnd: { argTypes: [], minArgs: 0, result: STRING },
21
- split: { argTypes: [STRING], minArgs: 1, result: arrayOf(STRING) },
21
+ split: { argTypes: [STRING, F64], minArgs: 2, result: arrayOf(STRING) },
22
22
  padStart: { argTypes: [F64, STRING], minArgs: 2, result: STRING },
23
23
  padEnd: { argTypes: [F64, STRING], minArgs: 2, result: STRING },
24
24
  toLowerCase: { argTypes: [], minArgs: 0, result: STRING },
@@ -44,7 +44,7 @@ export const REGEX_INTRINSIC_SIGS = {
44
44
  flags: { receiver: REGEX, argTypes: [], result: STRING },
45
45
  replace: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
46
46
  replaceAll: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
47
- split: { receiver: STRING, argTypes: [REGEX], result: arrayOf(STRING) },
47
+ split: { receiver: STRING, argTypes: [REGEX, F64], result: arrayOf(STRING) },
48
48
  };
49
49
  /** Closed-union signature table for `libCall` (mirrors ambient/scriptc.d.ts).
50
50
  * All argument positions are required — the surface has no optionals.
@@ -55,9 +55,11 @@ export const REGEX_INTRINSIC_SIGS = {
55
55
  * Exported for the frontend's lib-boundary pass (lib-boundary.ts). */
56
56
  export const LIB_FN_SIGS = {
57
57
  "fetch.start": { argTypes: [STRING, DYN], result: { kind: "promise", inner: DYN } },
58
+ "fetch.responseNew": { argTypes: [DYN, DYN], result: DYN },
58
59
  "fetch.responseJson": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
59
60
  "fetch.responseText": { argTypes: [DYN], result: { kind: "promise", inner: STRING } },
60
61
  "fetch.responseBytes": { argTypes: [DYN], result: { kind: "promise", inner: BYTES_U8 } },
62
+ "fetch.abortControllerNew": { argTypes: [], result: DYN },
61
63
  "fetch.abortTimeout": { argTypes: [DYN], result: DYN },
62
64
  "fetch.abortNow": { argTypes: [DYN], result: DYN },
63
65
  "fetch.abortAny": { argTypes: [DYN], result: DYN },
@@ -253,10 +255,13 @@ export const LIB_FN_SIGS = {
253
255
  "qs.stringify": { argTypes: [DYN, STRING, STRING], result: STRING },
254
256
  "qs.escape": { argTypes: [STRING], result: STRING },
255
257
  "qs.unescape": { argTypes: [STRING], result: STRING },
258
+ "util.parseArgs": { argTypes: [DYN], result: DYN },
256
259
  "fs.statSync": { argTypes: [STRING], result: STATS_T },
257
260
  "fs.lstatSync": { argTypes: [STRING], result: STATS_T },
258
261
  "fs.openSync": { argTypes: [STRING, STRING], result: F64 },
259
- "fs.readSync": { argTypes: [F64, BYTES_U8, F64, F64], result: F64 },
262
+ "fs.readSync": { argTypes: [F64, BYTES_U8, F64, F64, F64], result: F64 },
263
+ "fs.writeSync": { argTypes: [F64, BYTES_U8, F64, F64, F64], result: F64 },
264
+ "fs.writeStrSync": { argTypes: [F64, STRING, F64, STRING], result: F64 },
260
265
  // fs.watch's callback func type is program-dependent (zero params, or
261
266
  // the eventType string) — the slot pins arity and the path/receiver.
262
267
  "fs.watch": { argTypes: [STRING], result: FSWATCHER_T },
@@ -273,6 +278,9 @@ export const LIB_FN_SIGS = {
273
278
  "stats.isDirectory": { argTypes: [STATS_T], result: BOOL },
274
279
  "stats.isSymbolicLink": { argTypes: [STATS_T], result: BOOL },
275
280
  "stats.size": { argTypes: [STATS_T], result: F64 },
281
+ "stats.blocks": { argTypes: [STATS_T], result: F64 },
282
+ "stats.nlink": { argTypes: [STATS_T], result: F64 },
283
+ "stats.atimeMs": { argTypes: [STATS_T], result: F64 },
276
284
  "stats.mtimeMs": { argTypes: [STATS_T], result: F64 },
277
285
  // The wider sync fs slice (unlink/chmod/chown/copyfile and the
278
286
  // mode-carrying write/mkdir forms).
@@ -280,6 +288,9 @@ export const LIB_FN_SIGS = {
280
288
  "fs.chmodSync": { argTypes: [STRING, F64], result: VOID },
281
289
  "fs.chownSync": { argTypes: [STRING, F64, F64], result: VOID },
282
290
  "fs.copyFileSync": { argTypes: [STRING, STRING], result: VOID },
291
+ "fs.renameSync": { argTypes: [STRING, STRING], result: VOID },
292
+ // Callback type is program-dependent (zero params or Error | null).
293
+ "fs.renameCb": { argTypes: [STRING, STRING, null], result: VOID },
283
294
  "fs.writeFileModeSync": { argTypes: [STRING, STRING, F64], result: VOID },
284
295
  "fs.mkdirModeSync": { argTypes: [STRING, F64], result: VOID },
285
296
  "fs.mkdirRecursiveModeSync": { argTypes: [STRING, F64], result: VOID },
@@ -714,19 +725,38 @@ export const LIB_FN_SIGS = {
714
725
  "fsp.readFileBytes": { argTypes: [STRING], result: { kind: "promise", inner: BYTES_U8 } },
715
726
  "zlib.deflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
716
727
  "zlib.inflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
717
- "process.stdoutWriteBytes": { argTypes: [BYTES_U8], result: BOOL },
718
- "process.stderrWriteBytes": { argTypes: [BYTES_U8], result: BOOL },
728
+ "process.stdoutWriteBytes": { argTypes: [BYTES_U8, STRING], result: BOOL },
729
+ "process.stderrWriteBytes": { argTypes: [BYTES_U8, STRING], result: BOOL },
730
+ // Completion callback is program-dependent: zero params, checked-dynamic,
731
+ // or an optional Error | null slot (same success shape as fs.rename).
732
+ "process.stdoutWriteBytesCb": { argTypes: [BYTES_U8, STRING, null], result: BOOL },
733
+ "process.stderrWriteBytesCb": { argTypes: [BYTES_U8, STRING, null], result: BOOL },
719
734
  "fsp.readFile": { argTypes: [STRING, STRING], result: { kind: "promise", inner: STRING } },
720
735
  "fsp.writeFile": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
736
+ "fsp.writeFileMode": { argTypes: [STRING, STRING, F64], result: { kind: "promise", inner: VOID } },
721
737
  "fsp.mkdir": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
722
738
  "fsp.mkdirMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
723
739
  "fsp.mkdirRecursive": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
724
740
  "fsp.mkdirRecursiveMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
725
741
  "fsp.unlink": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
726
742
  "fsp.chmod": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
743
+ "fsp.rename": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
727
744
  "fsp.readdir": { argTypes: [STRING], result: { kind: "promise", inner: arrayOf(STRING) } },
728
745
  "fsp.rm": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
729
746
  "fsp.stat": { argTypes: [STRING], result: { kind: "promise", inner: STATS_T } },
747
+ "fsp.open": { argTypes: [STRING, STRING, F64], result: { kind: "promise", inner: FILEHANDLE_T } },
748
+ "fileHandle.fd": { argTypes: [FILEHANDLE_T], result: F64 },
749
+ "fileHandle.close": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: VOID } },
750
+ // read/write carry call-site result record shapes; the validator checks
751
+ // those below, so promise<void> is only a table sentinel.
752
+ "fileHandle.read": { argTypes: [FILEHANDLE_T, BYTES_U8, F64, F64, F64, BOOL], result: { kind: "promise", inner: VOID } },
753
+ "fileHandle.writeBytes": { argTypes: [FILEHANDLE_T, BYTES_U8, F64, F64, F64, BOOL], result: { kind: "promise", inner: VOID } },
754
+ "fileHandle.writeStr": { argTypes: [FILEHANDLE_T, STRING, F64, STRING], result: { kind: "promise", inner: VOID } },
755
+ "fileHandle.readFile": { argTypes: [FILEHANDLE_T, STRING], result: { kind: "promise", inner: STRING } },
756
+ "fileHandle.readFileBytes": { argTypes: [FILEHANDLE_T, STRING], result: { kind: "promise", inner: BYTES_U8 } },
757
+ "fileHandle.writeFile": { argTypes: [FILEHANDLE_T, STRING, STRING], result: { kind: "promise", inner: VOID } },
758
+ "fileHandle.writeFileBytes": { argTypes: [FILEHANDLE_T, BYTES_U8, STRING], result: { kind: "promise", inner: VOID } },
759
+ "fileHandle.stat": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: STATS_T } },
730
760
  "process.argv": { argTypes: [], result: arrayOf(STRING) },
731
761
  "process.platform": { argTypes: [], result: STRING },
732
762
  // The one libCall whose result type is program-dependent (union ids are
@@ -1021,10 +1051,34 @@ export const LIB_FN_SIGS = {
1021
1051
  "number.isInteger": { argTypes: [F64], result: BOOL },
1022
1052
  "number.isSafeInteger": { argTypes: [F64], result: BOOL },
1023
1053
  "date.now": { argTypes: [], result: F64 },
1054
+ "date.newNow": { argTypes: [], result: DATE_T },
1055
+ "date.newMs": { argTypes: [F64], result: DATE_T },
1056
+ "date.newString": { argTypes: [STRING], result: DATE_T },
1057
+ "date.getTime": { argTypes: [DATE_T], result: F64 },
1058
+ "date.valueOf": { argTypes: [DATE_T], result: F64 },
1024
1059
  "date.toISOString": { argTypes: [F64], result: STRING },
1060
+ "date.toISOStringValue": { argTypes: [DATE_T], result: STRING },
1061
+ "date.getFullYear": { argTypes: [DATE_T], result: F64 },
1062
+ "date.getUTCFullYear": { argTypes: [DATE_T], result: F64 },
1063
+ "date.getMonth": { argTypes: [DATE_T], result: F64 },
1064
+ "date.getUTCMonth": { argTypes: [DATE_T], result: F64 },
1065
+ "date.getDate": { argTypes: [DATE_T], result: F64 },
1066
+ "date.getUTCDate": { argTypes: [DATE_T], result: F64 },
1067
+ "date.getDay": { argTypes: [DATE_T], result: F64 },
1068
+ "date.getUTCDay": { argTypes: [DATE_T], result: F64 },
1069
+ "date.getHours": { argTypes: [DATE_T], result: F64 },
1070
+ "date.getUTCHours": { argTypes: [DATE_T], result: F64 },
1071
+ "date.getMinutes": { argTypes: [DATE_T], result: F64 },
1072
+ "date.getUTCMinutes": { argTypes: [DATE_T], result: F64 },
1073
+ "date.getSeconds": { argTypes: [DATE_T], result: F64 },
1074
+ "date.getUTCSeconds": { argTypes: [DATE_T], result: F64 },
1075
+ "date.getMilliseconds": { argTypes: [DATE_T], result: F64 },
1076
+ "date.getUTCMilliseconds": { argTypes: [DATE_T], result: F64 },
1077
+ "date.getTimezoneOffset": { argTypes: [DATE_T], result: F64 },
1025
1078
  "date.parseGetTime": { argTypes: [STRING], result: F64 },
1026
1079
  "date.utc": { argTypes: [F64, F64, F64, F64, F64, F64, F64], result: F64 },
1027
1080
  "text.decode": { argTypes: [BYTES_U8], result: STRING },
1081
+ "text.decodeLegacy": { argTypes: [BYTES_U8, F64], result: STRING },
1028
1082
  "fs.mkdirRecursiveSync": { argTypes: [STRING], result: VOID },
1029
1083
  "fs.rmOptsSync": { argTypes: [STRING, BOOL, BOOL], result: VOID },
1030
1084
  "fs.rmRetrySync": { argTypes: [STRING, BOOL, BOOL, F64, F64], result: VOID },
@@ -1306,15 +1360,22 @@ export function validateModule(mod) {
1306
1360
  }
1307
1361
  u.arms.forEach((arm, i) => {
1308
1362
  // The unit kinds (undefinedT/nullT) are valid arms — union membership
1309
- // is the ONLY place they may appear; void/union/map/dyn/jsval
1310
- // stay out (maps have no discriminant to narrow on). Func/set arm
1363
+ // is the ONLY place they may appear; void/union/map/dyn/jsval/date
1364
+ // stay out (maps and scalar Date values have no supported union
1365
+ // representation/discriminant to narrow on). Func/set arm
1311
1366
  // sibling rules live in unionFuncSetArmsOk (shared with the frontend's
1312
1367
  // union builders): a func arm allows unit and FUNC siblings (the
1313
1368
  // nullable-callback shape, and the primitive-constructor tables where
1314
1369
  // closure pointer identity per tag is the narrowing); a set arm is
1315
1370
  // valid exactly when every other arm is a unit (the defaulted-Set-
1316
1371
  // param ABI); func/set-beside-data stays out.
1317
- if (arm.kind === "void" || arm.kind === "union" || arm.kind === "map" || arm.kind === "dyn" || arm.kind === "jsval" || arm.kind === "generator") {
1372
+ if (arm.kind === "void" ||
1373
+ arm.kind === "union" ||
1374
+ arm.kind === "map" ||
1375
+ arm.kind === "dyn" ||
1376
+ arm.kind === "jsval" ||
1377
+ arm.kind === "date" ||
1378
+ arm.kind === "generator") {
1318
1379
  errors.push({ message: `union ${u.id}: arm ${i} is ${arm.kind}`, loc: noLoc });
1319
1380
  }
1320
1381
  if ((arm.kind === "func" || arm.kind === "set") &&
@@ -2183,7 +2244,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2183
2244
  const isDvGet = e.method.startsWith("dvGet");
2184
2245
  const isNum = e.method === "readNum" || e.method === "writeNum" || e.method === "readNumVar" || e.method === "writeNumVar";
2185
2246
  const U8_ONLY_EXTRA = new Set([
2186
- "toString", "equals", "compareBuf", "indexOf", "lastIndexOf", "includes",
2247
+ "toString", "toStringVar", "equals", "compareBuf", "indexOf", "lastIndexOf", "includes",
2187
2248
  "indexOfNum", "lastIndexOfNum", "includesNum", "fill", "fillNum", "fillStr",
2188
2249
  "copy", "swap16", "swap32", "swap64", "writeStr",
2189
2250
  ]);
@@ -2243,7 +2304,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2243
2304
  ? { argTypes: [], minArgs: 0, result: arrayOf(F64) }
2244
2305
  : e.method === "setFrom"
2245
2306
  ? { argTypes: [bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
2246
- : e.method === "toString"
2307
+ : e.method === "toString" || e.method === "toStringVar"
2247
2308
  ? { argTypes: [STRING, F64, F64], minArgs: 1, result: STRING }
2248
2309
  : e.method === "readNum"
2249
2310
  ? { argTypes: [STRING, F64], minArgs: 2, result: F64 }
@@ -2291,9 +2352,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2291
2352
  break;
2292
2353
  }
2293
2354
  const elem = e.receiver.type.elem;
2294
- const sig = e.method === "push"
2355
+ const sig = e.method === "push" || e.method === "unshift"
2295
2356
  ? { argTypes: e.args.map(() => elem), result: F64 }
2296
- : e.method === "pushSpread"
2357
+ : e.method === "pushSpread" || e.method === "unshiftSpread"
2297
2358
  ? { argTypes: [e.receiver.type], result: F64 }
2298
2359
  : e.method === "pop"
2299
2360
  ? { argTypes: [], result: elem }
@@ -2307,15 +2368,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
2307
2368
  ? { argTypes: [F64, F64], result: e.receiver.type }
2308
2369
  : e.method === "toReversed"
2309
2370
  ? { argTypes: [], result: e.receiver.type }
2310
- : e.method === "toSpliced"
2311
- ? { argTypes: [F64, F64, e.receiver.type], result: e.receiver.type }
2312
- : e.method === "with"
2313
- ? { argTypes: [F64, elem], result: e.receiver.type }
2314
- : e.method === "splice"
2315
- ? { argTypes: [F64, F64], result: e.receiver.type }
2316
- : e.method === "shift"
2317
- ? { argTypes: [], result: e.type } // union-checked below
2318
- : { argTypes: [], result: F64 }; // length
2371
+ : e.method === "reverse"
2372
+ ? { argTypes: [], result: e.receiver.type }
2373
+ : e.method === "toSpliced"
2374
+ ? { argTypes: [F64, F64, e.receiver.type], result: e.receiver.type }
2375
+ : e.method === "with"
2376
+ ? { argTypes: [F64, elem], result: e.receiver.type }
2377
+ : e.method === "splice"
2378
+ ? { argTypes: [F64, F64], result: e.receiver.type }
2379
+ : e.method === "shift"
2380
+ ? { argTypes: [], result: e.type } // union-checked below
2381
+ : { argTypes: [], result: F64 }; // length
2319
2382
  if (e.method === "join" &&
2320
2383
  elem.kind !== "f64" && elem.kind !== "string" && elem.kind !== "bool" &&
2321
2384
  !(elem.kind === "union" &&
@@ -3477,6 +3540,21 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3477
3540
  if (want)
3478
3541
  expectType(a, want, `libCall ${e.fn} arg ${i}`);
3479
3542
  });
3543
+ if (e.fn === "fileHandle.read" || e.fn === "fileHandle.writeBytes" || e.fn === "fileHandle.writeStr") {
3544
+ const inner = e.type.kind === "promise" ? e.type.inner : undefined;
3545
+ const shape = inner?.kind === "record" ? records.get(inner.shapeId) : undefined;
3546
+ const countName = e.fn === "fileHandle.read" ? "bytesRead" : "bytesWritten";
3547
+ const payload = e.args[1]?.type;
3548
+ const count = shape?.fields.find((f) => f.name === countName);
3549
+ const buffer = shape?.fields.find((f) => f.name === "buffer");
3550
+ const ok = shape !== undefined && !shape.tuple && shape.indexValue === undefined && shape.fields.length === 2 &&
3551
+ count?.type.kind === "f64" && payload !== undefined && buffer !== undefined &&
3552
+ typeEquals(buffer.type, payload);
3553
+ if (!ok) {
3554
+ err(`libCall ${e.fn} must return a promise of { ${countName}: number, buffer }`, e.loc);
3555
+ }
3556
+ break;
3557
+ }
3480
3558
  if (e.fn === "fetch.streamFrom") {
3481
3559
  const t = e.args[0]?.type;
3482
3560
  const ok = t?.kind === "string" ||
@@ -3887,6 +3965,34 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
3887
3965
  }
3888
3966
  break;
3889
3967
  }
3968
+ if (e.fn === "fs.renameCb" ||
3969
+ e.fn === "process.stdoutWriteBytesCb" ||
3970
+ e.fn === "process.stderrWriteBytesCb") {
3971
+ // The callback is void and accepts either no parameters, one
3972
+ // checked-dynamic error slot (JS), or Error | null (optionally
3973
+ // including undefined for an explicitly optional parameter).
3974
+ const cbT = e.args[2]?.type;
3975
+ let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
3976
+ if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
3977
+ const p = cbT.params[0];
3978
+ if (p.kind === "dyn") {
3979
+ ok = true;
3980
+ }
3981
+ else {
3982
+ const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
3983
+ ok =
3984
+ def !== undefined &&
3985
+ def.arms.some((a) => a.kind === "nullT") &&
3986
+ def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
3987
+ def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
3988
+ (a.kind === "object" && a.className === "%Error"));
3989
+ }
3990
+ }
3991
+ if (!ok) {
3992
+ err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
3993
+ }
3994
+ break;
3995
+ }
3890
3996
  if (e.fn === "net.serverAddress") {
3891
3997
  // Result is the {address, family, port} record (dgram.address's
3892
3998
  // check, another receiver).
@@ -4580,11 +4686,16 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
4580
4686
  }
4581
4687
  }
4582
4688
  else {
4583
- // throw: any throwable payload (the throw statement's rule).
4689
+ // throw: any exception-representable payload (the throw
4690
+ // statement's rule). Date cannot retain its object kind in the
4691
+ // untyped exception cell.
4584
4692
  if (e.arg === null) {
4585
4693
  err("genResume throw with no payload", e.loc);
4586
4694
  }
4587
- else if (e.arg.type.kind === "void" || e.arg.type.kind === "dyn" || e.arg.type.kind === "caught") {
4695
+ else if (e.arg.type.kind === "void" ||
4696
+ e.arg.type.kind === "dyn" ||
4697
+ e.arg.type.kind === "caught" ||
4698
+ e.arg.type.kind === "date") {
4588
4699
  err(`genResume throw of a ${e.arg.type.kind} value`, e.loc);
4589
4700
  }
4590
4701
  }
@@ -5098,7 +5209,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
5098
5209
  checkExpr(s.value);
5099
5210
  // dyn throws are allowed: the dyn node rides the REF cell arm by
5100
5211
  // reference (the JS-lane `throw err` of a dyn argument).
5101
- if (s.value.type.kind === "void" || s.value.type.kind === "caught") {
5212
+ if (s.value.type.kind === "void" || s.value.type.kind === "caught" || s.value.type.kind === "date") {
5102
5213
  err(`throw of a ${s.value.type.kind} value`, s.loc);
5103
5214
  }
5104
5215
  break;