@scriptc/compiler 0.2.1 → 0.2.2
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 +59 -4
- package/dist/backend/llvm/dyn.d.ts +3 -0
- package/dist/backend/llvm/dyn.js +84 -12
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +4 -1
- package/dist/backend/llvm/emitter.js +20 -5
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +9 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +5 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +30 -5
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +70 -9
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +41 -3
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +12 -9
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +35 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/may-throw.js +4 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +1 -1
- package/dist/backend/native-codegen.js +4 -3
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +11 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +5 -0
- package/dist/backend/target-diagnostics.js +72 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.d.ts +1 -0
- package/dist/backend/target-diagnostics.test.js +68 -0
- package/dist/backend/target-diagnostics.test.js.map +1 -0
- package/dist/coverage/surface-manifest.js +5 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +7 -3
- package/dist/executable/executable-cache.js +47 -11
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +109 -2
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/function-completion.d.ts +6 -0
- package/dist/frontend/function-completion.js +50 -0
- package/dist/frontend/function-completion.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.js +5 -1
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
- package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
- package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
- package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
- package/dist/frontend/lowering/checked-promise-all.js +31 -0
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/class-callbacks.js +7 -6
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +2 -0
- package/dist/frontend/lowering/class-construction.js +34 -5
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
- package/dist/frontend/lowering/class-descriptors.js +12 -5
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +11 -41
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +16 -0
- package/dist/frontend/lowering/class-method-values.js +60 -29
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
- package/dist/frontend/lowering/class-prototypes.js +69 -10
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
- package/dist/frontend/lowering/class-runtime-statics.js +26 -8
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.d.ts +1 -0
- package/dist/frontend/lowering/class-static-data.js +4 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +17 -4
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
- package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.js +31 -1
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +4 -9
- package/dist/frontend/lowering/lower-builtins.js +291 -51
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +283 -73
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +5 -0
- package/dist/frontend/lowering/lower-classes.js +439 -25
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +1 -1
- package/dist/frontend/lowering/lower-containers.js +39 -17
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
- package/dist/frontend/lowering/lower-exprs.js +294 -129
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +5 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +15 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +4 -0
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-island.test.js +51 -0
- package/dist/frontend/lowering/lower-island.test.js.map +1 -0
- package/dist/frontend/lowering/lower-modules.d.ts +1 -3
- package/dist/frontend/lowering/lower-modules.js +186 -82
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +69 -1
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +100 -35
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-stmts.test.js +77 -0
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
- package/dist/frontend/lowering/lower-stream.js +2 -0
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +2 -1
- package/dist/frontend/lowering/lower-url.js +32 -9
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +26 -9
- package/dist/frontend/lowering/lowerer.js +218 -27
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +38 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
- package/dist/frontend/lowering/module-namespace-elements.js +54 -0
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
- package/dist/frontend/lowering/object-factory-new.js +27 -14
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +1 -0
- package/dist/frontend/lowering/surfaces.js +24 -12
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
- package/dist/frontend/program.js +4 -2
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/type-mapper.js +83 -14
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/union-discriminants.js +22 -7
- package/dist/frontend/union-discriminants.js.map +1 -1
- package/dist/index.js +16 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/ir.d.ts +27 -13
- package/dist/ir/ir.js +26 -2
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/serialize.js +21 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +21 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/traverse.d.ts +0 -3
- package/dist/ir/traverse.js +33 -20
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +56 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +17 -1
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js +1 -1
- package/dist/library/compiler-self-identity.test.js +2 -2
- package/dist/library/compiler-self-identity.test.js.map +1 -1
- package/dist/library/int-infer.d.ts +2 -2
- package/dist/library/int-infer.js +10 -7
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +44 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/prepare.js +2 -1
- package/dist/library/prepare.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +115 -13
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { staticTextDecoderEncoding } from "./text-decoder-encoding.js";
|
|
2
|
+
import { checkedPromiseAll } from "./checked-promise-all.js";
|
|
2
3
|
import { InternalCompilerError } from "../../errors.js";
|
|
3
4
|
/* Builtin-surface lowering: node builtin-module calls (fs, path, os, url,
|
|
4
5
|
* crypto, child_process spawn/spawnSync and child/stats/spawn-result
|
|
@@ -1414,12 +1415,36 @@ function lowerZlibModuleCall(lowerer, expr, bi, loc) {
|
|
|
1414
1415
|
}
|
|
1415
1416
|
export function lowerBuiltinModuleCall(lowerer, expr, bi, fn, loc) {
|
|
1416
1417
|
const name = expr.expression.getText();
|
|
1418
|
+
if (bi.module === "process" && bi.member === "loadEnvFile")
|
|
1419
|
+
return lowerProcessLoadEnvFile(lowerer, expr);
|
|
1420
|
+
if (bi.module === "buffer" && ["isAscii", "isUtf8", "transcode"].includes(bi.member)) {
|
|
1421
|
+
if (expr.arguments.some(ts.isSpreadElement))
|
|
1422
|
+
lowerer.noLowering("buffer encoding call with spread arguments", expr);
|
|
1423
|
+
const arity = bi.member === "transcode" ? 3 : 1;
|
|
1424
|
+
const args = Array.from({ length: arity }, (_, index) => expr.arguments[index]
|
|
1425
|
+
? lowerer.lowerExprExpecting(stripTypeCasts(expr.arguments[index]), DYN) : dynUndefinedExpr(loc));
|
|
1426
|
+
if (expr.arguments.length > arity)
|
|
1427
|
+
lowerer.noLowering("buffer encoding call with extra arguments", expr);
|
|
1428
|
+
return { kind: "libCall", fn: fn.fn, args, type: fn.result, loc };
|
|
1429
|
+
}
|
|
1417
1430
|
if (fn.fn === "fs.callbackCall" && bi.member !== "rename") {
|
|
1418
1431
|
if (expr.arguments.some(ts.isSpreadElement))
|
|
1419
1432
|
lowerer.noLowering("filesystem callback call with spread arguments", expr);
|
|
1420
1433
|
const args = { kind: "dynArrLit", elems: expr.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
|
|
1421
1434
|
return { kind: "libCall", fn: "fs.callbackCall", args: [{ kind: "strLit", value: bi.member, type: STRING, loc }, args], type: DYN, loc };
|
|
1422
1435
|
}
|
|
1436
|
+
if (bi.module === "fs" && (bi.member === "readvSync" || bi.member === "writevSync" || bi.member === "ftruncateSync")) {
|
|
1437
|
+
const vector = bi.member !== "ftruncateSync";
|
|
1438
|
+
const required = vector ? 2 : 1;
|
|
1439
|
+
if (expr.arguments.length < required || expr.arguments.length > required + 1 || expr.arguments.some(ts.isSpreadElement))
|
|
1440
|
+
lowerer.noLowering(`${name} with this argument shape`, expr);
|
|
1441
|
+
const args = [lowerer.lowerExprExpecting(expr.arguments[0], F64)];
|
|
1442
|
+
if (vector)
|
|
1443
|
+
args.push(lowerer.lowerExprExpecting(expr.arguments[1], arrayOf(BYTES_U8)));
|
|
1444
|
+
const optional = expr.arguments[required];
|
|
1445
|
+
args.push(optional ? lowerBuiltinOptionalDefault(lowerer, optional, F64, numLit(vector ? -1 : 0, loc), vector) : numLit(vector ? -1 : 0, loc));
|
|
1446
|
+
return { kind: "libCall", fn: fn.fn, args, type: vector ? F64 : VOID, loc };
|
|
1447
|
+
}
|
|
1423
1448
|
// Numeric open flags are interpreted symbolically at the call site. The
|
|
1424
1449
|
// O_* bit values differ between Darwin and Linux, so emit a stable mask
|
|
1425
1450
|
// and let the target runtime select its own native constants.
|
|
@@ -2344,6 +2369,19 @@ export function lowerReflectCall(lowerer, call, access) {
|
|
|
2344
2369
|
}
|
|
2345
2370
|
if (call.questionDotToken)
|
|
2346
2371
|
return null;
|
|
2372
|
+
const reflectMember = lowerer.stdlibGlobalMember(access, "Reflect");
|
|
2373
|
+
if (reflectMember === "get" || reflectMember === "set") {
|
|
2374
|
+
const required = reflectMember === "get" ? 2 : 3;
|
|
2375
|
+
if (call.arguments.length < required || call.arguments.length > required + 1 || call.arguments.some(ts.isSpreadElement)) {
|
|
2376
|
+
lowerer.noLowering(`Reflect.${reflectMember} with this argument shape`, call, `use Reflect.${reflectMember}(target, key${reflectMember === "set" ? ", value" : ""}, receiver?)`);
|
|
2377
|
+
}
|
|
2378
|
+
const loc = locOf(call);
|
|
2379
|
+
const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
2380
|
+
const target = call.arguments.length === required ? lowerer.declareHiddenLocal("%reflectTarget", DYN) : null;
|
|
2381
|
+
const operation = { kind: "libCall", fn: reflectMember === "get" ? "dyn.reflectGet" : "dyn.reflectSet",
|
|
2382
|
+
args: target ? [varRef(target.id, DYN, loc), ...args.slice(1), varRef(target.id, DYN, loc)] : args, type: reflectMember === "get" ? DYN : BOOL, loc };
|
|
2383
|
+
return target ? { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: target.id, init: args[0], loc }], result: operation, type: operation.type, loc } : operation;
|
|
2384
|
+
}
|
|
2347
2385
|
if (lowerer.stdlibGlobalMember(access, "Reflect") !== "apply")
|
|
2348
2386
|
return null;
|
|
2349
2387
|
const loc = locOf(call);
|
|
@@ -4188,13 +4226,8 @@ function isStringDecoderTyped(lowerer, node) {
|
|
|
4188
4226
|
return lowerer.checker.declarationsOf(sym).some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
4189
4227
|
lowerer.isStdlibFile(d.getSourceFile()));
|
|
4190
4228
|
}
|
|
4191
|
-
/**
|
|
4192
|
-
|
|
4193
|
-
* sequence; `d.end()` flushes the buffered partial as its replacement
|
|
4194
|
-
* chars — Node's utf8 StringDecoder exactly (SEMANTICS.md), through the
|
|
4195
|
-
* interned %strdec helpers over the packed-f64 pending field. end(buf)
|
|
4196
|
-
* and the rest of @types/node's surface fence per member. Null for
|
|
4197
|
-
* non-decoder receivers. */
|
|
4229
|
+
/** StringDecoder writes preserve pending bytes; end(input) performs the
|
|
4230
|
+
* final write and flushes the state. String input passes through unchanged. */
|
|
4198
4231
|
export function lowerStringDecoderMethodCall(lowerer, call, access) {
|
|
4199
4232
|
if (call.questionDotToken || access.questionDotToken)
|
|
4200
4233
|
return null;
|
|
@@ -4204,29 +4237,37 @@ export function lowerStringDecoderMethodCall(lowerer, call, access) {
|
|
|
4204
4237
|
return null;
|
|
4205
4238
|
const name = access.name.text;
|
|
4206
4239
|
const loc = locOf(call);
|
|
4207
|
-
if (name
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
lowerer.badType(access.expression, lowerer.typeOf(access.expression));
|
|
4211
|
-
let chunk = lowerBuiltinValuePreservingUndefined(lowerer, call.arguments[0]);
|
|
4212
|
-
chunk = checkedOptionalBuiltinArm(lowerer, chunk, BYTES_U8) ?? chunk;
|
|
4213
|
-
if (!(chunk.type.kind === "bytes" && chunk.type.elem === "u8")) {
|
|
4214
|
-
lowerer.noLowering(`StringDecoder.write of '${lowerer.fmt(chunk.type)}' data`, call.arguments[0], "Buffer/Uint8Array chunks decode (narrow unions first)");
|
|
4215
|
-
}
|
|
4216
|
-
const helper = lowerer.strdecHelper("write", receiver.type.shapeId, loc);
|
|
4217
|
-
return { kind: "call", callee: helper, args: [receiver, chunk], type: STRING, loc };
|
|
4240
|
+
if ((name !== "write" && name !== "end") || call.arguments.length > 1 ||
|
|
4241
|
+
(name === "write" && call.arguments.length !== 1) || call.arguments.some(ts.isSpreadElement)) {
|
|
4242
|
+
lowerer.noLowering(`StringDecoder.${name}`, call, "use write(input) or end(input?)", lowerer.checker.getSymbolAtLocation(access.name));
|
|
4218
4243
|
}
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4244
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
4245
|
+
if (receiver.type.kind !== "record")
|
|
4246
|
+
lowerer.badType(access.expression, lowerer.typeOf(access.expression));
|
|
4247
|
+
if (call.arguments.length === 0) {
|
|
4248
|
+
return { kind: "call", callee: lowerer.strdecHelper("end", receiver.type.shapeId, loc), args: [receiver], type: STRING, loc };
|
|
4249
|
+
}
|
|
4250
|
+
const node = call.arguments[0];
|
|
4251
|
+
const undefinedArg = name === "end" ? lowerStaticallyUndefinedArgument(lowerer, node) : null;
|
|
4252
|
+
if (undefinedArg) {
|
|
4253
|
+
const saved = lowerer.declareHiddenLocal("%strdecRecv", receiver.type);
|
|
4254
|
+
const result = { kind: "call", callee: lowerer.strdecHelper("end", receiver.type.shapeId, loc), args: [varRef(saved.id, receiver.type, loc)], type: STRING, loc };
|
|
4255
|
+
return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: saved.id, init: receiver, loc }], result: defaultAfterUndefined(undefinedArg, result), type: STRING, loc };
|
|
4228
4256
|
}
|
|
4229
|
-
|
|
4257
|
+
let chunk = lowerBuiltinValuePreservingUndefined(lowerer, node);
|
|
4258
|
+
if (chunk.type.kind === "string") {
|
|
4259
|
+
const op = name === "end" ? "endString" : "writeString";
|
|
4260
|
+
return { kind: "call", callee: lowerer.strdecHelper(op, receiver.type.shapeId, loc), args: [receiver, chunk], type: STRING, loc };
|
|
4261
|
+
}
|
|
4262
|
+
chunk = checkedOptionalBuiltinArm(lowerer, chunk, BYTES_U8) ?? chunk;
|
|
4263
|
+
if (chunk.type.kind === "bytes" && chunk.type.elem !== "u8") {
|
|
4264
|
+
chunk = { kind: "libCall", fn: "bytes.bufferSource", args: [lowerer.coerceInto(node, chunk, DYN)], type: BYTES_U8, loc };
|
|
4265
|
+
}
|
|
4266
|
+
if (!(chunk.type.kind === "bytes" && chunk.type.elem === "u8")) {
|
|
4267
|
+
lowerer.noLowering(`StringDecoder.${name} of '${lowerer.fmt(chunk.type)}' data`, node, "pass a string or typed-array view (narrow unions first)");
|
|
4268
|
+
}
|
|
4269
|
+
const helper = lowerer.strdecHelper(name === "end" ? "endChunk" : "write", receiver.type.shapeId, loc);
|
|
4270
|
+
return { kind: "call", callee: helper, args: [receiver, chunk], type: STRING, loc };
|
|
4230
4271
|
}
|
|
4231
4272
|
/** The interned %strdec helpers: write(d, chunk) returns the decoded
|
|
4232
4273
|
* complete prefix and re-buffers the trailing partial into the pending
|
|
@@ -4264,7 +4305,7 @@ export function strdecHelper(lowerer, op, shapeId, loc) {
|
|
|
4264
4305
|
{ id: "s.0", name: "s", type: STRING, mutable: false },
|
|
4265
4306
|
];
|
|
4266
4307
|
let body;
|
|
4267
|
-
if (op === "write") {
|
|
4308
|
+
if (op === "write" || op === "endChunk") {
|
|
4268
4309
|
params.push({ localId: "chunk.0", name: "chunk", type: BYTES_U8 });
|
|
4269
4310
|
locals.splice(1, 0, { id: "chunk.0", name: "chunk", type: BYTES_U8, mutable: false });
|
|
4270
4311
|
body = [
|
|
@@ -4304,6 +4345,24 @@ export function strdecHelper(lowerer, op, shapeId, loc) {
|
|
|
4304
4345
|
{ kind: "return", value: varRef("s.0", STRING, loc), loc },
|
|
4305
4346
|
];
|
|
4306
4347
|
}
|
|
4348
|
+
if (op === "endString" || op === "writeString") {
|
|
4349
|
+
const inputT = STRING;
|
|
4350
|
+
params.push({ localId: "chunk.0", name: "chunk", type: inputT });
|
|
4351
|
+
locals.push({ id: "chunk.0", name: "chunk", type: inputT, mutable: false });
|
|
4352
|
+
if (op === "writeString")
|
|
4353
|
+
body = [{ kind: "return", value: varRef("chunk.0", STRING, loc), loc }];
|
|
4354
|
+
if (op === "endString")
|
|
4355
|
+
body[body.length - 1] = { kind: "return", value: {
|
|
4356
|
+
kind: "strConcat", left: varRef("chunk.0", STRING, loc), right: varRef("s.0", STRING, loc), type: STRING, loc,
|
|
4357
|
+
}, loc };
|
|
4358
|
+
}
|
|
4359
|
+
if (op === "endChunk") {
|
|
4360
|
+
locals.push({ id: "tail.0", name: "tail", type: STRING, mutable: false });
|
|
4361
|
+
body.splice(body.length - 1, 0, { kind: "varDecl", localId: "tail.0", init: { kind: "libCall", fn: "strdec.end", args: [encRead(), pendingRead()], type: STRING, loc }, loc }, { kind: "recordSet", obj: varRef("d.0", recT, loc), shapeId, field: "%pending", value: { kind: "numLit", value: 0, type: F64, loc }, loc });
|
|
4362
|
+
body[body.length - 1] = { kind: "return", value: {
|
|
4363
|
+
kind: "strConcat", left: varRef("s.0", STRING, loc), right: varRef("tail.0", STRING, loc), type: STRING, loc,
|
|
4364
|
+
}, loc };
|
|
4365
|
+
}
|
|
4307
4366
|
lowerer.liftedFns.push({ name, params, returnType: STRING, locals, body, loc });
|
|
4308
4367
|
return name;
|
|
4309
4368
|
}
|
|
@@ -4400,11 +4459,11 @@ export function lowerJsonMethodCall(lowerer, call, access) {
|
|
|
4400
4459
|
const optionalString = lowerOptionalStringifyRoot(lowerer, value, indent, loc);
|
|
4401
4460
|
if (optionalString)
|
|
4402
4461
|
return optionalString;
|
|
4403
|
-
if (value.type.kind === "dyn" || isJsonStringifyDynamicType(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
4462
|
+
if (value.type.kind === "url" || value.type.kind === "dyn" || isJsonStringifyDynamicType(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
4404
4463
|
// Keep the original containers live while the runtime visits them:
|
|
4405
4464
|
// a toJSON callback can mutate a later field, and shared/cyclic
|
|
4406
4465
|
// references must retain their identities throughout traversal.
|
|
4407
|
-
const boxed = value.type.kind === "dyn" ? value : { kind: "dynFrom", value, liveRef: true, type: DYN, loc };
|
|
4466
|
+
const boxed = value.type.kind === "dyn" ? value : { kind: "dynFrom", value, ...(value.type.kind === "url" ? {} : { liveRef: true }), type: DYN, loc };
|
|
4408
4467
|
const raw = {
|
|
4409
4468
|
kind: "libCall", fn: "json.stringifyReplacer",
|
|
4410
4469
|
args: [boxed, dynUndefinedExpr(loc), { kind: "strLit", value: indent, type: STRING, loc }],
|
|
@@ -4742,8 +4801,8 @@ function cryptoEncoding(lowerer, node, use) {
|
|
|
4742
4801
|
}
|
|
4743
4802
|
function cryptoAlgorithm(lowerer, node, use) {
|
|
4744
4803
|
const type = lowerer.typeOf(node);
|
|
4745
|
-
if (type.isStringLiteralType() && !["md5", "sha1", "sha256"].includes(type.value.toLowerCase())) {
|
|
4746
|
-
lowerer.noLowering(`${use} with algorithm '${type.value}'`, node, "md5, sha1,
|
|
4804
|
+
if (type.isStringLiteralType() && !["md5", "sha1", "sha224", "sha256", "sha384", "sha512"].includes(type.value.toLowerCase())) {
|
|
4805
|
+
lowerer.noLowering(`${use} with algorithm '${type.value}'`, node, "md5, sha1, sha224, sha256, sha384, and sha512 are the lowered digest algorithms");
|
|
4747
4806
|
}
|
|
4748
4807
|
return lowerer.lowerExprExpecting(node, STRING);
|
|
4749
4808
|
}
|
|
@@ -4762,7 +4821,19 @@ function cryptoInputBytes(lowerer, node, loc) {
|
|
|
4762
4821
|
}
|
|
4763
4822
|
lowerer.noLowering(`crypto byte input of '${lowerer.fmt(value.type)}' values`, node, "string and Buffer/Uint8Array values are supported");
|
|
4764
4823
|
}
|
|
4765
|
-
function
|
|
4824
|
+
function cryptoKdfInput(lowerer, node) {
|
|
4825
|
+
const loc = locOf(node);
|
|
4826
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
4827
|
+
if (type?.kind === "string" || (type?.kind === "bytes" && type.elem === "u8"))
|
|
4828
|
+
return cryptoInputBytes(lowerer, node, loc);
|
|
4829
|
+
const symbol = lowerer.typeOf(node).getSymbol();
|
|
4830
|
+
if (type?.kind === "bytes" || (symbol?.name === "ArrayBuffer" && lowerer.isStdlibSymbol(symbol))) {
|
|
4831
|
+
const value = lowerer.coerceInto(node, lowerer.lowerExpr(node), DYN);
|
|
4832
|
+
return { kind: "libCall", fn: "bytes.bufferSource", args: [value], type: BYTES_U8, loc };
|
|
4833
|
+
}
|
|
4834
|
+
lowerer.noLowering("crypto key derivation with this input", node, "strings, Buffers, numeric typed arrays, DataViews, and fixed-length ArrayBuffers are supported; KeyObjects are not yet lowered");
|
|
4835
|
+
}
|
|
4836
|
+
function errorFirstBytesCallback(lowerer, node, api, arrayBuffer = false) {
|
|
4766
4837
|
let callback = lowerer.lowerExpr(node);
|
|
4767
4838
|
if (callback.type.kind === "dyn") {
|
|
4768
4839
|
callback = { kind: "dynCheck", value: callback, type: funcOf([DYN, DYN], VOID), loc: locOf(node) };
|
|
@@ -4784,8 +4855,8 @@ function errorFirstBytesCallback(lowerer, node, api) {
|
|
|
4784
4855
|
lowerer.unsupported("SC1090", node, `${api} callback error parameters must be Error | null`);
|
|
4785
4856
|
}
|
|
4786
4857
|
const value = callback.type.params[1];
|
|
4787
|
-
if (value !== undefined && value.kind !== "dyn" && !(value.kind === "bytes" && value.elem === "u8")) {
|
|
4788
|
-
lowerer.unsupported("SC1090", node, `${api} callback result parameters must be Buffer/Uint8Array values`);
|
|
4858
|
+
if (value !== undefined && value.kind !== "dyn" && (arrayBuffer || !(value.kind === "bytes" && value.elem === "u8"))) {
|
|
4859
|
+
lowerer.unsupported("SC1090", node, `${api} callback result parameters must be ${arrayBuffer ? "ArrayBuffer" : "Buffer/Uint8Array"} values`);
|
|
4789
4860
|
}
|
|
4790
4861
|
return voidizedCallback(lowerer, callback, locOf(node));
|
|
4791
4862
|
}
|
|
@@ -4833,6 +4904,31 @@ export function lowerCryptoModuleCall(lowerer, expr, bi, loc) {
|
|
|
4833
4904
|
loc,
|
|
4834
4905
|
};
|
|
4835
4906
|
}
|
|
4907
|
+
if (bi.member === "hkdf" || bi.member === "hkdfSync") {
|
|
4908
|
+
const async = bi.member === "hkdf";
|
|
4909
|
+
if (args.length !== (async ? 6 : 5))
|
|
4910
|
+
lowerer.noLowering(`crypto.${bi.member} with ${args.length} arguments`, expr);
|
|
4911
|
+
const values = [
|
|
4912
|
+
cryptoAlgorithm(lowerer, args[0], `crypto.${bi.member}`),
|
|
4913
|
+
cryptoKdfInput(lowerer, args[1]), cryptoKdfInput(lowerer, args[2]), cryptoKdfInput(lowerer, args[3]),
|
|
4914
|
+
lowerer.lowerExprExpecting(args[4], F64),
|
|
4915
|
+
];
|
|
4916
|
+
if (async)
|
|
4917
|
+
values.push(errorFirstBytesCallback(lowerer, args[5], "crypto.hkdf", true));
|
|
4918
|
+
return { kind: "libCall", fn: async ? "crypto.hkdfCb" : "crypto.hkdf", args: values, type: async ? VOID : DYN, loc };
|
|
4919
|
+
}
|
|
4920
|
+
if (bi.member === "scrypt" || bi.member === "scryptSync") {
|
|
4921
|
+
const async = bi.member === "scrypt";
|
|
4922
|
+
const minimum = async ? 4 : 3;
|
|
4923
|
+
if (args.length < minimum || args.length > minimum + 1)
|
|
4924
|
+
lowerer.noLowering(`crypto.${bi.member} with ${args.length} arguments`, expr);
|
|
4925
|
+
const values = [cryptoKdfInput(lowerer, args[0]), cryptoKdfInput(lowerer, args[1]), lowerer.lowerExprExpecting(args[2], F64)];
|
|
4926
|
+
const options = args.length > minimum ? args[3] : undefined;
|
|
4927
|
+
values.push(options ? lowerer.coerceInto(options, lowerer.lowerExpr(options), DYN) : dynUndefinedExpr(loc));
|
|
4928
|
+
if (async)
|
|
4929
|
+
values.push(errorFirstBytesCallback(lowerer, args[args.length - 1], "crypto.scrypt"));
|
|
4930
|
+
return { kind: "libCall", fn: async ? "crypto.scryptCb" : "crypto.scrypt", args: values, type: async ? VOID : BYTES_U8, loc };
|
|
4931
|
+
}
|
|
4836
4932
|
if (bi.member === "createHash") {
|
|
4837
4933
|
if (args.length !== 1) {
|
|
4838
4934
|
lowerer.noLowering(`crypto.createHash with ${args.length} arguments`, expr, "createHash(algorithm) is supported; options are not yet lowered");
|
|
@@ -4940,7 +5036,7 @@ export function lowerCryptoModuleCall(lowerer, expr, bi, loc) {
|
|
|
4940
5036
|
loc,
|
|
4941
5037
|
};
|
|
4942
5038
|
}
|
|
4943
|
-
/** Method calls on URL-typed receivers: `u.toString()`
|
|
5039
|
+
/** Method calls on URL-typed receivers: `u.toString()` and `u.toJSON()` are Node's href
|
|
4944
5040
|
* serialization (the href getter's libCall). Everything else the lib
|
|
4945
5041
|
* declares fences member-qualified. Null for non-URL receivers. */
|
|
4946
5042
|
export function lowerUrlMethodCall(lowerer, call, access) {
|
|
@@ -4951,11 +5047,11 @@ export function lowerUrlMethodCall(lowerer, call, access) {
|
|
|
4951
5047
|
if (!lowerer.isStdlibMember(access))
|
|
4952
5048
|
return null;
|
|
4953
5049
|
const name = access.name.text;
|
|
4954
|
-
if (name === "toString" && call.arguments.length === 0) {
|
|
5050
|
+
if ((name === "toString" || name === "toJSON") && call.arguments.length === 0) {
|
|
4955
5051
|
const receiver = lowerer.lowerExpr(access.expression);
|
|
4956
5052
|
return { kind: "libCall", fn: "url.href", args: [receiver], type: STRING, loc: locOf(call) };
|
|
4957
5053
|
}
|
|
4958
|
-
lowerer.noLowering(`URL.${name}`, call, "protocol, origin, username, password, pathname, href, host, hostname, port, search, hash, searchParams, and
|
|
5054
|
+
lowerer.noLowering(`URL.${name}`, call, "protocol, origin, username, password, pathname, href, host, hostname, port, search, hash, searchParams, toString(), and toJSON() are the supported URL members", lowerer.checker.getSymbolAtLocation(access.name));
|
|
4959
5055
|
}
|
|
4960
5056
|
/** `new URLSearchParams(init?)` — the WHATWG constructor's lowered init
|
|
4961
5057
|
* shapes: omitted / literal `undefined` (empty list), a string (parsed,
|
|
@@ -5329,18 +5425,21 @@ export function lowerFileHandleMethodCall(lowerer, call, access) {
|
|
|
5329
5425
|
const loc = locOf(call);
|
|
5330
5426
|
const receiver = () => lowerer.lowerExprExpecting(access.expression, FILEHANDLE_T);
|
|
5331
5427
|
const promise = (inner) => ({ kind: "promise", inner });
|
|
5332
|
-
const num = (node, dflt) => {
|
|
5428
|
+
const num = (node, dflt, lowered) => {
|
|
5333
5429
|
const defaultValue = { kind: "numLit", value: dflt, type: F64, loc };
|
|
5334
|
-
if (!node)
|
|
5430
|
+
if (!node && !lowered)
|
|
5335
5431
|
return { value: defaultValue, defaulted: boolLit(true, loc) };
|
|
5336
|
-
|
|
5432
|
+
if (lowered && isUnitType(lowered.type)) {
|
|
5433
|
+
return { value: defaultAfterUndefined(lowered, defaultValue), defaulted: boolLit(true, loc) };
|
|
5434
|
+
}
|
|
5435
|
+
const undefinedArg = !lowered && node ? lowerStaticallyUndefinedArgument(lowerer, node) : null;
|
|
5337
5436
|
if (undefinedArg) {
|
|
5338
5437
|
return { value: defaultAfterUndefined(undefinedArg, defaultValue), defaulted: boolLit(true, loc) };
|
|
5339
5438
|
}
|
|
5340
|
-
if ((lowerer.typeOf(node).flags & ts.TypeFlags.Null) !== 0) {
|
|
5439
|
+
if (!lowered && node && (lowerer.typeOf(node).flags & ts.TypeFlags.Null) !== 0) {
|
|
5341
5440
|
return { value: defaultAfterUndefined(lowerer.lowerExpr(node), defaultValue), defaulted: boolLit(true, loc) };
|
|
5342
5441
|
}
|
|
5343
|
-
const value = lowerer.lowerExpr(node);
|
|
5442
|
+
const value = lowered ?? lowerer.lowerExpr(node);
|
|
5344
5443
|
if (value.type.kind === "union") {
|
|
5345
5444
|
const def = lowerer.unions.get(value.type.unionId);
|
|
5346
5445
|
const units = def?.arms.filter(isUnitType) ?? [];
|
|
@@ -5386,7 +5485,7 @@ export function lowerFileHandleMethodCall(lowerer, call, access) {
|
|
|
5386
5485
|
};
|
|
5387
5486
|
}
|
|
5388
5487
|
}
|
|
5389
|
-
return { value: lowerer.coerceInto(node, value, F64), defaulted: boolLit(false, loc) };
|
|
5488
|
+
return { value: lowerer.coerceInto(node ?? call, value, F64), defaulted: boolLit(false, loc) };
|
|
5390
5489
|
};
|
|
5391
5490
|
const utf8 = (node) => {
|
|
5392
5491
|
const dflt = { kind: "strLit", value: "utf8", type: STRING, loc };
|
|
@@ -5401,6 +5500,30 @@ export function lowerFileHandleMethodCall(lowerer, call, access) {
|
|
|
5401
5500
|
}
|
|
5402
5501
|
return lowerBuiltinOptionalDefault(lowerer, node, STRING, dflt, true);
|
|
5403
5502
|
};
|
|
5503
|
+
if (name === "sync" || name === "datasync") {
|
|
5504
|
+
if (call.arguments.length !== 0)
|
|
5505
|
+
lowerer.noLowering(`FileHandle.${name} with arguments`, call);
|
|
5506
|
+
return { kind: "libCall", fn: name === "sync" ? "fileHandle.sync" : "fileHandle.datasync", args: [receiver()], type: promise(VOID), loc };
|
|
5507
|
+
}
|
|
5508
|
+
if (name === "truncate" || name === "chmod") {
|
|
5509
|
+
if (call.arguments.length > 1 || (name === "chmod" && call.arguments.length !== 1))
|
|
5510
|
+
lowerer.noLowering(`FileHandle.${name} with ${call.arguments.length} arguments`, call);
|
|
5511
|
+
return {
|
|
5512
|
+
kind: "libCall", fn: name === "truncate" ? "fileHandle.truncate" : "fileHandle.chmod",
|
|
5513
|
+
args: [receiver(), num(call.arguments[0], 0).value], type: promise(VOID), loc,
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
if (name === "readv" || name === "writev") {
|
|
5517
|
+
if (call.arguments.length < 1 || call.arguments.length > 2)
|
|
5518
|
+
lowerer.noLowering(`FileHandle.${name} with ${call.arguments.length} arguments`, call);
|
|
5519
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
5520
|
+
if (type?.kind !== "promise" || type.inner.kind !== "record")
|
|
5521
|
+
lowerer.badType(call, lowerer.typeOf(call));
|
|
5522
|
+
return {
|
|
5523
|
+
kind: "libCall", fn: name === "readv" ? "fileHandle.readv" : "fileHandle.writev",
|
|
5524
|
+
args: [receiver(), lowerer.lowerExprExpecting(call.arguments[0], arrayOf(BYTES_U8)), num(call.arguments[1], -1).value], type, loc,
|
|
5525
|
+
};
|
|
5526
|
+
}
|
|
5404
5527
|
if (name === "close" || name === "stat") {
|
|
5405
5528
|
if (call.arguments.length !== 0)
|
|
5406
5529
|
lowerer.noLowering(`FileHandle.${name} with arguments`, call);
|
|
@@ -5458,6 +5581,65 @@ export function lowerFileHandleMethodCall(lowerer, call, access) {
|
|
|
5458
5581
|
}
|
|
5459
5582
|
lowerer.noLowering(`FileHandle.${name} of '${dataT ? lowerer.fmt(dataT) : lowerer.checker.typeToString(lowerer.typeOf(dataNode))}' data`, dataNode, "string and Uint8Array data are supported");
|
|
5460
5583
|
}
|
|
5584
|
+
if (name === "read" || name === "write") {
|
|
5585
|
+
const firstNode = call.arguments[0];
|
|
5586
|
+
const firstT = firstNode ? lowerer.mapTypeOf(lowerer.typeOf(firstNode)) : undefined;
|
|
5587
|
+
const secondT = call.arguments[1] ? lowerer.mapTypeOf(lowerer.typeOf(call.arguments[1])) : undefined;
|
|
5588
|
+
const readOptions = name === "read" && (!firstNode || firstT?.kind === "record" || (firstT && isUnitType(firstT)));
|
|
5589
|
+
const bufferOptions = firstT?.kind === "bytes" && firstT.elem === "u8" && secondT?.kind === "record";
|
|
5590
|
+
if (readOptions || bufferOptions) {
|
|
5591
|
+
if (call.arguments.length > (bufferOptions ? 2 : 1))
|
|
5592
|
+
lowerer.noLowering(`FileHandle.${name} options with extra arguments`, call);
|
|
5593
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
5594
|
+
if (type?.kind !== "promise" || type.inner.kind !== "record")
|
|
5595
|
+
lowerer.badType(call, lowerer.typeOf(call));
|
|
5596
|
+
const stmts = [];
|
|
5597
|
+
const stage = (value, label) => {
|
|
5598
|
+
const local = lowerer.declareHiddenLocal(label, value.type);
|
|
5599
|
+
stmts.push({ kind: "varDecl", localId: local.id, init: value, loc: value.loc });
|
|
5600
|
+
return varRef(local.id, local.type, loc);
|
|
5601
|
+
};
|
|
5602
|
+
const handle = stage(receiver(), "%fhWindowReceiver");
|
|
5603
|
+
let buffer = bufferOptions ? stage(lowerer.lowerExprExpecting(firstNode, BYTES_U8), "%fhWindowBuffer") : undefined;
|
|
5604
|
+
const optionsNode = bufferOptions ? call.arguments[1] : firstNode;
|
|
5605
|
+
const options = optionsNode ? stage(lowerer.lowerExpr(optionsNode), "%fhWindowOptions") : undefined;
|
|
5606
|
+
const field = (key) => {
|
|
5607
|
+
if (options?.type.kind !== "record")
|
|
5608
|
+
return undefined;
|
|
5609
|
+
const fields = lowerer.shapes.get(options.type.shapeId)?.fields;
|
|
5610
|
+
const getter = fields?.find((f) => f.name === `%get:${key}`);
|
|
5611
|
+
if (getter?.type.kind === "func") {
|
|
5612
|
+
const callee = { kind: "recordGet", obj: options, shapeId: options.type.shapeId, field: getter.name, type: getter.type, loc };
|
|
5613
|
+
return { kind: "callValue", callee, args: [], type: getter.type.ret, loc };
|
|
5614
|
+
}
|
|
5615
|
+
const member = fields?.find((f) => f.name === key);
|
|
5616
|
+
return member ? { kind: "recordGet", obj: options, shapeId: options.type.shapeId, field: key, type: member.type, loc } : undefined;
|
|
5617
|
+
};
|
|
5618
|
+
if (!buffer) {
|
|
5619
|
+
const supplied = field("buffer");
|
|
5620
|
+
const fresh = { kind: "bytesNew", source: numLit(16384, loc), type: BYTES_U8, loc };
|
|
5621
|
+
if (!supplied || isUnitType(supplied.type))
|
|
5622
|
+
buffer = supplied ? defaultAfterUndefined(supplied, fresh) : fresh;
|
|
5623
|
+
else if (supplied.type.kind === "union") {
|
|
5624
|
+
const arms = lowerer.unions.get(supplied.type.unionId)?.arms;
|
|
5625
|
+
if (!arms?.every((arm) => typeEquals(arm, BYTES_U8) || isUnitType(arm)))
|
|
5626
|
+
lowerer.noLowering("FileHandle.read with this buffer type", call);
|
|
5627
|
+
buffer = { kind: "nullish", left: supplied, right: fresh, type: BYTES_U8, loc };
|
|
5628
|
+
}
|
|
5629
|
+
else
|
|
5630
|
+
buffer = lowerer.coerceInto(call, supplied, BYTES_U8);
|
|
5631
|
+
buffer = stage(buffer, "%fhWindowBuffer");
|
|
5632
|
+
}
|
|
5633
|
+
const offset = num(undefined, 0, field("offset"));
|
|
5634
|
+
const length = num(undefined, -1, field("length"));
|
|
5635
|
+
const position = num(undefined, -1, field("position"));
|
|
5636
|
+
const result = {
|
|
5637
|
+
kind: "libCall", fn: name === "read" ? "fileHandle.read" : "fileHandle.writeBytes",
|
|
5638
|
+
args: [handle, buffer, offset.value, length.value, position.value, length.defaulted], type, loc,
|
|
5639
|
+
};
|
|
5640
|
+
return { kind: "seqExpr", stmts, result, type, loc };
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5461
5643
|
if (name === "read") {
|
|
5462
5644
|
if (call.arguments.length < 1 || call.arguments.length > 4) {
|
|
5463
5645
|
lowerer.noLowering(`FileHandle.read with ${call.arguments.length} arguments`, call, "use read(buffer[, offset[, length[, position]]])");
|
|
@@ -5516,7 +5698,7 @@ export function lowerFileHandleMethodCall(lowerer, call, access) {
|
|
|
5516
5698
|
}
|
|
5517
5699
|
lowerer.noLowering(`FileHandle.write of '${dataT ? lowerer.fmt(dataT) : lowerer.checker.typeToString(lowerer.typeOf(dataNode))}' data`, dataNode, "string and Uint8Array data are supported");
|
|
5518
5700
|
}
|
|
5519
|
-
lowerer.noLowering(`FileHandle.${name}`, call, "fd, close(), read(), write(), readFile(), writeFile(), appendFile(), and
|
|
5701
|
+
lowerer.noLowering(`FileHandle.${name}`, call, "fd, close(), read(), write(), readv(), writev(), readFile(), writeFile(), appendFile(), stat(), sync(), datasync(), truncate(), and chmod() are the supported FileHandle members", lowerer.checker.getSymbolAtLocation(access.name));
|
|
5520
5702
|
}
|
|
5521
5703
|
/** Method calls on Stats-typed receivers: isFile()/isDirectory()/
|
|
5522
5704
|
* isSymbolicLink() are pure reads on the stat snapshot (a followed
|
|
@@ -5670,6 +5852,21 @@ export function lowerAtomicsCall(lowerer, call, access) {
|
|
|
5670
5852
|
export function lowerBuiltinExtraProperty(lowerer, expr) {
|
|
5671
5853
|
if (expr.questionDotToken && !lowerer.chainHandled.has(expr))
|
|
5672
5854
|
return null;
|
|
5855
|
+
const codec = storedTextCodecClassOf(lowerer, expr.expression);
|
|
5856
|
+
if (codec && lowerer.isStdlibMember(expr) && ["encoding", "fatal", "ignoreBOM"].includes(expr.name.text)) {
|
|
5857
|
+
const receiver = lowerer.lowerExpr(expr.expression);
|
|
5858
|
+
if (receiver.type.kind !== "record")
|
|
5859
|
+
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
5860
|
+
const loc = locOf(expr);
|
|
5861
|
+
if (codec === "TextEncoder" && expr.name.text === "encoding") {
|
|
5862
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc }], result: strLit("utf-8", loc), type: STRING, loc };
|
|
5863
|
+
}
|
|
5864
|
+
if (codec === "TextDecoder") {
|
|
5865
|
+
const field = expr.name.text === "encoding" ? "%TextDecoder" : `%${expr.name.text}`;
|
|
5866
|
+
const value = { kind: "recordGet", obj: receiver, shapeId: receiver.type.shapeId, field, type: expr.name.text === "encoding" ? F64 : BOOL, loc };
|
|
5867
|
+
return expr.name.text === "encoding" ? { kind: "libCall", fn: "text.decoderName", args: [value], type: STRING, loc } : value;
|
|
5868
|
+
}
|
|
5869
|
+
}
|
|
5673
5870
|
// decoder.encoding on a StringDecoder-typed receiver: the record's
|
|
5674
5871
|
// hidden canonical-name field (construction folded the aliases —
|
|
5675
5872
|
// exactly what Node's normalized `.encoding` answers).
|
|
@@ -5680,6 +5877,15 @@ export function lowerBuiltinExtraProperty(lowerer, expr) {
|
|
|
5680
5877
|
return { kind: "recordGet", obj: receiver, shapeId: receiver.type.shapeId, field: "%enc", type: STRING, loc: locOf(expr) };
|
|
5681
5878
|
}
|
|
5682
5879
|
const kind = lowerer.mapTypeOf(lowerer.typeOf(expr.expression))?.kind;
|
|
5880
|
+
if (kind === "record" && ["read", "written"].includes(expr.name.text) && lowerer.isStdlibMember(expr)) {
|
|
5881
|
+
const receiver = lowerer.lowerExpr(expr.expression);
|
|
5882
|
+
if (receiver.type.kind === "record") {
|
|
5883
|
+
const fields = lowerer.shapes.get(receiver.type.shapeId)?.fields;
|
|
5884
|
+
if (fields?.length === 2 && fields.every((field) => ["read", "written"].includes(field.name) && field.type.kind === "f64")) {
|
|
5885
|
+
return { kind: "recordGet", obj: receiver, shapeId: receiver.type.shapeId, field: expr.name.text, type: F64, loc: locOf(expr) };
|
|
5886
|
+
}
|
|
5887
|
+
}
|
|
5888
|
+
}
|
|
5683
5889
|
if (kind !== "stats" && kind !== "fileHandle" && kind !== "spawnRes" && kind !== "child" && kind !== "childWriter")
|
|
5684
5890
|
return null;
|
|
5685
5891
|
if (kind === "child" ? !isChildSurfaceMember(lowerer, expr) : !lowerer.isStdlibMember(expr))
|
|
@@ -5896,14 +6102,15 @@ export function lowerChildMethodCall(lowerer, call, access) {
|
|
|
5896
6102
|
lowerer.checkedCallbackParams.add(param);
|
|
5897
6103
|
}
|
|
5898
6104
|
const cb = lowerer.lowerExpr(call.arguments[1]);
|
|
5899
|
-
if (cb.type.kind === "
|
|
5900
|
-
|
|
5901
|
-
|
|
6105
|
+
if (isJsSourceFile(listenerNode.getSourceFile()) && cb.type.kind === "dyn" ||
|
|
6106
|
+
cb.type.kind === "func" && (cb.type.rest || isJsSourceFile(listenerNode.getSourceFile()) && cb.type.params.some((param) => param.kind === "dyn"))) {
|
|
6107
|
+
if (cb.type.kind !== "dyn" && !canBoxFuncIntoDyn(cb.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
6108
|
+
lowerer.noLowering("child event listeners with non-representable parameters", call.arguments[1]);
|
|
5902
6109
|
}
|
|
5903
6110
|
return {
|
|
5904
6111
|
kind: "libCall", fn: "child.onDyn",
|
|
5905
6112
|
args: [receiver, { kind: "strLit", value: event, type: STRING, loc },
|
|
5906
|
-
{ kind: "dynFrom", value: cb, type: DYN, loc }],
|
|
6113
|
+
cb.type.kind === "dyn" ? cb : { kind: "dynFrom", value: cb, type: DYN, loc }],
|
|
5907
6114
|
type: VOID, loc,
|
|
5908
6115
|
};
|
|
5909
6116
|
}
|
|
@@ -6286,7 +6493,8 @@ export function lowerErrorCodeProperty(lowerer, expr) {
|
|
|
6286
6493
|
return null;
|
|
6287
6494
|
if (!lowerer.isStdlibMember(expr))
|
|
6288
6495
|
return null;
|
|
6289
|
-
const
|
|
6496
|
+
const rawReceiver = lowerer.lowerExpr(expr.expression);
|
|
6497
|
+
const receiver = rawReceiver.type.kind === "dyn" ? lowerer.coerceInto(expr.expression, rawReceiver, recvT) : rawReceiver;
|
|
6290
6498
|
return {
|
|
6291
6499
|
kind: "libCall",
|
|
6292
6500
|
fn: expr.name.text === "stack" ? "error.stack" : expr.name.text === "cause" ? "error.cause" : "error.code",
|
|
@@ -6986,6 +7194,19 @@ export function lowerProcessEnvGet(lowerer, expr) {
|
|
|
6986
7194
|
const key = { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) };
|
|
6987
7195
|
return { kind: "libCall", fn: "process.envGet", args: [key], type: lowerer.envValueType(), loc };
|
|
6988
7196
|
}
|
|
7197
|
+
function lowerProcessLoadEnvFile(lowerer, call) {
|
|
7198
|
+
if (call.arguments.length > 1 || call.arguments.some(ts.isSpreadElement)) {
|
|
7199
|
+
lowerer.noLowering("process.loadEnvFile with spread or extra arguments", call);
|
|
7200
|
+
}
|
|
7201
|
+
const loc = locOf(call);
|
|
7202
|
+
const path = call.arguments[0] ? lowerer.lowerExprExpecting(call.arguments[0], DYN)
|
|
7203
|
+
: { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
|
|
7204
|
+
const load = { kind: "libCall", fn: "process.loadEnvFile", args: [path], type: VOID, loc };
|
|
7205
|
+
if (ts.isExpressionStatement(call.parent))
|
|
7206
|
+
return load;
|
|
7207
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: load, loc }],
|
|
7208
|
+
result: { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc }, type: DYN, loc };
|
|
7209
|
+
}
|
|
6989
7210
|
/** `process.exit(code)` / `process.cwd()` → libCall. The fallback
|
|
6990
7211
|
* declaration makes exit's code required; @types/node declares it
|
|
6991
7212
|
* optional. A bare `process.exit()` uses the current exitCode, or zero
|
|
@@ -7003,6 +7224,8 @@ export function lowerProcessMethodCall(lowerer, call, access) {
|
|
|
7003
7224
|
}
|
|
7004
7225
|
}
|
|
7005
7226
|
const directProcessMember = lowerer.stdlibGlobalMember(access, "process");
|
|
7227
|
+
if (directProcessMember === "loadEnvFile")
|
|
7228
|
+
return lowerProcessLoadEnvFile(lowerer, call);
|
|
7006
7229
|
if (directProcessMember === "hrtime") {
|
|
7007
7230
|
if (call.arguments.some(ts.isSpreadElement))
|
|
7008
7231
|
lowerer.noLowering("process.hrtime with spread arguments", call);
|
|
@@ -7991,6 +8214,18 @@ export function lowerTextCodecCall(lowerer, call, access) {
|
|
|
7991
8214
|
if (call.questionDotToken || access.questionDotToken)
|
|
7992
8215
|
return null;
|
|
7993
8216
|
const member = access.name.text;
|
|
8217
|
+
if (member === "encodeInto" && storedTextCodecClassOf(lowerer, access.expression) === "TextEncoder" && lowerer.isStdlibMember(access)) {
|
|
8218
|
+
if (call.arguments.length !== 2 || call.arguments.some(ts.isSpreadElement))
|
|
8219
|
+
lowerer.noLowering("TextEncoder.encodeInto with this argument shape", call);
|
|
8220
|
+
const loc = locOf(call);
|
|
8221
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
8222
|
+
const result = { kind: "libCall", fn: "text.encodeInto", args: call.arguments.map((arg) => lowerer.lowerExprExpecting(stripTypeCasts(arg), DYN)), type: DYN, loc };
|
|
8223
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
8224
|
+
if (!type)
|
|
8225
|
+
lowerer.badType(call, lowerer.typeOf(call));
|
|
8226
|
+
const checked = lowerer.coerceInto(call, result, type);
|
|
8227
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc }], result: checked, type, loc };
|
|
8228
|
+
}
|
|
7994
8229
|
if (member !== "decode" && member !== "encode")
|
|
7995
8230
|
return null;
|
|
7996
8231
|
const info = directTextCodecCtorOf(lowerer, access.expression);
|
|
@@ -8294,9 +8529,14 @@ export function lowerPromiseStaticCall(lowerer, call, access) {
|
|
|
8294
8529
|
lowerer.diags.splice(diagsBefore);
|
|
8295
8530
|
}
|
|
8296
8531
|
}
|
|
8532
|
+
if (!lowerer.dynamic && isJsSourceFile(call.getSourceFile()) && elems.every((entry) => lowerer.dynConvertible(entry.type))) {
|
|
8533
|
+
return checkedPromiseAll(lowerer, { kind: "arrayLit", elems: elems.map((entry) => lowerer.coerceToExpected(entry, DYN)), type: arrayOf(DYN), loc }, loc);
|
|
8534
|
+
}
|
|
8297
8535
|
lowerer.noLowering("Promise.all over this argument shape", argNode, "the entries must share ONE promise type — Promise.all([p, q]) lowers when p and q are the same Promise<T>");
|
|
8298
8536
|
}
|
|
8299
8537
|
const entries = lowerer.lowerExpr(argNode);
|
|
8538
|
+
if (!lowerer.dynamic && isJsSourceFile(call.getSourceFile()) && entries.type.kind === "dyn")
|
|
8539
|
+
return checkedPromiseAll(lowerer, entries, loc);
|
|
8300
8540
|
// A NON-literal island argument (`Promise.all(plugins.map((p) =>
|
|
8301
8541
|
// loadPlugin(p)))` — the loadPlugins shape, where the checker
|
|
8302
8542
|
// spells `any[]`): the ENGINE's own Promise.all runs over the
|