@scriptc/compiler 0.0.23 → 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.
- package/ambient/scriptc-node-fallback.d.ts +100 -11
- package/dist/backend/cc.d.ts +13 -0
- package/dist/backend/cc.js +11 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.d.ts +4 -0
- package/dist/backend/emission/emit-async.js +31 -1
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +147 -14
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -0
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +24 -5
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.js +10 -0
- package/dist/backend/emission/emit-types.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +10 -2
- package/dist/backend/emission/emitter.js +49 -30
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.js +284 -25
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +9 -1
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/mangle.d.ts +3 -0
- package/dist/backend/mangle.js +5 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +14 -9
- package/dist/frontend/lowering/lower-builtins.js +737 -62
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +2 -1
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +2 -1
- package/dist/frontend/lowering/lower-containers.js +99 -32
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +53 -2
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +59 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +5 -0
- package/dist/frontend/lowering/lower-server.js +1 -1
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +6 -2
- package/dist/frontend/lowering/lower-stmts.js +45 -10
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +2 -2
- package/dist/frontend/lowering/lowerer.js +11 -6
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +65 -13
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/types.d.ts +3 -0
- package/dist/frontend/types.js +78 -0
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +23 -0
- package/dist/ir/integer-loops.js +82 -0
- package/dist/ir/integer-loops.js.map +1 -0
- package/dist/ir/nodes.d.ts +84 -21
- package/dist/ir/nodes.js +84 -1
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +92 -18
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.js +4 -3
- package/dist/library/fence-eval.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +50 -2
package/dist/ir/validate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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, 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:
|
|
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.
|
|
@@ -255,10 +255,13 @@ export const LIB_FN_SIGS = {
|
|
|
255
255
|
"qs.stringify": { argTypes: [DYN, STRING, STRING], result: STRING },
|
|
256
256
|
"qs.escape": { argTypes: [STRING], result: STRING },
|
|
257
257
|
"qs.unescape": { argTypes: [STRING], result: STRING },
|
|
258
|
+
"util.parseArgs": { argTypes: [DYN], result: DYN },
|
|
258
259
|
"fs.statSync": { argTypes: [STRING], result: STATS_T },
|
|
259
260
|
"fs.lstatSync": { argTypes: [STRING], result: STATS_T },
|
|
260
261
|
"fs.openSync": { argTypes: [STRING, STRING], result: F64 },
|
|
261
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 },
|
|
262
265
|
// fs.watch's callback func type is program-dependent (zero params, or
|
|
263
266
|
// the eventType string) — the slot pins arity and the path/receiver.
|
|
264
267
|
"fs.watch": { argTypes: [STRING], result: FSWATCHER_T },
|
|
@@ -275,6 +278,9 @@ export const LIB_FN_SIGS = {
|
|
|
275
278
|
"stats.isDirectory": { argTypes: [STATS_T], result: BOOL },
|
|
276
279
|
"stats.isSymbolicLink": { argTypes: [STATS_T], result: BOOL },
|
|
277
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 },
|
|
278
284
|
"stats.mtimeMs": { argTypes: [STATS_T], result: F64 },
|
|
279
285
|
// The wider sync fs slice (unlink/chmod/chown/copyfile and the
|
|
280
286
|
// mode-carrying write/mkdir forms).
|
|
@@ -282,6 +288,9 @@ export const LIB_FN_SIGS = {
|
|
|
282
288
|
"fs.chmodSync": { argTypes: [STRING, F64], result: VOID },
|
|
283
289
|
"fs.chownSync": { argTypes: [STRING, F64, F64], result: VOID },
|
|
284
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 },
|
|
285
294
|
"fs.writeFileModeSync": { argTypes: [STRING, STRING, F64], result: VOID },
|
|
286
295
|
"fs.mkdirModeSync": { argTypes: [STRING, F64], result: VOID },
|
|
287
296
|
"fs.mkdirRecursiveModeSync": { argTypes: [STRING, F64], result: VOID },
|
|
@@ -716,19 +725,38 @@ export const LIB_FN_SIGS = {
|
|
|
716
725
|
"fsp.readFileBytes": { argTypes: [STRING], result: { kind: "promise", inner: BYTES_U8 } },
|
|
717
726
|
"zlib.deflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
718
727
|
"zlib.inflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
719
|
-
"process.stdoutWriteBytes": { argTypes: [BYTES_U8], result: BOOL },
|
|
720
|
-
"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 },
|
|
721
734
|
"fsp.readFile": { argTypes: [STRING, STRING], result: { kind: "promise", inner: STRING } },
|
|
722
735
|
"fsp.writeFile": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
|
|
736
|
+
"fsp.writeFileMode": { argTypes: [STRING, STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
723
737
|
"fsp.mkdir": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
|
|
724
738
|
"fsp.mkdirMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
725
739
|
"fsp.mkdirRecursive": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
|
|
726
740
|
"fsp.mkdirRecursiveMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
727
741
|
"fsp.unlink": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
|
|
728
742
|
"fsp.chmod": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
743
|
+
"fsp.rename": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
|
|
729
744
|
"fsp.readdir": { argTypes: [STRING], result: { kind: "promise", inner: arrayOf(STRING) } },
|
|
730
745
|
"fsp.rm": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
|
|
731
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 } },
|
|
732
760
|
"process.argv": { argTypes: [], result: arrayOf(STRING) },
|
|
733
761
|
"process.platform": { argTypes: [], result: STRING },
|
|
734
762
|
// The one libCall whose result type is program-dependent (union ids are
|
|
@@ -1050,6 +1078,7 @@ export const LIB_FN_SIGS = {
|
|
|
1050
1078
|
"date.parseGetTime": { argTypes: [STRING], result: F64 },
|
|
1051
1079
|
"date.utc": { argTypes: [F64, F64, F64, F64, F64, F64, F64], result: F64 },
|
|
1052
1080
|
"text.decode": { argTypes: [BYTES_U8], result: STRING },
|
|
1081
|
+
"text.decodeLegacy": { argTypes: [BYTES_U8, F64], result: STRING },
|
|
1053
1082
|
"fs.mkdirRecursiveSync": { argTypes: [STRING], result: VOID },
|
|
1054
1083
|
"fs.rmOptsSync": { argTypes: [STRING, BOOL, BOOL], result: VOID },
|
|
1055
1084
|
"fs.rmRetrySync": { argTypes: [STRING, BOOL, BOOL, F64, F64], result: VOID },
|
|
@@ -2215,7 +2244,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2215
2244
|
const isDvGet = e.method.startsWith("dvGet");
|
|
2216
2245
|
const isNum = e.method === "readNum" || e.method === "writeNum" || e.method === "readNumVar" || e.method === "writeNumVar";
|
|
2217
2246
|
const U8_ONLY_EXTRA = new Set([
|
|
2218
|
-
"toString", "equals", "compareBuf", "indexOf", "lastIndexOf", "includes",
|
|
2247
|
+
"toString", "toStringVar", "equals", "compareBuf", "indexOf", "lastIndexOf", "includes",
|
|
2219
2248
|
"indexOfNum", "lastIndexOfNum", "includesNum", "fill", "fillNum", "fillStr",
|
|
2220
2249
|
"copy", "swap16", "swap32", "swap64", "writeStr",
|
|
2221
2250
|
]);
|
|
@@ -2275,7 +2304,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2275
2304
|
? { argTypes: [], minArgs: 0, result: arrayOf(F64) }
|
|
2276
2305
|
: e.method === "setFrom"
|
|
2277
2306
|
? { argTypes: [bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
|
|
2278
|
-
: e.method === "toString"
|
|
2307
|
+
: e.method === "toString" || e.method === "toStringVar"
|
|
2279
2308
|
? { argTypes: [STRING, F64, F64], minArgs: 1, result: STRING }
|
|
2280
2309
|
: e.method === "readNum"
|
|
2281
2310
|
? { argTypes: [STRING, F64], minArgs: 2, result: F64 }
|
|
@@ -2323,9 +2352,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2323
2352
|
break;
|
|
2324
2353
|
}
|
|
2325
2354
|
const elem = e.receiver.type.elem;
|
|
2326
|
-
const sig = e.method === "push"
|
|
2355
|
+
const sig = e.method === "push" || e.method === "unshift"
|
|
2327
2356
|
? { argTypes: e.args.map(() => elem), result: F64 }
|
|
2328
|
-
: e.method === "pushSpread"
|
|
2357
|
+
: e.method === "pushSpread" || e.method === "unshiftSpread"
|
|
2329
2358
|
? { argTypes: [e.receiver.type], result: F64 }
|
|
2330
2359
|
: e.method === "pop"
|
|
2331
2360
|
? { argTypes: [], result: elem }
|
|
@@ -2339,15 +2368,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2339
2368
|
? { argTypes: [F64, F64], result: e.receiver.type }
|
|
2340
2369
|
: e.method === "toReversed"
|
|
2341
2370
|
? { argTypes: [], result: e.receiver.type }
|
|
2342
|
-
: e.method === "
|
|
2343
|
-
? { argTypes: [
|
|
2344
|
-
: e.method === "
|
|
2345
|
-
? { argTypes: [F64,
|
|
2346
|
-
: e.method === "
|
|
2347
|
-
? { argTypes: [F64,
|
|
2348
|
-
: e.method === "
|
|
2349
|
-
? { argTypes: [], result: e.type }
|
|
2350
|
-
:
|
|
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
|
|
2351
2382
|
if (e.method === "join" &&
|
|
2352
2383
|
elem.kind !== "f64" && elem.kind !== "string" && elem.kind !== "bool" &&
|
|
2353
2384
|
!(elem.kind === "union" &&
|
|
@@ -3509,6 +3540,21 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3509
3540
|
if (want)
|
|
3510
3541
|
expectType(a, want, `libCall ${e.fn} arg ${i}`);
|
|
3511
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
|
+
}
|
|
3512
3558
|
if (e.fn === "fetch.streamFrom") {
|
|
3513
3559
|
const t = e.args[0]?.type;
|
|
3514
3560
|
const ok = t?.kind === "string" ||
|
|
@@ -3919,6 +3965,34 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3919
3965
|
}
|
|
3920
3966
|
break;
|
|
3921
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
|
+
}
|
|
3922
3996
|
if (e.fn === "net.serverAddress") {
|
|
3923
3997
|
// Result is the {address, family, port} record (dgram.address's
|
|
3924
3998
|
// check, another receiver).
|