@scriptc/compiler 0.0.10 → 0.0.12
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 +63 -15
- package/ambient/scriptc.d.ts +2 -2
- package/dist/backend/cc.d.ts +2 -2
- package/dist/backend/emission/emit-async.js +1 -1
- package/dist/backend/emission/emit-exprs.js +131 -54
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +14 -14
- package/dist/backend/emission/emit-walkers.js +44 -44
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +3 -3
- package/dist/backend/emission/emitter.js +33 -9
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +1 -1
- package/dist/backend/llvm/dyn.d.ts +10 -10
- package/dist/backend/llvm/dyn.js +26 -26
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +156 -47
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -1
- package/dist/backend/llvm/walkers.js +2 -2
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/coverage/surface-manifest.js +16 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +21 -8
- package/dist/diagnostics/diagnostic.js +48 -14
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +5 -5
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +12 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +63 -7
- package/dist/frontend/lowering/lower-builtins.js +327 -35
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +4 -4
- package/dist/frontend/lowering/lower-calls.js +104 -70
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -0
- package/dist/frontend/lowering/lower-classes.js +82 -6
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +9 -5
- package/dist/frontend/lowering/lower-containers.js +88 -26
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
- package/dist/frontend/lowering/lower-emitter.js +438 -31
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +87 -12
- package/dist/frontend/lowering/lower-exprs.js +630 -125
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +5 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +12 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +8 -5
- package/dist/frontend/lowering/lower-modules.js +157 -63
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +24 -0
- package/dist/frontend/lowering/lower-namespaces.js +158 -16
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +11 -11
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
- package/dist/frontend/lowering/lower-stmts.js +271 -36
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +171 -20
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +27 -10
- package/dist/frontend/lowering/lowerer.js +156 -54
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +44 -0
- package/dist/frontend/lowering/surfaces.js +236 -5
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm.d.ts +12 -0
- package/dist/frontend/npm.js +30 -0
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +25 -0
- package/dist/frontend/program.js +145 -136
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +1 -1
- package/dist/frontend/shared.js +8 -8
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +2 -2
- package/dist/frontend/types.js +15 -15
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +169 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +174 -106
- package/dist/ir/nodes.js +69 -24
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +55 -36
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.js +12 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +119 -0
- package/dist/library/int-infer.js +1314 -0
- package/dist/library/int-infer.js.map +1 -0
- package/dist/library/int-infer.test.d.ts +1 -0
- package/dist/library/int-infer.test.js +279 -0
- package/dist/library/int-infer.test.js.map +1 -0
- package/dist/library/profile.d.ts +34 -5
- package/dist/library/profile.js +77 -13
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +24 -1
- package/dist/library/sidecar.js +163 -16
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +210 -12
|
@@ -31,7 +31,7 @@ import { dynFallbackType, nodeThrowExpr } from "./lowerer.js";
|
|
|
31
31
|
import { isJsSourceFile, locOf } from "../program.js";
|
|
32
32
|
import { newFnCtx, own } from "./lowerer.js";
|
|
33
33
|
import { appendImplicitUndefinedReturn } from "./lower-calls.js";
|
|
34
|
-
import { bufEncoding } from "./lower-containers.js";
|
|
34
|
+
import { bufEncoding, knownBufEncoding } from "./lower-containers.js";
|
|
35
35
|
import { probeLower } from "./lower-exprs.js";
|
|
36
36
|
import { BOOL, DYN, F64, RUNTIME_STREAM_CLASSES, STRING, VOID, arrayOf, bytesOf, canBoxFuncIntoDyn, funcOf, typeEquals, typeKey } from "../../ir/nodes.js";
|
|
37
37
|
const BYTES = bytesOf("u8");
|
|
@@ -337,7 +337,7 @@ function followOptionsArg(L, arg) {
|
|
|
337
337
|
* values as they are), then dynCheck'd into the all-dyn full Node tuple.
|
|
338
338
|
* The emitted option thunk recognizes the THISLESS shape (its first
|
|
339
339
|
* param is not the stream) and boxes each position by kind — the chunk
|
|
340
|
-
* as
|
|
340
|
+
* as dyn bytes, the error via the boundary's encoding, the completion
|
|
341
341
|
* callback as a callable dyn whose glue reports to the runtime's *_done.
|
|
342
342
|
* DIVERGENCE (SEMANTICS.md): Node binds `this` to the stream when it
|
|
343
343
|
* calls option callbacks; a value adapted through the dyn boundary is
|
|
@@ -412,6 +412,8 @@ fallbackCb) {
|
|
|
412
412
|
readableSide: true,
|
|
413
413
|
writableSide: true,
|
|
414
414
|
encoding: null,
|
|
415
|
+
badEncoding: null,
|
|
416
|
+
pushEncoding: null,
|
|
415
417
|
flags: 0,
|
|
416
418
|
cbs: [],
|
|
417
419
|
};
|
|
@@ -517,19 +519,41 @@ fallbackCb) {
|
|
|
517
519
|
}
|
|
518
520
|
case "encoding": {
|
|
519
521
|
// The readable-side string-chunk mode: a literal encoding, folded
|
|
520
|
-
// to its canonical name (Writable has no such option).
|
|
522
|
+
// to its canonical name (Writable has no such option). A literal
|
|
523
|
+
// spelling Node does not know is Node's RUNTIME rejection —
|
|
524
|
+
// ERR_UNKNOWN_ENCODING at construction, not a compile fence.
|
|
521
525
|
if (ctorName === "Writable")
|
|
522
526
|
L.noLowering(`the Writable option 'encoding'`, prop);
|
|
527
|
+
{
|
|
528
|
+
const t = L.typeOf(value);
|
|
529
|
+
if (t.isStringLiteralType() && knownBufEncoding(t.value) === undefined) {
|
|
530
|
+
out.badEncoding = t.value;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
523
534
|
out.encoding = bufEncoding(L, `the ${ctorName} option 'encoding'`, value);
|
|
524
535
|
break;
|
|
525
536
|
}
|
|
526
537
|
case "defaultEncoding":
|
|
527
|
-
//
|
|
528
|
-
//
|
|
538
|
+
// utf8 is the byte default — admit the literal. A literal Node
|
|
539
|
+
// does not know throws ERR_UNKNOWN_ENCODING at construction (the
|
|
540
|
+
// state ctor validates it), Node's ladder. On a pure Readable a
|
|
541
|
+
// valid non-utf8 name governs how push(string) DECODES chunks
|
|
542
|
+
// (Buffer.from(chunk, enc)) — lowered as a follow-up
|
|
543
|
+
// readable.pushEncoding. The write-side meaning (what
|
|
544
|
+
// write(string) does) stays fenced on the writable classes.
|
|
529
545
|
{
|
|
530
546
|
const t = L.typeOf(value);
|
|
531
547
|
if (t.isStringLiteralType() && (t.value === "utf8" || t.value === "utf-8"))
|
|
532
548
|
break;
|
|
549
|
+
if (t.isStringLiteralType() && knownBufEncoding(t.value) === undefined) {
|
|
550
|
+
out.badEncoding = t.value;
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
if (t.isStringLiteralType() && ctorName === "Readable") {
|
|
554
|
+
out.pushEncoding = knownBufEncoding(t.value);
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
533
557
|
}
|
|
534
558
|
L.noLowering(`the ${ctorName} option 'defaultEncoding'`, prop, "utf8 (the default) is the supported write-side string encoding");
|
|
535
559
|
break;
|
|
@@ -602,7 +626,7 @@ function streamCtorArgs(L, cls, arg, thisType, loc, fallbackCb) {
|
|
|
602
626
|
? [o.hwmR, o.hwmW, o.autoDestroy, o.emitClose, o.allowHalfOpen,
|
|
603
627
|
boolLit(o.readableSide, loc), boolLit(o.writableSide, loc), f64Lit(o.flags, loc)]
|
|
604
628
|
: [cls === "%Writable" ? o.hwmW : o.hwmR, o.autoDestroy, o.emitClose, f64Lit(o.flags, loc)];
|
|
605
|
-
return { args: [...head, ...o.cbs], encoding: o.encoding };
|
|
629
|
+
return { args: [...head, ...o.cbs], encoding: o.encoding, badEncoding: o.badEncoding, pushEncoding: o.pushEncoding };
|
|
606
630
|
}
|
|
607
631
|
/** `new Readable(opts?)` and friends — called from lowerNew once the
|
|
608
632
|
* callee resolved to a builtin stream class. */
|
|
@@ -624,7 +648,17 @@ export function lowerStreamNew(L, expr, info) {
|
|
|
624
648
|
}
|
|
625
649
|
const fn = `${streamCtorShape(cls).fn}.new`;
|
|
626
650
|
const parsed = streamCtorArgs(L, cls, args[0], thisType, loc);
|
|
627
|
-
|
|
651
|
+
if (parsed.badEncoding !== null) {
|
|
652
|
+
// Node's state constructors validate encodings first: an unknown
|
|
653
|
+
// spelling never constructs — the whole expression throws.
|
|
654
|
+
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${parsed.badEncoding}`, thisType, loc);
|
|
655
|
+
}
|
|
656
|
+
let built = { kind: "libCall", fn, args: parsed.args, type: thisType, loc };
|
|
657
|
+
if (parsed.pushEncoding !== null) {
|
|
658
|
+
// { defaultEncoding }: chain the push-side decode default (the
|
|
659
|
+
// setEncoding chaining shape — answers the receiver +1).
|
|
660
|
+
built = { kind: "libCall", fn: "readable.pushEncoding", args: [built, strLit(parsed.pushEncoding, loc)], type: thisType, loc };
|
|
661
|
+
}
|
|
628
662
|
if (parsed.encoding === null)
|
|
629
663
|
return built;
|
|
630
664
|
// { encoding }: chain a setEncoding over the fresh stream (the operand
|
|
@@ -781,11 +815,27 @@ export function lowerStreamSuperCall(L, info, base, argNodes, thisLocal, loc, bl
|
|
|
781
815
|
}
|
|
782
816
|
}
|
|
783
817
|
const parsed = streamCtorArgs(L, cls, argNodes[0], thisType, loc, fallback);
|
|
818
|
+
if (parsed.badEncoding !== null) {
|
|
819
|
+
// super(options) with an unknown literal encoding: the state ctor
|
|
820
|
+
// rejects before any initialization, Node's ladder.
|
|
821
|
+
return [{
|
|
822
|
+
kind: "exprStmt",
|
|
823
|
+
expr: nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${parsed.badEncoding}`, VOID, loc),
|
|
824
|
+
loc,
|
|
825
|
+
}];
|
|
826
|
+
}
|
|
784
827
|
const out = [{
|
|
785
828
|
kind: "exprStmt",
|
|
786
829
|
expr: { kind: "libCall", fn: `${shape.fn}.init`, args: [thisRef(), ...parsed.args], type: VOID, loc },
|
|
787
830
|
loc,
|
|
788
831
|
}];
|
|
832
|
+
if (parsed.pushEncoding !== null) {
|
|
833
|
+
out.push({
|
|
834
|
+
kind: "exprStmt",
|
|
835
|
+
expr: { kind: "libCall", fn: "readable.pushEncoding", args: [thisRef(), strLit(parsed.pushEncoding, loc)], type: thisType, loc },
|
|
836
|
+
loc,
|
|
837
|
+
});
|
|
838
|
+
}
|
|
789
839
|
if (parsed.encoding !== null) {
|
|
790
840
|
out.push({
|
|
791
841
|
kind: "exprStmt",
|
|
@@ -969,32 +1019,57 @@ export function streamClassAliasDecl(L, nameNode, init) {
|
|
|
969
1019
|
return L.builtinNamespaceModuleOf(init.expression) === "stream";
|
|
970
1020
|
}
|
|
971
1021
|
/* ── the module functions (finished / pipeline — the callback forms) ──── */
|
|
1022
|
+
/** Node's pipeline stage ladder text (lib/internal/streams/pipeline.js's
|
|
1023
|
+
* makeAsyncIterable — every stage position renders the same "body"
|
|
1024
|
+
* clause). finished() keeps its narrower isNodeStream wording. */
|
|
1025
|
+
const PIPELINE_STAGE_EXPECTED = "of type function or an instance of Blob, ReadableStream, WritableStream, Stream, Iterable, AsyncIterable, or Promise or { readable, writable } pair";
|
|
972
1026
|
/** A stream-rooted argument, lowered — or the pointed fence (pipeline's
|
|
973
|
-
* iterable/generator/function stages have no lowering yet).
|
|
1027
|
+
* iterable/generator/function stages have no lowering yet). `what` picks
|
|
1028
|
+
* the validation ladder: finished() rejects EVERY non-stream through
|
|
1029
|
+
* isNodeStream, while pipeline() accepts iterables (strings, arrays) and
|
|
1030
|
+
* { readable, writable } pairs — those shapes fence instead of throwing
|
|
1031
|
+
* a ladder Node never throws. */
|
|
974
1032
|
function lowerStreamArg(L, node, what) {
|
|
975
1033
|
const v = L.lowerExpr(node);
|
|
976
1034
|
const info = v.type.kind === "object" ? L.classes.get(v.type.className) : undefined;
|
|
977
1035
|
if (!streamSidesOf(L, info)) {
|
|
978
1036
|
// A provably-non-stream value in a JS source (the invalid-input
|
|
979
|
-
// probes: finished({}, cb)): Node's
|
|
980
|
-
// ERR_INVALID_ARG_TYPE before any watcher exists.
|
|
981
|
-
|
|
982
|
-
(v.type.kind === "record" || v.type.kind === "string" || v.type.kind === "f64" ||
|
|
983
|
-
v.type.kind === "bool" || v.type.kind === "array") &&
|
|
984
|
-
L.dynConvertible(v.type)) {
|
|
1037
|
+
// probes: finished({}, cb), pipeline(42, dst, cb)): Node's gate
|
|
1038
|
+
// throws ERR_INVALID_ARG_TYPE before any watcher exists.
|
|
1039
|
+
const argTypeThrow = (argName, expected) => {
|
|
985
1040
|
throw new StreamArgTypeThrow({
|
|
986
1041
|
kind: "libCall",
|
|
987
1042
|
fn: "error.argTypeThrow",
|
|
988
1043
|
args: [
|
|
989
|
-
{ kind: "strLit", value:
|
|
990
|
-
{ kind: "strLit", value:
|
|
1044
|
+
{ kind: "strLit", value: argName, type: STRING, loc: locOf(node) },
|
|
1045
|
+
{ kind: "strLit", value: expected, type: STRING, loc: locOf(node) },
|
|
991
1046
|
{ kind: "dynFrom", value: v, type: DYN, loc: locOf(node) },
|
|
992
1047
|
],
|
|
993
1048
|
type: VOID,
|
|
994
1049
|
loc: locOf(node),
|
|
995
1050
|
});
|
|
1051
|
+
};
|
|
1052
|
+
if (isJsSourceFile(node.getSourceFile()) && L.dynConvertible(v.type)) {
|
|
1053
|
+
if (what === "pipeline") {
|
|
1054
|
+
// Strings and arrays are iterables — VALID pipeline stages in
|
|
1055
|
+
// Node — and a record carrying a readable/writable member may be
|
|
1056
|
+
// the duplex-pair form; none of those shapes has a lowering, so
|
|
1057
|
+
// they take the pointed fence below, never a throw.
|
|
1058
|
+
const pairish = v.type.kind === "record" &&
|
|
1059
|
+
(L.shapes.get(v.type.shapeId)?.fields ?? []).some((f) => f.name === "readable" || f.name === "writable");
|
|
1060
|
+
if ((v.type.kind === "record" && !pairish) || v.type.kind === "f64" ||
|
|
1061
|
+
v.type.kind === "bool" || v.type.kind === "nullT") {
|
|
1062
|
+
argTypeThrow("body", PIPELINE_STAGE_EXPECTED);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
else if (v.type.kind === "record" || v.type.kind === "string" || v.type.kind === "f64" ||
|
|
1066
|
+
v.type.kind === "bool" || v.type.kind === "array" || v.type.kind === "nullT") {
|
|
1067
|
+
argTypeThrow("stream", "an instance of ReadableStream, WritableStream, or Stream");
|
|
1068
|
+
}
|
|
996
1069
|
}
|
|
997
|
-
L.noLowering(`${what} over a '${L.fmt(v.type)}'`, node,
|
|
1070
|
+
L.noLowering(`${what} over a '${L.fmt(v.type)}'`, node, what === "pipeline"
|
|
1071
|
+
? "stream stages are the lowered surface — Node also accepts iterables (strings, arrays), generators, plain functions, and { readable, writable } pairs, but those have no lowering yet"
|
|
1072
|
+
: "stream arguments are the lowered surface (iterables, generators, and plain functions have no lowering yet)");
|
|
998
1073
|
}
|
|
999
1074
|
return v;
|
|
1000
1075
|
}
|
|
@@ -1095,7 +1170,15 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1095
1170
|
if (args.length < 2) {
|
|
1096
1171
|
L.noLowering(`stream/promises.pipeline with ${args.length} arguments`, call, "the supported form is pipeline(source, ...streams)");
|
|
1097
1172
|
}
|
|
1098
|
-
|
|
1173
|
+
let streams;
|
|
1174
|
+
try {
|
|
1175
|
+
streams = args.map((a) => lowerStreamArg(L, a, "pipeline"));
|
|
1176
|
+
}
|
|
1177
|
+
catch (e) {
|
|
1178
|
+
if (e instanceof StreamArgTypeThrow)
|
|
1179
|
+
return e.expr;
|
|
1180
|
+
throw e;
|
|
1181
|
+
}
|
|
1099
1182
|
return {
|
|
1100
1183
|
kind: "libCall",
|
|
1101
1184
|
fn: "sp.pipeline",
|
|
@@ -1106,6 +1189,43 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1106
1189
|
}
|
|
1107
1190
|
return null;
|
|
1108
1191
|
}
|
|
1192
|
+
if (bi.module === "stream/consumers") {
|
|
1193
|
+
const args = call.arguments;
|
|
1194
|
+
// text/json/buffer(stream) → a pending promise the accumulate-and-
|
|
1195
|
+
// settle machinery resolves at the terminal point (the utf8 decode / the parsed
|
|
1196
|
+
// JSON DOM / the concatenated bytes) or rejects — with the stream's
|
|
1197
|
+
// error, ERR_STREAM_PREMATURE_CLOSE on an early close, or json's
|
|
1198
|
+
// SyntaxError on malformed text, Node's own rejection set.
|
|
1199
|
+
// arrayBuffer/blob return null here: neither value has a
|
|
1200
|
+
// representation, so the module-qualified fence (with the pointed
|
|
1201
|
+
// hints in BUILTIN_MODULE_FENCE_HINTS) speaks.
|
|
1202
|
+
if (bi.member === "text" || bi.member === "json" || bi.member === "buffer") {
|
|
1203
|
+
if (args.length !== 1) {
|
|
1204
|
+
L.noLowering(`stream/consumers.${bi.member} with ${args.length} arguments`, call, `the supported form is ${bi.member}(stream)`);
|
|
1205
|
+
}
|
|
1206
|
+
// A provably-non-stream argument: Node's consumers reject the
|
|
1207
|
+
// returned promise asynchronously with the plain "stream is not
|
|
1208
|
+
// async iterable" TypeError — no sync ladder exists to borrow
|
|
1209
|
+
// (finished/pipeline throw synchronously; consumers do not). A
|
|
1210
|
+
// sync throw here would be observably wrong timing, so the
|
|
1211
|
+
// provable case takes the named fence instead.
|
|
1212
|
+
const argV = L.lowerExpr(args[0]);
|
|
1213
|
+
const argInfo = argV.type.kind === "object" ? L.classes.get(argV.type.className) : undefined;
|
|
1214
|
+
if (argV.type.kind !== "dyn" && argV.type.kind !== "jsval" && !streamSidesOf(L, argInfo)) {
|
|
1215
|
+
L.noLowering(`stream/consumers.${bi.member} over a value that is not a stream`, call, "Node rejects the promise with 'stream is not async iterable' — pass a readable stream");
|
|
1216
|
+
}
|
|
1217
|
+
const recv = argV;
|
|
1218
|
+
const inner = bi.member === "text" ? STRING : bi.member === "json" ? DYN : BYTES;
|
|
1219
|
+
return {
|
|
1220
|
+
kind: "libCall",
|
|
1221
|
+
fn: `sc.${bi.member}`,
|
|
1222
|
+
args: [recv],
|
|
1223
|
+
type: { kind: "promise", inner },
|
|
1224
|
+
loc,
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1109
1229
|
if (bi.module !== "stream")
|
|
1110
1230
|
return null;
|
|
1111
1231
|
const args = call.arguments;
|
|
@@ -1147,7 +1267,15 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1147
1267
|
if (args.length < 3) {
|
|
1148
1268
|
L.noLowering(`pipeline with ${args.length} arguments`, call, "the supported form is pipeline(source, ...streams, callback)");
|
|
1149
1269
|
}
|
|
1150
|
-
|
|
1270
|
+
let streams;
|
|
1271
|
+
try {
|
|
1272
|
+
streams = args.slice(0, -1).map((a) => lowerStreamArg(L, a, "pipeline"));
|
|
1273
|
+
}
|
|
1274
|
+
catch (e) {
|
|
1275
|
+
if (e instanceof StreamArgTypeThrow)
|
|
1276
|
+
return e.expr;
|
|
1277
|
+
throw e;
|
|
1278
|
+
}
|
|
1151
1279
|
const last = streams[streams.length - 1];
|
|
1152
1280
|
const { cb, dyn } = lowerEosCallback(L, "pipeline", args[args.length - 1], last.type);
|
|
1153
1281
|
return {
|
|
@@ -1204,7 +1332,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1204
1332
|
if (t?.kind === "nullT")
|
|
1205
1333
|
return "null";
|
|
1206
1334
|
if (t?.kind === "dyn") {
|
|
1207
|
-
// The JS lane's any-typed chunk: the runtime dispatches by
|
|
1335
|
+
// The JS lane's any-typed chunk: the runtime dispatches by dyn tag
|
|
1208
1336
|
// (bytes / string / null; anything else is the write TypeError).
|
|
1209
1337
|
return "dyn";
|
|
1210
1338
|
}
|
|
@@ -1235,6 +1363,29 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1235
1363
|
if (args.length === 0 || args.length > 2) {
|
|
1236
1364
|
L.noLowering(`${member} with ${args.length} arguments`, call, "the supported forms are (chunk) and (chunk, \"utf8\")");
|
|
1237
1365
|
}
|
|
1366
|
+
// push(chunk, enc) with a LITERAL encoding: the per-call decode
|
|
1367
|
+
// (Buffer.from(chunk, enc)) — an explicit encoding (utf8 included)
|
|
1368
|
+
// overrides the stream's defaultEncoding; unknown literals throw
|
|
1369
|
+
// Node's ERR_UNKNOWN_ENCODING when the push evaluates. unshift keeps
|
|
1370
|
+
// the utf8-only fence below.
|
|
1371
|
+
if (member === "push" && args[1] !== undefined && chunkKind(args[0]) === "string") {
|
|
1372
|
+
const t = L.typeOf(args[1]);
|
|
1373
|
+
if (t.isStringLiteralType()) {
|
|
1374
|
+
const canonical = knownBufEncoding(t.value);
|
|
1375
|
+
if (canonical === undefined) {
|
|
1376
|
+
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${t.value}`, BOOL, loc);
|
|
1377
|
+
}
|
|
1378
|
+
const receiver = L.lowerExpr(access.expression);
|
|
1379
|
+
const chunk = L.lowerExprExpecting(args[0], STRING);
|
|
1380
|
+
return {
|
|
1381
|
+
kind: "libCall",
|
|
1382
|
+
fn: "readable.pushStrEnc",
|
|
1383
|
+
args: [receiver, chunk, strLit(canonical, loc)],
|
|
1384
|
+
type: BOOL,
|
|
1385
|
+
loc,
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1238
1389
|
checkUtf8Encoding(L, member, args[1]);
|
|
1239
1390
|
const kind = chunkKind(args[0]);
|
|
1240
1391
|
if ((kind === "null" || kind === "union" || kind === "dyn") && member === "unshift") {
|