@scriptc/compiler 0.0.35 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +14 -11
- package/ambient/scriptc-overrides.d.ts +0 -7
- package/ambient/scriptc.d.ts +1 -1
- package/dist/backend/build-cache.d.ts +44 -0
- package/dist/backend/build-cache.js +241 -0
- package/dist/backend/build-cache.js.map +1 -0
- package/dist/backend/{emission/emit-async.d.ts → c/async.d.ts} +21 -30
- package/dist/backend/{emission/emit-async.js → c/async.js} +270 -286
- package/dist/backend/c/async.js.map +1 -0
- package/dist/backend/{emission/emitter.d.ts → c/c-emitter.d.ts} +6 -23
- package/dist/backend/{emission/emitter.js → c/c-emitter.js} +53 -107
- package/dist/backend/c/c-emitter.js.map +1 -0
- package/dist/backend/c/exprs.d.ts +8 -0
- package/dist/backend/c/exprs.js +7937 -0
- package/dist/backend/c/exprs.js.map +1 -0
- package/dist/backend/{emission/emit-island.d.ts → c/island.d.ts} +5 -5
- package/dist/backend/{emission/emit-island.js → c/island.js} +24 -22
- package/dist/backend/c/island.js.map +1 -0
- package/dist/backend/{emission → c}/may-throw.d.ts +1 -1
- package/dist/backend/{emission → c}/may-throw.js +4 -1
- package/dist/backend/c/may-throw.js.map +1 -0
- package/dist/backend/{emission/emit-shapes.d.ts → c/shapes.d.ts} +19 -19
- package/dist/backend/{emission/emit-shapes.js → c/shapes.js} +78 -87
- package/dist/backend/c/shapes.js.map +1 -0
- package/dist/backend/{emission/emit-stmts.d.ts → c/stmts.d.ts} +12 -12
- package/dist/backend/{emission/emit-stmts.js → c/stmts.js} +395 -343
- package/dist/backend/c/stmts.js.map +1 -0
- package/dist/backend/{emission/emit-types.d.ts → c/types.d.ts} +1 -1
- package/dist/backend/{emission/emit-types.js → c/types.js} +42 -286
- package/dist/backend/c/types.js.map +1 -0
- package/dist/backend/c/types.test.js +25 -0
- package/dist/backend/c/types.test.js.map +1 -0
- package/dist/backend/{emission/emit-walkers.d.ts → c/walkers.d.ts} +19 -41
- package/dist/backend/{emission/emit-walkers.js → c/walkers.js} +242 -304
- package/dist/backend/c/walkers.js.map +1 -0
- package/dist/backend/external-c.d.ts +33 -0
- package/dist/backend/external-c.js +51 -0
- package/dist/backend/external-c.js.map +1 -0
- package/dist/backend/ffi-callbacks.d.ts +1 -1
- package/dist/backend/ffi-callbacks.js +4 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/{library-identity.d.ts → library-identity-markers.d.ts} +0 -4
- package/dist/backend/{library-identity.js → library-identity-markers.js} +10 -9
- package/dist/backend/library-identity-markers.js.map +1 -0
- package/dist/backend/link-plan.d.ts +37 -0
- package/dist/backend/link-plan.js +26 -0
- package/dist/backend/link-plan.js.map +1 -0
- package/dist/backend/linker.d.ts +22 -0
- package/dist/backend/linker.js +236 -0
- package/dist/backend/linker.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +4 -0
- package/dist/backend/llvm/blocks.js +29 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +2 -19
- package/dist/backend/llvm/classes.js +20 -52
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +4 -0
- package/dist/backend/llvm/common.js +27 -0
- package/dist/backend/llvm/common.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +3 -8
- package/dist/backend/llvm/dyn.js +159 -224
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +4 -1
- package/dist/backend/llvm/emitter.js +548 -9988
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-async.d.ts +4 -0
- package/dist/backend/llvm/expr-async.js +726 -0
- package/dist/backend/llvm/expr-async.js.map +1 -0
- package/dist/backend/llvm/expr-bytes.d.ts +13 -0
- package/dist/backend/llvm/expr-bytes.js +456 -0
- package/dist/backend/llvm/expr-bytes.js.map +1 -0
- package/dist/backend/llvm/expr-callbacks.d.ts +22 -0
- package/dist/backend/llvm/expr-callbacks.js +520 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -0
- package/dist/backend/llvm/expr-calls.d.ts +2 -0
- package/dist/backend/llvm/expr-calls.js +618 -0
- package/dist/backend/llvm/expr-calls.js.map +1 -0
- package/dist/backend/llvm/expr-containers.d.ts +25 -0
- package/dist/backend/llvm/expr-containers.js +637 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -0
- package/dist/backend/llvm/expr-context.d.ts +255 -0
- package/dist/backend/llvm/expr-context.js +2 -0
- package/dist/backend/llvm/expr-context.js.map +1 -0
- package/dist/backend/llvm/expr-control.d.ts +2 -0
- package/dist/backend/llvm/expr-control.js +473 -0
- package/dist/backend/llvm/expr-control.js.map +1 -0
- package/dist/backend/llvm/expr-dispatch.d.ts +4 -0
- package/dist/backend/llvm/expr-dispatch.js +153 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -0
- package/dist/backend/llvm/expr-dynamic.d.ts +2 -0
- package/dist/backend/llvm/expr-dynamic.js +810 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -0
- package/dist/backend/llvm/expr-island.d.ts +15 -0
- package/dist/backend/llvm/expr-island.js +690 -0
- package/dist/backend/llvm/expr-island.js.map +1 -0
- package/dist/backend/llvm/expr-primitives.d.ts +6 -0
- package/dist/backend/llvm/expr-primitives.js +642 -0
- package/dist/backend/llvm/expr-primitives.js.map +1 -0
- package/dist/backend/llvm/expr-records.d.ts +9 -0
- package/dist/backend/llvm/expr-records.js +299 -0
- package/dist/backend/llvm/expr-records.js.map +1 -0
- package/dist/backend/llvm/expr-stream-bridges.d.ts +13 -0
- package/dist/backend/llvm/expr-stream-bridges.js +420 -0
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +12 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +360 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.d.ts +5 -0
- package/dist/backend/llvm/lib-dispatch.js +267 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -0
- package/dist/backend/llvm/lib-filesystem.d.ts +6 -0
- package/dist/backend/llvm/lib-filesystem.js +594 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -0
- package/dist/backend/llvm/lib-network.d.ts +2 -0
- package/dist/backend/llvm/lib-network.js +429 -0
- package/dist/backend/llvm/lib-network.js.map +1 -0
- package/dist/backend/llvm/lib-process.d.ts +5 -0
- package/dist/backend/llvm/lib-process.js +585 -0
- package/dist/backend/llvm/lib-process.js.map +1 -0
- package/dist/backend/llvm/lib-shared.d.ts +6 -0
- package/dist/backend/llvm/lib-shared.js +687 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -0
- package/dist/backend/llvm/lib-stream.d.ts +2 -0
- package/dist/backend/llvm/lib-stream.js +470 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +12 -2
- package/dist/backend/llvm/shapes.js +66 -307
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +52 -0
- package/dist/backend/llvm/shapes.test.js.map +1 -0
- package/dist/backend/llvm/unsupported.d.ts +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -3
- package/dist/backend/llvm/walkers.js +195 -222
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +45 -0
- package/dist/backend/native-codegen.js +275 -0
- package/dist/backend/native-codegen.js.map +1 -0
- package/dist/backend/native-codegen.test.js +226 -0
- package/dist/backend/native-codegen.test.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +96 -0
- package/dist/backend/native-link-info.js +243 -0
- package/dist/backend/native-link-info.js.map +1 -0
- package/dist/backend/native-link-info.test.d.ts +1 -0
- package/dist/backend/native-link-info.test.js +134 -0
- package/dist/backend/native-link-info.test.js.map +1 -0
- package/dist/backend/{cc.d.ts → native-toolchain.d.ts} +54 -34
- package/dist/backend/{cc.js → native-toolchain.js} +231 -810
- package/dist/backend/native-toolchain.js.map +1 -0
- package/dist/backend/native-toolchain.test.d.ts +1 -0
- package/dist/backend/{cc-cache.test.js → native-toolchain.test.js} +219 -7
- package/dist/backend/native-toolchain.test.js.map +1 -0
- package/dist/backend/object-localize.js +1 -1
- package/dist/backend/runtime-abi.d.ts +10 -0
- package/dist/backend/runtime-abi.js +11 -0
- package/dist/backend/runtime-abi.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
- package/dist/backend/runtime-pack-targets.test.js +54 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -0
- package/dist/backend/runtime-pack.d.ts +112 -0
- package/dist/backend/runtime-pack.js +305 -0
- package/dist/backend/runtime-pack.js.map +1 -0
- package/dist/backend/runtime-pack.test.d.ts +1 -0
- package/dist/backend/runtime-pack.test.js +473 -0
- package/dist/backend/runtime-pack.test.js.map +1 -0
- package/dist/backend/targets.d.ts +76 -0
- package/dist/backend/targets.js +262 -0
- package/dist/backend/targets.js.map +1 -0
- package/dist/backend/targets.test.d.ts +1 -0
- package/dist/backend/targets.test.js +41 -0
- package/dist/backend/targets.test.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +41 -0
- package/dist/backend/vendor-archives.js +462 -0
- package/dist/backend/vendor-archives.js.map +1 -0
- package/dist/compat/fetch-profile.d.ts +0 -1
- package/dist/compat/fetch-profile.js +0 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js +3 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +35 -33
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -12
- package/dist/diagnostics/diagnostic.js +19 -17
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.d.ts +1 -1
- package/dist/diagnostics/render.js +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/executable/{early-cache.d.ts → executable-cache.d.ts} +2 -2
- package/dist/executable/{early-cache.js → executable-cache.js} +36 -98
- package/dist/executable/executable-cache.js.map +1 -0
- package/dist/executable/executable-cache.test.d.ts +1 -0
- package/dist/executable/{early-cache.test.js → executable-cache.test.js} +3 -3
- package/dist/executable/executable-cache.test.js.map +1 -0
- package/dist/ffi/{profile.js → ffi-manifest.js} +1 -1
- package/dist/ffi/ffi-manifest.js.map +1 -0
- package/dist/frontend/builtin-modules.d.ts +21 -0
- package/dist/frontend/builtin-modules.js +82 -0
- package/dist/frontend/builtin-modules.js.map +1 -0
- package/dist/frontend/cjs-lexer.d.ts +7 -0
- package/dist/frontend/cjs-lexer.js +15 -17
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/dts-paths.d.ts +26 -0
- package/dist/frontend/dts-paths.js +41 -0
- package/dist/frontend/dts-paths.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +0 -2
- package/dist/frontend/input-tracker.js +1 -4
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +1 -5
- package/dist/frontend/lib-contract.js +1 -1
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lib-exports.d.ts +1 -1
- package/dist/frontend/lowering/array-values.d.ts +8 -0
- package/dist/frontend/lowering/array-values.js +60 -0
- package/dist/frontend/lowering/array-values.js.map +1 -0
- package/dist/frontend/lowering/call-position.d.ts +4 -0
- package/dist/frontend/lowering/call-position.js +7 -0
- package/dist/frontend/lowering/call-position.js.map +1 -0
- package/dist/frontend/lowering/callback-arg.d.ts +20 -0
- package/dist/frontend/lowering/callback-arg.js +44 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +1 -1
- package/dist/frontend/lowering/lib-boundary.js +34 -34
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
- package/dist/frontend/lowering/lower-array-sort.js +619 -0
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.d.ts +3 -3
- package/dist/frontend/lowering/lower-assert.js +214 -241
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +74 -146
- package/dist/frontend/lowering/lower-builtins.js +1285 -1233
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +59 -192
- package/dist/frontend/lowering/lower-calls.js +1644 -1506
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +62 -125
- package/dist/frontend/lowering/lower-classes.js +832 -866
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +5 -12
- package/dist/frontend/lowering/lower-comptime.js +32 -31
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +35 -135
- package/dist/frontend/lowering/lower-containers.js +1984 -2227
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +3 -7
- package/dist/frontend/lowering/lower-dgram.js +97 -111
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +4 -4
- package/dist/frontend/lowering/lower-enums.js +30 -30
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/{lower-emitter.d.ts → lower-event-emitter.d.ts} +7 -18
- package/dist/frontend/lowering/{lower-emitter.js → lower-event-emitter.js} +172 -174
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -0
- package/dist/frontend/lowering/lower-expando.d.ts +5 -5
- package/dist/frontend/lowering/lower-expando.js +40 -40
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +60 -264
- package/dist/frontend/lowering/lower-exprs.js +2361 -1765
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +6 -6
- package/dist/frontend/lowering/lower-generators.js +73 -72
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +5 -17
- package/dist/frontend/lowering/lower-inspect.js +273 -261
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +39 -49
- package/dist/frontend/lowering/lower-island.js +447 -513
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +7 -10
- package/dist/frontend/lowering/lower-mixins.js +85 -85
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +12 -18
- package/dist/frontend/lowering/lower-modules.js +284 -283
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +23 -49
- package/dist/frontend/lowering/lower-namespaces.js +123 -115
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +18 -25
- package/dist/frontend/lowering/lower-server.js +909 -899
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +30 -149
- package/dist/frontend/lowering/lower-stmts.js +1463 -1285
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +12 -12
- package/dist/frontend/lowering/lower-stream.js +300 -301
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +5 -5
- package/dist/frontend/lowering/lower-test.js +82 -82
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +134 -22
- package/dist/frontend/lowering/lowerer.js +1277 -126
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.d.ts +11 -0
- package/dist/frontend/lowering/pairs-snapshot.js +85 -0
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +6 -0
- package/dist/frontend/lowering/static-this.js +24 -0
- package/dist/frontend/lowering/static-this.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +24 -35
- package/dist/frontend/lowering/surfaces.js +78 -66
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js +6 -28
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +0 -10
- package/dist/frontend/npm-static.js +4 -7
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +0 -24
- package/dist/frontend/npm.js +11 -85
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +3 -1
- package/dist/frontend/program.js +9 -4
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance-registry.d.ts +0 -2
- package/dist/frontend/provenance-registry.js +0 -10
- package/dist/frontend/provenance-registry.js.map +1 -1
- package/dist/frontend/provenance.js +4 -7
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +7 -2
- package/dist/frontend/resolve.js +12 -17
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.d.ts +1 -0
- package/dist/frontend/resolve.test.js +29 -0
- package/dist/frontend/resolve.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +2 -2
- package/dist/frontend/ts7/adapter.js +1 -1
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/checker.js +2 -36
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/enums.js +2 -1
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/{program.js → program-adapter.js} +7 -6
- package/dist/frontend/ts7/program-adapter.js.map +1 -0
- package/dist/frontend/ts7/world-check.d.ts +1 -3
- package/dist/frontend/ts7/world-check.js +3 -1
- package/dist/frontend/ts7/world-check.js.map +1 -1
- package/dist/frontend/tsc-codes.d.ts +8 -0
- package/dist/frontend/tsc-codes.js +109 -0
- package/dist/frontend/tsc-codes.js.map +1 -0
- package/dist/frontend/{types.d.ts → type-mapper.d.ts} +2 -25
- package/dist/frontend/{types.js → type-mapper.js} +12 -11
- package/dist/frontend/type-mapper.js.map +1 -0
- package/dist/frontend/workspace-registry.d.ts +26 -0
- package/dist/frontend/workspace-registry.js +71 -0
- package/dist/frontend/workspace-registry.js.map +1 -0
- package/dist/index.d.ts +113 -31
- package/dist/index.js +536 -128
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +37 -0
- package/dist/ir/analysis.js +118 -0
- package/dist/ir/analysis.js.map +1 -0
- package/dist/ir/analysis.test.d.ts +1 -0
- package/dist/ir/analysis.test.js +21 -0
- package/dist/ir/analysis.test.js.map +1 -0
- package/dist/ir/build.d.ts +9 -0
- package/dist/ir/build.js +33 -0
- package/dist/ir/build.js.map +1 -0
- package/dist/ir/integer-loops.d.ts +1 -1
- package/dist/ir/{nodes.d.ts → ir.d.ts} +119 -37
- package/dist/ir/{nodes.js → ir.js} +170 -166
- package/dist/ir/ir.js.map +1 -0
- package/dist/ir/ir.test.d.ts +1 -0
- package/dist/ir/ir.test.js +17 -0
- package/dist/ir/ir.test.js.map +1 -0
- package/dist/ir/serialize.d.ts +2 -2
- package/dist/ir/serialize.js +3 -2
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.d.ts +1 -1
- package/dist/ir/validate.js +93 -41
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +24 -0
- package/dist/library/cache-primitives.js +83 -0
- package/dist/library/cache-primitives.js.map +1 -0
- package/dist/library/cache-reset.test.d.ts +1 -0
- package/dist/library/cache-reset.test.js +47 -0
- package/dist/library/cache-reset.test.js.map +1 -0
- package/dist/library/{implementation-identity.js → compiler-self-identity.js} +1 -1
- package/dist/library/compiler-self-identity.js.map +1 -0
- package/dist/library/fence-eval.d.ts +3 -1
- package/dist/library/fence-eval.js +8 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +1 -36
- package/dist/library/int-infer.js +29 -18
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
- package/dist/library/{early-cache.js → library-cache.js} +34 -89
- package/dist/library/library-cache.js.map +1 -0
- package/dist/library/library-cache.test.d.ts +1 -0
- package/dist/library/{early-cache.test.js → library-cache.test.js} +7 -7
- package/dist/library/library-cache.test.js.map +1 -0
- package/dist/library/{profile.d.ts → library-profile.d.ts} +4 -7
- package/dist/library/{profile.js → library-profile.js} +18 -11
- package/dist/library/library-profile.js.map +1 -0
- package/dist/library/semantic-source.js +2 -1
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar.d.ts +5 -2
- package/dist/library/sidecar.js +11 -5
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.d.ts +11 -3
- package/dist/startup-cache.js +17 -2
- package/dist/startup-cache.js.map +1 -1
- package/package.json +19 -2
- package/surface-manifest.json +5 -5
- package/dist/backend/cc-cache.test.js.map +0 -1
- package/dist/backend/cc.js.map +0 -1
- package/dist/backend/emission/emit-async.js.map +0 -1
- package/dist/backend/emission/emit-exprs.d.ts +0 -13
- package/dist/backend/emission/emit-exprs.js +0 -7407
- package/dist/backend/emission/emit-exprs.js.map +0 -1
- package/dist/backend/emission/emit-island.js.map +0 -1
- package/dist/backend/emission/emit-shapes.js.map +0 -1
- package/dist/backend/emission/emit-stmts.js.map +0 -1
- package/dist/backend/emission/emit-types.js.map +0 -1
- package/dist/backend/emission/emit-walkers.js.map +0 -1
- package/dist/backend/emission/emitter.js.map +0 -1
- package/dist/backend/emission/may-throw.js.map +0 -1
- package/dist/backend/library-identity.js.map +0 -1
- package/dist/executable/early-cache.js.map +0 -1
- package/dist/executable/early-cache.test.js.map +0 -1
- package/dist/ffi/profile.js.map +0 -1
- package/dist/frontend/lowering/lower-emitter.js.map +0 -1
- package/dist/frontend/shared.d.ts +0 -82
- package/dist/frontend/shared.js +0 -308
- package/dist/frontend/shared.js.map +0 -1
- package/dist/frontend/ts7/program.js.map +0 -1
- package/dist/frontend/types.js.map +0 -1
- package/dist/ir/nodes.js.map +0 -1
- package/dist/library/early-cache.js.map +0 -1
- package/dist/library/early-cache.test.js.map +0 -1
- package/dist/library/implementation-identity.js.map +0 -1
- package/dist/library/profile.js.map +0 -1
- /package/dist/backend/{cc-cache.test.d.ts → c/types.test.d.ts} +0 -0
- /package/dist/{executable/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
- /package/dist/{library/early-cache.test.d.ts → backend/native-codegen.test.d.ts} +0 -0
- /package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +0 -0
- /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
- /package/dist/library/{implementation-identity.d.ts → compiler-self-identity.d.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
1
2
|
/* The node:stream lowering (the spoke-module pattern, like
|
|
2
|
-
* lower-emitter.ts): construction of the five runtime stream classes
|
|
3
|
+
* lower-event-emitter.ts): construction of the five runtime stream classes
|
|
3
4
|
* (`new Readable({ read() {} })` et al — the OPTIONS-OBJECT form), user
|
|
4
5
|
* subclasses (`class My extends Readable { _read() {...} }` — the
|
|
5
6
|
* underscore-override form: super(options) lowers to a stream.init
|
|
@@ -33,11 +34,12 @@ import { newFnCtx, own } from "./lowerer.js";
|
|
|
33
34
|
import { appendImplicitUndefinedReturn } from "./lower-calls.js";
|
|
34
35
|
import { bufEncoding, knownBufEncoding } from "./lower-containers.js";
|
|
35
36
|
import { probeLower } from "./lower-exprs.js";
|
|
36
|
-
import { BOOL, DYN, F64, RUNTIME_STREAM_CLASSES, STRING, VOID, arrayOf, bytesOf, canBoxFuncIntoDyn, funcOf, typeEquals, typeKey } from "../../ir/
|
|
37
|
+
import { BOOL, DYN, F64, RUNTIME_STREAM_CLASSES, STRING, VOID, arrayOf, bytesOf, canBoxFuncIntoDyn, funcOf, typeEquals, typeKey } from "../../ir/ir.js";
|
|
38
|
+
import { boolLit, numLit, strLit } from "../../ir/build.js";
|
|
37
39
|
const BYTES = bytesOf("u8");
|
|
38
40
|
/** The stream sides of a receiver class: the nearest stream-class
|
|
39
41
|
* ancestor's, or null off the stream hierarchy. */
|
|
40
|
-
export function streamSidesOf(
|
|
42
|
+
export function streamSidesOf(lowerer, info) {
|
|
41
43
|
for (let c = info ?? null; c; c = c.base) {
|
|
42
44
|
if (c.builtinStream)
|
|
43
45
|
return c.builtinStream;
|
|
@@ -90,15 +92,15 @@ export function streamCtorShape(cls) {
|
|
|
90
92
|
case "%PassThrough":
|
|
91
93
|
return { fn: "passthrough", accepted: ["transform", "flush", "destroy"], duplexShape: true };
|
|
92
94
|
default:
|
|
93
|
-
throw new
|
|
95
|
+
throw new InternalCompilerError(`lowerer bug: streamCtorShape of ${cls}`);
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
/** The per-base FORCED event tuples (runtime-emitted payloads): consulted
|
|
97
99
|
* by the emitter spoke BEFORE the program-global table, so a stream's
|
|
98
100
|
* 'data' never collides with a user event named 'data' on a plain
|
|
99
101
|
* emitter. 'error' stays globally forced to the one-%Error tuple. */
|
|
100
|
-
export function streamForcedTuple(
|
|
101
|
-
const sides = streamSidesOf(
|
|
102
|
+
export function streamForcedTuple(lowerer, info, name) {
|
|
103
|
+
const sides = streamSidesOf(lowerer, info);
|
|
102
104
|
if (!sides)
|
|
103
105
|
return null;
|
|
104
106
|
const readable = {
|
|
@@ -130,9 +132,6 @@ export function streamForcedTuple(L, info, name) {
|
|
|
130
132
|
}
|
|
131
133
|
return null;
|
|
132
134
|
}
|
|
133
|
-
const strLit = (value, loc) => ({ kind: "strLit", value, type: STRING, loc });
|
|
134
|
-
const boolLit = (value, loc) => ({ kind: "boolLit", value, type: BOOL, loc });
|
|
135
|
-
const f64Lit = (value, loc) => ({ kind: "numLit", value, type: F64, loc });
|
|
136
135
|
/* ── option callbacks (the leading-`this` closures) ─────────────────── */
|
|
137
136
|
/** Lowers one option callback (method shorthand, function expression, or
|
|
138
137
|
* arrow) into a closure whose lifted function takes the STREAM as a
|
|
@@ -140,14 +139,14 @@ const f64Lit = (value, loc) => ({ kind: "numLit", value, type: F64, loc });
|
|
|
140
139
|
* (Node calls them stream-bound); arrows keep lexical `this` (the hidden
|
|
141
140
|
* leading param is ABI-only). The declared parameters must be a
|
|
142
141
|
* typeEquals PREFIX of the callback's Node signature. */
|
|
143
|
-
function lowerStreamCallback(
|
|
142
|
+
function lowerStreamCallback(lowerer, which, node, thisType, fullTuple) {
|
|
144
143
|
const loc = locOf(node);
|
|
145
|
-
const { shapes, funcType } =
|
|
144
|
+
const { shapes, funcType } = lowerer.lambdaSignature(node);
|
|
146
145
|
if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
|
|
147
|
-
|
|
146
|
+
lowerer.unsupported("SC1090", node, `async stream '${which}' callbacks`);
|
|
148
147
|
}
|
|
149
148
|
if (funcType.params.length > fullTuple.length) {
|
|
150
|
-
|
|
149
|
+
lowerer.noLowering(`a '${which}' callback declaring ${funcType.params.length} parameters where Node passes ${fullTuple.length}`, node, "stream option callbacks may declare a prefix of their Node signature");
|
|
151
150
|
}
|
|
152
151
|
for (let i = 0; i < funcType.params.length; i++) {
|
|
153
152
|
// A checked-dynamic parameter (the JS lane's implicitly-any
|
|
@@ -157,23 +156,23 @@ function lowerStreamCallback(L, which, node, thisType, fullTuple) {
|
|
|
157
156
|
if (funcType.params[i].kind === "dyn")
|
|
158
157
|
continue;
|
|
159
158
|
if (!typeEquals(funcType.params[i], fullTuple[i])) {
|
|
160
|
-
|
|
159
|
+
lowerer.noLowering(`a '${which}' callback whose parameter ${i} is '${lowerer.fmt(funcType.params[i])}' where Node passes '${lowerer.fmt(fullTuple[i])}'`, node, "annotate the parameter with the Node signature's type (chunks are Buffers here)");
|
|
161
160
|
}
|
|
162
161
|
}
|
|
163
|
-
const fnName = `%fn${
|
|
162
|
+
const fnName = `%fn${lowerer.lambdaCounter++}_${which}cb`;
|
|
164
163
|
const fnCtx = newFnCtx(true, null, funcType, funcType.ret);
|
|
165
|
-
|
|
164
|
+
lowerer.fnStack.push(fnCtx);
|
|
166
165
|
try {
|
|
167
166
|
// Method shorthand and function expressions see the stream as `this`
|
|
168
167
|
// (Node binds it); arrows keep lexical `this`, so their slot is a
|
|
169
168
|
// hidden ABI local no body reference can resolve to.
|
|
170
169
|
const thisLocal = ts.isArrowFunction(node)
|
|
171
|
-
?
|
|
172
|
-
:
|
|
173
|
-
const { params, prologue } =
|
|
170
|
+
? lowerer.declareHiddenLocal("this", thisType)
|
|
171
|
+
: lowerer.declareThis(thisType);
|
|
172
|
+
const { params, prologue } = lowerer.declareParams(node.parameters, shapes);
|
|
174
173
|
let body;
|
|
175
174
|
if (node.body !== undefined && ts.isBlock(node.body)) {
|
|
176
|
-
body =
|
|
175
|
+
body = lowerer.lowerStmts(node.body.statements);
|
|
177
176
|
}
|
|
178
177
|
else if (node.body !== undefined) {
|
|
179
178
|
// Bare-expression bodies (`read: () => this.push(null)`): the value
|
|
@@ -181,19 +180,19 @@ function lowerStreamCallback(L, which, node, thisType, fullTuple) {
|
|
|
181
180
|
// option-callback results either way.
|
|
182
181
|
const bodyExpr = node.body;
|
|
183
182
|
if (funcType.ret.kind === "void") {
|
|
184
|
-
body = [{ kind: "exprStmt", expr:
|
|
183
|
+
body = [{ kind: "exprStmt", expr: lowerer.lowerExpr(bodyExpr), loc: locOf(node.body) }];
|
|
185
184
|
}
|
|
186
185
|
else {
|
|
187
|
-
const value =
|
|
188
|
-
body = [{ kind: "return", value:
|
|
186
|
+
const value = lowerer.lowerExpr(bodyExpr);
|
|
187
|
+
body = [{ kind: "return", value: lowerer.coerceInto(bodyExpr, value, funcType.ret), loc: locOf(node.body) }];
|
|
189
188
|
}
|
|
190
189
|
}
|
|
191
190
|
else {
|
|
192
191
|
body = [];
|
|
193
192
|
}
|
|
194
193
|
body = [...prologue, ...body];
|
|
195
|
-
appendImplicitUndefinedReturn(
|
|
196
|
-
const ctx =
|
|
194
|
+
appendImplicitUndefinedReturn(lowerer, body, funcType.ret, loc);
|
|
195
|
+
const ctx = lowerer.ctx;
|
|
197
196
|
const lifted = {
|
|
198
197
|
name: fnName,
|
|
199
198
|
params: [{ localId: thisLocal.id, name: "this", type: thisType }, ...params],
|
|
@@ -203,7 +202,7 @@ function lowerStreamCallback(L, which, node, thisType, fullTuple) {
|
|
|
203
202
|
body,
|
|
204
203
|
loc,
|
|
205
204
|
};
|
|
206
|
-
|
|
205
|
+
lowerer.liftedFns.push(lifted);
|
|
207
206
|
return {
|
|
208
207
|
kind: "closure",
|
|
209
208
|
fnName,
|
|
@@ -213,7 +212,7 @@ function lowerStreamCallback(L, which, node, thisType, fullTuple) {
|
|
|
213
212
|
};
|
|
214
213
|
}
|
|
215
214
|
finally {
|
|
216
|
-
|
|
215
|
+
lowerer.fnStack.pop();
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
218
|
/** The full Node parameter tuples of the option callbacks, given the
|
|
@@ -221,32 +220,32 @@ function lowerStreamCallback(L, which, node, thisType, fullTuple) {
|
|
|
221
220
|
* whatever func type the checker contextually gave the user's parameter
|
|
222
221
|
* (the emitted adapter constructs a matching closure), so only their
|
|
223
222
|
* FUNC-ness is checked here. */
|
|
224
|
-
function cbTuples(
|
|
223
|
+
function cbTuples(lowerer) {
|
|
225
224
|
return {
|
|
226
225
|
read: [F64],
|
|
227
226
|
write: [BYTES, STRING, "fn"],
|
|
228
227
|
final: ["fn"],
|
|
229
|
-
destroy: [errorOrNull(
|
|
228
|
+
destroy: [errorOrNull(lowerer), "fn"],
|
|
230
229
|
transform: [BYTES, STRING, "fn"],
|
|
231
230
|
flush: ["fn"],
|
|
232
231
|
};
|
|
233
232
|
}
|
|
234
233
|
/** Interns a union from unsorted arms (the interner's identity is the
|
|
235
234
|
* typeKey-SORTED arm list — mapType's canonicalization). */
|
|
236
|
-
function unionOf(
|
|
235
|
+
function unionOf(lowerer, arms) {
|
|
237
236
|
const sorted = [...arms].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
238
|
-
return { kind: "union", unionId:
|
|
237
|
+
return { kind: "union", unionId: lowerer.unions.intern(sorted) };
|
|
239
238
|
}
|
|
240
|
-
function errorOrNull(
|
|
241
|
-
return unionOf(
|
|
239
|
+
function errorOrNull(lowerer) {
|
|
240
|
+
return unionOf(lowerer, [{ kind: "object", className: "%Error" }, { kind: "nullT" }]);
|
|
242
241
|
}
|
|
243
242
|
/** The program's property-mutated symbols (`opts.read = f`, `opts["x"]
|
|
244
243
|
* op= v`, `delete opts.y`): a const-initialized options record whose
|
|
245
244
|
* symbol appears here cannot be followed to its literal — the runtime
|
|
246
245
|
* record and the compile-time walk would split-brain. Built once, lazily
|
|
247
246
|
* (the emitterEvents pre-pass precedent); the scan is diagnostic-free. */
|
|
248
|
-
function propMutatedSymbols(
|
|
249
|
-
const holder =
|
|
247
|
+
function propMutatedSymbols(lowerer) {
|
|
248
|
+
const holder = lowerer;
|
|
250
249
|
if (holder.streamPropMutatedSyms)
|
|
251
250
|
return holder.streamPropMutatedSyms;
|
|
252
251
|
const set = new Set();
|
|
@@ -258,7 +257,7 @@ function propMutatedSymbols(L) {
|
|
|
258
257
|
if (!ts.isIdentifier(base))
|
|
259
258
|
return;
|
|
260
259
|
try {
|
|
261
|
-
const sym =
|
|
260
|
+
const sym = lowerer.resolveValueSymbol(base);
|
|
262
261
|
if (sym)
|
|
263
262
|
set.add(sym);
|
|
264
263
|
}
|
|
@@ -266,7 +265,7 @@ function propMutatedSymbols(L) {
|
|
|
266
265
|
/* not a candidate */
|
|
267
266
|
}
|
|
268
267
|
};
|
|
269
|
-
for (const sf of
|
|
268
|
+
for (const sf of lowerer.program.getSourceFiles()) {
|
|
270
269
|
if (sf.isDeclarationFile)
|
|
271
270
|
continue;
|
|
272
271
|
const walk = (node) => {
|
|
@@ -297,7 +296,7 @@ function propMutatedSymbols(L) {
|
|
|
297
296
|
* (propMutatedSymbols). Returns the argument unchanged when the chain
|
|
298
297
|
* breaks; `undefined`/null arguments answer null (Node's `if (options)`
|
|
299
298
|
* guard — all defaults). */
|
|
300
|
-
function followOptionsArg(
|
|
299
|
+
function followOptionsArg(lowerer, arg) {
|
|
301
300
|
let node = arg;
|
|
302
301
|
for (let hops = 0; node !== undefined && hops < 16; hops++) {
|
|
303
302
|
if (ts.isObjectLiteralExpression(node))
|
|
@@ -314,17 +313,17 @@ function followOptionsArg(L, arg) {
|
|
|
314
313
|
return null;
|
|
315
314
|
let sym;
|
|
316
315
|
try {
|
|
317
|
-
sym =
|
|
316
|
+
sym = lowerer.resolveValueSymbol(node);
|
|
318
317
|
}
|
|
319
318
|
catch {
|
|
320
319
|
return node;
|
|
321
320
|
}
|
|
322
|
-
const decl = sym ?
|
|
321
|
+
const decl = sym ? lowerer.checker.valueDeclarationOf(sym) : undefined;
|
|
323
322
|
if (!sym || !decl || !ts.isVariableDeclaration(decl) || decl.initializer === undefined)
|
|
324
323
|
return node;
|
|
325
324
|
if ((ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0)
|
|
326
325
|
return node;
|
|
327
|
-
if (propMutatedSymbols(
|
|
326
|
+
if (propMutatedSymbols(lowerer).has(sym))
|
|
328
327
|
return node;
|
|
329
328
|
node = decl.initializer;
|
|
330
329
|
}
|
|
@@ -343,32 +342,32 @@ function followOptionsArg(L, arg) {
|
|
|
343
342
|
* calls option callbacks; a value adapted through the dyn boundary is
|
|
344
343
|
* called with `this` undefined (the dyn call ABI carries no receiver) —
|
|
345
344
|
* reference the stream through a lexical binding instead. */
|
|
346
|
-
function lowerStreamCallbackValue(
|
|
345
|
+
function lowerStreamCallbackValue(lowerer, ctorName, which, node, fullLen) {
|
|
347
346
|
const loc = locOf(node);
|
|
348
|
-
const getRecord = (id) =>
|
|
349
|
-
const getUnion = (id) =>
|
|
347
|
+
const getRecord = (id) => lowerer.shapes.get(id);
|
|
348
|
+
const getUnion = (id) => lowerer.unions.get(id);
|
|
350
349
|
let t;
|
|
351
350
|
try {
|
|
352
|
-
const ct =
|
|
353
|
-
t =
|
|
351
|
+
const ct = lowerer.typeOf(node);
|
|
352
|
+
t = lowerer.mapTypeOf(ct) ?? dynFallbackType(lowerer, node, ct);
|
|
354
353
|
}
|
|
355
354
|
catch {
|
|
356
355
|
t = null;
|
|
357
356
|
}
|
|
358
357
|
let cbDyn;
|
|
359
358
|
if (t?.kind === "dyn") {
|
|
360
|
-
const v =
|
|
359
|
+
const v = lowerer.lowerExpr(node);
|
|
361
360
|
cbDyn = v.type.kind === "dyn" ? v : { kind: "dynFrom", value: v, type: DYN, loc };
|
|
362
361
|
}
|
|
363
362
|
else if (t?.kind === "func") {
|
|
364
|
-
const cb =
|
|
363
|
+
const cb = lowerer.lowerExpr(node);
|
|
365
364
|
if (cb.type.kind !== "func" || !canBoxFuncIntoDyn(cb.type, getRecord, getUnion)) {
|
|
366
|
-
|
|
365
|
+
lowerer.noLowering(`the ${ctorName} option '${which}' with a function value of this signature`, node, "a callback value's own parameters and return must cross the checked-dynamic boundary — write the callback inline to keep it fully static");
|
|
367
366
|
}
|
|
368
367
|
cbDyn = { kind: "dynFrom", value: cb, type: DYN, loc };
|
|
369
368
|
}
|
|
370
369
|
else {
|
|
371
|
-
|
|
370
|
+
lowerer.noLowering(`the ${ctorName} option '${which}' with a non-function value`, node, "the callback slot takes an inline function (fully static) or a function value that crosses the checked-dynamic boundary");
|
|
372
371
|
}
|
|
373
372
|
const adapterT = funcOf(Array.from({ length: fullLen }, () => DYN), VOID);
|
|
374
373
|
return { kind: "dynCheck", value: cbDyn, type: adapterT, loc };
|
|
@@ -378,34 +377,34 @@ function lowerStreamCallbackValue(L, ctorName, which, node, fullLen) {
|
|
|
378
377
|
* record's shape is runtime data, so the option walk runs in the runtime
|
|
379
378
|
* (the `.newDyn`/`.initDyn` twins) with Node's own reading rules. Null
|
|
380
379
|
* when the argument is not dyn-flavored (the static walk owns it). */
|
|
381
|
-
function dynOptionsValue(
|
|
382
|
-
const followed = followOptionsArg(
|
|
380
|
+
function dynOptionsValue(lowerer, arg) {
|
|
381
|
+
const followed = followOptionsArg(lowerer, arg);
|
|
383
382
|
if (followed === null || followed === undefined || ts.isObjectLiteralExpression(followed))
|
|
384
383
|
return null;
|
|
385
384
|
let t;
|
|
386
385
|
try {
|
|
387
|
-
const ct =
|
|
388
|
-
t =
|
|
386
|
+
const ct = lowerer.typeOf(followed);
|
|
387
|
+
t = lowerer.mapTypeOf(ct) ?? dynFallbackType(lowerer, followed, ct);
|
|
389
388
|
}
|
|
390
389
|
catch {
|
|
391
390
|
return null;
|
|
392
391
|
}
|
|
393
392
|
if (t?.kind !== "dyn")
|
|
394
393
|
return null;
|
|
395
|
-
const v =
|
|
394
|
+
const v = lowerer.lowerExpr(followed);
|
|
396
395
|
return v.type.kind === "dyn" ? v : null;
|
|
397
396
|
}
|
|
398
397
|
/** Parses the options object literal of a stream constructor. `which`
|
|
399
398
|
* names the callbacks this class accepts, in canonical flag order. */
|
|
400
|
-
function parseStreamOptions(
|
|
399
|
+
function parseStreamOptions(lowerer, ctorName, arg, thisType, accepted, loc,
|
|
401
400
|
/** Subclass construction: the wrapper closure for an overridden
|
|
402
401
|
* underscore method, consulted for callbacks the options did not
|
|
403
402
|
* provide (an options callback shadows the method, Node's instance-
|
|
404
403
|
* property rule). */
|
|
405
404
|
fallbackCb) {
|
|
406
405
|
const out = {
|
|
407
|
-
hwmR:
|
|
408
|
-
hwmW:
|
|
406
|
+
hwmR: numLit(-1, loc),
|
|
407
|
+
hwmW: numLit(-1, loc),
|
|
409
408
|
autoDestroy: boolLit(true, loc),
|
|
410
409
|
emitClose: boolLit(true, loc),
|
|
411
410
|
allowHalfOpen: boolLit(true, loc),
|
|
@@ -417,12 +416,12 @@ fallbackCb) {
|
|
|
417
416
|
flags: 0,
|
|
418
417
|
cbs: [],
|
|
419
418
|
};
|
|
420
|
-
const followed = followOptionsArg(
|
|
419
|
+
const followed = followOptionsArg(lowerer, arg);
|
|
421
420
|
const optsLit = followed === null ? undefined : followed;
|
|
422
421
|
if (optsLit !== undefined && !ts.isObjectLiteralExpression(optsLit)) {
|
|
423
|
-
|
|
422
|
+
lowerer.noLowering(`new ${ctorName} with a non-literal options argument`, optsLit, "the options must be an object literal, inline or through const-initialized bindings (the callbacks lower as compile-time closures)");
|
|
424
423
|
}
|
|
425
|
-
const tuples = cbTuples(
|
|
424
|
+
const tuples = cbTuples(lowerer);
|
|
426
425
|
const present = new Map();
|
|
427
426
|
for (const prop of optsLit?.properties ?? []) {
|
|
428
427
|
const propName = ts.isSpreadAssignment(prop) ? undefined : prop.name;
|
|
@@ -432,7 +431,7 @@ fallbackCb) {
|
|
|
432
431
|
? propName.text
|
|
433
432
|
: null;
|
|
434
433
|
if (name === null) {
|
|
435
|
-
|
|
434
|
+
lowerer.unsupported("SC1090", prop, `computed or spread members in ${ctorName} options`);
|
|
436
435
|
}
|
|
437
436
|
// Callback members: shorthand methods and function-valued properties.
|
|
438
437
|
if (accepted.includes(name)) {
|
|
@@ -453,54 +452,54 @@ fallbackCb) {
|
|
|
453
452
|
? prop.name
|
|
454
453
|
: null;
|
|
455
454
|
if (valueNode === null) {
|
|
456
|
-
|
|
455
|
+
lowerer.noLowering(`the ${ctorName} option '${name}' as this member form`, prop, "write the callback inline (method shorthand or an inline function/arrow), or pass a function value");
|
|
457
456
|
}
|
|
458
|
-
present.set(name, lowerStreamCallbackValue(
|
|
457
|
+
present.set(name, lowerStreamCallbackValue(lowerer, ctorName, name, valueNode, tuples[name].length));
|
|
459
458
|
continue;
|
|
460
459
|
}
|
|
461
460
|
const full = tuples[name].map((t) => (t === "fn" ? null : t));
|
|
462
461
|
// The completion-callback tail: typed by the checker contextually;
|
|
463
462
|
// accept the user's declared func type as the tuple's entry so the
|
|
464
463
|
// prefix check compares like with like.
|
|
465
|
-
const { funcType } =
|
|
464
|
+
const { funcType } = lowerer.lambdaSignature(fnNode);
|
|
466
465
|
const tuple = full.map((t, i) => {
|
|
467
466
|
if (t !== null)
|
|
468
467
|
return t;
|
|
469
468
|
const declared = funcType.params[i];
|
|
470
469
|
if (declared !== undefined && declared.kind !== "func" && declared.kind !== "dyn") {
|
|
471
|
-
|
|
470
|
+
lowerer.noLowering(`a '${name}' callback whose parameter ${i} is '${lowerer.fmt(declared)}' where Node passes the completion callback`, fnNode);
|
|
472
471
|
}
|
|
473
472
|
return declared ?? funcOf([], VOID);
|
|
474
473
|
});
|
|
475
|
-
present.set(name, lowerStreamCallback(
|
|
474
|
+
present.set(name, lowerStreamCallback(lowerer, name, fnNode, thisType, tuple));
|
|
476
475
|
continue;
|
|
477
476
|
}
|
|
478
477
|
// Scalar options.
|
|
479
478
|
if (!ts.isPropertyAssignment(prop)) {
|
|
480
|
-
|
|
479
|
+
lowerer.unsupported("SC1090", prop, `the ${ctorName} option '${name}' as a shorthand/method member`);
|
|
481
480
|
}
|
|
482
481
|
const value = prop.initializer;
|
|
483
482
|
switch (name) {
|
|
484
483
|
case "highWaterMark": {
|
|
485
|
-
const v =
|
|
484
|
+
const v = lowerer.lowerExprExpecting(value, F64);
|
|
486
485
|
out.hwmR = v;
|
|
487
486
|
out.hwmW = v;
|
|
488
487
|
break;
|
|
489
488
|
}
|
|
490
489
|
case "readableHighWaterMark":
|
|
491
|
-
out.hwmR =
|
|
490
|
+
out.hwmR = lowerer.lowerExprExpecting(value, F64);
|
|
492
491
|
break;
|
|
493
492
|
case "writableHighWaterMark":
|
|
494
|
-
out.hwmW =
|
|
493
|
+
out.hwmW = lowerer.lowerExprExpecting(value, F64);
|
|
495
494
|
break;
|
|
496
495
|
case "autoDestroy":
|
|
497
|
-
out.autoDestroy =
|
|
496
|
+
out.autoDestroy = lowerer.lowerExprExpecting(value, BOOL);
|
|
498
497
|
break;
|
|
499
498
|
case "emitClose":
|
|
500
|
-
out.emitClose =
|
|
499
|
+
out.emitClose = lowerer.lowerExprExpecting(value, BOOL);
|
|
501
500
|
break;
|
|
502
501
|
case "allowHalfOpen":
|
|
503
|
-
out.allowHalfOpen =
|
|
502
|
+
out.allowHalfOpen = lowerer.lowerExprExpecting(value, BOOL);
|
|
504
503
|
break;
|
|
505
504
|
case "objectMode":
|
|
506
505
|
case "readableObjectMode":
|
|
@@ -508,13 +507,13 @@ fallbackCb) {
|
|
|
508
507
|
// `objectMode: false` is the byte default — admit the literal.
|
|
509
508
|
if (value.kind === ts.SyntaxKind.FalseKeyword)
|
|
510
509
|
break;
|
|
511
|
-
|
|
510
|
+
lowerer.noLowering(`${ctorName} in objectMode`, prop, "object-mode streams have no static chunk type yet — chunks are Buffers (utf8 strings convert at push/write)");
|
|
512
511
|
break;
|
|
513
512
|
}
|
|
514
513
|
case "decodeStrings": {
|
|
515
514
|
if (value.kind === ts.SyntaxKind.TrueKeyword)
|
|
516
515
|
break; // Node's default
|
|
517
|
-
|
|
516
|
+
lowerer.noLowering(`${ctorName} with decodeStrings: false`, prop, "chunks always decode to Buffers here (Node's default)");
|
|
518
517
|
break;
|
|
519
518
|
}
|
|
520
519
|
case "encoding": {
|
|
@@ -523,15 +522,15 @@ fallbackCb) {
|
|
|
523
522
|
// spelling Node does not know is Node's RUNTIME rejection —
|
|
524
523
|
// ERR_UNKNOWN_ENCODING at construction, not a compile fence.
|
|
525
524
|
if (ctorName === "Writable")
|
|
526
|
-
|
|
525
|
+
lowerer.noLowering(`the Writable option 'encoding'`, prop);
|
|
527
526
|
{
|
|
528
|
-
const t =
|
|
527
|
+
const t = lowerer.typeOf(value);
|
|
529
528
|
if (t.isStringLiteralType() && knownBufEncoding(t.value) === undefined) {
|
|
530
529
|
out.badEncoding = t.value;
|
|
531
530
|
break;
|
|
532
531
|
}
|
|
533
532
|
}
|
|
534
|
-
out.encoding = bufEncoding(
|
|
533
|
+
out.encoding = bufEncoding(lowerer, `the ${ctorName} option 'encoding'`, value);
|
|
535
534
|
break;
|
|
536
535
|
}
|
|
537
536
|
case "defaultEncoding":
|
|
@@ -543,7 +542,7 @@ fallbackCb) {
|
|
|
543
542
|
// readable.pushEncoding. The write-side meaning (what
|
|
544
543
|
// write(string) does) stays fenced on the writable classes.
|
|
545
544
|
{
|
|
546
|
-
const t =
|
|
545
|
+
const t = lowerer.typeOf(value);
|
|
547
546
|
if (t.isStringLiteralType() && (t.value === "utf8" || t.value === "utf-8"))
|
|
548
547
|
break;
|
|
549
548
|
if (t.isStringLiteralType() && knownBufEncoding(t.value) === undefined) {
|
|
@@ -555,10 +554,10 @@ fallbackCb) {
|
|
|
555
554
|
break;
|
|
556
555
|
}
|
|
557
556
|
}
|
|
558
|
-
|
|
557
|
+
lowerer.noLowering(`the ${ctorName} option 'defaultEncoding'`, prop, "utf8 (the default) is the supported write-side string encoding");
|
|
559
558
|
break;
|
|
560
559
|
case "signal":
|
|
561
|
-
|
|
560
|
+
lowerer.noLowering(`the ${ctorName} option 'signal'`, prop, "AbortSignal-driven destruction is not lowered yet");
|
|
562
561
|
break;
|
|
563
562
|
case "captureRejections": {
|
|
564
563
|
// `false` is the default — admit the literal; the rejection-
|
|
@@ -566,7 +565,7 @@ fallbackCb) {
|
|
|
566
565
|
// abandoned unobserved).
|
|
567
566
|
if (value.kind === ts.SyntaxKind.FalseKeyword)
|
|
568
567
|
break;
|
|
569
|
-
|
|
568
|
+
lowerer.noLowering(`the ${ctorName} option 'captureRejections'`, prop, "captureRejections has no lowering (listener rejections are not routed to 'error')");
|
|
570
569
|
break;
|
|
571
570
|
}
|
|
572
571
|
case "readable":
|
|
@@ -574,7 +573,7 @@ fallbackCb) {
|
|
|
574
573
|
// Duplex side toggles: compile-time literals only (they decide
|
|
575
574
|
// which halves EXIST).
|
|
576
575
|
if (ctorName !== "Duplex") {
|
|
577
|
-
|
|
576
|
+
lowerer.noLowering(`the ${ctorName} option '${name}'`, prop);
|
|
578
577
|
}
|
|
579
578
|
if (value.kind === ts.SyntaxKind.TrueKeyword)
|
|
580
579
|
break;
|
|
@@ -585,23 +584,23 @@ fallbackCb) {
|
|
|
585
584
|
out.writableSide = false;
|
|
586
585
|
break;
|
|
587
586
|
}
|
|
588
|
-
|
|
587
|
+
lowerer.noLowering(`the Duplex option '${name}' with a non-literal value`, prop, "the side toggles must be compile-time booleans");
|
|
589
588
|
break;
|
|
590
589
|
}
|
|
591
590
|
case "final": {
|
|
592
|
-
|
|
591
|
+
lowerer.noLowering(`the ${ctorName} option 'final'`, prop, ctorName === "Transform"
|
|
593
592
|
? "a user final on a Transform replaces the _flush composition — no lowering yet"
|
|
594
593
|
: "the final callback is supported on Writable and Duplex");
|
|
595
594
|
break;
|
|
596
595
|
}
|
|
597
596
|
case "construct":
|
|
598
|
-
|
|
597
|
+
lowerer.noLowering(`the ${ctorName} option 'construct'`, prop, "deferred construction (_construct) is not lowered yet");
|
|
599
598
|
break;
|
|
600
599
|
case "writev":
|
|
601
|
-
|
|
600
|
+
lowerer.noLowering(`the ${ctorName} option 'writev'`, prop, "batched writes (_writev) are not lowered yet — writes deliver one chunk at a time");
|
|
602
601
|
break;
|
|
603
602
|
default:
|
|
604
|
-
|
|
603
|
+
lowerer.noLowering(`the ${ctorName} option '${name}'`, prop);
|
|
605
604
|
}
|
|
606
605
|
}
|
|
607
606
|
// Canonical flag order = the accepted list's order. Options win over
|
|
@@ -619,35 +618,35 @@ fallbackCb) {
|
|
|
619
618
|
/** The head + flags argument list of a stream construction/initialization
|
|
620
619
|
* (shared by `new Readable({...})` and a subclass's super(options)),
|
|
621
620
|
* plus the parsed `encoding` option (applied as a follow-up setEncoding). */
|
|
622
|
-
function streamCtorArgs(
|
|
621
|
+
function streamCtorArgs(lowerer, cls, arg, thisType, loc, fallbackCb) {
|
|
623
622
|
const shape = streamCtorShape(cls);
|
|
624
|
-
const o = parseStreamOptions(
|
|
623
|
+
const o = parseStreamOptions(lowerer, cls.slice(1), arg, thisType, shape.accepted, loc, fallbackCb);
|
|
625
624
|
const head = shape.duplexShape
|
|
626
625
|
? [o.hwmR, o.hwmW, o.autoDestroy, o.emitClose, o.allowHalfOpen,
|
|
627
|
-
boolLit(o.readableSide, loc), boolLit(o.writableSide, loc),
|
|
628
|
-
: [cls === "%Writable" ? o.hwmW : o.hwmR, o.autoDestroy, o.emitClose,
|
|
626
|
+
boolLit(o.readableSide, loc), boolLit(o.writableSide, loc), numLit(o.flags, loc)]
|
|
627
|
+
: [cls === "%Writable" ? o.hwmW : o.hwmR, o.autoDestroy, o.emitClose, numLit(o.flags, loc)];
|
|
629
628
|
return { args: [...head, ...o.cbs], encoding: o.encoding, badEncoding: o.badEncoding, pushEncoding: o.pushEncoding };
|
|
630
629
|
}
|
|
631
630
|
/** `new Readable(opts?)` and friends — called from lowerNew once the
|
|
632
631
|
* callee resolved to a builtin stream class. */
|
|
633
|
-
export function lowerStreamNew(
|
|
632
|
+
export function lowerStreamNew(lowerer, expr, info) {
|
|
634
633
|
const loc = locOf(expr);
|
|
635
634
|
const cls = info.def.name;
|
|
636
635
|
if (!RUNTIME_STREAM_CLASSES.has(cls))
|
|
637
|
-
|
|
636
|
+
lowerer.unsupported("SC1090", expr, `constructing ${cls}`);
|
|
638
637
|
const thisType = { kind: "object", className: cls };
|
|
639
638
|
const args = expr.arguments ?? [];
|
|
640
639
|
if (args.length > 1) {
|
|
641
|
-
|
|
640
|
+
lowerer.noLowering(`new ${info.def.name.slice(1)} with ${args.length} arguments`, expr, "the supported form takes one options object");
|
|
642
641
|
}
|
|
643
642
|
if (args[0] !== undefined) {
|
|
644
|
-
const dynOpts = dynOptionsValue(
|
|
643
|
+
const dynOpts = dynOptionsValue(lowerer, args[0]);
|
|
645
644
|
if (dynOpts !== null) {
|
|
646
645
|
return { kind: "libCall", fn: `${streamCtorShape(cls).fn}.newDyn`, args: [dynOpts], type: thisType, loc };
|
|
647
646
|
}
|
|
648
647
|
}
|
|
649
648
|
const fn = `${streamCtorShape(cls).fn}.new`;
|
|
650
|
-
const parsed = streamCtorArgs(
|
|
649
|
+
const parsed = streamCtorArgs(lowerer, cls, args[0], thisType, loc);
|
|
651
650
|
if (parsed.badEncoding !== null) {
|
|
652
651
|
// Node's state constructors validate encodings first: an unknown
|
|
653
652
|
// spelling never constructs — the whole expression throws.
|
|
@@ -672,14 +671,14 @@ export function lowerStreamNew(L, expr, info) {
|
|
|
672
671
|
* overrides it (the ordinary devirtualization rule), so an inherited
|
|
673
672
|
* constructor still binds the DYNAMIC class's override. The method may
|
|
674
673
|
* declare any PREFIX of its Node signature (the option-callback rule). */
|
|
675
|
-
function streamMethodWrapper(
|
|
676
|
-
const found =
|
|
674
|
+
function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, blame) {
|
|
675
|
+
const found = lowerer.findMethodOn(info, methodName);
|
|
677
676
|
if (!found) {
|
|
678
677
|
// A DESCENDANT-only declaration (the base chain never declares it):
|
|
679
678
|
// this constructor cannot see it, and silently binding nothing would
|
|
680
679
|
// diverge from Node (which dispatches through the prototype chain).
|
|
681
|
-
if (
|
|
682
|
-
|
|
680
|
+
if (lowerer.overrideBelow(info, methodName)) {
|
|
681
|
+
lowerer.noLowering(`a subclass of ${info.def.name.replace(/^%/, "")} declaring '${methodName}' below a base whose constructor cannot see it`, blame, `declare '${methodName}' on the class whose constructor calls the stream super(), and override it below`);
|
|
683
682
|
}
|
|
684
683
|
return null;
|
|
685
684
|
}
|
|
@@ -688,22 +687,22 @@ function streamMethodWrapper(L, info, which, methodName, thisType, loc, blame) {
|
|
|
688
687
|
// class itself is abstract, so this constructor only ever runs under a
|
|
689
688
|
// subclass — which, if concrete, implements the method and flips
|
|
690
689
|
// overrideBelow into the virtual branch below).
|
|
691
|
-
if (found.sig.abstract === true && !
|
|
692
|
-
|
|
690
|
+
if (found.sig.abstract === true && !lowerer.overrideBelow(info, methodName)) {
|
|
691
|
+
lowerer.noLowering(`an abstract '${methodName}' declaration with no concrete implementation below ${info.def.name.replace(/^%/, "")}`, blame, `implement '${methodName}' on a subclass the program constructs`);
|
|
693
692
|
return null;
|
|
694
693
|
}
|
|
695
|
-
const tuples = cbTuples(
|
|
694
|
+
const tuples = cbTuples(lowerer);
|
|
696
695
|
const full = tuples[which];
|
|
697
696
|
const declared = found.sig.params;
|
|
698
697
|
if (declared.length > full.length) {
|
|
699
|
-
|
|
698
|
+
lowerer.noLowering(`a '${methodName}' method declaring ${declared.length} parameters where Node passes ${full.length}`, blame, "stream underscore methods may declare a prefix of their Node signature");
|
|
700
699
|
}
|
|
701
700
|
const paramTypes = [];
|
|
702
701
|
for (let i = 0; i < declared.length; i++) {
|
|
703
702
|
const want = full[i];
|
|
704
703
|
const got = declared[i];
|
|
705
704
|
if (got.mode !== "required") {
|
|
706
|
-
|
|
705
|
+
lowerer.noLowering(`a '${methodName}' method with optional or defaulted parameters`, blame, "declare the Node signature's parameters plainly (any prefix is fine)");
|
|
707
706
|
}
|
|
708
707
|
if (got.type.kind === "dyn") {
|
|
709
708
|
// The JS lane's implicitly-any parameters: the emitted invoke
|
|
@@ -711,39 +710,39 @@ function streamMethodWrapper(L, info, which, methodName, thisType, loc, blame) {
|
|
|
711
710
|
}
|
|
712
711
|
else if (want === "fn") {
|
|
713
712
|
if (got.type.kind !== "func") {
|
|
714
|
-
|
|
713
|
+
lowerer.noLowering(`a '${methodName}' method whose parameter ${i} is '${lowerer.fmt(got.type)}' where Node passes the completion callback`, blame);
|
|
715
714
|
}
|
|
716
715
|
}
|
|
717
716
|
else if (!typeEquals(got.type, want)) {
|
|
718
|
-
|
|
717
|
+
lowerer.noLowering(`a '${methodName}' method whose parameter ${i} is '${lowerer.fmt(got.type)}' where Node passes '${lowerer.fmt(want)}'`, blame, "annotate the parameter with the Node signature's type (chunks are Buffers here)");
|
|
719
718
|
}
|
|
720
719
|
paramTypes.push(got.type);
|
|
721
720
|
}
|
|
722
721
|
const ret = found.sig.ret;
|
|
723
|
-
const fnName = `%fn${
|
|
722
|
+
const fnName = `%fn${lowerer.lambdaCounter++}_${which}vt`;
|
|
724
723
|
const funcType = funcOf([thisType, ...paramTypes], ret);
|
|
725
|
-
|
|
724
|
+
lowerer.fnStack.push(newFnCtx(true, null, funcType, ret));
|
|
726
725
|
try {
|
|
727
|
-
const thisLocal =
|
|
726
|
+
const thisLocal = lowerer.declareThis(thisType);
|
|
728
727
|
const params = [{ localId: thisLocal.id, name: "this", type: thisType }];
|
|
729
728
|
const argRefs = [];
|
|
730
729
|
for (let i = 0; i < paramTypes.length; i++) {
|
|
731
|
-
const local =
|
|
730
|
+
const local = lowerer.declareHiddenLocal(`a${i}`, paramTypes[i]);
|
|
732
731
|
params.push({ localId: local.id, name: local.name, type: paramTypes[i] });
|
|
733
732
|
argRefs.push({ kind: "varRef", localId: local.id, type: paramTypes[i], loc });
|
|
734
733
|
}
|
|
735
734
|
const thisRef = { kind: "varRef", localId: thisLocal.id, type: thisType, loc };
|
|
736
735
|
let call;
|
|
737
|
-
if (
|
|
738
|
-
|
|
736
|
+
if (lowerer.overrideBelow(info, methodName)) {
|
|
737
|
+
lowerer.noteVirtualEdge(info, methodName);
|
|
739
738
|
call = { kind: "virtualCall", className: info.def.name, method: methodName, args: [thisRef, ...argRefs], type: ret, loc };
|
|
740
739
|
}
|
|
741
740
|
else {
|
|
742
|
-
|
|
741
|
+
lowerer.noteEdge(`%${found.declarer.def.name}.${methodName}`);
|
|
743
742
|
call = {
|
|
744
743
|
kind: "call",
|
|
745
744
|
callee: `%${found.declarer.def.name}.${methodName}`,
|
|
746
|
-
args: [
|
|
745
|
+
args: [lowerer.upcastTo(thisRef, found.declarer.def.name), ...argRefs],
|
|
747
746
|
type: ret,
|
|
748
747
|
loc,
|
|
749
748
|
};
|
|
@@ -751,9 +750,9 @@ function streamMethodWrapper(L, info, which, methodName, thisType, loc, blame) {
|
|
|
751
750
|
const body = ret.kind === "void"
|
|
752
751
|
? [{ kind: "exprStmt", expr: call, loc }]
|
|
753
752
|
: [{ kind: "return", value: call, loc }];
|
|
754
|
-
appendImplicitUndefinedReturn(
|
|
755
|
-
const ctx =
|
|
756
|
-
|
|
753
|
+
appendImplicitUndefinedReturn(lowerer, body, ret, loc);
|
|
754
|
+
const ctx = lowerer.ctx;
|
|
755
|
+
lowerer.liftedFns.push({
|
|
757
756
|
name: fnName,
|
|
758
757
|
params,
|
|
759
758
|
returnType: ret,
|
|
@@ -765,7 +764,7 @@ function streamMethodWrapper(L, info, which, methodName, thisType, loc, blame) {
|
|
|
765
764
|
return { kind: "closure", fnName, captures: ctx.captureSources, type: funcType, loc };
|
|
766
765
|
}
|
|
767
766
|
finally {
|
|
768
|
-
|
|
767
|
+
lowerer.fnStack.pop();
|
|
769
768
|
}
|
|
770
769
|
}
|
|
771
770
|
/** `super(options?)` in a class whose direct base chain lands on a
|
|
@@ -774,20 +773,20 @@ function streamMethodWrapper(L, info, which, methodName, thisType, loc, blame) {
|
|
|
774
773
|
* display name; the runtime builds the state block). Options parse
|
|
775
774
|
* exactly like the construction form; overridden underscore methods on
|
|
776
775
|
* the class chain fill callbacks the options leave unset. */
|
|
777
|
-
export function lowerStreamSuperCall(
|
|
776
|
+
export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, loc, blame) {
|
|
778
777
|
const cls = base.def.name;
|
|
779
778
|
const thisType = { kind: "object", className: info.def.name };
|
|
780
779
|
if (argNodes.length > 1) {
|
|
781
|
-
|
|
780
|
+
lowerer.noLowering(`super(...) with ${argNodes.length} arguments in a ${cls.slice(1)} subclass`, blame, "the supported form takes one inline options object (or none)");
|
|
782
781
|
}
|
|
783
782
|
const shape = streamCtorShape(cls);
|
|
784
783
|
const fallback = (name) => {
|
|
785
784
|
const methodName = UNDERSCORE_METHODS.get(name);
|
|
786
|
-
return methodName ? streamMethodWrapper(
|
|
785
|
+
return methodName ? streamMethodWrapper(lowerer, info, name, methodName, thisType, loc, blame) : null;
|
|
787
786
|
};
|
|
788
787
|
const thisRef = () => ({ kind: "varRef", localId: thisLocal.id, type: thisType, loc });
|
|
789
788
|
if (argNodes[0] !== undefined) {
|
|
790
|
-
const dynOpts = dynOptionsValue(
|
|
789
|
+
const dynOpts = dynOptionsValue(lowerer, argNodes[0]);
|
|
791
790
|
if (dynOpts !== null) {
|
|
792
791
|
// The dyn-options twin: the runtime walks the record; the class's
|
|
793
792
|
// overridden underscore methods ride as FALLBACK wrappers (an
|
|
@@ -806,7 +805,7 @@ export function lowerStreamSuperCall(L, info, base, argNodes, thisLocal, loc, bl
|
|
|
806
805
|
expr: {
|
|
807
806
|
kind: "libCall",
|
|
808
807
|
fn: `${shape.fn}.initDyn`,
|
|
809
|
-
args: [thisRef(), dynOpts,
|
|
808
|
+
args: [thisRef(), dynOpts, numLit(flags, loc), ...cbs],
|
|
810
809
|
type: VOID,
|
|
811
810
|
loc,
|
|
812
811
|
},
|
|
@@ -814,7 +813,7 @@ export function lowerStreamSuperCall(L, info, base, argNodes, thisLocal, loc, bl
|
|
|
814
813
|
}];
|
|
815
814
|
}
|
|
816
815
|
}
|
|
817
|
-
const parsed = streamCtorArgs(
|
|
816
|
+
const parsed = streamCtorArgs(lowerer, cls, argNodes[0], thisType, loc, fallback);
|
|
818
817
|
if (parsed.badEncoding !== null) {
|
|
819
818
|
// super(options) with an unknown literal encoding: the state ctor
|
|
820
819
|
// rejects before any initialization, Node's ladder.
|
|
@@ -859,7 +858,7 @@ export function lowerStreamSuperCall(L, info, base, argNodes, thisLocal, loc, bl
|
|
|
859
858
|
* runtime-stream-rooted receiver (the caller's routes continue);
|
|
860
859
|
* `_writev` and methods outside the receiver's base set keep pointed
|
|
861
860
|
* fences (Node would consume them through unlowered machinery). */
|
|
862
|
-
export function lowerStreamUnderscoreAssign(
|
|
861
|
+
export function lowerStreamUnderscoreAssign(lowerer, expr) {
|
|
863
862
|
if (!ts.isPropertyAccessExpression(expr.left) || expr.left.questionDotToken)
|
|
864
863
|
return null;
|
|
865
864
|
const methodName = expr.left.name.text;
|
|
@@ -868,10 +867,10 @@ export function lowerStreamUnderscoreAssign(L, expr) {
|
|
|
868
867
|
const optionByMethod = new Map(Array.from(UNDERSCORE_METHODS, ([o, m]) => [m, o]));
|
|
869
868
|
if (!optionByMethod.has(methodName) && methodName !== "_writev" && methodName !== "_construct")
|
|
870
869
|
return null;
|
|
871
|
-
const recv = probeLower(
|
|
870
|
+
const recv = probeLower(lowerer, expr.left.expression);
|
|
872
871
|
if (!recv || recv.type.kind !== "object")
|
|
873
872
|
return null;
|
|
874
|
-
const info =
|
|
873
|
+
const info = lowerer.classes.get(recv.type.className);
|
|
875
874
|
let base = null;
|
|
876
875
|
for (let c = info ?? null; c; c = c.base) {
|
|
877
876
|
if (RUNTIME_STREAM_CLASSES.has(c.def.name)) {
|
|
@@ -885,35 +884,35 @@ export function lowerStreamUnderscoreAssign(L, expr) {
|
|
|
885
884
|
const cls = base.def.name;
|
|
886
885
|
const clsName = cls.slice(1);
|
|
887
886
|
if (methodName === "_writev" || methodName === "_construct") {
|
|
888
|
-
|
|
887
|
+
lowerer.noLowering(`assigning '${methodName}' on a ${clsName}`, expr.left, methodName === "_writev"
|
|
889
888
|
? "batched writes (_writev) are not lowered yet — writes deliver one chunk at a time"
|
|
890
889
|
: "deferred construction (_construct) is not lowered yet");
|
|
891
890
|
}
|
|
892
891
|
const which = optionByMethod.get(methodName);
|
|
893
892
|
const { accepted } = streamCtorShape(cls);
|
|
894
893
|
if (!accepted.includes(which)) {
|
|
895
|
-
|
|
894
|
+
lowerer.noLowering(`assigning '${methodName}' on a ${clsName}`, expr.left, `a ${clsName}'s machinery consumes ${accepted.map((a) => `'${UNDERSCORE_METHODS.get(a)}'`).join("/")} — '${methodName}' would ride machinery with no lowering here`);
|
|
896
895
|
}
|
|
897
896
|
const thisType = recv.type;
|
|
898
|
-
const tuples = cbTuples(
|
|
897
|
+
const tuples = cbTuples(lowerer);
|
|
899
898
|
let cb;
|
|
900
899
|
const rhs = expr.right;
|
|
901
900
|
if (ts.isFunctionExpression(rhs) || ts.isArrowFunction(rhs)) {
|
|
902
901
|
const full = tuples[which].map((t) => (t === "fn" ? null : t));
|
|
903
|
-
const { funcType } =
|
|
902
|
+
const { funcType } = lowerer.lambdaSignature(rhs);
|
|
904
903
|
const tuple = full.map((t, i) => {
|
|
905
904
|
if (t !== null)
|
|
906
905
|
return t;
|
|
907
906
|
const declared = funcType.params[i];
|
|
908
907
|
if (declared !== undefined && declared.kind !== "func" && declared.kind !== "dyn") {
|
|
909
|
-
|
|
908
|
+
lowerer.noLowering(`a '${methodName}' callback whose parameter ${i} is '${lowerer.fmt(declared)}' where Node passes the completion callback`, rhs);
|
|
910
909
|
}
|
|
911
910
|
return declared ?? funcOf([], VOID);
|
|
912
911
|
});
|
|
913
|
-
cb = lowerStreamCallback(
|
|
912
|
+
cb = lowerStreamCallback(lowerer, which, rhs, thisType, tuple);
|
|
914
913
|
}
|
|
915
914
|
else {
|
|
916
|
-
cb = lowerStreamCallbackValue(
|
|
915
|
+
cb = lowerStreamCallbackValue(lowerer, clsName, which, rhs, tuples[which].length);
|
|
917
916
|
}
|
|
918
917
|
const SET_FNS = {
|
|
919
918
|
read: "stream.setRead",
|
|
@@ -936,22 +935,22 @@ export function lowerStreamUnderscoreAssign(L, expr) {
|
|
|
936
935
|
* accounting; hwm 1), and a single string/Buffer argument is a
|
|
937
936
|
* one-chunk stream (Node's special case). Called from the method-call
|
|
938
937
|
* chain once the receiver resolved to a stream class value. */
|
|
939
|
-
export function lowerStreamStaticCall(
|
|
938
|
+
export function lowerStreamStaticCall(lowerer, call, access) {
|
|
940
939
|
if (call.questionDotToken || access.questionDotToken)
|
|
941
940
|
return null;
|
|
942
941
|
let symbol = null;
|
|
943
942
|
if (ts.isIdentifier(access.expression)) {
|
|
944
|
-
symbol =
|
|
943
|
+
symbol = lowerer.resolveValueSymbol(access.expression);
|
|
945
944
|
}
|
|
946
945
|
else if (ts.isPropertyAccessExpression(access.expression) && ts.isIdentifier(access.expression.name)) {
|
|
947
|
-
const memberSym =
|
|
946
|
+
const memberSym = lowerer.checker.getSymbolAtLocation(access.expression.name);
|
|
948
947
|
symbol = memberSym && memberSym.flags & ts.SymbolFlags.Alias
|
|
949
|
-
?
|
|
948
|
+
? lowerer.checker.getAliasedSymbol(memberSym)
|
|
950
949
|
: memberSym;
|
|
951
950
|
}
|
|
952
951
|
if (!symbol)
|
|
953
952
|
return null;
|
|
954
|
-
const info =
|
|
953
|
+
const info = lowerer.builtinStreamInfoOf(symbol);
|
|
955
954
|
if (!info)
|
|
956
955
|
return null;
|
|
957
956
|
const member = access.name.text;
|
|
@@ -964,39 +963,39 @@ export function lowerStreamStaticCall(L, call, access) {
|
|
|
964
963
|
isJsSourceFile(call.getSourceFile()) && ts.isObjectLiteralExpression(call.arguments[1])) {
|
|
965
964
|
for (const p of call.arguments[1].properties) {
|
|
966
965
|
if (ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "type") {
|
|
967
|
-
const t =
|
|
966
|
+
const t = lowerer.typeOf(p.initializer);
|
|
968
967
|
if (t.isStringLiteralType() && t.value !== "bytes") {
|
|
969
|
-
|
|
970
|
-
return nodeThrowExpr(1, "ERR_INVALID_ARG_VALUE", `The property 'options.type' must be one of: 'bytes', undefined. Received '${t.value}'`,
|
|
968
|
+
lowerer.lowerExpr(call.arguments[0]); // evaluation order (the stream argument)
|
|
969
|
+
return nodeThrowExpr(1, "ERR_INVALID_ARG_VALUE", `The property 'options.type' must be one of: 'bytes', undefined. Received '${t.value}'`, lowerer.mapTypeOf(lowerer.typeOf(call)) ?? DYN, loc);
|
|
971
970
|
}
|
|
972
971
|
}
|
|
973
972
|
}
|
|
974
973
|
}
|
|
975
974
|
if (member !== "from") {
|
|
976
|
-
|
|
975
|
+
lowerer.noLowering(`${cls.slice(1)}.${member}`, call);
|
|
977
976
|
}
|
|
978
977
|
if (cls !== "%Readable") {
|
|
979
|
-
|
|
978
|
+
lowerer.noLowering(`${cls.slice(1)}.from`, call, "Readable.from is the lowered form");
|
|
980
979
|
}
|
|
981
980
|
const args = call.arguments;
|
|
982
981
|
if (args.length !== 1) {
|
|
983
|
-
|
|
982
|
+
lowerer.noLowering(`Readable.from with ${args.length} arguments`, call, "the one-argument form (an array, string, or Buffer) is supported");
|
|
984
983
|
}
|
|
985
|
-
const srcT =
|
|
984
|
+
const srcT = lowerer.mapTypeOf(lowerer.typeOf(args[0]));
|
|
986
985
|
const type = { kind: "object", className: "%Readable" };
|
|
987
986
|
if (srcT?.kind === "array" && (srcT.elem.kind === "string" || (srcT.elem.kind === "bytes" && srcT.elem.elem === "u8"))) {
|
|
988
|
-
const arr =
|
|
987
|
+
const arr = lowerer.lowerExpr(args[0]);
|
|
989
988
|
const strings = srcT.elem.kind === "string";
|
|
990
989
|
return { kind: "libCall", fn: "readable.fromArr", args: [arr, boolLit(strings, loc)], type, loc };
|
|
991
990
|
}
|
|
992
991
|
if (srcT?.kind === "string" || (srcT?.kind === "bytes" && srcT.elem === "u8")) {
|
|
993
992
|
// Node special-cases a single string/Buffer: ONE whole chunk.
|
|
994
|
-
const v =
|
|
993
|
+
const v = lowerer.lowerExpr(args[0]);
|
|
995
994
|
const strings = srcT.kind === "string";
|
|
996
995
|
const arr = { kind: "arrayLit", elems: [v], type: arrayOf(v.type), loc };
|
|
997
996
|
return { kind: "libCall", fn: "readable.fromArr", args: [arr, boolLit(strings, loc)], type, loc };
|
|
998
997
|
}
|
|
999
|
-
|
|
998
|
+
lowerer.noLowering(`Readable.from over a '${srcT ? lowerer.fmt(srcT) : "?"}' source`, args[0], "string[] / Buffer[] arrays (and a single string or Buffer) are the supported sources — generators and async iterables have no lowering yet");
|
|
1000
999
|
}
|
|
1001
1000
|
/** `const Writable = stream.Writable` — a runtime stream CLASS bound
|
|
1002
1001
|
* through a namespace member: alias plumbing with no storage (both
|
|
@@ -1004,7 +1003,7 @@ export function lowerStreamStaticCall(L, call, access) {
|
|
|
1004
1003
|
* alias following). Only the five stream class names count — value
|
|
1005
1004
|
* members (stream.getDefaultHighWaterMark as a value, ...) keep their
|
|
1006
1005
|
* per-site fences. */
|
|
1007
|
-
export function streamClassAliasDecl(
|
|
1006
|
+
export function streamClassAliasDecl(lowerer, nameNode, init) {
|
|
1008
1007
|
if (!ts.isIdentifier(nameNode) || !init)
|
|
1009
1008
|
return false;
|
|
1010
1009
|
if (!ts.isPropertyAccessExpression(init) || init.questionDotToken)
|
|
@@ -1016,7 +1015,7 @@ export function streamClassAliasDecl(L, nameNode, init) {
|
|
|
1016
1015
|
}
|
|
1017
1016
|
if (!isStreamClass)
|
|
1018
1017
|
return false;
|
|
1019
|
-
return
|
|
1018
|
+
return lowerer.builtinNamespaceModuleOf(init.expression) === "stream";
|
|
1020
1019
|
}
|
|
1021
1020
|
/* ── the module functions (finished / pipeline — the callback forms) ──── */
|
|
1022
1021
|
/** Node's pipeline stage ladder text (lib/internal/streams/pipeline.js's
|
|
@@ -1029,10 +1028,10 @@ const PIPELINE_STAGE_EXPECTED = "of type function or an instance of Blob, Readab
|
|
|
1029
1028
|
* isNodeStream, while pipeline() accepts iterables (strings, arrays) and
|
|
1030
1029
|
* { readable, writable } pairs — those shapes fence instead of throwing
|
|
1031
1030
|
* a ladder Node never throws. */
|
|
1032
|
-
function lowerStreamArg(
|
|
1033
|
-
const v =
|
|
1034
|
-
const info = v.type.kind === "object" ?
|
|
1035
|
-
if (!streamSidesOf(
|
|
1031
|
+
function lowerStreamArg(lowerer, node, what) {
|
|
1032
|
+
const v = lowerer.lowerExpr(node);
|
|
1033
|
+
const info = v.type.kind === "object" ? lowerer.classes.get(v.type.className) : undefined;
|
|
1034
|
+
if (!streamSidesOf(lowerer, info)) {
|
|
1036
1035
|
// A provably-non-stream value in a JS source (the invalid-input
|
|
1037
1036
|
// probes: finished({}, cb), pipeline(42, dst, cb)): Node's gate
|
|
1038
1037
|
// throws ERR_INVALID_ARG_TYPE before any watcher exists.
|
|
@@ -1049,14 +1048,14 @@ function lowerStreamArg(L, node, what) {
|
|
|
1049
1048
|
loc: locOf(node),
|
|
1050
1049
|
});
|
|
1051
1050
|
};
|
|
1052
|
-
if (isJsSourceFile(node.getSourceFile()) &&
|
|
1051
|
+
if (isJsSourceFile(node.getSourceFile()) && lowerer.dynConvertible(v.type)) {
|
|
1053
1052
|
if (what === "pipeline") {
|
|
1054
1053
|
// Strings and arrays are iterables — VALID pipeline stages in
|
|
1055
1054
|
// Node — and a record carrying a readable/writable member may be
|
|
1056
1055
|
// the duplex-pair form; none of those shapes has a lowering, so
|
|
1057
1056
|
// they take the pointed fence below, never a throw.
|
|
1058
1057
|
const pairish = v.type.kind === "record" &&
|
|
1059
|
-
(
|
|
1058
|
+
(lowerer.shapes.get(v.type.shapeId)?.fields ?? []).some((f) => f.name === "readable" || f.name === "writable");
|
|
1060
1059
|
if ((v.type.kind === "record" && !pairish) || v.type.kind === "f64" ||
|
|
1061
1060
|
v.type.kind === "bool" || v.type.kind === "nullT") {
|
|
1062
1061
|
argTypeThrow("body", PIPELINE_STAGE_EXPECTED);
|
|
@@ -1067,7 +1066,7 @@ function lowerStreamArg(L, node, what) {
|
|
|
1067
1066
|
argTypeThrow("stream", "an instance of ReadableStream, WritableStream, or Stream");
|
|
1068
1067
|
}
|
|
1069
1068
|
}
|
|
1070
|
-
|
|
1069
|
+
lowerer.noLowering(`${what} over a '${lowerer.fmt(v.type)}'`, node, what === "pipeline"
|
|
1071
1070
|
? "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
1071
|
: "stream arguments are the lowered surface (iterables, generators, and plain functions have no lowering yet)");
|
|
1073
1072
|
}
|
|
@@ -1090,17 +1089,17 @@ class StreamArgTypeThrow {
|
|
|
1090
1089
|
* value adapts through the checked-dynamic boundary (mustCall wrappers —
|
|
1091
1090
|
* the runtime inv calls it with NO arguments on success, Node's eos
|
|
1092
1091
|
* convention). */
|
|
1093
|
-
function lowerEosCallback(
|
|
1092
|
+
function lowerEosCallback(lowerer, which, node, thisType) {
|
|
1094
1093
|
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
1095
1094
|
// The error parameter takes what the user declared when it is an
|
|
1096
1095
|
// Error/null/undefined union (@types spells `ErrnoException | null |
|
|
1097
1096
|
// undefined`); the emitted thunk picks the undefined arm on success.
|
|
1098
|
-
let tuple = [errorOrNull(
|
|
1097
|
+
let tuple = [errorOrNull(lowerer)];
|
|
1099
1098
|
try {
|
|
1100
|
-
const { funcType } =
|
|
1099
|
+
const { funcType } = lowerer.lambdaSignature(node);
|
|
1101
1100
|
const p0 = funcType.params[0];
|
|
1102
1101
|
if (p0?.kind === "union") {
|
|
1103
|
-
const def =
|
|
1102
|
+
const def = lowerer.unions.get(p0.unionId);
|
|
1104
1103
|
if (def && def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
1105
1104
|
def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
|
|
1106
1105
|
(a.kind === "object" && a.className === "%Error"))) {
|
|
@@ -1111,36 +1110,36 @@ function lowerEosCallback(L, which, node, thisType) {
|
|
|
1111
1110
|
catch {
|
|
1112
1111
|
/* the fixed tuple speaks */
|
|
1113
1112
|
}
|
|
1114
|
-
return { cb: lowerStreamCallback(
|
|
1113
|
+
return { cb: lowerStreamCallback(lowerer, which, node, thisType, tuple), dyn: false };
|
|
1115
1114
|
}
|
|
1116
|
-
const getRecord = (id) =>
|
|
1117
|
-
const getUnion = (id) =>
|
|
1115
|
+
const getRecord = (id) => lowerer.shapes.get(id);
|
|
1116
|
+
const getUnion = (id) => lowerer.unions.get(id);
|
|
1118
1117
|
let t;
|
|
1119
1118
|
try {
|
|
1120
|
-
const ct =
|
|
1121
|
-
t =
|
|
1119
|
+
const ct = lowerer.typeOf(node);
|
|
1120
|
+
t = lowerer.mapTypeOf(ct) ?? dynFallbackType(lowerer, node, ct);
|
|
1122
1121
|
}
|
|
1123
1122
|
catch {
|
|
1124
1123
|
t = null;
|
|
1125
1124
|
}
|
|
1126
1125
|
if (t?.kind === "dyn") {
|
|
1127
|
-
const v =
|
|
1126
|
+
const v = lowerer.lowerExpr(node);
|
|
1128
1127
|
if (v.type.kind === "dyn")
|
|
1129
1128
|
return { cb: v, dyn: true };
|
|
1130
1129
|
}
|
|
1131
1130
|
else if (t?.kind === "func") {
|
|
1132
|
-
const cb =
|
|
1131
|
+
const cb = lowerer.lowerExpr(node);
|
|
1133
1132
|
if (cb.type.kind === "func" && canBoxFuncIntoDyn(cb.type, getRecord, getUnion)) {
|
|
1134
1133
|
return { cb: { kind: "dynFrom", value: cb, type: DYN, loc: locOf(node) }, dyn: true };
|
|
1135
1134
|
}
|
|
1136
1135
|
}
|
|
1137
|
-
|
|
1136
|
+
lowerer.noLowering(`${which} with this callback value`, node, "write the callback inline, or pass a function value that crosses the checked-dynamic boundary");
|
|
1138
1137
|
}
|
|
1139
1138
|
/** `finished(...)` / `pipeline(...)` / `getDefaultHighWaterMark(...)`
|
|
1140
1139
|
* imported from node:stream (named imports, destructured requires, and
|
|
1141
1140
|
* namespace-member calls all land here). Null for members this spoke
|
|
1142
1141
|
* does not own — the caller's module-qualified fence speaks. */
|
|
1143
|
-
export function lowerStreamModuleCall(
|
|
1142
|
+
export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
1144
1143
|
if (bi.module === "stream/promises") {
|
|
1145
1144
|
const args = call.arguments;
|
|
1146
1145
|
// finished(stream) → a pending void promise the terminal watcher
|
|
@@ -1149,11 +1148,11 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1149
1148
|
// through the promise instead). The options argument has no lowering.
|
|
1150
1149
|
if (bi.member === "finished") {
|
|
1151
1150
|
if (args.length !== 1) {
|
|
1152
|
-
|
|
1151
|
+
lowerer.noLowering(`stream/promises.finished with ${args.length} arguments`, call, args.length === 2 ? "the options argument has no lowering yet — the one-argument form is supported" : "the supported form is finished(stream)");
|
|
1153
1152
|
}
|
|
1154
1153
|
let recv;
|
|
1155
1154
|
try {
|
|
1156
|
-
recv = lowerStreamArg(
|
|
1155
|
+
recv = lowerStreamArg(lowerer, args[0], "finished");
|
|
1157
1156
|
}
|
|
1158
1157
|
catch (e) {
|
|
1159
1158
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -1168,11 +1167,11 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1168
1167
|
// stream destinations, so the result is a void promise.
|
|
1169
1168
|
if (bi.member === "pipeline") {
|
|
1170
1169
|
if (args.length < 2) {
|
|
1171
|
-
|
|
1170
|
+
lowerer.noLowering(`stream/promises.pipeline with ${args.length} arguments`, call, "the supported form is pipeline(source, ...streams)");
|
|
1172
1171
|
}
|
|
1173
1172
|
let streams;
|
|
1174
1173
|
try {
|
|
1175
|
-
streams = args.map((a) => lowerStreamArg(
|
|
1174
|
+
streams = args.map((a) => lowerStreamArg(lowerer, a, "pipeline"));
|
|
1176
1175
|
}
|
|
1177
1176
|
catch (e) {
|
|
1178
1177
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -1182,7 +1181,7 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1182
1181
|
return {
|
|
1183
1182
|
kind: "libCall",
|
|
1184
1183
|
fn: "sp.pipeline",
|
|
1185
|
-
args: [
|
|
1184
|
+
args: [numLit(streams.length, loc), ...streams],
|
|
1186
1185
|
type: { kind: "promise", inner: VOID },
|
|
1187
1186
|
loc,
|
|
1188
1187
|
};
|
|
@@ -1201,7 +1200,7 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1201
1200
|
// hints in BUILTIN_MODULE_FENCE_HINTS) speaks.
|
|
1202
1201
|
if (bi.member === "text" || bi.member === "json" || bi.member === "buffer") {
|
|
1203
1202
|
if (args.length !== 1) {
|
|
1204
|
-
|
|
1203
|
+
lowerer.noLowering(`stream/consumers.${bi.member} with ${args.length} arguments`, call, `the supported form is ${bi.member}(stream)`);
|
|
1205
1204
|
}
|
|
1206
1205
|
// A provably-non-stream argument: Node's consumers reject the
|
|
1207
1206
|
// returned promise asynchronously with the plain "stream is not
|
|
@@ -1209,10 +1208,10 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1209
1208
|
// (finished/pipeline throw synchronously; consumers do not). A
|
|
1210
1209
|
// sync throw here would be observably wrong timing, so the
|
|
1211
1210
|
// provable case takes the named fence instead.
|
|
1212
|
-
const argV =
|
|
1213
|
-
const argInfo = argV.type.kind === "object" ?
|
|
1214
|
-
if (argV.type.kind !== "dyn" && argV.type.kind !== "jsval" && !streamSidesOf(
|
|
1215
|
-
|
|
1211
|
+
const argV = lowerer.lowerExpr(args[0]);
|
|
1212
|
+
const argInfo = argV.type.kind === "object" ? lowerer.classes.get(argV.type.className) : undefined;
|
|
1213
|
+
if (argV.type.kind !== "dyn" && argV.type.kind !== "jsval" && !streamSidesOf(lowerer, argInfo)) {
|
|
1214
|
+
lowerer.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
1215
|
}
|
|
1217
1216
|
const recv = argV;
|
|
1218
1217
|
const inner = bi.member === "text" ? STRING : bi.member === "json" ? DYN : BYTES;
|
|
@@ -1235,26 +1234,26 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1235
1234
|
// (lib/internal/streams/state.js: win32 keeps 16 KiB), so the fold
|
|
1236
1235
|
// follows the TARGET platform like the path-module binding.
|
|
1237
1236
|
if (args.length === 1 && args[0].kind === ts.SyntaxKind.FalseKeyword) {
|
|
1238
|
-
return
|
|
1237
|
+
return numLit(lowerer.targetPlatform === "win32" ? 16384 : 65536, loc);
|
|
1239
1238
|
}
|
|
1240
1239
|
if (args.length === 1 && args[0].kind === ts.SyntaxKind.TrueKeyword)
|
|
1241
|
-
return
|
|
1242
|
-
|
|
1240
|
+
return numLit(16, loc);
|
|
1241
|
+
lowerer.noLowering("getDefaultHighWaterMark with a non-literal argument", call, "the objectMode flag must be a compile-time boolean");
|
|
1243
1242
|
}
|
|
1244
1243
|
if (bi.member === "finished") {
|
|
1245
1244
|
if (args.length !== 2) {
|
|
1246
|
-
|
|
1245
|
+
lowerer.noLowering(`finished with ${args.length} arguments`, call, args.length === 3 ? "the options argument has no lowering yet — the two-argument form is supported" : "the supported form is finished(stream, callback)");
|
|
1247
1246
|
}
|
|
1248
1247
|
let recv;
|
|
1249
1248
|
try {
|
|
1250
|
-
recv = lowerStreamArg(
|
|
1249
|
+
recv = lowerStreamArg(lowerer, args[0], "finished");
|
|
1251
1250
|
}
|
|
1252
1251
|
catch (e) {
|
|
1253
1252
|
if (e instanceof StreamArgTypeThrow)
|
|
1254
1253
|
return e.expr;
|
|
1255
1254
|
throw e;
|
|
1256
1255
|
}
|
|
1257
|
-
const { cb, dyn } = lowerEosCallback(
|
|
1256
|
+
const { cb, dyn } = lowerEosCallback(lowerer, "finished", args[1], recv.type);
|
|
1258
1257
|
return {
|
|
1259
1258
|
kind: "libCall",
|
|
1260
1259
|
fn: dyn ? "stream.finishedDyn" : "stream.finished",
|
|
@@ -1265,11 +1264,11 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1265
1264
|
}
|
|
1266
1265
|
if (bi.member === "pipeline") {
|
|
1267
1266
|
if (args.length < 3) {
|
|
1268
|
-
|
|
1267
|
+
lowerer.noLowering(`pipeline with ${args.length} arguments`, call, "the supported form is pipeline(source, ...streams, callback)");
|
|
1269
1268
|
}
|
|
1270
1269
|
let streams;
|
|
1271
1270
|
try {
|
|
1272
|
-
streams = args.slice(0, -1).map((a) => lowerStreamArg(
|
|
1271
|
+
streams = args.slice(0, -1).map((a) => lowerStreamArg(lowerer, a, "pipeline"));
|
|
1273
1272
|
}
|
|
1274
1273
|
catch (e) {
|
|
1275
1274
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -1277,11 +1276,11 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1277
1276
|
throw e;
|
|
1278
1277
|
}
|
|
1279
1278
|
const last = streams[streams.length - 1];
|
|
1280
|
-
const { cb, dyn } = lowerEosCallback(
|
|
1279
|
+
const { cb, dyn } = lowerEosCallback(lowerer, "pipeline", args[args.length - 1], last.type);
|
|
1281
1280
|
return {
|
|
1282
1281
|
kind: "libCall",
|
|
1283
1282
|
fn: dyn ? "stream.pipelineDyn" : "stream.pipeline",
|
|
1284
|
-
args: [
|
|
1283
|
+
args: [numLit(streams.length, loc), ...streams, cb],
|
|
1285
1284
|
type: last.type,
|
|
1286
1285
|
loc,
|
|
1287
1286
|
};
|
|
@@ -1291,21 +1290,21 @@ export function lowerStreamModuleCall(L, call, bi, loc) {
|
|
|
1291
1290
|
/* ── the method surface ───────────────────────────────────────────────── */
|
|
1292
1291
|
/** The one supported encoding argument: utf8 (Node's default), as a
|
|
1293
1292
|
* compile-time literal or absent. */
|
|
1294
|
-
function checkUtf8Encoding(
|
|
1293
|
+
function checkUtf8Encoding(lowerer, member, arg) {
|
|
1295
1294
|
if (arg === undefined)
|
|
1296
1295
|
return;
|
|
1297
|
-
const t =
|
|
1296
|
+
const t = lowerer.typeOf(arg);
|
|
1298
1297
|
if (t.isStringLiteralType() && (t.value === "utf8" || t.value === "utf-8"))
|
|
1299
1298
|
return;
|
|
1300
|
-
|
|
1299
|
+
lowerer.noLowering(`${member} with a ${t.isStringLiteralType() ? `'${t.value}'` : "non-literal"} encoding`, arg, "utf8 (as a compile-time literal) is the supported encoding");
|
|
1301
1300
|
}
|
|
1302
1301
|
/** `recv.<member>(...)` over a stream-rooted receiver. Returns null only
|
|
1303
1302
|
* for members this spoke does not own. */
|
|
1304
|
-
export function lowerStreamMethodCall(
|
|
1303
|
+
export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
1305
1304
|
const member = access.name.text;
|
|
1306
1305
|
if (!STREAM_API_MEMBERS.has(member))
|
|
1307
1306
|
return null;
|
|
1308
|
-
const sides = streamSidesOf(
|
|
1307
|
+
const sides = streamSidesOf(lowerer, info);
|
|
1309
1308
|
if (!sides)
|
|
1310
1309
|
return null;
|
|
1311
1310
|
const loc = locOf(call);
|
|
@@ -1315,7 +1314,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1315
1314
|
const cls = info.def.name.slice(1);
|
|
1316
1315
|
const requireSide = (need, what) => {
|
|
1317
1316
|
if (!need) {
|
|
1318
|
-
|
|
1317
|
+
lowerer.noLowering(`${what} on a ${cls} (the ${what.startsWith("write") || what === "end" || what === "cork" || what === "uncork" ? "writable" : "readable"} half is absent)`, call);
|
|
1319
1318
|
}
|
|
1320
1319
|
};
|
|
1321
1320
|
// Chunk classification for push/unshift/write/end. Union-typed chunks
|
|
@@ -1324,7 +1323,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1324
1323
|
const chunkKind = (node) => {
|
|
1325
1324
|
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
1326
1325
|
return "null";
|
|
1327
|
-
const t =
|
|
1326
|
+
const t = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
1328
1327
|
if (t?.kind === "bytes" && t.elem === "u8")
|
|
1329
1328
|
return "bytes";
|
|
1330
1329
|
if (t?.kind === "string")
|
|
@@ -1337,7 +1336,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1337
1336
|
return "dyn";
|
|
1338
1337
|
}
|
|
1339
1338
|
if (t?.kind === "union") {
|
|
1340
|
-
const def =
|
|
1339
|
+
const def = lowerer.unions.get(t.unionId);
|
|
1341
1340
|
if (def && def.arms.every((a) => (a.kind === "bytes" && a.elem === "u8") || a.kind === "string" || a.kind === "nullT")) {
|
|
1342
1341
|
return "union";
|
|
1343
1342
|
}
|
|
@@ -1346,7 +1345,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1346
1345
|
// A checker-untyped chunk (the JS lane's `t.write(x.toString())`
|
|
1347
1346
|
// shapes): the LOWERING may still land on a supported kind — probe
|
|
1348
1347
|
// it (the probe's IR is discarded; the caller re-lowers the node).
|
|
1349
|
-
const probed = probeLower(
|
|
1348
|
+
const probed = probeLower(lowerer, node);
|
|
1350
1349
|
if (probed?.type.kind === "string")
|
|
1351
1350
|
return "string";
|
|
1352
1351
|
if (probed?.type.kind === "bytes" && probed.type.elem === "u8")
|
|
@@ -1356,12 +1355,12 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1356
1355
|
if (probed?.type.kind === "nullT")
|
|
1357
1356
|
return "null";
|
|
1358
1357
|
}
|
|
1359
|
-
|
|
1358
|
+
lowerer.noLowering(`${member} with a '${t ? lowerer.fmt(t) : "?"}' chunk`, node, "chunks are Buffers or utf8 strings — or unions of those with null (objectMode is not lowered)");
|
|
1360
1359
|
};
|
|
1361
1360
|
if (member === "push" || member === "unshift") {
|
|
1362
1361
|
requireSide(readableSide, member);
|
|
1363
1362
|
if (args.length === 0 || args.length > 2) {
|
|
1364
|
-
|
|
1363
|
+
lowerer.noLowering(`${member} with ${args.length} arguments`, call, "the supported forms are (chunk) and (chunk, \"utf8\")");
|
|
1365
1364
|
}
|
|
1366
1365
|
// push(chunk, enc) with a LITERAL encoding: the per-call decode
|
|
1367
1366
|
// (Buffer.from(chunk, enc)) — an explicit encoding (utf8 included)
|
|
@@ -1369,14 +1368,14 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1369
1368
|
// Node's ERR_UNKNOWN_ENCODING when the push evaluates. unshift keeps
|
|
1370
1369
|
// the utf8-only fence below.
|
|
1371
1370
|
if (member === "push" && args[1] !== undefined && chunkKind(args[0]) === "string") {
|
|
1372
|
-
const t =
|
|
1371
|
+
const t = lowerer.typeOf(args[1]);
|
|
1373
1372
|
if (t.isStringLiteralType()) {
|
|
1374
1373
|
const canonical = knownBufEncoding(t.value);
|
|
1375
1374
|
if (canonical === undefined) {
|
|
1376
1375
|
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${t.value}`, BOOL, loc);
|
|
1377
1376
|
}
|
|
1378
|
-
const receiver =
|
|
1379
|
-
const chunk =
|
|
1377
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1378
|
+
const chunk = lowerer.lowerExprExpecting(args[0], STRING);
|
|
1380
1379
|
return {
|
|
1381
1380
|
kind: "libCall",
|
|
1382
1381
|
fn: "readable.pushStrEnc",
|
|
@@ -1386,23 +1385,23 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1386
1385
|
};
|
|
1387
1386
|
}
|
|
1388
1387
|
}
|
|
1389
|
-
checkUtf8Encoding(
|
|
1388
|
+
checkUtf8Encoding(lowerer, member, args[1]);
|
|
1390
1389
|
const kind = chunkKind(args[0]);
|
|
1391
1390
|
if ((kind === "null" || kind === "union" || kind === "dyn") && member === "unshift") {
|
|
1392
|
-
|
|
1391
|
+
lowerer.noLowering(kind === "null" ? "unshift(null)" : "unshift with a nullable or dynamic chunk", call, "EOF signals through push(null)");
|
|
1393
1392
|
}
|
|
1394
|
-
const receiver =
|
|
1393
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1395
1394
|
if (kind === "null") {
|
|
1396
1395
|
return { kind: "libCall", fn: "readable.pushNull", args: [receiver], type: BOOL, loc };
|
|
1397
1396
|
}
|
|
1398
1397
|
if (kind === "dyn") {
|
|
1399
|
-
const chunk =
|
|
1398
|
+
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
1400
1399
|
return { kind: "libCall", fn: "readable.pushDyn", args: [receiver, chunk], type: BOOL, loc };
|
|
1401
1400
|
}
|
|
1402
1401
|
if (kind === "union") {
|
|
1403
1402
|
// The lowered value may have collapsed to one arm (checker
|
|
1404
1403
|
// narrowing) — re-dispatch on its IR type.
|
|
1405
|
-
const chunk =
|
|
1404
|
+
const chunk = lowerer.lowerExpr(args[0]);
|
|
1406
1405
|
if (chunk.type.kind === "union") {
|
|
1407
1406
|
return { kind: "libCall", fn: "readable.pushU", args: [receiver, chunk], type: BOOL, loc };
|
|
1408
1407
|
}
|
|
@@ -1414,7 +1413,7 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1414
1413
|
}
|
|
1415
1414
|
return { kind: "libCall", fn: "readable.pushNull", args: [receiver], type: BOOL, loc };
|
|
1416
1415
|
}
|
|
1417
|
-
const chunk = kind === "bytes" ?
|
|
1416
|
+
const chunk = kind === "bytes" ? lowerer.lowerExprExpecting(args[0], BYTES) : lowerer.lowerExprExpecting(args[0], STRING);
|
|
1418
1417
|
const fn = member === "push"
|
|
1419
1418
|
? (kind === "bytes" ? "readable.push" : "readable.pushStr")
|
|
1420
1419
|
: (kind === "bytes" ? "readable.unshift" : "readable.unshiftStr");
|
|
@@ -1423,64 +1422,64 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1423
1422
|
if (member === "read") {
|
|
1424
1423
|
requireSide(readableSide, "read");
|
|
1425
1424
|
if (args.length > 1)
|
|
1426
|
-
|
|
1427
|
-
const receiver =
|
|
1428
|
-
const size = args[0] ?
|
|
1429
|
-
const type = unionOf(
|
|
1425
|
+
lowerer.noLowering(`read with ${args.length} arguments`, call);
|
|
1426
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1427
|
+
const size = args[0] ? lowerer.lowerExprExpecting(args[0], F64) : numLit(-1, loc);
|
|
1428
|
+
const type = unionOf(lowerer, [BYTES, { kind: "nullT" }]);
|
|
1430
1429
|
const read = { kind: "libCall", fn: "readable.read", args: [receiver, size], type, loc };
|
|
1431
|
-
return
|
|
1430
|
+
return lowerer.maybeNarrow(read, call);
|
|
1432
1431
|
}
|
|
1433
1432
|
if (member === "pause" || member === "resume") {
|
|
1434
1433
|
requireSide(readableSide, member);
|
|
1435
1434
|
if (args.length !== 0)
|
|
1436
|
-
|
|
1437
|
-
const receiver =
|
|
1435
|
+
lowerer.noLowering(`${member} with arguments`, call);
|
|
1436
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1438
1437
|
return { kind: "libCall", fn: member === "pause" ? "readable.pause" : "readable.resume", args: [receiver], type: receiver.type, loc };
|
|
1439
1438
|
}
|
|
1440
1439
|
if (member === "isPaused") {
|
|
1441
1440
|
requireSide(readableSide, "isPaused");
|
|
1442
1441
|
if (args.length !== 0)
|
|
1443
|
-
|
|
1444
|
-
const receiver =
|
|
1442
|
+
lowerer.noLowering(`isPaused with arguments`, call);
|
|
1443
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1445
1444
|
return { kind: "libCall", fn: "readable.isPaused", args: [receiver], type: BOOL, loc };
|
|
1446
1445
|
}
|
|
1447
1446
|
if (member === "pipe") {
|
|
1448
1447
|
requireSide(readableSide, "pipe");
|
|
1449
1448
|
if (args.length === 0 || args.length > 2) {
|
|
1450
|
-
|
|
1449
|
+
lowerer.noLowering(`pipe with ${args.length} arguments`, call, "the supported forms are (destination) and (destination, { end })");
|
|
1451
1450
|
}
|
|
1452
|
-
const dst =
|
|
1453
|
-
const dstInfo = dst.type.kind === "object" ?
|
|
1454
|
-
const dstSides = streamSidesOf(
|
|
1451
|
+
const dst = lowerer.lowerExpr(args[0]);
|
|
1452
|
+
const dstInfo = dst.type.kind === "object" ? lowerer.classes.get(dst.type.className) : undefined;
|
|
1453
|
+
const dstSides = streamSidesOf(lowerer, dstInfo);
|
|
1455
1454
|
if (dstSides !== "w" && dstSides !== "rw") {
|
|
1456
|
-
|
|
1455
|
+
lowerer.noLowering(`pipe into a '${lowerer.fmt(dst.type)}'`, args[0], "the destination must be a stream Writable/Duplex (process streams and sockets are not pipe destinations yet)");
|
|
1457
1456
|
}
|
|
1458
1457
|
let end = boolLit(true, loc);
|
|
1459
1458
|
if (args[1] !== undefined) {
|
|
1460
1459
|
if (!ts.isObjectLiteralExpression(args[1])) {
|
|
1461
|
-
|
|
1460
|
+
lowerer.noLowering("pipe with a non-literal options argument", args[1], "{ end: <bool> } inline is the supported form");
|
|
1462
1461
|
}
|
|
1463
1462
|
for (const prop of args[1].properties) {
|
|
1464
1463
|
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== "end") {
|
|
1465
|
-
|
|
1464
|
+
lowerer.noLowering("a pipe option other than 'end'", prop);
|
|
1466
1465
|
}
|
|
1467
|
-
end =
|
|
1466
|
+
end = lowerer.lowerExprExpecting(prop.initializer, BOOL);
|
|
1468
1467
|
}
|
|
1469
1468
|
}
|
|
1470
|
-
const receiver =
|
|
1469
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1471
1470
|
return { kind: "libCall", fn: "readable.pipe", args: [receiver, dst, end], type: dst.type, loc };
|
|
1472
1471
|
}
|
|
1473
1472
|
if (member === "unpipe") {
|
|
1474
1473
|
requireSide(readableSide, "unpipe");
|
|
1475
1474
|
if (args.length > 1)
|
|
1476
|
-
|
|
1477
|
-
const receiver =
|
|
1475
|
+
lowerer.noLowering(`unpipe with ${args.length} arguments`, call);
|
|
1476
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1478
1477
|
if (args[0] !== undefined) {
|
|
1479
|
-
const dst =
|
|
1480
|
-
const dstInfo = dst.type.kind === "object" ?
|
|
1481
|
-
const dstSides = streamSidesOf(
|
|
1478
|
+
const dst = lowerer.lowerExpr(args[0]);
|
|
1479
|
+
const dstInfo = dst.type.kind === "object" ? lowerer.classes.get(dst.type.className) : undefined;
|
|
1480
|
+
const dstSides = streamSidesOf(lowerer, dstInfo);
|
|
1482
1481
|
if (dstSides !== "w" && dstSides !== "rw") {
|
|
1483
|
-
|
|
1482
|
+
lowerer.noLowering(`unpipe of a '${lowerer.fmt(dst.type)}'`, args[0]);
|
|
1484
1483
|
}
|
|
1485
1484
|
return { kind: "libCall", fn: "readable.unpipe", args: [receiver, dst], type: receiver.type, loc };
|
|
1486
1485
|
}
|
|
@@ -1488,39 +1487,39 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1488
1487
|
}
|
|
1489
1488
|
if (member === "destroy") {
|
|
1490
1489
|
if (args.length > 1)
|
|
1491
|
-
|
|
1492
|
-
const receiver =
|
|
1490
|
+
lowerer.noLowering(`destroy with ${args.length} arguments`, call);
|
|
1491
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1493
1492
|
if (args[0] !== undefined) {
|
|
1494
|
-
const err =
|
|
1493
|
+
const err = lowerer.lowerExpr(args[0]);
|
|
1495
1494
|
const rootsAtError = (t) => {
|
|
1496
1495
|
if (t.kind !== "object")
|
|
1497
1496
|
return false;
|
|
1498
|
-
for (let c =
|
|
1497
|
+
for (let c = lowerer.classes.get(t.className) ?? null; c; c = c.base) {
|
|
1499
1498
|
if (c.def.name === "%Error")
|
|
1500
1499
|
return true;
|
|
1501
1500
|
}
|
|
1502
1501
|
return false;
|
|
1503
1502
|
};
|
|
1504
1503
|
if (!rootsAtError(err.type)) {
|
|
1505
|
-
|
|
1504
|
+
lowerer.noLowering(`destroy with a '${lowerer.fmt(err.type)}' argument`, args[0], "the supported argument is an Error-hierarchy instance");
|
|
1506
1505
|
}
|
|
1507
|
-
return { kind: "libCall", fn: "stream.destroyErr", args: [receiver,
|
|
1506
|
+
return { kind: "libCall", fn: "stream.destroyErr", args: [receiver, lowerer.upcastTo(err, "%Error")], type: receiver.type, loc };
|
|
1508
1507
|
}
|
|
1509
1508
|
return { kind: "libCall", fn: "stream.destroy", args: [receiver], type: receiver.type, loc };
|
|
1510
1509
|
}
|
|
1511
1510
|
if (member === "write") {
|
|
1512
1511
|
requireSide(writableSide, "write");
|
|
1513
1512
|
if (args.length === 0 || args.length > 3) {
|
|
1514
|
-
|
|
1513
|
+
lowerer.noLowering(`write with ${args.length} arguments`, call);
|
|
1515
1514
|
}
|
|
1516
1515
|
const kind = chunkKind(args[0]);
|
|
1517
1516
|
if (kind === "null")
|
|
1518
|
-
|
|
1517
|
+
lowerer.noLowering("write(null)", call, "end() finishes a writable");
|
|
1519
1518
|
if (kind === "dyn") {
|
|
1520
1519
|
if (args.length > 1)
|
|
1521
|
-
|
|
1522
|
-
const receiver =
|
|
1523
|
-
const chunk =
|
|
1520
|
+
lowerer.noLowering("write with a dynamic chunk and more arguments", call);
|
|
1521
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1522
|
+
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
1524
1523
|
return { kind: "libCall", fn: "writable.writeDyn", args: [receiver, chunk], type: BOOL, loc };
|
|
1525
1524
|
}
|
|
1526
1525
|
if (kind === "union") {
|
|
@@ -1529,36 +1528,36 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1529
1528
|
// lowered value may have collapsed to one arm (checker narrowing) —
|
|
1530
1529
|
// re-dispatch on its IR type.
|
|
1531
1530
|
if (args.length > 1)
|
|
1532
|
-
|
|
1533
|
-
const receiver =
|
|
1534
|
-
const chunk =
|
|
1531
|
+
lowerer.noLowering("write with a union chunk and more arguments", call);
|
|
1532
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1533
|
+
const chunk = lowerer.lowerExpr(args[0]);
|
|
1535
1534
|
const fn = chunk.type.kind === "union" ? "writable.writeU"
|
|
1536
1535
|
: chunk.type.kind === "string" ? "writable.writeStr" : "writable.write";
|
|
1537
1536
|
if (chunk.type.kind === "nullT")
|
|
1538
|
-
|
|
1537
|
+
lowerer.noLowering("write(null)", call, "end() finishes a writable");
|
|
1539
1538
|
return { kind: "libCall", fn, args: [receiver, chunk], type: BOOL, loc };
|
|
1540
1539
|
}
|
|
1541
1540
|
// Disambiguate (chunk, cb?) vs (chunk, encoding, cb?) by the second
|
|
1542
1541
|
// argument's static type.
|
|
1543
1542
|
let cbArg;
|
|
1544
1543
|
if (args.length === 2) {
|
|
1545
|
-
const t =
|
|
1544
|
+
const t = lowerer.mapTypeOf(lowerer.typeOf(args[1]));
|
|
1546
1545
|
if (t?.kind === "string")
|
|
1547
|
-
checkUtf8Encoding(
|
|
1546
|
+
checkUtf8Encoding(lowerer, "write", args[1]);
|
|
1548
1547
|
else
|
|
1549
1548
|
cbArg = args[1];
|
|
1550
1549
|
}
|
|
1551
1550
|
else if (args.length === 3) {
|
|
1552
|
-
checkUtf8Encoding(
|
|
1551
|
+
checkUtf8Encoding(lowerer, "write", args[1]);
|
|
1553
1552
|
cbArg = args[2];
|
|
1554
1553
|
}
|
|
1555
|
-
const receiver =
|
|
1556
|
-
const chunk = kind === "bytes" ?
|
|
1554
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1555
|
+
const chunk = kind === "bytes" ? lowerer.lowerExprExpecting(args[0], BYTES) : lowerer.lowerExprExpecting(args[0], STRING);
|
|
1557
1556
|
const fn = kind === "bytes" ? "writable.write" : "writable.writeStr";
|
|
1558
1557
|
if (cbArg !== undefined) {
|
|
1559
|
-
const cb =
|
|
1558
|
+
const cb = lowerer.lowerExprExpecting(cbArg, funcOf([], VOID));
|
|
1560
1559
|
if (cb.type.kind !== "func" || cb.type.params.length > 0) {
|
|
1561
|
-
|
|
1560
|
+
lowerer.noLowering("write completion callbacks taking the error argument", cbArg, "() => void callbacks are supported (listen for 'error' to observe failures)");
|
|
1562
1561
|
}
|
|
1563
1562
|
return { kind: "libCall", fn, args: [receiver, chunk, cb], type: BOOL, loc };
|
|
1564
1563
|
}
|
|
@@ -1567,12 +1566,12 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1567
1566
|
if (member === "end") {
|
|
1568
1567
|
requireSide(writableSide, "end");
|
|
1569
1568
|
if (args.length > 3)
|
|
1570
|
-
|
|
1569
|
+
lowerer.noLowering(`end with ${args.length} arguments`, call);
|
|
1571
1570
|
// Forms: (), (cb), (chunk), (chunk, cb), (chunk, encoding, cb).
|
|
1572
1571
|
let chunkNode;
|
|
1573
1572
|
let cbArg;
|
|
1574
1573
|
if (args.length === 1) {
|
|
1575
|
-
const t =
|
|
1574
|
+
const t = lowerer.mapTypeOf(lowerer.typeOf(args[0]));
|
|
1576
1575
|
if (t?.kind === "func")
|
|
1577
1576
|
cbArg = args[0];
|
|
1578
1577
|
else
|
|
@@ -1580,64 +1579,64 @@ export function lowerStreamMethodCall(L, call, access, info) {
|
|
|
1580
1579
|
}
|
|
1581
1580
|
else if (args.length === 2) {
|
|
1582
1581
|
chunkNode = args[0];
|
|
1583
|
-
const t =
|
|
1582
|
+
const t = lowerer.mapTypeOf(lowerer.typeOf(args[1]));
|
|
1584
1583
|
if (t?.kind === "string")
|
|
1585
|
-
checkUtf8Encoding(
|
|
1584
|
+
checkUtf8Encoding(lowerer, "end", args[1]);
|
|
1586
1585
|
else
|
|
1587
1586
|
cbArg = args[1];
|
|
1588
1587
|
}
|
|
1589
1588
|
else if (args.length === 3) {
|
|
1590
1589
|
chunkNode = args[0];
|
|
1591
|
-
checkUtf8Encoding(
|
|
1590
|
+
checkUtf8Encoding(lowerer, "end", args[1]);
|
|
1592
1591
|
cbArg = args[2];
|
|
1593
1592
|
}
|
|
1594
|
-
const receiver =
|
|
1593
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1595
1594
|
let flags = 0;
|
|
1596
1595
|
const tail = [];
|
|
1597
1596
|
if (chunkNode !== undefined) {
|
|
1598
1597
|
const kind = chunkKind(chunkNode);
|
|
1599
1598
|
if (kind === "null" || kind === "union")
|
|
1600
|
-
|
|
1599
|
+
lowerer.noLowering("end(null)", call);
|
|
1601
1600
|
flags |= kind === "bytes" ? 1 : kind === "dyn" ? 8 : 2;
|
|
1602
|
-
tail.push(kind === "bytes" ?
|
|
1603
|
-
: kind === "dyn" ?
|
|
1604
|
-
:
|
|
1601
|
+
tail.push(kind === "bytes" ? lowerer.lowerExprExpecting(chunkNode, BYTES)
|
|
1602
|
+
: kind === "dyn" ? lowerer.lowerExprExpecting(chunkNode, DYN)
|
|
1603
|
+
: lowerer.lowerExprExpecting(chunkNode, STRING));
|
|
1605
1604
|
}
|
|
1606
1605
|
if (cbArg !== undefined) {
|
|
1607
|
-
const cb =
|
|
1606
|
+
const cb = lowerer.lowerExprExpecting(cbArg, funcOf([], VOID));
|
|
1608
1607
|
if (cb.type.kind !== "func" || cb.type.params.length > 0) {
|
|
1609
|
-
|
|
1608
|
+
lowerer.noLowering("end callbacks with parameters", cbArg, "() => void callbacks are supported");
|
|
1610
1609
|
}
|
|
1611
1610
|
flags |= 4;
|
|
1612
1611
|
tail.push(cb);
|
|
1613
1612
|
}
|
|
1614
|
-
return { kind: "libCall", fn: "writable.end", args: [receiver,
|
|
1613
|
+
return { kind: "libCall", fn: "writable.end", args: [receiver, numLit(flags, loc), ...tail], type: receiver.type, loc };
|
|
1615
1614
|
}
|
|
1616
1615
|
if (member === "cork" || member === "uncork") {
|
|
1617
1616
|
requireSide(writableSide, member);
|
|
1618
1617
|
if (args.length !== 0)
|
|
1619
|
-
|
|
1620
|
-
const receiver =
|
|
1618
|
+
lowerer.noLowering(`${member} with arguments`, call);
|
|
1619
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1621
1620
|
return { kind: "libCall", fn: member === "cork" ? "writable.cork" : "writable.uncork", args: [receiver], type: VOID, loc };
|
|
1622
1621
|
}
|
|
1623
1622
|
if (member === "setEncoding") {
|
|
1624
1623
|
requireSide(readableSide, "setEncoding");
|
|
1625
1624
|
if (args.length !== 1) {
|
|
1626
|
-
|
|
1625
|
+
lowerer.noLowering(`setEncoding with ${args.length} arguments`, call, "one literal encoding is the supported form");
|
|
1627
1626
|
}
|
|
1628
|
-
const enc = bufEncoding(
|
|
1629
|
-
const receiver =
|
|
1627
|
+
const enc = bufEncoding(lowerer, "setEncoding", args[0]);
|
|
1628
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1630
1629
|
return { kind: "libCall", fn: "readable.setEncoding", args: [receiver, strLit(enc, loc)], type: receiver.type, loc };
|
|
1631
1630
|
}
|
|
1632
1631
|
if (member === "setDefaultEncoding") {
|
|
1633
1632
|
// The write-side default: utf8 IS the default — admit it; other
|
|
1634
1633
|
// encodings would change what write(string) means.
|
|
1635
1634
|
requireSide(writableSide, "setDefaultEncoding");
|
|
1636
|
-
const t = args[0] ?
|
|
1635
|
+
const t = args[0] ? lowerer.typeOf(args[0]) : null;
|
|
1637
1636
|
if (t?.isStringLiteralType() && (t.value === "utf8" || t.value === "utf-8")) {
|
|
1638
|
-
return
|
|
1637
|
+
return lowerer.lowerExpr(access.expression);
|
|
1639
1638
|
}
|
|
1640
|
-
|
|
1639
|
+
lowerer.noLowering("setDefaultEncoding", call, "utf8 (the default, as a compile-time literal) is the supported write-side string encoding");
|
|
1641
1640
|
}
|
|
1642
1641
|
return null;
|
|
1643
1642
|
}
|
|
@@ -1663,7 +1662,7 @@ const WS_BOOL_PROPS = new Set([
|
|
|
1663
1662
|
const WS_NUM_PROPS = new Set([
|
|
1664
1663
|
"length", "highWaterMark", "corked", "bufferedRequestCount",
|
|
1665
1664
|
]);
|
|
1666
|
-
export function lowerStreamStateProperty(
|
|
1665
|
+
export function lowerStreamStateProperty(lowerer, expr) {
|
|
1667
1666
|
if (expr.questionDotToken)
|
|
1668
1667
|
return null;
|
|
1669
1668
|
const inner = expr.expression;
|
|
@@ -1674,34 +1673,34 @@ export function lowerStreamStateProperty(L, expr) {
|
|
|
1674
1673
|
return null;
|
|
1675
1674
|
let recvT;
|
|
1676
1675
|
try {
|
|
1677
|
-
recvT =
|
|
1676
|
+
recvT = lowerer.mapTypeOf(lowerer.typeOf(inner.expression));
|
|
1678
1677
|
}
|
|
1679
1678
|
catch {
|
|
1680
1679
|
return null;
|
|
1681
1680
|
}
|
|
1682
1681
|
if (recvT?.kind !== "object")
|
|
1683
1682
|
return null;
|
|
1684
|
-
const info =
|
|
1685
|
-
const sides = streamSidesOf(
|
|
1683
|
+
const info = lowerer.classes.get(recvT.className);
|
|
1684
|
+
const sides = streamSidesOf(lowerer, info);
|
|
1686
1685
|
if (!sides)
|
|
1687
1686
|
return null;
|
|
1688
1687
|
const loc = locOf(expr);
|
|
1689
1688
|
const readable = stateName === "_readableState";
|
|
1690
1689
|
if (readable ? sides === "w" : sides === "r") {
|
|
1691
|
-
|
|
1690
|
+
lowerer.noLowering(`${stateName} on a ${recvT.className.slice(1)} (that half is absent)`, expr);
|
|
1692
1691
|
}
|
|
1693
1692
|
const name = expr.name.text;
|
|
1694
1693
|
const prefix = readable ? "rs:" : "ws:";
|
|
1695
|
-
const receiver = () =>
|
|
1694
|
+
const receiver = () => lowerer.lowerExpr(inner.expression);
|
|
1696
1695
|
if (name === "flowing" && readable) {
|
|
1697
|
-
const type = unionOf(
|
|
1696
|
+
const type = unionOf(lowerer, [BOOL, { kind: "nullT" }]);
|
|
1698
1697
|
const read = { kind: "libCall", fn: "readable.flowing", args: [receiver()], type, loc };
|
|
1699
|
-
return
|
|
1698
|
+
return lowerer.maybeNarrow(read, expr);
|
|
1700
1699
|
}
|
|
1701
1700
|
if (name === "errored") {
|
|
1702
|
-
const type = unionOf(
|
|
1701
|
+
const type = unionOf(lowerer, [{ kind: "object", className: "%Error" }, { kind: "nullT" }]);
|
|
1703
1702
|
const read = { kind: "libCall", fn: "stream.errored", args: [receiver()], type, loc };
|
|
1704
|
-
return
|
|
1703
|
+
return lowerer.maybeNarrow(read, expr);
|
|
1705
1704
|
}
|
|
1706
1705
|
const bools = readable ? RS_BOOL_PROPS : WS_BOOL_PROPS;
|
|
1707
1706
|
const nums = readable ? RS_NUM_PROPS : WS_NUM_PROPS;
|
|
@@ -1714,7 +1713,7 @@ export function lowerStreamStateProperty(L, expr) {
|
|
|
1714
1713
|
loc,
|
|
1715
1714
|
};
|
|
1716
1715
|
}
|
|
1717
|
-
|
|
1716
|
+
lowerer.noLowering(`reading ${stateName}.${name}`, expr, "the lowered internal-state view covers the scalar fields (length, ended, flowing, errorEmitted, ...) — object-valued members like pipes and buffered entries have no lowering");
|
|
1718
1717
|
}
|
|
1719
1718
|
/* ── the property surface ─────────────────────────────────────────────── */
|
|
1720
1719
|
const READABLE_BOOL_PROPS = new Set(["readable", "readableEnded"]);
|
|
@@ -1724,8 +1723,8 @@ const READABLE_NUM_PROPS = new Set(["readableLength", "readableHighWaterMark"]);
|
|
|
1724
1723
|
const WRITABLE_NUM_PROPS = new Set(["writableLength", "writableHighWaterMark", "writableCorked"]);
|
|
1725
1724
|
/** Property reads on stream-rooted receivers (`r.readableEnded`,
|
|
1726
1725
|
* `w.destroyed`, ...). Null for names this spoke does not own. */
|
|
1727
|
-
export function lowerStreamProperty(
|
|
1728
|
-
const sides = streamSidesOf(
|
|
1726
|
+
export function lowerStreamProperty(lowerer, expr, info) {
|
|
1727
|
+
const sides = streamSidesOf(lowerer, info);
|
|
1729
1728
|
if (!sides)
|
|
1730
1729
|
return null;
|
|
1731
1730
|
const name = expr.name.text;
|
|
@@ -1735,7 +1734,7 @@ export function lowerStreamProperty(L, expr, info) {
|
|
|
1735
1734
|
const propCall = (type) => ({
|
|
1736
1735
|
kind: "libCall",
|
|
1737
1736
|
fn: "stream.prop",
|
|
1738
|
-
args: [
|
|
1737
|
+
args: [lowerer.lowerExpr(expr.expression), strLit(name, loc)],
|
|
1739
1738
|
type,
|
|
1740
1739
|
loc,
|
|
1741
1740
|
});
|
|
@@ -1746,14 +1745,14 @@ export function lowerStreamProperty(L, expr, info) {
|
|
|
1746
1745
|
return propCall(F64);
|
|
1747
1746
|
}
|
|
1748
1747
|
if (name === "readableFlowing" && readableSide) {
|
|
1749
|
-
const type = unionOf(
|
|
1750
|
-
const read = { kind: "libCall", fn: "readable.flowing", args: [
|
|
1751
|
-
return
|
|
1748
|
+
const type = unionOf(lowerer, [BOOL, { kind: "nullT" }]);
|
|
1749
|
+
const read = { kind: "libCall", fn: "readable.flowing", args: [lowerer.lowerExpr(expr.expression)], type, loc };
|
|
1750
|
+
return lowerer.maybeNarrow(read, expr);
|
|
1752
1751
|
}
|
|
1753
1752
|
if (name === "errored") {
|
|
1754
|
-
const type = unionOf(
|
|
1755
|
-
const read = { kind: "libCall", fn: "stream.errored", args: [
|
|
1756
|
-
return
|
|
1753
|
+
const type = unionOf(lowerer, [{ kind: "object", className: "%Error" }, { kind: "nullT" }]);
|
|
1754
|
+
const read = { kind: "libCall", fn: "stream.errored", args: [lowerer.lowerExpr(expr.expression)], type, loc };
|
|
1755
|
+
return lowerer.maybeNarrow(read, expr);
|
|
1757
1756
|
}
|
|
1758
1757
|
if (name === "readableObjectMode" && readableSide) {
|
|
1759
1758
|
// Runtime state: Readable.from streams answer true (object entries).
|