@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,10 +1,11 @@
|
|
|
1
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
1
2
|
/* Island-boundary lowering: jsval marshaling into the island (jsvalIn and
|
|
2
3
|
* its boundary fences), island-expression detection, the island method-call
|
|
3
4
|
* surface (Math and number/string methods under --dynamic), and the npm
|
|
4
5
|
* package boundary fences for node_modules-declared symbols. */
|
|
5
6
|
import * as ts from "../ts7/adapter.js";
|
|
6
|
-
import { BOOL, BYTES_U8, DYN, F64, JSVAL, MAX_ISLAND_CALLBACK_ARITY, STRING, VOID, canConvertToDyn, canMarshalTypedFuncIntoIsland, islandPromisePayloadTag, isUnitType } from "../../ir/
|
|
7
|
-
import { ISLAND_SURFACE, STATIC_MATH_FNS, boundaryIntoIslandMsg } from "./surfaces.js";
|
|
7
|
+
import { BOOL, BYTES_U8, DYN, F64, JSVAL, MAX_ISLAND_CALLBACK_ARITY, STRING, VOID, canConvertToDyn, canMarshalTypedFuncIntoIsland, islandPromisePayloadTag, isUnitType } from "../../ir/ir.js";
|
|
8
|
+
import { ISLAND_SURFACE, STATIC_MATH_FNS, STATIC_MATH_PROPS, boundaryIntoIslandMsg } from "./surfaces.js";
|
|
8
9
|
import { requiresDynamicApiDiag, requiresDynamicPackageDiag } from "../../diagnostics/diagnostic.js";
|
|
9
10
|
import { isCjsJsFile, isJsSourceFile, locOf, npmPackageNameOf } from "../program.js";
|
|
10
11
|
import { foldedStringKeyOf, lowerDynObjectLiteral, pureReemittable } from "./lower-exprs.js";
|
|
@@ -20,18 +21,18 @@ import { NODE24_FETCH_COMPAT_PROFILE, STATIC_HEADERS_CALLS, STATIC_READABLE_STRE
|
|
|
20
21
|
* re-reporting the declared type. The one exclusion is promise-mapped
|
|
21
22
|
* declared types: a package promise held as a handle keeps its existing
|
|
22
23
|
* checker-driven dispatch (the await/.catch bridge lowerings own it). */
|
|
23
|
-
export function isIslandExpr(
|
|
24
|
-
const mapped =
|
|
24
|
+
export function isIslandExpr(lowerer, node) {
|
|
25
|
+
const mapped = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
25
26
|
if (mapped?.kind === "jsval")
|
|
26
27
|
return true;
|
|
27
28
|
if (mapped?.kind !== "promise" && ts.isIdentifier(node)) {
|
|
28
|
-
const local =
|
|
29
|
+
const local = lowerer.peekLocal(node);
|
|
29
30
|
if (local?.type.kind === "jsval")
|
|
30
31
|
return true;
|
|
31
32
|
// File-scope handle bindings (a module global slotted jsval by the
|
|
32
33
|
// island-pattern or unchecked-overload rules) take the same rule as
|
|
33
34
|
// locals: the handle is the value's only story.
|
|
34
|
-
if (!local &&
|
|
35
|
+
if (!local && lowerer.globalOf(node)?.type.kind === "jsval")
|
|
35
36
|
return true;
|
|
36
37
|
}
|
|
37
38
|
return false;
|
|
@@ -47,44 +48,25 @@ export function isIslandExpr(L, node) {
|
|
|
47
48
|
* invoked — building the value compiles; only a call through the
|
|
48
49
|
* island stops the run. Null (caller rethrows) outside the JS deferral
|
|
49
50
|
* gate: TypeScript sources, probe mode, ICEs. */
|
|
50
|
-
export function islandFuncValueFence(
|
|
51
|
-
if (!(err instanceof PoisonError) ||
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const captured = L.diags.splice(diagsBefore);
|
|
59
|
-
L.runtimeFences.push(...captured);
|
|
60
|
-
const first = captured[0];
|
|
61
|
-
const pos = ts.getLineAndCharacterOfPosition(L.program.getSourceFile(first.loc.file) ?? node.getSourceFile(), first.loc.start);
|
|
62
|
-
const loc = locOf(node);
|
|
63
|
-
const fnName = `%fn${L.lambdaCounter++}_islfence`;
|
|
64
|
-
L.liftedFns.push({
|
|
65
|
-
name: fnName,
|
|
66
|
-
params: [],
|
|
51
|
+
export function islandFuncValueFence(lowerer, err, diagsBefore, node) {
|
|
52
|
+
if (!(err instanceof PoisonError) || !isJsSourceFile(node.getSourceFile()))
|
|
53
|
+
return null;
|
|
54
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, node, {
|
|
55
|
+
kind: "closure",
|
|
56
|
+
name: () => `%fn${lowerer.lambdaCounter++}_islfence`,
|
|
67
57
|
returnType: VOID,
|
|
68
|
-
|
|
69
|
-
captures: [],
|
|
70
|
-
body: [
|
|
71
|
-
{
|
|
72
|
-
kind: "runtimeFence",
|
|
73
|
-
code: first.code,
|
|
74
|
-
message: `${first.message} [${first.code} at ${first.loc.file}:${pos.line + 1}]`,
|
|
75
|
-
loc,
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
loc,
|
|
58
|
+
type: { kind: "func", params: [], ret: VOID },
|
|
79
59
|
});
|
|
60
|
+
if (!fence)
|
|
61
|
+
return null;
|
|
80
62
|
return {
|
|
81
63
|
kind: "jsMarshal",
|
|
82
|
-
value:
|
|
64
|
+
value: fence,
|
|
83
65
|
type: JSVAL,
|
|
84
|
-
loc,
|
|
66
|
+
loc: fence.loc,
|
|
85
67
|
};
|
|
86
68
|
}
|
|
87
|
-
export function jsvalIn(
|
|
69
|
+
export function jsvalIn(lowerer, e, node) {
|
|
88
70
|
if (e.type.kind === "jsval")
|
|
89
71
|
return e;
|
|
90
72
|
// Bare unit literals (`undefined` / `null` in an 'any' slot): the
|
|
@@ -110,10 +92,10 @@ export function jsvalIn(L, e, node) {
|
|
|
110
92
|
// Anything outside both shapes gets the specific fix, not the generic
|
|
111
93
|
// boundary recitation.
|
|
112
94
|
if (e.type.kind === "func" &&
|
|
113
|
-
!canMarshalTypedFuncIntoIsland(e.type, (id) =>
|
|
114
|
-
const diagsBefore =
|
|
95
|
+
!canMarshalTypedFuncIntoIsland(e.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
96
|
+
const diagsBefore = lowerer.diags.length;
|
|
115
97
|
try {
|
|
116
|
-
|
|
98
|
+
lowerer.unsupported("SC1090", node, `functions with this signature crossing into dynamically-executed code ` +
|
|
117
99
|
`(a callback passed to a package/'any' API may take 'any' parameters — ` +
|
|
118
100
|
`leave them unannotated so contextual typing keeps them 'any' — or parameters ` +
|
|
119
101
|
`convertible at the boundary (number, string, boolean, JSON-safe ` +
|
|
@@ -128,7 +110,7 @@ export function jsvalIn(L, e, node) {
|
|
|
128
110
|
// diagnostic when INVOKED (the withPlugins aggregation shape —
|
|
129
111
|
// wrappers built at module init around functions the smoke path
|
|
130
112
|
// never calls). TypeScript and probe mode keep the poison.
|
|
131
|
-
const fence = islandFuncValueFence(
|
|
113
|
+
const fence = islandFuncValueFence(lowerer, err, diagsBefore, node);
|
|
132
114
|
if (fence)
|
|
133
115
|
return fence;
|
|
134
116
|
throw err;
|
|
@@ -143,7 +125,7 @@ export function jsvalIn(L, e, node) {
|
|
|
143
125
|
if (e.type.kind === "promise" && islandPromisePayloadTag(e.type.inner) !== null) {
|
|
144
126
|
return { kind: "jsMarshal", value: e, type: JSVAL, loc: e.loc };
|
|
145
127
|
}
|
|
146
|
-
if (e.type.kind !== "func" && !
|
|
128
|
+
if (e.type.kind !== "func" && !lowerer.boundarySafe(e.type)) {
|
|
147
129
|
// A RegExp crossing INTO the island (`z.string().regex(/^a+$/)` —
|
|
148
130
|
// the validation-pattern argument): the engine compiles its own
|
|
149
131
|
// from source+flags. A fresh engine RegExp per marshal — identity
|
|
@@ -158,9 +140,9 @@ export function jsvalIn(L, e, node) {
|
|
|
158
140
|
// jsval-BEARING composites (an `any[]` value, a record holding one)
|
|
159
141
|
// have no JSON marshal but an honest per-field/per-element island
|
|
160
142
|
// construction — the same lift the implicit coercion path uses.
|
|
161
|
-
if (
|
|
162
|
-
return
|
|
163
|
-
|
|
143
|
+
if (lowerer.jsvalLiftable(e.type))
|
|
144
|
+
return lowerer.jsvalLiftExpr(e, e.loc);
|
|
145
|
+
lowerer.unsupported("SC1090", node, boundaryIntoIslandMsg(lowerer.fmt(e.type)));
|
|
164
146
|
}
|
|
165
147
|
return { kind: "jsMarshal", value: e, type: JSVAL, loc: e.loc };
|
|
166
148
|
}
|
|
@@ -204,26 +186,26 @@ export function islandRegexpOf(e) {
|
|
|
204
186
|
* proceeds to engine ops; without it the use site is a per-site SC2012
|
|
205
187
|
* (poison-recovered, so every site in the program reports — and the
|
|
206
188
|
* coverage report groups them under "runs with --dynamic"). */
|
|
207
|
-
export function requireDynamicApi(
|
|
208
|
-
if (
|
|
189
|
+
export function requireDynamicApi(lowerer, feature, node) {
|
|
190
|
+
if (lowerer.dynamic)
|
|
209
191
|
return;
|
|
210
|
-
|
|
192
|
+
lowerer.pushDiag(requiresDynamicApiDiag(feature, locOf(node)));
|
|
211
193
|
throw new PoisonError();
|
|
212
194
|
}
|
|
213
195
|
/** Resolves an identifier to an island-backed ambient GLOBAL function
|
|
214
196
|
* (parseFloat, isFinite). Provenance, not name: the
|
|
215
197
|
* symbol's declaration must live in the ambient file, so a user function
|
|
216
198
|
* named `parseFloat` never matches. */
|
|
217
|
-
export function islandGlobalFnOf(
|
|
199
|
+
export function islandGlobalFnOf(lowerer, ident) {
|
|
218
200
|
const entry = own(ISLAND_SURFACE.globals, ident.text);
|
|
219
201
|
if (!entry)
|
|
220
202
|
return null;
|
|
221
|
-
const symbol =
|
|
222
|
-
if (!symbol || !
|
|
203
|
+
const symbol = lowerer.resolveValueSymbol(ident);
|
|
204
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
223
205
|
return null;
|
|
224
206
|
return entry;
|
|
225
207
|
}
|
|
226
|
-
function requestInitLiteralKey(
|
|
208
|
+
function requestInitLiteralKey(lowerer, prop) {
|
|
227
209
|
if (!ts.isPropertyAssignment(prop) &&
|
|
228
210
|
!ts.isShorthandPropertyAssignment(prop) &&
|
|
229
211
|
!ts.isMethodDeclaration(prop)) {
|
|
@@ -235,7 +217,7 @@ function requestInitLiteralKey(L, prop) {
|
|
|
235
217
|
if (ts.isNumericLiteral(name))
|
|
236
218
|
return String(Number(name.text));
|
|
237
219
|
if (ts.isComputedPropertyName(name))
|
|
238
|
-
return foldedStringKeyOf(
|
|
220
|
+
return foldedStringKeyOf(lowerer, name.expression);
|
|
239
221
|
return null;
|
|
240
222
|
}
|
|
241
223
|
/** Fence declared RequestInit members outside the selected compiler tier.
|
|
@@ -253,21 +235,21 @@ function requestInitValueExpr(expr) {
|
|
|
253
235
|
}
|
|
254
236
|
return current;
|
|
255
237
|
}
|
|
256
|
-
function requestInitStaticBoolean(
|
|
238
|
+
function requestInitStaticBoolean(lowerer, value) {
|
|
257
239
|
const expr = requestInitValueExpr(value);
|
|
258
240
|
if (expr.kind === ts.SyntaxKind.TrueKeyword)
|
|
259
241
|
return true;
|
|
260
242
|
if (expr.kind === ts.SyntaxKind.FalseKeyword)
|
|
261
243
|
return false;
|
|
262
|
-
const text =
|
|
244
|
+
const text = lowerer.checker.typeToString(lowerer.typeOf(expr));
|
|
263
245
|
return text === "true" ? true : text === "false" ? false : null;
|
|
264
246
|
}
|
|
265
247
|
/** Symbols whose object value is mutated through a property write. A const
|
|
266
248
|
* binding keeps the binding stable, not the object: following its initializer
|
|
267
249
|
* after `init.cache = undefined` would diagnose the stale literal instead of
|
|
268
250
|
* the value fetch actually observes. Built lazily and diagnostic-free. */
|
|
269
|
-
function requestInitPropMutatedSymbols(
|
|
270
|
-
const holder =
|
|
251
|
+
function requestInitPropMutatedSymbols(lowerer) {
|
|
252
|
+
const holder = lowerer;
|
|
271
253
|
if (holder.requestInitPropMutatedSyms) {
|
|
272
254
|
return holder.requestInitPropMutatedSyms;
|
|
273
255
|
}
|
|
@@ -281,7 +263,7 @@ function requestInitPropMutatedSymbols(L) {
|
|
|
281
263
|
if (!ts.isIdentifier(base))
|
|
282
264
|
return;
|
|
283
265
|
try {
|
|
284
|
-
const symbol =
|
|
266
|
+
const symbol = lowerer.resolveValueSymbol(base);
|
|
285
267
|
if (symbol)
|
|
286
268
|
symbols.add(symbol);
|
|
287
269
|
}
|
|
@@ -289,7 +271,7 @@ function requestInitPropMutatedSymbols(L) {
|
|
|
289
271
|
/* not a traceable RequestInit candidate */
|
|
290
272
|
}
|
|
291
273
|
};
|
|
292
|
-
for (const source of
|
|
274
|
+
for (const source of lowerer.program.getSourceFiles()) {
|
|
293
275
|
if (source.isDeclarationFile)
|
|
294
276
|
continue;
|
|
295
277
|
const walk = (node) => {
|
|
@@ -318,39 +300,38 @@ function requestInitPropMutatedSymbols(L) {
|
|
|
318
300
|
holder.requestInitPropMutatedSyms = symbols;
|
|
319
301
|
return symbols;
|
|
320
302
|
}
|
|
321
|
-
function requestInitConstBacked(
|
|
303
|
+
function requestInitConstBacked(lowerer, value, seen) {
|
|
322
304
|
const expr = requestInitValueExpr(value);
|
|
323
305
|
if (ts.isObjectLiteralExpression(expr))
|
|
324
306
|
return true;
|
|
325
307
|
if (ts.isConditionalExpression(expr)) {
|
|
326
|
-
const selected = requestInitStaticBoolean(
|
|
308
|
+
const selected = requestInitStaticBoolean(lowerer, expr.condition);
|
|
327
309
|
if (selected !== null) {
|
|
328
|
-
return requestInitConstBacked(
|
|
310
|
+
return requestInitConstBacked(lowerer, selected ? expr.whenTrue : expr.whenFalse, new Set(seen));
|
|
329
311
|
}
|
|
330
|
-
return requestInitConstBacked(
|
|
331
|
-
requestInitConstBacked(
|
|
312
|
+
return requestInitConstBacked(lowerer, expr.whenTrue, new Set(seen)) &&
|
|
313
|
+
requestInitConstBacked(lowerer, expr.whenFalse, new Set(seen));
|
|
332
314
|
}
|
|
333
315
|
if (!ts.isIdentifier(expr))
|
|
334
316
|
return false;
|
|
335
|
-
const symbol =
|
|
317
|
+
const symbol = lowerer.resolveValueSymbol(expr);
|
|
336
318
|
if (!symbol || seen.has(symbol))
|
|
337
319
|
return false;
|
|
338
|
-
if (requestInitPropMutatedSymbols(
|
|
320
|
+
if (requestInitPropMutatedSymbols(lowerer).has(symbol))
|
|
339
321
|
return false;
|
|
340
322
|
seen.add(symbol);
|
|
341
|
-
const declarations =
|
|
323
|
+
const declarations = lowerer.checker.declarationsOf(symbol).filter((declaration) => ts.isVariableDeclaration(declaration) &&
|
|
342
324
|
declaration.initializer !== undefined &&
|
|
343
325
|
ts.isVariableDeclarationList(declaration.parent) &&
|
|
344
326
|
(declaration.parent.flags & ts.NodeFlags.Const) !== 0);
|
|
345
|
-
return declarations.length > 0 && declarations.every((declaration) => requestInitConstBacked(
|
|
327
|
+
return declarations.length > 0 && declarations.every((declaration) => requestInitConstBacked(lowerer, declaration.initializer, new Set(seen)));
|
|
346
328
|
}
|
|
347
|
-
/** Visit the
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
|
|
351
|
-
function visitRequestInitConstPropertyValues(L, value, key, seen, visit) {
|
|
329
|
+
/** Visit the values selected by one key or index on a const-backed object or
|
|
330
|
+
* array. Property symbols can come from annotations rather than the literal
|
|
331
|
+
* supplying the runtime value, so tracing follows receiver initializers. */
|
|
332
|
+
function visitRequestInitConstSelectedValues(lowerer, value, selector, seen, visit) {
|
|
352
333
|
const expr = requestInitValueExpr(value);
|
|
353
|
-
if (ts.isObjectLiteralExpression(expr)) {
|
|
334
|
+
if (selector.kind === "property" && ts.isObjectLiteralExpression(expr)) {
|
|
354
335
|
// Last contributor wins. A definite later property (including one from
|
|
355
336
|
// a statically traced spread) hides earlier values exactly as it does at
|
|
356
337
|
// runtime; a conditional/missing spread keeps the earlier contributor
|
|
@@ -358,12 +339,12 @@ function visitRequestInitConstPropertyValues(L, value, key, seen, visit) {
|
|
|
358
339
|
for (let i = expr.properties.length - 1; i >= 0; i--) {
|
|
359
340
|
const property = expr.properties[i];
|
|
360
341
|
if (ts.isSpreadAssignment(property)) {
|
|
361
|
-
const defines =
|
|
342
|
+
const defines = visitRequestInitConstSelectedValues(lowerer, property.expression, selector, new Set(seen), visit);
|
|
362
343
|
if (defines)
|
|
363
344
|
return true;
|
|
364
345
|
continue;
|
|
365
346
|
}
|
|
366
|
-
if (requestInitLiteralKey(
|
|
347
|
+
if (requestInitLiteralKey(lowerer, property) !== selector.key)
|
|
367
348
|
continue;
|
|
368
349
|
if (ts.isPropertyAssignment(property)) {
|
|
369
350
|
visit(property.initializer);
|
|
@@ -376,58 +357,8 @@ function visitRequestInitConstPropertyValues(L, value, key, seen, visit) {
|
|
|
376
357
|
}
|
|
377
358
|
return false;
|
|
378
359
|
}
|
|
379
|
-
if (ts.
|
|
380
|
-
const
|
|
381
|
-
if (selected !== null) {
|
|
382
|
-
return visitRequestInitConstPropertyValues(L, selected ? expr.whenTrue : expr.whenFalse, key, seen, visit);
|
|
383
|
-
}
|
|
384
|
-
const whenTrue = visitRequestInitConstPropertyValues(L, expr.whenTrue, key, new Set(seen), visit);
|
|
385
|
-
const whenFalse = visitRequestInitConstPropertyValues(L, expr.whenFalse, key, new Set(seen), visit);
|
|
386
|
-
return whenTrue && whenFalse;
|
|
387
|
-
}
|
|
388
|
-
if (ts.isPropertyAccessExpression(expr) || ts.isElementAccessExpression(expr)) {
|
|
389
|
-
const member = ts.isPropertyAccessExpression(expr)
|
|
390
|
-
? expr.name.text
|
|
391
|
-
: foldedStringKeyOf(L, expr.argumentExpression);
|
|
392
|
-
if (member === null)
|
|
393
|
-
return false;
|
|
394
|
-
const nested = [];
|
|
395
|
-
const receiverDefines = visitRequestInitConstPropertyValues(L, expr.expression, member, new Set(seen), (value) => nested.push(value));
|
|
396
|
-
let nestedDefines = nested.length > 0;
|
|
397
|
-
for (const value of nested) {
|
|
398
|
-
if (!visitRequestInitConstPropertyValues(L, value, key, new Set(seen), visit)) {
|
|
399
|
-
nestedDefines = false;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return receiverDefines && nestedDefines;
|
|
403
|
-
}
|
|
404
|
-
if (!ts.isIdentifier(expr))
|
|
405
|
-
return false;
|
|
406
|
-
const symbol = L.resolveValueSymbol(expr);
|
|
407
|
-
if (!symbol || seen.has(symbol))
|
|
408
|
-
return false;
|
|
409
|
-
if (requestInitPropMutatedSymbols(L).has(symbol))
|
|
410
|
-
return false;
|
|
411
|
-
seen.add(symbol);
|
|
412
|
-
let sawDeclaration = false;
|
|
413
|
-
let defines = true;
|
|
414
|
-
for (const declaration of L.checker.declarationsOf(symbol)) {
|
|
415
|
-
if (ts.isVariableDeclaration(declaration) &&
|
|
416
|
-
declaration.initializer !== undefined &&
|
|
417
|
-
ts.isVariableDeclarationList(declaration.parent) &&
|
|
418
|
-
(declaration.parent.flags & ts.NodeFlags.Const) !== 0) {
|
|
419
|
-
sawDeclaration = true;
|
|
420
|
-
if (!visitRequestInitConstPropertyValues(L, declaration.initializer, key, new Set(seen), visit)) {
|
|
421
|
-
defines = false;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return sawDeclaration && defines;
|
|
426
|
-
}
|
|
427
|
-
function visitRequestInitConstIndexValues(L, value, index, seen, visit) {
|
|
428
|
-
const expr = requestInitValueExpr(value);
|
|
429
|
-
if (ts.isArrayLiteralExpression(expr)) {
|
|
430
|
-
const element = expr.elements[index];
|
|
360
|
+
if (selector.kind === "index" && ts.isArrayLiteralExpression(expr)) {
|
|
361
|
+
const element = expr.elements[selector.index];
|
|
431
362
|
if (element === undefined ||
|
|
432
363
|
ts.isOmittedExpression(element) ||
|
|
433
364
|
ts.isSpreadElement(element)) {
|
|
@@ -437,25 +368,25 @@ function visitRequestInitConstIndexValues(L, value, index, seen, visit) {
|
|
|
437
368
|
return true;
|
|
438
369
|
}
|
|
439
370
|
if (ts.isConditionalExpression(expr)) {
|
|
440
|
-
const selected = requestInitStaticBoolean(
|
|
371
|
+
const selected = requestInitStaticBoolean(lowerer, expr.condition);
|
|
441
372
|
if (selected !== null) {
|
|
442
|
-
return
|
|
373
|
+
return visitRequestInitConstSelectedValues(lowerer, selected ? expr.whenTrue : expr.whenFalse, selector, seen, visit);
|
|
443
374
|
}
|
|
444
|
-
const whenTrue =
|
|
445
|
-
const whenFalse =
|
|
375
|
+
const whenTrue = visitRequestInitConstSelectedValues(lowerer, expr.whenTrue, selector, new Set(seen), visit);
|
|
376
|
+
const whenFalse = visitRequestInitConstSelectedValues(lowerer, expr.whenFalse, selector, new Set(seen), visit);
|
|
446
377
|
return whenTrue && whenFalse;
|
|
447
378
|
}
|
|
448
379
|
if (ts.isPropertyAccessExpression(expr) || ts.isElementAccessExpression(expr)) {
|
|
449
380
|
const member = ts.isPropertyAccessExpression(expr)
|
|
450
381
|
? expr.name.text
|
|
451
|
-
: foldedStringKeyOf(
|
|
382
|
+
: foldedStringKeyOf(lowerer, expr.argumentExpression);
|
|
452
383
|
if (member === null)
|
|
453
384
|
return false;
|
|
454
385
|
const nested = [];
|
|
455
|
-
const receiverDefines =
|
|
386
|
+
const receiverDefines = visitRequestInitConstSelectedValues(lowerer, expr.expression, { kind: "property", key: member }, new Set(seen), (value) => nested.push(value));
|
|
456
387
|
let nestedDefines = nested.length > 0;
|
|
457
388
|
for (const value of nested) {
|
|
458
|
-
if (!
|
|
389
|
+
if (!visitRequestInitConstSelectedValues(lowerer, value, selector, new Set(seen), visit)) {
|
|
459
390
|
nestedDefines = false;
|
|
460
391
|
}
|
|
461
392
|
}
|
|
@@ -463,28 +394,28 @@ function visitRequestInitConstIndexValues(L, value, index, seen, visit) {
|
|
|
463
394
|
}
|
|
464
395
|
if (!ts.isIdentifier(expr))
|
|
465
396
|
return false;
|
|
466
|
-
const symbol =
|
|
397
|
+
const symbol = lowerer.resolveValueSymbol(expr);
|
|
467
398
|
if (!symbol || seen.has(symbol))
|
|
468
399
|
return false;
|
|
469
|
-
if (requestInitPropMutatedSymbols(
|
|
400
|
+
if (requestInitPropMutatedSymbols(lowerer).has(symbol))
|
|
470
401
|
return false;
|
|
471
402
|
seen.add(symbol);
|
|
472
403
|
let sawDeclaration = false;
|
|
473
404
|
let defines = true;
|
|
474
|
-
for (const declaration of
|
|
405
|
+
for (const declaration of lowerer.checker.declarationsOf(symbol)) {
|
|
475
406
|
if (ts.isVariableDeclaration(declaration) &&
|
|
476
407
|
declaration.initializer !== undefined &&
|
|
477
408
|
ts.isVariableDeclarationList(declaration.parent) &&
|
|
478
409
|
(declaration.parent.flags & ts.NodeFlags.Const) !== 0) {
|
|
479
410
|
sawDeclaration = true;
|
|
480
|
-
if (!
|
|
411
|
+
if (!visitRequestInitConstSelectedValues(lowerer, declaration.initializer, selector, new Set(seen), visit)) {
|
|
481
412
|
defines = false;
|
|
482
413
|
}
|
|
483
414
|
}
|
|
484
415
|
}
|
|
485
416
|
return sawDeclaration && defines;
|
|
486
417
|
}
|
|
487
|
-
function requestInitConstBindingSource(
|
|
418
|
+
function requestInitConstBindingSource(lowerer, declaration) {
|
|
488
419
|
const selectors = [];
|
|
489
420
|
let current = declaration;
|
|
490
421
|
while (true) {
|
|
@@ -492,7 +423,7 @@ function requestInitConstBindingSource(L, declaration) {
|
|
|
492
423
|
if (ts.isObjectBindingPattern(pattern)) {
|
|
493
424
|
if (current.dotDotDotToken)
|
|
494
425
|
return null;
|
|
495
|
-
const key = fetchObjectBindingMemberName(
|
|
426
|
+
const key = fetchObjectBindingMemberName(lowerer, current);
|
|
496
427
|
if (key === null)
|
|
497
428
|
return null;
|
|
498
429
|
selectors.unshift({ kind: "property", key });
|
|
@@ -522,7 +453,7 @@ function requestInitConstBindingSource(L, declaration) {
|
|
|
522
453
|
return { initializer: owner.initializer, selectors };
|
|
523
454
|
}
|
|
524
455
|
}
|
|
525
|
-
function visitRequestInitConstBindingValues(
|
|
456
|
+
function visitRequestInitConstBindingValues(lowerer, value, selectors, seen, visit) {
|
|
526
457
|
const selector = selectors[0];
|
|
527
458
|
if (selector === undefined) {
|
|
528
459
|
visit(value);
|
|
@@ -530,59 +461,57 @@ function visitRequestInitConstBindingValues(L, value, selectors, seen, visit) {
|
|
|
530
461
|
}
|
|
531
462
|
let nestedDefines = true;
|
|
532
463
|
const visitNested = (nested) => {
|
|
533
|
-
if (!visitRequestInitConstBindingValues(
|
|
464
|
+
if (!visitRequestInitConstBindingValues(lowerer, nested, selectors.slice(1), new Set(seen), visit)) {
|
|
534
465
|
nestedDefines = false;
|
|
535
466
|
}
|
|
536
467
|
};
|
|
537
|
-
const defines = selector
|
|
538
|
-
? visitRequestInitConstPropertyValues(L, value, selector.key, seen, visitNested)
|
|
539
|
-
: visitRequestInitConstIndexValues(L, value, selector.index, seen, visitNested);
|
|
468
|
+
const defines = visitRequestInitConstSelectedValues(lowerer, value, selector, seen, visitNested);
|
|
540
469
|
return defines && nestedDefines;
|
|
541
470
|
}
|
|
542
|
-
function fenceRequestInitProperty(
|
|
471
|
+
function fenceRequestInitProperty(lowerer, access, seen) {
|
|
543
472
|
const key = ts.isPropertyAccessExpression(access)
|
|
544
473
|
? access.name.text
|
|
545
|
-
: foldedStringKeyOf(
|
|
474
|
+
: foldedStringKeyOf(lowerer, access.argumentExpression);
|
|
546
475
|
if (key === null)
|
|
547
476
|
return;
|
|
548
|
-
|
|
549
|
-
if (!requestInitConstBacked(
|
|
477
|
+
visitRequestInitConstSelectedValues(lowerer, access.expression, { kind: "property", key }, new Set(), (value) => fenceRequestInitValueInner(lowerer, value, seen));
|
|
478
|
+
if (!requestInitConstBacked(lowerer, access.expression, new Set()))
|
|
550
479
|
return;
|
|
551
480
|
const symbol = ts.isPropertyAccessExpression(access)
|
|
552
|
-
?
|
|
553
|
-
:
|
|
481
|
+
? lowerer.checker.getSymbolAtLocation(access.name)
|
|
482
|
+
: lowerer.checker.getPropertyOfType(lowerer.typeOf(access.expression), key);
|
|
554
483
|
if (!symbol || seen.has(symbol))
|
|
555
484
|
return;
|
|
556
485
|
seen.add(symbol);
|
|
557
|
-
for (const declaration of
|
|
486
|
+
for (const declaration of lowerer.checker.declarationsOf(symbol)) {
|
|
558
487
|
if (ts.isPropertyAssignment(declaration)) {
|
|
559
|
-
fenceRequestInitValueInner(
|
|
488
|
+
fenceRequestInitValueInner(lowerer, declaration.initializer, seen);
|
|
560
489
|
}
|
|
561
490
|
else if (ts.isShorthandPropertyAssignment(declaration) &&
|
|
562
491
|
ts.isIdentifier(declaration.name)) {
|
|
563
|
-
fenceRequestInitValueInner(
|
|
492
|
+
fenceRequestInitValueInner(lowerer, declaration.name, seen);
|
|
564
493
|
}
|
|
565
494
|
}
|
|
566
495
|
}
|
|
567
|
-
function fenceRequestInitObject(
|
|
568
|
-
const contextual =
|
|
496
|
+
function fenceRequestInitObject(lowerer, init, seen) {
|
|
497
|
+
const contextual = lowerer.checker.getContextualType(init);
|
|
569
498
|
const contextualArms = contextual?.isUnionType() ? ts.constituentTypes(contextual) : contextual ? [contextual] : [];
|
|
570
499
|
const rows = NODE24_FETCH_COMPAT_PROFILE.inventory.entries.filter((entry) => entry.owner === "RequestInit" && entry.placement === "dictionary");
|
|
571
500
|
const shadowed = new Set();
|
|
572
501
|
const fence = (row, value, blame) => {
|
|
573
|
-
if (
|
|
502
|
+
if (lowerer.dynamic ? row.status !== "unsupported" : row.status === "static")
|
|
574
503
|
return;
|
|
575
504
|
if (value !== null) {
|
|
576
|
-
const type =
|
|
505
|
+
const type = lowerer.typeOf(requestInitValueExpr(value));
|
|
577
506
|
if (ts.isVoidExpression(requestInitValueExpr(value)) ||
|
|
578
507
|
(type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) !== 0) {
|
|
579
508
|
return;
|
|
580
509
|
}
|
|
581
510
|
}
|
|
582
511
|
const sym = contextualArms
|
|
583
|
-
.map((arm) =>
|
|
512
|
+
.map((arm) => lowerer.checker.getPropertyOfType(arm, row.member))
|
|
584
513
|
.find((member) => member !== undefined);
|
|
585
|
-
|
|
514
|
+
lowerer.noLowering(`RequestInit option '${row.member}'${lowerer.dynamic ? "" : " in a static build"}`, blame, row.reason ??
|
|
586
515
|
"the native static RequestInit surface is method, headers, body, duplex, redirect, and signal", sym);
|
|
587
516
|
};
|
|
588
517
|
// Object spread is last-write-wins. Walk from the end and trace only the
|
|
@@ -595,13 +524,13 @@ function fenceRequestInitObject(L, init, seen) {
|
|
|
595
524
|
for (const row of rows) {
|
|
596
525
|
if (shadowed.has(row.member))
|
|
597
526
|
continue;
|
|
598
|
-
const defines =
|
|
527
|
+
const defines = visitRequestInitConstSelectedValues(lowerer, prop.expression, { kind: "property", key: row.member }, new Set(seen), (value) => fence(row, value, value));
|
|
599
528
|
if (defines)
|
|
600
529
|
shadowed.add(row.member);
|
|
601
530
|
}
|
|
602
531
|
continue;
|
|
603
532
|
}
|
|
604
|
-
const key = requestInitLiteralKey(
|
|
533
|
+
const key = requestInitLiteralKey(lowerer, prop);
|
|
605
534
|
if (key === null || shadowed.has(key))
|
|
606
535
|
continue;
|
|
607
536
|
shadowed.add(key);
|
|
@@ -622,25 +551,25 @@ function fenceRequestInitObject(L, init, seen) {
|
|
|
622
551
|
* members, so follow their initializers until the profile can make the
|
|
623
552
|
* decision. Runtime-computed values keep both fetch runtimes' defensive
|
|
624
553
|
* validation because there is no source member to diagnose. */
|
|
625
|
-
function fenceRequestInitValueInner(
|
|
554
|
+
function fenceRequestInitValueInner(lowerer, value, seen) {
|
|
626
555
|
const expr = requestInitValueExpr(value);
|
|
627
556
|
if (ts.isObjectLiteralExpression(expr)) {
|
|
628
|
-
fenceRequestInitObject(
|
|
557
|
+
fenceRequestInitObject(lowerer, expr, seen);
|
|
629
558
|
return;
|
|
630
559
|
}
|
|
631
560
|
if (ts.isConditionalExpression(expr)) {
|
|
632
|
-
const selected = requestInitStaticBoolean(
|
|
561
|
+
const selected = requestInitStaticBoolean(lowerer, expr.condition);
|
|
633
562
|
if (selected !== null) {
|
|
634
|
-
fenceRequestInitValueInner(
|
|
563
|
+
fenceRequestInitValueInner(lowerer, selected ? expr.whenTrue : expr.whenFalse, seen);
|
|
635
564
|
}
|
|
636
565
|
else {
|
|
637
|
-
fenceRequestInitValueInner(
|
|
638
|
-
fenceRequestInitValueInner(
|
|
566
|
+
fenceRequestInitValueInner(lowerer, expr.whenTrue, seen);
|
|
567
|
+
fenceRequestInitValueInner(lowerer, expr.whenFalse, seen);
|
|
639
568
|
}
|
|
640
569
|
return;
|
|
641
570
|
}
|
|
642
571
|
if (ts.isPropertyAccessExpression(expr) || ts.isElementAccessExpression(expr)) {
|
|
643
|
-
fenceRequestInitProperty(
|
|
572
|
+
fenceRequestInitProperty(lowerer, expr, seen);
|
|
644
573
|
return;
|
|
645
574
|
}
|
|
646
575
|
if (!ts.isIdentifier(expr))
|
|
@@ -649,17 +578,17 @@ function fenceRequestInitValueInner(L, value, seen) {
|
|
|
649
578
|
// exported const whose initializer carries the dictionary members.
|
|
650
579
|
// Chase the value alias so local and cross-module const plumbing share
|
|
651
580
|
// the same source-profile fence.
|
|
652
|
-
const symbol =
|
|
581
|
+
const symbol = lowerer.resolveValueSymbol(expr);
|
|
653
582
|
if (!symbol || seen.has(symbol))
|
|
654
583
|
return;
|
|
655
|
-
if (requestInitPropMutatedSymbols(
|
|
584
|
+
if (requestInitPropMutatedSymbols(lowerer).has(symbol))
|
|
656
585
|
return;
|
|
657
586
|
seen.add(symbol);
|
|
658
|
-
for (const declaration of
|
|
587
|
+
for (const declaration of lowerer.checker.declarationsOf(symbol)) {
|
|
659
588
|
if (ts.isBindingElement(declaration)) {
|
|
660
|
-
const source = requestInitConstBindingSource(
|
|
589
|
+
const source = requestInitConstBindingSource(lowerer, declaration);
|
|
661
590
|
if (source !== null) {
|
|
662
|
-
visitRequestInitConstBindingValues(
|
|
591
|
+
visitRequestInitConstBindingValues(lowerer, source.initializer, source.selectors, new Set(seen), (bindingValue) => fenceRequestInitValueInner(lowerer, bindingValue, new Set(seen)));
|
|
663
592
|
}
|
|
664
593
|
continue;
|
|
665
594
|
}
|
|
@@ -669,11 +598,11 @@ function fenceRequestInitValueInner(L, value, seen) {
|
|
|
669
598
|
(declaration.parent.flags & ts.NodeFlags.Const) === 0) {
|
|
670
599
|
continue;
|
|
671
600
|
}
|
|
672
|
-
fenceRequestInitValueInner(
|
|
601
|
+
fenceRequestInitValueInner(lowerer, declaration.initializer, seen);
|
|
673
602
|
}
|
|
674
603
|
}
|
|
675
|
-
function fenceRequestInitValue(
|
|
676
|
-
fenceRequestInitValueInner(
|
|
604
|
+
function fenceRequestInitValue(lowerer, value) {
|
|
605
|
+
fenceRequestInitValueInner(lowerer, value, new Set());
|
|
677
606
|
}
|
|
678
607
|
/** USER-code `fetch(url)` / `fetch(url, init)` — the ambient global
|
|
679
608
|
* (provenance, not the name: a user's own `fetch` never matches).
|
|
@@ -697,41 +626,41 @@ function fenceRequestInitValue(L, value) {
|
|
|
697
626
|
* the user's narrowing sites through the validated-exit machinery.
|
|
698
627
|
* Null for anything that isn't THE ambient fetch, so lowerCall keeps
|
|
699
628
|
* trying. */
|
|
700
|
-
export function lowerFetchCall(
|
|
629
|
+
export function lowerFetchCall(lowerer, call) {
|
|
701
630
|
const callee = call.expression;
|
|
702
631
|
if (!ts.isIdentifier(callee) || callee.text !== "fetch")
|
|
703
632
|
return null;
|
|
704
633
|
if (call.questionDotToken)
|
|
705
634
|
return null;
|
|
706
|
-
const symbol =
|
|
707
|
-
if (!symbol || !
|
|
635
|
+
const symbol = lowerer.resolveValueSymbol(callee);
|
|
636
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
708
637
|
return null;
|
|
709
638
|
if (call.arguments.length < 1)
|
|
710
639
|
return null;
|
|
711
640
|
const loc = locOf(call);
|
|
712
641
|
const initNode = call.arguments[1];
|
|
713
642
|
if (initNode !== undefined)
|
|
714
|
-
fenceRequestInitValue(
|
|
715
|
-
if (!
|
|
643
|
+
fenceRequestInitValue(lowerer, initNode);
|
|
644
|
+
if (!lowerer.dynamic) {
|
|
716
645
|
const inputNode = call.arguments[0];
|
|
717
|
-
const input =
|
|
646
|
+
const input = lowerer.lowerExpr(inputNode);
|
|
718
647
|
let init;
|
|
719
648
|
if (initNode === undefined) {
|
|
720
649
|
init = dynUndefinedExpr(loc);
|
|
721
650
|
}
|
|
722
651
|
else if (ts.isObjectLiteralExpression(initNode)) {
|
|
723
|
-
init = lowerDynObjectLiteral(
|
|
652
|
+
init = lowerDynObjectLiteral(lowerer, initNode);
|
|
724
653
|
}
|
|
725
654
|
else {
|
|
726
|
-
init =
|
|
655
|
+
init = lowerer.lowerExprExpecting(initNode, DYN);
|
|
727
656
|
}
|
|
728
657
|
// Calling a WebIDL operation has two distinct phases: JavaScript
|
|
729
658
|
// first evaluates every argument expression, then the callee converts
|
|
730
659
|
// those values. In particular, evaluating RequestInit may mutate a
|
|
731
660
|
// URL object passed as input; its href must not be snapshotted until
|
|
732
661
|
// all argument expressions (including ignored surplus ones) ran.
|
|
733
|
-
const inputLocal =
|
|
734
|
-
const initLocal =
|
|
662
|
+
const inputLocal = lowerer.declareHiddenLocal("%fetchInput", input.type);
|
|
663
|
+
const initLocal = lowerer.declareHiddenLocal("%fetchInit", init.type);
|
|
735
664
|
const inputRef = {
|
|
736
665
|
kind: "varRef",
|
|
737
666
|
localId: inputLocal.id,
|
|
@@ -750,11 +679,11 @@ export function lowerFetchCall(L, call) {
|
|
|
750
679
|
];
|
|
751
680
|
for (const argument of call.arguments.slice(2)) {
|
|
752
681
|
if (ts.isSpreadElement(argument)) {
|
|
753
|
-
|
|
682
|
+
lowerer.noLowering("spread surplus arguments on static fetch()", argument, "pass surplus arguments without spread syntax");
|
|
754
683
|
}
|
|
755
684
|
const discarded = ts.isVoidExpression(argument)
|
|
756
|
-
?
|
|
757
|
-
:
|
|
685
|
+
? lowerer.lowerExpr(argument.expression)
|
|
686
|
+
: lowerer.lowerExpr(argument);
|
|
758
687
|
stmts.push({ kind: "exprStmt", expr: discarded, loc: discarded.loc });
|
|
759
688
|
}
|
|
760
689
|
const url = input.type.kind === "url"
|
|
@@ -765,7 +694,7 @@ export function lowerFetchCall(L, call) {
|
|
|
765
694
|
type: STRING,
|
|
766
695
|
loc: locOf(inputNode),
|
|
767
696
|
}
|
|
768
|
-
:
|
|
697
|
+
: lowerer.coerceInto(inputNode, inputRef, STRING);
|
|
769
698
|
const answer = {
|
|
770
699
|
kind: "libCall",
|
|
771
700
|
fn: "fetch.start",
|
|
@@ -783,22 +712,22 @@ export function lowerFetchCall(L, call) {
|
|
|
783
712
|
// through and dashed header keys ("content-type") are plain engine
|
|
784
713
|
// property names. Non-literal inits marshal as a whole (JSON-safe
|
|
785
714
|
// records; a signal field inside one fences with the boundary rule).
|
|
786
|
-
const args = call.arguments.map((a) => ts.isObjectLiteralExpression(a) ? lowerIslandObjectLiteral(
|
|
715
|
+
const args = call.arguments.map((a) => ts.isObjectLiteralExpression(a) ? lowerIslandObjectLiteral(lowerer, a) : lowerer.jsvalIn(lowerer.lowerExpr(a), a));
|
|
787
716
|
const raw = { kind: "jsOp", op: "callFn", args: [fetchFn, ...args], type: JSVAL, loc };
|
|
788
717
|
return { kind: "jsBridgePromise", value: raw, type: { kind: "promise", inner: JSVAL }, loc };
|
|
789
718
|
}
|
|
790
719
|
/** Static Response.json(): consume the native Response's readable body
|
|
791
720
|
* stream and parse its UTF-8 payload into the ordinary checked-dynamic
|
|
792
721
|
* JSON tree. Syntax and stream failures reject at await like the web API. */
|
|
793
|
-
export function lowerStaticResponseCall(
|
|
794
|
-
if (
|
|
722
|
+
export function lowerStaticResponseCall(lowerer, call) {
|
|
723
|
+
if (lowerer.dynamic ||
|
|
795
724
|
call.questionDotToken ||
|
|
796
725
|
(!ts.isPropertyAccessExpression(call.expression) &&
|
|
797
726
|
!ts.isElementAccessExpression(call.expression))) {
|
|
798
727
|
return null;
|
|
799
728
|
}
|
|
800
729
|
const access = call.expression;
|
|
801
|
-
const member = staticResponseMemberName(
|
|
730
|
+
const member = staticResponseMemberName(lowerer, access);
|
|
802
731
|
if (access.questionDotToken ||
|
|
803
732
|
(member !== "json" &&
|
|
804
733
|
member !== "text" &&
|
|
@@ -807,17 +736,17 @@ export function lowerStaticResponseCall(L, call) {
|
|
|
807
736
|
call.arguments.length !== 0) {
|
|
808
737
|
return null;
|
|
809
738
|
}
|
|
810
|
-
const recvType =
|
|
739
|
+
const recvType = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
811
740
|
const sym = recvType.getAliasSymbol() ?? recvType.getSymbol();
|
|
812
|
-
if (!sym || sym.name !== "Response" || !
|
|
741
|
+
if (!sym || sym.name !== "Response" || !lowerer.isStdlibSymbol(sym))
|
|
813
742
|
return null;
|
|
814
743
|
if (member === "arrayBuffer") {
|
|
815
|
-
|
|
744
|
+
lowerer.noLowering("Response.arrayBuffer() in a static build", call, "use Response.bytes() for the native Uint8Array body; free-standing ArrayBuffer values have no static representation", sym);
|
|
816
745
|
}
|
|
817
|
-
const recv =
|
|
746
|
+
const recv = lowerer.lowerExpr(access.expression);
|
|
818
747
|
if (recv.type.kind !== "dyn")
|
|
819
748
|
return null;
|
|
820
|
-
return lowerStaticFixedFetchMethodCall(
|
|
749
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, member, recv, [], (receiver) => member === "text" || member === "bytes"
|
|
821
750
|
? {
|
|
822
751
|
kind: "libCall",
|
|
823
752
|
fn: member === "text" ? "fetch.responseText" : "fetch.responseBytes",
|
|
@@ -836,25 +765,25 @@ export function lowerStaticResponseCall(L, call) {
|
|
|
836
765
|
loc: locOf(call),
|
|
837
766
|
});
|
|
838
767
|
}
|
|
839
|
-
function staticResponseMemberName(
|
|
768
|
+
function staticResponseMemberName(lowerer, access) {
|
|
840
769
|
if (ts.isPropertyAccessExpression(access))
|
|
841
770
|
return access.name.text;
|
|
842
|
-
const members = fetchElementMemberNames(
|
|
771
|
+
const members = fetchElementMemberNames(lowerer, access.argumentExpression);
|
|
843
772
|
return members?.length === 1 ? members[0] : null;
|
|
844
773
|
}
|
|
845
774
|
/** A singleton computed member is still an evaluated JavaScript expression.
|
|
846
775
|
* The specialized static bridges know the only permitted method name, but
|
|
847
776
|
* must preserve receiver -> key -> arguments order and reject a lying cast
|
|
848
777
|
* whose runtime key is not that name. */
|
|
849
|
-
function lowerStaticFixedFetchMethodCall(
|
|
778
|
+
function lowerStaticFixedFetchMethodCall(lowerer, call, access, member, receiver, argumentValues, invoke) {
|
|
850
779
|
if (ts.isPropertyAccessExpression(access)) {
|
|
851
780
|
return invoke(receiver, [...argumentValues]);
|
|
852
781
|
}
|
|
853
782
|
const loc = locOf(call);
|
|
854
|
-
const key =
|
|
855
|
-
const receiverLocal =
|
|
856
|
-
const keyLocal =
|
|
857
|
-
const argumentLocals = argumentValues.map((argument) =>
|
|
783
|
+
const key = lowerer.lowerExprExpecting(access.argumentExpression, STRING);
|
|
784
|
+
const receiverLocal = lowerer.declareHiddenLocal("%fetchReceiver", receiver.type);
|
|
785
|
+
const keyLocal = lowerer.declareHiddenLocal("%fetchMember", STRING);
|
|
786
|
+
const argumentLocals = argumentValues.map((argument) => lowerer.declareHiddenLocal("%fetchMethodArg", argument.type));
|
|
858
787
|
const receiverRef = {
|
|
859
788
|
kind: "varRef",
|
|
860
789
|
localId: receiverLocal.id,
|
|
@@ -921,15 +850,15 @@ function lowerStaticFixedFetchMethodCall(L, call, access, member, receiver, argu
|
|
|
921
850
|
loc,
|
|
922
851
|
};
|
|
923
852
|
}
|
|
924
|
-
function fetchElementMemberNames(
|
|
853
|
+
function fetchElementMemberNames(lowerer, keyExpr) {
|
|
925
854
|
if (ts.isPropertyAccessExpression(keyExpr) &&
|
|
926
|
-
|
|
855
|
+
lowerer.isStdlibGlobal(keyExpr.expression, "Symbol") &&
|
|
927
856
|
(keyExpr.name.text === "iterator" ||
|
|
928
857
|
keyExpr.name.text === "asyncIterator" ||
|
|
929
858
|
keyExpr.name.text === "toStringTag")) {
|
|
930
859
|
return [`[Symbol.${keyExpr.name.text}]`];
|
|
931
860
|
}
|
|
932
|
-
const key =
|
|
861
|
+
const key = lowerer.typeOf(keyExpr);
|
|
933
862
|
if (key.isStringLiteralType())
|
|
934
863
|
return [key.value];
|
|
935
864
|
if (!key.isUnionType())
|
|
@@ -943,10 +872,10 @@ function fetchElementMemberNames(L, keyExpr) {
|
|
|
943
872
|
}
|
|
944
873
|
return members;
|
|
945
874
|
}
|
|
946
|
-
function fetchAccessMemberNames(
|
|
875
|
+
function fetchAccessMemberNames(lowerer, access) {
|
|
947
876
|
return ts.isPropertyAccessExpression(access)
|
|
948
877
|
? [access.name.text]
|
|
949
|
-
: fetchElementMemberNames(
|
|
878
|
+
: fetchElementMemberNames(lowerer, access.argumentExpression);
|
|
950
879
|
}
|
|
951
880
|
function fetchInventoryStatus(owner, member, placement) {
|
|
952
881
|
return NODE24_FETCH_COMPAT_PROFILE.inventory.entries.find((entry) => entry.owner === owner &&
|
|
@@ -962,18 +891,18 @@ function fetchInventoryReason(owner, member, placement) {
|
|
|
962
891
|
* methods. The inventory marks the former unsupported in both tiers; fence
|
|
963
892
|
* them explicitly so the generic call fallback cannot report SC1090 for
|
|
964
893
|
* Response.json while the other statics report SC2020. */
|
|
965
|
-
export function fenceUnsupportedFetchConstructorMember(
|
|
966
|
-
if (!
|
|
894
|
+
export function fenceUnsupportedFetchConstructorMember(lowerer, access) {
|
|
895
|
+
if (!lowerer.isStdlibGlobal(access.expression, "Response"))
|
|
967
896
|
return null;
|
|
968
|
-
const members = fetchAccessMemberNames(
|
|
897
|
+
const members = fetchAccessMemberNames(lowerer, access);
|
|
969
898
|
if (members === null)
|
|
970
899
|
return null;
|
|
971
900
|
const member = members.find((candidate) => fetchInventoryStatus("Response", candidate, "static") === "unsupported");
|
|
972
901
|
if (member === undefined)
|
|
973
902
|
return null;
|
|
974
|
-
|
|
903
|
+
lowerer.noLowering(`Response.${member}`, access, "Response static constructor-object operations have no compiler lowering in either tier");
|
|
975
904
|
}
|
|
976
|
-
function hasLiveWebMutableArm(
|
|
905
|
+
function hasLiveWebMutableArm(lowerer, type) {
|
|
977
906
|
if (type.kind === "record" ||
|
|
978
907
|
type.kind === "array" ||
|
|
979
908
|
type.kind === "bytes") {
|
|
@@ -981,17 +910,17 @@ function hasLiveWebMutableArm(L, type) {
|
|
|
981
910
|
}
|
|
982
911
|
if (type.kind !== "union")
|
|
983
912
|
return false;
|
|
984
|
-
return
|
|
913
|
+
return lowerer.unions.get(type.unionId)?.arms.some((arm) => hasLiveWebMutableArm(lowerer, arm)) ?? false;
|
|
985
914
|
}
|
|
986
915
|
/** Box mutable data for Web API slots that expose the exact JavaScript
|
|
987
916
|
* value again. Ordinary dynFrom remains the documented copy boundary;
|
|
988
917
|
* this capsule is deliberately limited to records/arrays/bytes (including
|
|
989
918
|
* those selected at runtime from a union) that the live materializer can
|
|
990
919
|
* snapshot and commit. */
|
|
991
|
-
function lowerLiveWebValue(
|
|
992
|
-
const value = lowered ??
|
|
993
|
-
if (hasLiveWebMutableArm(
|
|
994
|
-
canConvertToDyn(value.type, (id) =>
|
|
920
|
+
function lowerLiveWebValue(lowerer, node, lowered) {
|
|
921
|
+
const value = lowered ?? lowerer.lowerExpr(node);
|
|
922
|
+
if (hasLiveWebMutableArm(lowerer, value.type) &&
|
|
923
|
+
canConvertToDyn(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
995
924
|
return {
|
|
996
925
|
kind: "dynFrom",
|
|
997
926
|
value,
|
|
@@ -1000,7 +929,7 @@ function lowerLiveWebValue(L, node, lowered) {
|
|
|
1000
929
|
loc: value.loc,
|
|
1001
930
|
};
|
|
1002
931
|
}
|
|
1003
|
-
return
|
|
932
|
+
return lowerer.coerceInto(node, value, DYN);
|
|
1004
933
|
}
|
|
1005
934
|
function fetchMethodArgumentIsLive(owner, members, index) {
|
|
1006
935
|
return ((index === 0 &&
|
|
@@ -1018,82 +947,82 @@ function fetchMethodArgumentIsLive(owner, members, index) {
|
|
|
1018
947
|
* handle. Keep the supported fallback slice on checked-dynamic dispatch, but
|
|
1019
948
|
* fence every other declared member before the generic dyn keyed-read/call
|
|
1020
949
|
* paths can turn a missing handle operation into a runtime TypeError. */
|
|
1021
|
-
export function fenceStaticResponseMember(
|
|
1022
|
-
const recvType =
|
|
950
|
+
export function fenceStaticResponseMember(lowerer, access, use) {
|
|
951
|
+
const recvType = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
1023
952
|
const sym = recvType.getAliasSymbol() ?? recvType.getSymbol();
|
|
1024
|
-
if (!sym || sym.name !== "Response" || !
|
|
953
|
+
if (!sym || sym.name !== "Response" || !lowerer.isStdlibSymbol(sym))
|
|
1025
954
|
return null;
|
|
1026
|
-
const members = fetchAccessMemberNames(
|
|
955
|
+
const members = fetchAccessMemberNames(lowerer, access);
|
|
1027
956
|
if (members === null)
|
|
1028
957
|
return null;
|
|
1029
958
|
const status = (member) => fetchInventoryStatus("Response", member, member.startsWith("[Symbol.") ? "prototype-symbol" : "prototype");
|
|
1030
|
-
if (
|
|
959
|
+
if (lowerer.dynamic && members.every((member) => status(member) !== "unsupported")) {
|
|
1031
960
|
return null;
|
|
1032
961
|
}
|
|
1033
962
|
const supported = (member) => use === "call"
|
|
1034
963
|
? STATIC_RESPONSE_CALLS.has(member)
|
|
1035
964
|
: STATIC_RESPONSE_READS.has(member);
|
|
1036
|
-
if (!
|
|
965
|
+
if (!lowerer.dynamic && members.every(supported))
|
|
1037
966
|
return null;
|
|
1038
|
-
const member = members.find((candidate) =>
|
|
967
|
+
const member = members.find((candidate) => lowerer.dynamic ? status(candidate) === "unsupported" : !supported(candidate));
|
|
1039
968
|
if (status(member) === "unsupported") {
|
|
1040
|
-
|
|
969
|
+
lowerer.noLowering(`Response.${member}`, access, fetchInventoryReason("Response", member, "prototype") ??
|
|
1041
970
|
"this Response operation has no compiler lowering in either tier", sym);
|
|
1042
971
|
}
|
|
1043
|
-
|
|
972
|
+
lowerer.noLowering(`Response.${member} in a static build`, access, "the native static Response surface is status/ok/statusText/url/redirected/headers/body/bodyUsed plus json(), text(), and bytes(); use --dynamic for the wider Web API", sym);
|
|
1044
973
|
}
|
|
1045
974
|
/** Response Headers are native checked-dynamic handles. Keep their exact
|
|
1046
975
|
* supported method slice aligned with the compatibility census so newly
|
|
1047
976
|
* observed Node members cannot fall through to a runtime missing-method
|
|
1048
977
|
* error in an engine-free build. */
|
|
1049
|
-
export function fenceStaticHeadersMember(
|
|
1050
|
-
const recvType =
|
|
978
|
+
export function fenceStaticHeadersMember(lowerer, access, use) {
|
|
979
|
+
const recvType = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
1051
980
|
const sym = recvType.getAliasSymbol() ?? recvType.getSymbol();
|
|
1052
|
-
if (!sym || sym.name !== "Headers" || !
|
|
981
|
+
if (!sym || sym.name !== "Headers" || !lowerer.isStdlibSymbol(sym))
|
|
1053
982
|
return null;
|
|
1054
|
-
const members = fetchAccessMemberNames(
|
|
983
|
+
const members = fetchAccessMemberNames(lowerer, access);
|
|
1055
984
|
if (members === null)
|
|
1056
985
|
return null;
|
|
1057
986
|
const status = (member) => fetchInventoryStatus("Headers", member, member.startsWith("[Symbol.") ? "prototype-symbol" : "prototype");
|
|
1058
|
-
if (
|
|
987
|
+
if (lowerer.dynamic && members.every((member) => status(member) !== "unsupported")) {
|
|
1059
988
|
return null;
|
|
1060
989
|
}
|
|
1061
|
-
if (!
|
|
990
|
+
if (!lowerer.dynamic && use === "call" && members.every((member) => STATIC_HEADERS_CALLS.has(member))) {
|
|
1062
991
|
return null;
|
|
1063
992
|
}
|
|
1064
|
-
const member = members.find((candidate) =>
|
|
993
|
+
const member = members.find((candidate) => lowerer.dynamic
|
|
1065
994
|
? status(candidate) === "unsupported"
|
|
1066
995
|
: use !== "call" || !STATIC_HEADERS_CALLS.has(candidate));
|
|
1067
996
|
if (status(member) === "unsupported") {
|
|
1068
|
-
|
|
997
|
+
lowerer.noLowering(`Headers.${member}`, access, "symbol-keyed Headers iteration has no compiler lowering in either tier; call entries() with --dynamic instead", sym);
|
|
1069
998
|
}
|
|
1070
|
-
|
|
999
|
+
lowerer.noLowering(`Headers.${member} in a static build`, access, "the native static Headers surface is append/delete/get/getSetCookie/has/set/forEach; use keys()/values()/entries() or symbol-keyed iteration with --dynamic, while construction remains unsupported", sym);
|
|
1071
1000
|
}
|
|
1072
1001
|
/** The native AbortController handle dispatches `abort()` directly and
|
|
1073
1002
|
* exposes `.signal` as data, but it has no first-class function value for
|
|
1074
1003
|
* the prototype method. Fence method extraction before the checked-dynamic
|
|
1075
1004
|
* keyed-read fallback can silently answer `undefined`. Dynamic builds use
|
|
1076
1005
|
* the engine's real AbortController object and retain ordinary method reads. */
|
|
1077
|
-
export function fenceStaticAbortControllerMemberRead(
|
|
1078
|
-
if (
|
|
1006
|
+
export function fenceStaticAbortControllerMemberRead(lowerer, access) {
|
|
1007
|
+
if (lowerer.dynamic)
|
|
1079
1008
|
return null;
|
|
1080
|
-
const symbol = isStdlibFetchInterface(
|
|
1009
|
+
const symbol = isStdlibFetchInterface(lowerer, access.expression, "AbortController");
|
|
1081
1010
|
if (!symbol)
|
|
1082
1011
|
return null;
|
|
1083
|
-
const members = fetchAccessMemberNames(
|
|
1012
|
+
const members = fetchAccessMemberNames(lowerer, access);
|
|
1084
1013
|
if (members === null || !members.includes("abort"))
|
|
1085
1014
|
return null;
|
|
1086
|
-
|
|
1015
|
+
lowerer.noLowering("AbortController.abort through method extraction in a static build", access, "call controller.abort(...) directly; the native AbortController handle does not expose abort as a first-class function value", symbol);
|
|
1087
1016
|
}
|
|
1088
|
-
function isStdlibFetchInterface(
|
|
1089
|
-
const type =
|
|
1017
|
+
function isStdlibFetchInterface(lowerer, node, owner) {
|
|
1018
|
+
const type = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(node));
|
|
1090
1019
|
for (const symbol of [type.getSymbol(), type.getAliasSymbol()]) {
|
|
1091
|
-
if (symbol?.name === owner &&
|
|
1020
|
+
if (symbol?.name === owner && lowerer.isStdlibSymbol(symbol))
|
|
1092
1021
|
return symbol;
|
|
1093
1022
|
}
|
|
1094
1023
|
return null;
|
|
1095
1024
|
}
|
|
1096
|
-
function fetchObjectBindingMemberName(
|
|
1025
|
+
function fetchObjectBindingMemberName(lowerer, element) {
|
|
1097
1026
|
const name = element.propertyName ??
|
|
1098
1027
|
(element.name !== undefined && ts.isIdentifier(element.name) ? element.name : undefined);
|
|
1099
1028
|
if (name === undefined)
|
|
@@ -1105,12 +1034,12 @@ function fetchObjectBindingMemberName(L, element) {
|
|
|
1105
1034
|
if (ts.isNumericLiteral(name))
|
|
1106
1035
|
return String(Number(name.text));
|
|
1107
1036
|
if (ts.isComputedPropertyName(name)) {
|
|
1108
|
-
const members = fetchElementMemberNames(
|
|
1037
|
+
const members = fetchElementMemberNames(lowerer, name.expression);
|
|
1109
1038
|
return members?.length === 1 ? members[0] : null;
|
|
1110
1039
|
}
|
|
1111
1040
|
return null;
|
|
1112
1041
|
}
|
|
1113
|
-
function fetchObjectAssignmentMemberName(
|
|
1042
|
+
function fetchObjectAssignmentMemberName(lowerer, property) {
|
|
1114
1043
|
if (ts.isSpreadAssignment(property))
|
|
1115
1044
|
return null;
|
|
1116
1045
|
const name = property.name;
|
|
@@ -1121,20 +1050,20 @@ function fetchObjectAssignmentMemberName(L, property) {
|
|
|
1121
1050
|
if (ts.isNumericLiteral(name))
|
|
1122
1051
|
return String(Number(name.text));
|
|
1123
1052
|
if (ts.isComputedPropertyName(name)) {
|
|
1124
|
-
const members = fetchElementMemberNames(
|
|
1053
|
+
const members = fetchElementMemberNames(lowerer, name.expression);
|
|
1125
1054
|
return members?.length === 1 ? members[0] : null;
|
|
1126
1055
|
}
|
|
1127
1056
|
return null;
|
|
1128
1057
|
}
|
|
1129
|
-
function fetchInterfaceInventoryOwner(
|
|
1130
|
-
const type =
|
|
1058
|
+
function fetchInterfaceInventoryOwner(lowerer, node) {
|
|
1059
|
+
const type = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(node));
|
|
1131
1060
|
const symbol = [type.getSymbol(), type.getAliasSymbol()].find((candidate) => candidate !== undefined &&
|
|
1132
1061
|
NODE24_FETCH_COMPAT_PROFILE.inventory.interfaces.includes(candidate.name) &&
|
|
1133
|
-
|
|
1062
|
+
lowerer.isStdlibSymbol(candidate));
|
|
1134
1063
|
return symbol ? { owner: symbol.name, symbol } : null;
|
|
1135
1064
|
}
|
|
1136
|
-
function fenceFetchObjectMembers(
|
|
1137
|
-
const resolved = fetchInterfaceInventoryOwner(
|
|
1065
|
+
function fenceFetchObjectMembers(lowerer, ownerNode, members) {
|
|
1066
|
+
const resolved = fetchInterfaceInventoryOwner(lowerer, ownerNode);
|
|
1138
1067
|
if (!resolved)
|
|
1139
1068
|
return;
|
|
1140
1069
|
const { owner, symbol } = resolved;
|
|
@@ -1146,16 +1075,16 @@ function fenceFetchObjectMembers(L, ownerNode, members) {
|
|
|
1146
1075
|
entry.placement === "prototype-symbol"));
|
|
1147
1076
|
if (!row || row.status === "out-of-scope")
|
|
1148
1077
|
continue;
|
|
1149
|
-
if (
|
|
1078
|
+
if (lowerer.dynamic && row.status !== "unsupported")
|
|
1150
1079
|
continue;
|
|
1151
1080
|
// Static data properties retain the ordinary checked-dynamic keyed-read
|
|
1152
1081
|
// lowering. Only a method extraction loses the receiver that its direct
|
|
1153
1082
|
// call bridge would preserve; non-static rows keep their inventory fence.
|
|
1154
1083
|
const operation = NODE24_FETCH_COMPAT_PROFILE.operations.find((candidate) => candidate.id === row.id);
|
|
1155
|
-
if (!
|
|
1084
|
+
if (!lowerer.dynamic && row.status === "static" && operation?.kind === "property") {
|
|
1156
1085
|
continue;
|
|
1157
1086
|
}
|
|
1158
|
-
|
|
1087
|
+
lowerer.noLowering(`${owner}.${member}${lowerer.dynamic ? "" : " through object destructuring in a static build"}`, node, row.reason ??
|
|
1159
1088
|
"the direct lowered read/call form has a compiler bridge, but extracting this member as a value does not", symbol);
|
|
1160
1089
|
}
|
|
1161
1090
|
}
|
|
@@ -1164,20 +1093,20 @@ function fenceFetchObjectMembers(L, ownerNode, members) {
|
|
|
1164
1093
|
* see it. Attribute those reads to the same inventory rows before generic
|
|
1165
1094
|
* dyn/jsval destructuring either reports SC1031 or admits an unsupported
|
|
1166
1095
|
* member in the dynamic tier. */
|
|
1167
|
-
export function fenceFetchObjectBinding(
|
|
1168
|
-
fenceFetchObjectMembers(
|
|
1096
|
+
export function fenceFetchObjectBinding(lowerer, pattern) {
|
|
1097
|
+
fenceFetchObjectMembers(lowerer, pattern, pattern.elements.flatMap((element) => {
|
|
1169
1098
|
if (element.dotDotDotToken)
|
|
1170
1099
|
return [];
|
|
1171
|
-
const member = fetchObjectBindingMemberName(
|
|
1100
|
+
const member = fetchObjectBindingMemberName(lowerer, element);
|
|
1172
1101
|
return member === null ? [] : [{ member, node: element }];
|
|
1173
1102
|
}));
|
|
1174
1103
|
}
|
|
1175
1104
|
/** Assignment-position object destructuring is the same member-read form as
|
|
1176
1105
|
* a binding pattern, but its source type lives on the right-hand expression
|
|
1177
1106
|
* instead of the target AST. */
|
|
1178
|
-
export function fenceFetchObjectAssignment(
|
|
1179
|
-
fenceFetchObjectMembers(
|
|
1180
|
-
const member = fetchObjectAssignmentMemberName(
|
|
1107
|
+
export function fenceFetchObjectAssignment(lowerer, target, source) {
|
|
1108
|
+
fenceFetchObjectMembers(lowerer, source, target.properties.flatMap((property) => {
|
|
1109
|
+
const member = fetchObjectAssignmentMemberName(lowerer, property);
|
|
1181
1110
|
return member === null ? [] : [{ member, node: property }];
|
|
1182
1111
|
}));
|
|
1183
1112
|
}
|
|
@@ -1186,29 +1115,29 @@ export function fenceFetchObjectAssignment(L, target, source) {
|
|
|
1186
1115
|
* Keep engine-free builds on the same SC2020 profile row for for-of,
|
|
1187
1116
|
* array spread, and array destructuring. The dynamic tier uses the
|
|
1188
1117
|
* engine's iterator protocol and is intentionally allowed. */
|
|
1189
|
-
export function fenceStaticHeadersIteration(
|
|
1190
|
-
if (
|
|
1118
|
+
export function fenceStaticHeadersIteration(lowerer, node) {
|
|
1119
|
+
if (lowerer.dynamic)
|
|
1191
1120
|
return;
|
|
1192
1121
|
const value = ts.isExpression(node) ? requestInitValueExpr(node) : node;
|
|
1193
|
-
const sym = isStdlibFetchInterface(
|
|
1122
|
+
const sym = isStdlibFetchInterface(lowerer, value, "Headers");
|
|
1194
1123
|
if (!sym)
|
|
1195
1124
|
return;
|
|
1196
|
-
|
|
1125
|
+
lowerer.noLowering("Headers.[Symbol.iterator] in a static build", node, "Headers iteration requires --dynamic; append/delete/get/getSetCookie/has/set/forEach remain engine-free", sym);
|
|
1197
1126
|
}
|
|
1198
1127
|
/** Dynamic element-spelled Headers iteration. Symbol.iterator uses the
|
|
1199
1128
|
* engine's GetIterator operation. A finite union of keys()/values()/entries()
|
|
1200
1129
|
* dispatches through fixed-name engine calls after evaluating the receiver
|
|
1201
1130
|
* and key once, preserving the method receiver and JavaScript evaluation
|
|
1202
1131
|
* order without trying to represent the union of method values. */
|
|
1203
|
-
export function lowerDynamicHeadersIteratorCall(
|
|
1204
|
-
if (!
|
|
1132
|
+
export function lowerDynamicHeadersIteratorCall(lowerer, call, access) {
|
|
1133
|
+
if (!lowerer.dynamic ||
|
|
1205
1134
|
call.questionDotToken ||
|
|
1206
1135
|
access.questionDotToken ||
|
|
1207
1136
|
call.arguments.length !== 0 ||
|
|
1208
|
-
!isStdlibFetchInterface(
|
|
1137
|
+
!isStdlibFetchInterface(lowerer, access.expression, "Headers")) {
|
|
1209
1138
|
return null;
|
|
1210
1139
|
}
|
|
1211
|
-
const members = fetchElementMemberNames(
|
|
1140
|
+
const members = fetchElementMemberNames(lowerer, access.argumentExpression);
|
|
1212
1141
|
if (members === null)
|
|
1213
1142
|
return null;
|
|
1214
1143
|
const symbolIterator = members.length === 1 && members[0] === "[Symbol.iterator]";
|
|
@@ -1216,16 +1145,16 @@ export function lowerDynamicHeadersIteratorCall(L, call, access) {
|
|
|
1216
1145
|
!members.every((member) => member === "keys" || member === "values" || member === "entries")) {
|
|
1217
1146
|
return null;
|
|
1218
1147
|
}
|
|
1219
|
-
const receiver =
|
|
1148
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1220
1149
|
if (receiver.type.kind !== "jsval")
|
|
1221
1150
|
return null;
|
|
1222
1151
|
const loc = locOf(call);
|
|
1223
1152
|
if (!symbolIterator) {
|
|
1224
|
-
const key =
|
|
1153
|
+
const key = lowerer.lowerExpr(access.argumentExpression);
|
|
1225
1154
|
if (key.type.kind !== "string")
|
|
1226
1155
|
return null;
|
|
1227
|
-
const recvLocal =
|
|
1228
|
-
const keyLocal =
|
|
1156
|
+
const recvLocal = lowerer.declareHiddenLocal("%headers", JSVAL);
|
|
1157
|
+
const keyLocal = lowerer.declareHiddenLocal("%headersKey", STRING);
|
|
1229
1158
|
const recvRef = {
|
|
1230
1159
|
kind: "varRef",
|
|
1231
1160
|
localId: recvLocal.id,
|
|
@@ -1295,7 +1224,7 @@ export function lowerDynamicHeadersIteratorCall(L, call, access) {
|
|
|
1295
1224
|
* path (which correctly fences bare method extraction), evaluating receiver,
|
|
1296
1225
|
* key, and arguments once in source order. Finite string-literal unions
|
|
1297
1226
|
* dispatch through fixed-name calls after the key value is captured. */
|
|
1298
|
-
export function lowerFetchElementMethodCall(
|
|
1227
|
+
export function lowerFetchElementMethodCall(lowerer, call) {
|
|
1299
1228
|
if (call.questionDotToken ||
|
|
1300
1229
|
!ts.isElementAccessExpression(call.expression) ||
|
|
1301
1230
|
call.expression.questionDotToken ||
|
|
@@ -1303,10 +1232,10 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1303
1232
|
return null;
|
|
1304
1233
|
}
|
|
1305
1234
|
const access = call.expression;
|
|
1306
|
-
const resolved = fetchInterfaceInventoryOwner(
|
|
1235
|
+
const resolved = fetchInterfaceInventoryOwner(lowerer, access.expression);
|
|
1307
1236
|
if (!resolved)
|
|
1308
1237
|
return null;
|
|
1309
|
-
const members = fetchElementMemberNames(
|
|
1238
|
+
const members = fetchElementMemberNames(lowerer, access.argumentExpression);
|
|
1310
1239
|
if (members === null ||
|
|
1311
1240
|
members.length === 0 ||
|
|
1312
1241
|
members.some((member) => member.startsWith("[Symbol."))) {
|
|
@@ -1318,27 +1247,27 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1318
1247
|
entry.placement === "prototype-inherited")));
|
|
1319
1248
|
if (rows.some((row) => row === undefined ||
|
|
1320
1249
|
row.status === "out-of-scope" ||
|
|
1321
|
-
(
|
|
1250
|
+
(lowerer.dynamic ? row.status === "unsupported" : row.status !== "static"))) {
|
|
1322
1251
|
return null;
|
|
1323
1252
|
}
|
|
1324
|
-
const receiver =
|
|
1325
|
-
if (receiver.type.kind !== (
|
|
1253
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1254
|
+
if (receiver.type.kind !== (lowerer.dynamic ? "jsval" : "dyn"))
|
|
1326
1255
|
return null;
|
|
1327
|
-
const key =
|
|
1256
|
+
const key = lowerer.lowerExpr(access.argumentExpression);
|
|
1328
1257
|
if (key.type.kind !== "string")
|
|
1329
1258
|
return null;
|
|
1330
1259
|
const loc = locOf(call);
|
|
1331
|
-
const receiverLocal =
|
|
1332
|
-
const keyLocal =
|
|
1333
|
-
const calleeLocal =
|
|
1334
|
-
?
|
|
1260
|
+
const receiverLocal = lowerer.declareHiddenLocal("%fetchReceiver", lowerer.dynamic ? JSVAL : DYN);
|
|
1261
|
+
const keyLocal = lowerer.declareHiddenLocal("%fetchMember", STRING);
|
|
1262
|
+
const calleeLocal = lowerer.dynamic
|
|
1263
|
+
? lowerer.declareHiddenLocal("%fetchMethod", JSVAL)
|
|
1335
1264
|
: null;
|
|
1336
|
-
const argumentValues = call.arguments.map((argument, index) =>
|
|
1337
|
-
?
|
|
1265
|
+
const argumentValues = call.arguments.map((argument, index) => lowerer.dynamic
|
|
1266
|
+
? lowerer.jsvalIn(lowerer.lowerExpr(argument), argument)
|
|
1338
1267
|
: fetchMethodArgumentIsLive(resolved.owner, members, index)
|
|
1339
|
-
? lowerLiveWebValue(
|
|
1340
|
-
:
|
|
1341
|
-
const argumentLocals = argumentValues.map((argument) =>
|
|
1268
|
+
? lowerLiveWebValue(lowerer, argument)
|
|
1269
|
+
: lowerer.lowerExprExpecting(argument, DYN));
|
|
1270
|
+
const argumentLocals = argumentValues.map((argument) => lowerer.declareHiddenLocal("%fetchMethodArg", argument.type));
|
|
1342
1271
|
const receiverRef = {
|
|
1343
1272
|
kind: "varRef",
|
|
1344
1273
|
localId: receiverLocal.id,
|
|
@@ -1392,7 +1321,7 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1392
1321
|
type: argument.type,
|
|
1393
1322
|
loc,
|
|
1394
1323
|
}));
|
|
1395
|
-
const staticResponsePromise = !
|
|
1324
|
+
const staticResponsePromise = !lowerer.dynamic &&
|
|
1396
1325
|
resolved.owner === "Response" &&
|
|
1397
1326
|
call.arguments.length === 0 &&
|
|
1398
1327
|
members.every((member) => member === "text" || member === "bytes")
|
|
@@ -1403,12 +1332,12 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1403
1332
|
// result is the ordinary representable value union; use that
|
|
1404
1333
|
// contextual type for the bridge's fulfillment adapter.
|
|
1405
1334
|
const inner = ts.isAwaitExpression(call.parent)
|
|
1406
|
-
?
|
|
1335
|
+
? lowerer.mapTypeOf(lowerer.typeOf(call.parent))
|
|
1407
1336
|
: null;
|
|
1408
1337
|
return inner ? { kind: "promise", inner } : null;
|
|
1409
1338
|
})()
|
|
1410
1339
|
: null;
|
|
1411
|
-
const invoke = (member) =>
|
|
1340
|
+
const invoke = (member) => lowerer.dynamic
|
|
1412
1341
|
? {
|
|
1413
1342
|
kind: "jsOp",
|
|
1414
1343
|
op: "callFnThis",
|
|
@@ -1436,7 +1365,7 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1436
1365
|
// Literal-string unions share the STRING carrier. A cast can therefore
|
|
1437
1366
|
// smuggle a different runtime key into this call; validate all arms and
|
|
1438
1367
|
// fail loudly rather than dispatching every mismatch to the last member.
|
|
1439
|
-
const invocationType = staticResponsePromise ?? (
|
|
1368
|
+
const invocationType = staticResponsePromise ?? (lowerer.dynamic ? JSVAL : DYN);
|
|
1440
1369
|
let result = nodeThrowExpr(1, "", `${access.getText()} is not a function`, invocationType, loc);
|
|
1441
1370
|
for (let index = members.length - 1; index >= 0; index--) {
|
|
1442
1371
|
const member = members[index];
|
|
@@ -1456,7 +1385,7 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1456
1385
|
loc,
|
|
1457
1386
|
};
|
|
1458
1387
|
}
|
|
1459
|
-
const declared =
|
|
1388
|
+
const declared = lowerer.dynamic ? lowerer.mapTypeOf(lowerer.typeOf(call)) : null;
|
|
1460
1389
|
if (declared &&
|
|
1461
1390
|
(declared.kind === "f64" ||
|
|
1462
1391
|
declared.kind === "bool" ||
|
|
@@ -1485,11 +1414,11 @@ export function lowerFetchElementMethodCall(L, call) {
|
|
|
1485
1414
|
* over the real Headers iterator, then the resulting pair array exits
|
|
1486
1415
|
* through the checker's declared array type. For Headers this is the
|
|
1487
1416
|
* spread algorithm's exact iterable snapshot. */
|
|
1488
|
-
export function lowerDynamicHeadersSpread(
|
|
1489
|
-
if (!
|
|
1417
|
+
export function lowerDynamicHeadersSpread(lowerer, node, type) {
|
|
1418
|
+
if (!lowerer.dynamic || !isStdlibFetchInterface(lowerer, requestInitValueExpr(node), "Headers")) {
|
|
1490
1419
|
return null;
|
|
1491
1420
|
}
|
|
1492
|
-
const receiver =
|
|
1421
|
+
const receiver = lowerer.lowerExpr(node);
|
|
1493
1422
|
if (receiver.type.kind !== "jsval")
|
|
1494
1423
|
return null;
|
|
1495
1424
|
const loc = locOf(node);
|
|
@@ -1515,37 +1444,37 @@ export function lowerDynamicHeadersSpread(L, node, type) {
|
|
|
1515
1444
|
* stream slice, but @types/node adopts the complete WHATWG ReadableStream
|
|
1516
1445
|
* interface. Fence that wider surface before its checked-dynamic handle can
|
|
1517
1446
|
* fall through to a runtime missing-method error. */
|
|
1518
|
-
export function fenceStaticReadableStreamMember(
|
|
1519
|
-
const sym = isStdlibFetchInterface(
|
|
1447
|
+
export function fenceStaticReadableStreamMember(lowerer, access, use) {
|
|
1448
|
+
const sym = isStdlibFetchInterface(lowerer, access.expression, "ReadableStream");
|
|
1520
1449
|
if (!sym)
|
|
1521
1450
|
return null;
|
|
1522
|
-
const members = fetchAccessMemberNames(
|
|
1451
|
+
const members = fetchAccessMemberNames(lowerer, access);
|
|
1523
1452
|
if (members === null)
|
|
1524
1453
|
return null;
|
|
1525
1454
|
const status = (member) => fetchInventoryStatus("ReadableStream", member, member.startsWith("[Symbol.") ? "prototype-symbol" : "prototype");
|
|
1526
|
-
if (
|
|
1455
|
+
if (lowerer.dynamic && members.every((member) => status(member) !== "unsupported")) {
|
|
1527
1456
|
return null;
|
|
1528
1457
|
}
|
|
1529
1458
|
const supported = (member) => use === "call"
|
|
1530
1459
|
? STATIC_READABLE_STREAM_CALLS.has(member)
|
|
1531
1460
|
: STATIC_READABLE_STREAM_READS.has(member);
|
|
1532
|
-
if (!
|
|
1461
|
+
if (!lowerer.dynamic && members.every(supported))
|
|
1533
1462
|
return null;
|
|
1534
|
-
const member = members.find((candidate) =>
|
|
1463
|
+
const member = members.find((candidate) => lowerer.dynamic ? status(candidate) === "unsupported" : !supported(candidate));
|
|
1535
1464
|
if (status(member) === "unsupported") {
|
|
1536
|
-
|
|
1465
|
+
lowerer.noLowering(`ReadableStream.${member}`, access, fetchInventoryReason("ReadableStream", member, member.startsWith("[Symbol.") ? "prototype-symbol" : "prototype") ?? "this ReadableStream operation has no compiler lowering in either tier", sym);
|
|
1537
1466
|
}
|
|
1538
|
-
|
|
1467
|
+
lowerer.noLowering(`ReadableStream.${member} in a static build`, access, "the native static ReadableStream surface is locked plus cancel() and getReader(); use a reader directly or --dynamic for the wider Web Streams API", sym);
|
|
1539
1468
|
}
|
|
1540
1469
|
/** Static AbortSignal constructors and ReadableStream.from(). These
|
|
1541
1470
|
* ambient globals have no first-class constructor-object representation;
|
|
1542
1471
|
* claim the direct calls by declaration provenance before the general
|
|
1543
1472
|
* member-call path tries to lower the receiver as a value. */
|
|
1544
|
-
function staticFirstArgWithSurplusArgs(
|
|
1473
|
+
function staticFirstArgWithSurplusArgs(lowerer, call, first) {
|
|
1545
1474
|
const loc = locOf(call);
|
|
1546
1475
|
if (call.arguments.length <= 1)
|
|
1547
1476
|
return first;
|
|
1548
|
-
const firstLocal =
|
|
1477
|
+
const firstLocal = lowerer.declareHiddenLocal("%fetchArg", first.type);
|
|
1549
1478
|
const firstRef = {
|
|
1550
1479
|
kind: "varRef",
|
|
1551
1480
|
localId: firstLocal.id,
|
|
@@ -1557,14 +1486,14 @@ function staticFirstArgWithSurplusArgs(L, call, first) {
|
|
|
1557
1486
|
];
|
|
1558
1487
|
for (const argument of call.arguments.slice(1)) {
|
|
1559
1488
|
if (ts.isSpreadElement(argument)) {
|
|
1560
|
-
|
|
1489
|
+
lowerer.noLowering("spread surplus arguments on the static fetch companion APIs", argument, "pass surplus arguments without spread syntax");
|
|
1561
1490
|
}
|
|
1562
1491
|
// The callee ignores the value, but JavaScript still evaluates every
|
|
1563
1492
|
// surplus argument in source order. A direct void has the operand's
|
|
1564
1493
|
// effects and no additional work of its own.
|
|
1565
1494
|
const discarded = ts.isVoidExpression(argument)
|
|
1566
|
-
?
|
|
1567
|
-
:
|
|
1495
|
+
? lowerer.lowerExpr(argument.expression)
|
|
1496
|
+
: lowerer.lowerExpr(argument);
|
|
1568
1497
|
stmts.push({ kind: "exprStmt", expr: discarded, loc: discarded.loc });
|
|
1569
1498
|
}
|
|
1570
1499
|
return {
|
|
@@ -1575,11 +1504,11 @@ function staticFirstArgWithSurplusArgs(L, call, first) {
|
|
|
1575
1504
|
loc,
|
|
1576
1505
|
};
|
|
1577
1506
|
}
|
|
1578
|
-
function staticCallWithSurplusArgs(
|
|
1579
|
-
return result(staticFirstArgWithSurplusArgs(
|
|
1507
|
+
function staticCallWithSurplusArgs(lowerer, call, first, result) {
|
|
1508
|
+
return result(staticFirstArgWithSurplusArgs(lowerer, call, first));
|
|
1580
1509
|
}
|
|
1581
|
-
export function lowerStaticFetchCompanionCall(
|
|
1582
|
-
if (
|
|
1510
|
+
export function lowerStaticFetchCompanionCall(lowerer, call) {
|
|
1511
|
+
if (lowerer.dynamic ||
|
|
1583
1512
|
call.questionDotToken ||
|
|
1584
1513
|
!ts.isPropertyAccessExpression(call.expression) ||
|
|
1585
1514
|
call.expression.questionDotToken ||
|
|
@@ -1587,8 +1516,8 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1587
1516
|
return null;
|
|
1588
1517
|
}
|
|
1589
1518
|
const root = call.expression.expression;
|
|
1590
|
-
const symbol =
|
|
1591
|
-
if (!symbol || !
|
|
1519
|
+
const symbol = lowerer.resolveValueSymbol(root);
|
|
1520
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
1592
1521
|
return null;
|
|
1593
1522
|
const loc = locOf(call);
|
|
1594
1523
|
if (root.text === "AbortSignal") {
|
|
@@ -1597,8 +1526,8 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1597
1526
|
if (call.arguments[0] && ts.isSpreadElement(call.arguments[0])) {
|
|
1598
1527
|
return null;
|
|
1599
1528
|
}
|
|
1600
|
-
return staticCallWithSurplusArgs(
|
|
1601
|
-
?
|
|
1529
|
+
return staticCallWithSurplusArgs(lowerer, call, call.arguments[0]
|
|
1530
|
+
? lowerer.lowerExprExpecting(call.arguments[0], DYN)
|
|
1602
1531
|
: dynUndefinedExpr(loc), (first) => ({
|
|
1603
1532
|
kind: "libCall",
|
|
1604
1533
|
fn: "fetch.abortTimeout",
|
|
@@ -1618,7 +1547,7 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1618
1547
|
}
|
|
1619
1548
|
if (ts.isSpreadElement(call.arguments[0]))
|
|
1620
1549
|
return null;
|
|
1621
|
-
return staticCallWithSurplusArgs(
|
|
1550
|
+
return staticCallWithSurplusArgs(lowerer, call, lowerLiveWebValue(lowerer, call.arguments[0]), (first) => ({
|
|
1622
1551
|
kind: "libCall",
|
|
1623
1552
|
fn: "fetch.abortNow",
|
|
1624
1553
|
args: [first],
|
|
@@ -1629,8 +1558,8 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1629
1558
|
if (call.arguments[0] && ts.isSpreadElement(call.arguments[0])) {
|
|
1630
1559
|
return null;
|
|
1631
1560
|
}
|
|
1632
|
-
return staticCallWithSurplusArgs(
|
|
1633
|
-
?
|
|
1561
|
+
return staticCallWithSurplusArgs(lowerer, call, call.arguments[0]
|
|
1562
|
+
? lowerer.lowerExprExpecting(call.arguments[0], DYN)
|
|
1634
1563
|
: dynUndefinedExpr(loc), (first) => ({
|
|
1635
1564
|
kind: "libCall",
|
|
1636
1565
|
fn: "fetch.abortAny",
|
|
@@ -1654,31 +1583,31 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1654
1583
|
loc,
|
|
1655
1584
|
};
|
|
1656
1585
|
}
|
|
1657
|
-
let source =
|
|
1586
|
+
let source = lowerer.lowerExpr(call.arguments[0]);
|
|
1658
1587
|
// A readonly tuple satisfies the fallback's readonly-array overload,
|
|
1659
1588
|
// but maps to a monomorphic record in IR. Reuse the ordinary
|
|
1660
1589
|
// tuple→array width conversion with the resolved generic parameter so
|
|
1661
1590
|
// `ReadableStream.from([1, 2] as const)` follows every other tuple
|
|
1662
1591
|
// flowing into a readonly T[] slot.
|
|
1663
1592
|
if (source.type.kind === "record") {
|
|
1664
|
-
const signature =
|
|
1593
|
+
const signature = lowerer.checker.getResolvedSignature(call);
|
|
1665
1594
|
const iterableParam = signature?.getParameters()[0];
|
|
1666
1595
|
const iterableType = iterableParam
|
|
1667
|
-
?
|
|
1596
|
+
? lowerer.mapTypeOf(lowerer.checker.getTypeOfSymbol(iterableParam))
|
|
1668
1597
|
: null;
|
|
1669
1598
|
if (iterableType?.kind === "array") {
|
|
1670
|
-
source =
|
|
1599
|
+
source = lowerer.widthCoerce(source, iterableType) ?? source;
|
|
1671
1600
|
}
|
|
1672
1601
|
}
|
|
1673
1602
|
const preserve = source.type.kind === "string" ||
|
|
1674
1603
|
(source.type.kind === "bytes" && source.type.elem === "u8") ||
|
|
1675
1604
|
(source.type.kind === "array" &&
|
|
1676
|
-
canConvertToDyn(source.type.elem, (id) =>
|
|
1605
|
+
canConvertToDyn(source.type.elem, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) ||
|
|
1677
1606
|
source.type.kind === "dyn";
|
|
1678
1607
|
if (!preserve) {
|
|
1679
|
-
|
|
1608
|
+
lowerer.noLowering(`ReadableStream.from() over ${lowerer.checker.typeToString(lowerer.typeOf(call.arguments[0]))} iterables`, call.arguments[0], "arrays, Uint8Array, and strings are supported — spread other synchronous iterables into an array first: [...iterable]");
|
|
1680
1609
|
}
|
|
1681
|
-
return staticCallWithSurplusArgs(
|
|
1610
|
+
return staticCallWithSurplusArgs(lowerer, call, source, (first) => ({
|
|
1682
1611
|
kind: "libCall",
|
|
1683
1612
|
fn: "fetch.streamFrom",
|
|
1684
1613
|
// Arrays and bytes must cross by reference: their iterators read each
|
|
@@ -1696,33 +1625,33 @@ export function lowerStaticFetchCompanionCall(L, call) {
|
|
|
1696
1625
|
* `.signal` and fetch. Preserve a mutable reason's identity just like
|
|
1697
1626
|
* `AbortSignal.abort(reason)`; surplus arguments still evaluate in order and
|
|
1698
1627
|
* are ignored by the runtime operation. */
|
|
1699
|
-
export function lowerStaticAbortControllerCall(
|
|
1628
|
+
export function lowerStaticAbortControllerCall(lowerer, call) {
|
|
1700
1629
|
const access = call.expression;
|
|
1701
|
-
if (
|
|
1630
|
+
if (lowerer.dynamic ||
|
|
1702
1631
|
call.questionDotToken ||
|
|
1703
1632
|
call.arguments.some((argument) => ts.isSpreadElement(argument)) ||
|
|
1704
1633
|
(!ts.isPropertyAccessExpression(access) &&
|
|
1705
1634
|
!ts.isElementAccessExpression(access)) ||
|
|
1706
1635
|
access.questionDotToken ||
|
|
1707
|
-
staticResponseMemberName(
|
|
1636
|
+
staticResponseMemberName(lowerer, access) !== "abort") {
|
|
1708
1637
|
return null;
|
|
1709
1638
|
}
|
|
1710
|
-
const receiverTs =
|
|
1639
|
+
const receiverTs = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
1711
1640
|
const symbol = receiverTs.getAliasSymbol() ?? receiverTs.getSymbol();
|
|
1712
1641
|
if (symbol?.name !== "AbortController" ||
|
|
1713
|
-
!
|
|
1714
|
-
|
|
1642
|
+
!lowerer.checker.declarationsOf(symbol).some((d) => ts.isInterfaceDeclaration(d) &&
|
|
1643
|
+
lowerer.isStdlibFile(d.getSourceFile()))) {
|
|
1715
1644
|
return null;
|
|
1716
1645
|
}
|
|
1717
|
-
const receiver =
|
|
1646
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1718
1647
|
if (receiver.type.kind !== "dyn")
|
|
1719
1648
|
return null;
|
|
1720
1649
|
const loc = locOf(call);
|
|
1721
1650
|
const first = call.arguments[0]
|
|
1722
|
-
? lowerLiveWebValue(
|
|
1651
|
+
? lowerLiveWebValue(lowerer, call.arguments[0])
|
|
1723
1652
|
: dynUndefinedExpr(loc);
|
|
1724
|
-
const args = [staticFirstArgWithSurplusArgs(
|
|
1725
|
-
return lowerStaticFixedFetchMethodCall(
|
|
1653
|
+
const args = [staticFirstArgWithSurplusArgs(lowerer, call, first)];
|
|
1654
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, "abort", receiver, args, (receiverRef, argumentRefs) => ({
|
|
1726
1655
|
kind: "dynInvoke",
|
|
1727
1656
|
recv: receiverRef,
|
|
1728
1657
|
method: "abort",
|
|
@@ -1735,9 +1664,9 @@ export function lowerStaticAbortControllerCall(L, call) {
|
|
|
1735
1664
|
/** Controller chunks and error reasons are dyn-handle calls, but unlike a
|
|
1736
1665
|
* general checked-dynamic boundary the Web Streams contract preserves their
|
|
1737
1666
|
* object identity for the reader/source callbacks that observe them. */
|
|
1738
|
-
export function lowerStaticReadableStreamControllerCall(
|
|
1667
|
+
export function lowerStaticReadableStreamControllerCall(lowerer, call) {
|
|
1739
1668
|
const access = call.expression;
|
|
1740
|
-
if (
|
|
1669
|
+
if (lowerer.dynamic ||
|
|
1741
1670
|
call.questionDotToken ||
|
|
1742
1671
|
call.arguments.length > 1 ||
|
|
1743
1672
|
(!ts.isPropertyAccessExpression(access) &&
|
|
@@ -1745,26 +1674,26 @@ export function lowerStaticReadableStreamControllerCall(L, call) {
|
|
|
1745
1674
|
access.questionDotToken) {
|
|
1746
1675
|
return null;
|
|
1747
1676
|
}
|
|
1748
|
-
const member = staticResponseMemberName(
|
|
1677
|
+
const member = staticResponseMemberName(lowerer, access);
|
|
1749
1678
|
if (member !== "enqueue" && member !== "error")
|
|
1750
1679
|
return null;
|
|
1751
|
-
const receiverTs =
|
|
1680
|
+
const receiverTs = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
1752
1681
|
const symbol = receiverTs.getAliasSymbol() ?? receiverTs.getSymbol();
|
|
1753
1682
|
if (symbol?.name !== "ReadableStreamDefaultController" ||
|
|
1754
|
-
!
|
|
1755
|
-
|
|
1683
|
+
!lowerer.checker.declarationsOf(symbol).some((d) => ts.isInterfaceDeclaration(d) &&
|
|
1684
|
+
lowerer.isStdlibFile(d.getSourceFile()))) {
|
|
1756
1685
|
return null;
|
|
1757
1686
|
}
|
|
1758
|
-
const recv =
|
|
1687
|
+
const recv = lowerer.lowerExpr(access.expression);
|
|
1759
1688
|
if (recv.type.kind !== "dyn")
|
|
1760
1689
|
return null;
|
|
1761
1690
|
const loc = locOf(call);
|
|
1762
1691
|
const args = [
|
|
1763
1692
|
call.arguments[0]
|
|
1764
|
-
? lowerLiveWebValue(
|
|
1693
|
+
? lowerLiveWebValue(lowerer, call.arguments[0])
|
|
1765
1694
|
: dynUndefinedExpr(loc),
|
|
1766
1695
|
];
|
|
1767
|
-
return lowerStaticFixedFetchMethodCall(
|
|
1696
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, member, recv, args, (receiver, argumentRefs) => ({
|
|
1768
1697
|
kind: "dynInvoke",
|
|
1769
1698
|
recv: receiver,
|
|
1770
1699
|
method: member,
|
|
@@ -1777,33 +1706,33 @@ export function lowerStaticReadableStreamControllerCall(L, call) {
|
|
|
1777
1706
|
/** `ReadableStream.cancel(reason)` and default-reader `cancel(reason)` pass
|
|
1778
1707
|
* the same reason object to the underlying source's cancel callback. Keep a
|
|
1779
1708
|
* live typed-reference capsule instead of the general dyn boundary's copy. */
|
|
1780
|
-
export function lowerStaticReadableStreamCancelCall(
|
|
1709
|
+
export function lowerStaticReadableStreamCancelCall(lowerer, call) {
|
|
1781
1710
|
const access = call.expression;
|
|
1782
|
-
if (
|
|
1711
|
+
if (lowerer.dynamic ||
|
|
1783
1712
|
call.questionDotToken ||
|
|
1784
1713
|
call.arguments.length > 1 ||
|
|
1785
1714
|
call.arguments.some((argument) => ts.isSpreadElement(argument)) ||
|
|
1786
1715
|
(!ts.isPropertyAccessExpression(access) &&
|
|
1787
1716
|
!ts.isElementAccessExpression(access)) ||
|
|
1788
1717
|
access.questionDotToken ||
|
|
1789
|
-
staticResponseMemberName(
|
|
1718
|
+
staticResponseMemberName(lowerer, access) !== "cancel") {
|
|
1790
1719
|
return null;
|
|
1791
1720
|
}
|
|
1792
|
-
const resolved = fetchInterfaceInventoryOwner(
|
|
1721
|
+
const resolved = fetchInterfaceInventoryOwner(lowerer, access.expression);
|
|
1793
1722
|
if (resolved?.owner !== "ReadableStream" &&
|
|
1794
1723
|
resolved?.owner !== "ReadableStreamDefaultReader") {
|
|
1795
1724
|
return null;
|
|
1796
1725
|
}
|
|
1797
|
-
const receiver =
|
|
1726
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
1798
1727
|
if (receiver.type.kind !== "dyn")
|
|
1799
1728
|
return null;
|
|
1800
1729
|
const loc = locOf(call);
|
|
1801
1730
|
const args = [
|
|
1802
1731
|
call.arguments[0]
|
|
1803
|
-
? lowerLiveWebValue(
|
|
1732
|
+
? lowerLiveWebValue(lowerer, call.arguments[0])
|
|
1804
1733
|
: dynUndefinedExpr(loc),
|
|
1805
1734
|
];
|
|
1806
|
-
return lowerStaticFixedFetchMethodCall(
|
|
1735
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, "cancel", receiver, args, (receiverRef, argumentRefs) => ({
|
|
1807
1736
|
kind: "dynInvoke",
|
|
1808
1737
|
recv: receiverRef,
|
|
1809
1738
|
method: "cancel",
|
|
@@ -1817,9 +1746,9 @@ export function lowerStaticReadableStreamCancelCall(L, call) {
|
|
|
1817
1746
|
* removeEventListener(). Functions already box by closure identity; mutable
|
|
1818
1747
|
* record/array/bytes listeners need the same live capsule used by stream
|
|
1819
1748
|
* chunks so repeated crossings still denote one EventListener object. */
|
|
1820
|
-
export function lowerStaticAbortSignalListenerCall(
|
|
1749
|
+
export function lowerStaticAbortSignalListenerCall(lowerer, call) {
|
|
1821
1750
|
const access = call.expression;
|
|
1822
|
-
if (
|
|
1751
|
+
if (lowerer.dynamic ||
|
|
1823
1752
|
call.questionDotToken ||
|
|
1824
1753
|
call.arguments.length < 2 ||
|
|
1825
1754
|
call.arguments.some((arg) => ts.isSpreadElement(arg)) ||
|
|
@@ -1828,25 +1757,25 @@ export function lowerStaticAbortSignalListenerCall(L, call) {
|
|
|
1828
1757
|
access.questionDotToken) {
|
|
1829
1758
|
return null;
|
|
1830
1759
|
}
|
|
1831
|
-
const member = staticResponseMemberName(
|
|
1760
|
+
const member = staticResponseMemberName(lowerer, access);
|
|
1832
1761
|
if (member !== "addEventListener" && member !== "removeEventListener") {
|
|
1833
1762
|
return null;
|
|
1834
1763
|
}
|
|
1835
|
-
const receiverTs =
|
|
1764
|
+
const receiverTs = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(access.expression));
|
|
1836
1765
|
const symbol = receiverTs.getAliasSymbol() ?? receiverTs.getSymbol();
|
|
1837
1766
|
if (symbol?.name !== "AbortSignal" ||
|
|
1838
|
-
!
|
|
1839
|
-
|
|
1767
|
+
!lowerer.checker.declarationsOf(symbol).some((d) => ts.isInterfaceDeclaration(d) &&
|
|
1768
|
+
lowerer.isStdlibFile(d.getSourceFile()))) {
|
|
1840
1769
|
return null;
|
|
1841
1770
|
}
|
|
1842
|
-
const recv =
|
|
1771
|
+
const recv = lowerer.lowerExpr(access.expression);
|
|
1843
1772
|
if (recv.type.kind !== "dyn")
|
|
1844
1773
|
return null;
|
|
1845
1774
|
const loc = locOf(call);
|
|
1846
1775
|
const args = call.arguments.map((arg, index) => index === 1
|
|
1847
|
-
? lowerLiveWebValue(
|
|
1848
|
-
:
|
|
1849
|
-
return lowerStaticFixedFetchMethodCall(
|
|
1776
|
+
? lowerLiveWebValue(lowerer, arg)
|
|
1777
|
+
: lowerer.lowerExprExpecting(arg, DYN));
|
|
1778
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, member, recv, args, (receiver, argumentRefs) => ({
|
|
1850
1779
|
kind: "dynInvoke",
|
|
1851
1780
|
recv: receiver,
|
|
1852
1781
|
method: member,
|
|
@@ -1860,19 +1789,19 @@ export function lowerStaticAbortSignalListenerCall(L, call) {
|
|
|
1860
1789
|
* over the same signal state consumed by fetch; dynamic builds construct the
|
|
1861
1790
|
* island Web object. JavaScript accepts surplus constructor arguments, so
|
|
1862
1791
|
* both tiers evaluate them even though AbortController ignores their values. */
|
|
1863
|
-
export function lowerAbortControllerNew(
|
|
1792
|
+
export function lowerAbortControllerNew(lowerer, expr) {
|
|
1864
1793
|
if (!ts.isIdentifier(expr.expression) ||
|
|
1865
1794
|
expr.expression.text !== "AbortController") {
|
|
1866
1795
|
return null;
|
|
1867
1796
|
}
|
|
1868
|
-
const symbol =
|
|
1869
|
-
if (!symbol || !
|
|
1797
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
1798
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
1870
1799
|
return null;
|
|
1871
1800
|
const args = expr.arguments ?? [];
|
|
1872
1801
|
if (args.some((argument) => ts.isSpreadElement(argument)))
|
|
1873
1802
|
return null;
|
|
1874
1803
|
const loc = locOf(expr);
|
|
1875
|
-
if (
|
|
1804
|
+
if (lowerer.dynamic) {
|
|
1876
1805
|
const ctor = {
|
|
1877
1806
|
kind: "jsOp",
|
|
1878
1807
|
op: "globalGet",
|
|
@@ -1884,7 +1813,7 @@ export function lowerAbortControllerNew(L, expr) {
|
|
|
1884
1813
|
return {
|
|
1885
1814
|
kind: "jsOp",
|
|
1886
1815
|
op: "construct",
|
|
1887
|
-
args: [ctor, ...args.map((argument) =>
|
|
1816
|
+
args: [ctor, ...args.map((argument) => lowerer.jsvalIn(lowerer.lowerExpr(argument), argument))],
|
|
1888
1817
|
type: JSVAL,
|
|
1889
1818
|
loc,
|
|
1890
1819
|
};
|
|
@@ -1902,7 +1831,7 @@ export function lowerAbortControllerNew(L, expr) {
|
|
|
1902
1831
|
kind: "seqExpr",
|
|
1903
1832
|
stmts: args.map((argument) => ({
|
|
1904
1833
|
kind: "exprStmt",
|
|
1905
|
-
expr:
|
|
1834
|
+
expr: lowerer.lowerExpr(argument),
|
|
1906
1835
|
loc: locOf(argument),
|
|
1907
1836
|
})),
|
|
1908
1837
|
result,
|
|
@@ -1913,19 +1842,19 @@ export function lowerAbortControllerNew(L, expr) {
|
|
|
1913
1842
|
/** `new ReadableStream(source?)`. Static builds box the source record into
|
|
1914
1843
|
* the checked-dynamic tree; dynamic builds construct the island's Web
|
|
1915
1844
|
* stream directly so the returned handle composes with dynamic fetch. */
|
|
1916
|
-
export function lowerStaticReadableStreamNew(
|
|
1845
|
+
export function lowerStaticReadableStreamNew(lowerer, expr) {
|
|
1917
1846
|
if (!ts.isIdentifier(expr.expression) ||
|
|
1918
1847
|
expr.expression.text !== "ReadableStream") {
|
|
1919
1848
|
return null;
|
|
1920
1849
|
}
|
|
1921
|
-
const symbol =
|
|
1922
|
-
if (!symbol || !
|
|
1850
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
1851
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
1923
1852
|
return null;
|
|
1924
1853
|
const args = expr.arguments ?? [];
|
|
1925
1854
|
if (args.length > 1)
|
|
1926
1855
|
return null;
|
|
1927
1856
|
const loc = locOf(expr);
|
|
1928
|
-
if (
|
|
1857
|
+
if (lowerer.dynamic) {
|
|
1929
1858
|
const ctor = {
|
|
1930
1859
|
kind: "jsOp",
|
|
1931
1860
|
op: "globalGet",
|
|
@@ -1937,8 +1866,8 @@ export function lowerStaticReadableStreamNew(L, expr) {
|
|
|
1937
1866
|
const source = args[0] === undefined
|
|
1938
1867
|
? null
|
|
1939
1868
|
: ts.isObjectLiteralExpression(args[0])
|
|
1940
|
-
? lowerIslandObjectLiteral(
|
|
1941
|
-
:
|
|
1869
|
+
? lowerIslandObjectLiteral(lowerer, args[0])
|
|
1870
|
+
: lowerer.jsvalIn(lowerer.lowerExpr(args[0]), args[0]);
|
|
1942
1871
|
return {
|
|
1943
1872
|
kind: "jsOp",
|
|
1944
1873
|
op: "construct",
|
|
@@ -1950,8 +1879,8 @@ export function lowerStaticReadableStreamNew(L, expr) {
|
|
|
1950
1879
|
const source = args.length === 0
|
|
1951
1880
|
? dynUndefinedExpr(loc)
|
|
1952
1881
|
: ts.isObjectLiteralExpression(args[0])
|
|
1953
|
-
? lowerDynObjectLiteral(
|
|
1954
|
-
: lowerLiveWebValue(
|
|
1882
|
+
? lowerDynObjectLiteral(lowerer, args[0])
|
|
1883
|
+
: lowerLiveWebValue(lowerer, args[0]);
|
|
1955
1884
|
return {
|
|
1956
1885
|
kind: "libCall",
|
|
1957
1886
|
fn: "fetch.streamNew",
|
|
@@ -1964,19 +1893,19 @@ export function lowerStaticReadableStreamNew(L, expr) {
|
|
|
1964
1893
|
* Web Response directly. Static builds hand a checked-dynamic BodyInit and
|
|
1965
1894
|
* ResponseInit snapshot to the native fetch runtime, which returns the same
|
|
1966
1895
|
* opaque Response handle as fetch(). */
|
|
1967
|
-
export function lowerResponseNew(
|
|
1896
|
+
export function lowerResponseNew(lowerer, expr) {
|
|
1968
1897
|
if (!ts.isIdentifier(expr.expression) ||
|
|
1969
1898
|
expr.expression.text !== "Response") {
|
|
1970
1899
|
return null;
|
|
1971
1900
|
}
|
|
1972
|
-
const symbol =
|
|
1973
|
-
if (!symbol || !
|
|
1901
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
1902
|
+
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
1974
1903
|
return null;
|
|
1975
1904
|
const args = expr.arguments ?? [];
|
|
1976
1905
|
if (args.some(ts.isSpreadElement))
|
|
1977
1906
|
return null;
|
|
1978
1907
|
const loc = locOf(expr);
|
|
1979
|
-
if (
|
|
1908
|
+
if (lowerer.dynamic) {
|
|
1980
1909
|
const ctor = {
|
|
1981
1910
|
kind: "jsOp",
|
|
1982
1911
|
op: "globalGet",
|
|
@@ -1986,8 +1915,8 @@ export function lowerResponseNew(L, expr) {
|
|
|
1986
1915
|
loc,
|
|
1987
1916
|
};
|
|
1988
1917
|
const lowered = args.map((arg) => ts.isObjectLiteralExpression(arg)
|
|
1989
|
-
? lowerIslandObjectLiteral(
|
|
1990
|
-
:
|
|
1918
|
+
? lowerIslandObjectLiteral(lowerer, arg)
|
|
1919
|
+
: lowerer.jsvalIn(lowerer.lowerExpr(arg), arg));
|
|
1991
1920
|
return {
|
|
1992
1921
|
kind: "jsOp",
|
|
1993
1922
|
op: "construct",
|
|
@@ -2007,25 +1936,25 @@ export function lowerResponseNew(L, expr) {
|
|
|
2007
1936
|
* deliberately declines accessors/methods, whose observable reads
|
|
2008
1937
|
* cannot be moved into the runtime WebIDL conversion phase. */
|
|
2009
1938
|
if (what === "an init value" && value.type.kind === "object") {
|
|
2010
|
-
const sourceType =
|
|
1939
|
+
const sourceType = lowerer.typeOf(node);
|
|
2011
1940
|
const fields = [];
|
|
2012
1941
|
for (const name of ["headers", "status", "statusText"]) {
|
|
2013
|
-
const property =
|
|
1942
|
+
const property = lowerer.checker.getPropertyOfType(sourceType, name);
|
|
2014
1943
|
if (!property)
|
|
2015
1944
|
continue;
|
|
2016
|
-
const propertyType =
|
|
2017
|
-
const mapped =
|
|
1945
|
+
const propertyType = lowerer.checker.getTypeOfSymbolAtLocation(property, node);
|
|
1946
|
+
const mapped = lowerer.mapTypeOf(propertyType);
|
|
2018
1947
|
if (!mapped || mapped.kind === "void") {
|
|
2019
|
-
|
|
1948
|
+
lowerer.noLowering(`new Response with ${what} of type '${lowerer.fmt(value.type)}'`, node, `the '${name}' field does not have a checked-dynamic representation`);
|
|
2020
1949
|
}
|
|
2021
1950
|
fields.push({ name, type: mapped });
|
|
2022
1951
|
}
|
|
2023
1952
|
const recordType = {
|
|
2024
1953
|
kind: "record",
|
|
2025
|
-
shapeId:
|
|
1954
|
+
shapeId: lowerer.shapes.intern(fields, false, undefined, fields.map((field) => field.name)),
|
|
2026
1955
|
};
|
|
2027
|
-
const projected =
|
|
2028
|
-
if (projected &&
|
|
1956
|
+
const projected = lowerer.widthCoerce(value, recordType);
|
|
1957
|
+
if (projected && lowerer.dynConvertible(projected.type)) {
|
|
2029
1958
|
return {
|
|
2030
1959
|
kind: "dynFrom",
|
|
2031
1960
|
value: projected,
|
|
@@ -2035,9 +1964,9 @@ export function lowerResponseNew(L, expr) {
|
|
|
2035
1964
|
};
|
|
2036
1965
|
}
|
|
2037
1966
|
}
|
|
2038
|
-
if (value.kind === "unitLit" ||
|
|
1967
|
+
if (value.kind === "unitLit" || lowerer.dynConvertible(value.type)) {
|
|
2039
1968
|
if (what === "an init value" &&
|
|
2040
|
-
hasLiveWebMutableArm(
|
|
1969
|
+
hasLiveWebMutableArm(lowerer, value.type)) {
|
|
2041
1970
|
return {
|
|
2042
1971
|
kind: "dynFrom",
|
|
2043
1972
|
value,
|
|
@@ -2053,18 +1982,18 @@ export function lowerResponseNew(L, expr) {
|
|
|
2053
1982
|
loc: value.loc,
|
|
2054
1983
|
};
|
|
2055
1984
|
}
|
|
2056
|
-
|
|
1985
|
+
lowerer.noLowering(`new Response with ${what} of type '${lowerer.fmt(value.type)}'`, node, "the static constructor accepts string, Uint8Array, ReadableStream, null, and the declared ResponseInit dictionary");
|
|
2057
1986
|
};
|
|
2058
1987
|
const bodyNode = args[0];
|
|
2059
1988
|
const body = bodyNode === undefined
|
|
2060
1989
|
? { kind: "unitLit", unit: "undefined", type: { kind: "undefinedT" }, loc }
|
|
2061
|
-
:
|
|
1990
|
+
: lowerer.lowerExpr(bodyNode);
|
|
2062
1991
|
const initNode = args[1];
|
|
2063
1992
|
const init = initNode === undefined
|
|
2064
1993
|
? { kind: "unitLit", unit: "undefined", type: { kind: "undefinedT" }, loc }
|
|
2065
1994
|
: ts.isObjectLiteralExpression(initNode)
|
|
2066
|
-
? lowerDynObjectLiteral(
|
|
2067
|
-
:
|
|
1995
|
+
? lowerDynObjectLiteral(lowerer, initNode, (node, value) => lowerLiveWebValue(lowerer, node, value))
|
|
1996
|
+
: lowerer.lowerExpr(initNode);
|
|
2068
1997
|
/* JavaScript evaluates every argument expression before WebIDL starts
|
|
2069
1998
|
* converting either BodyInit or ResponseInit. Capture the raw values in
|
|
2070
1999
|
* source order; only the final libCall boxes the body and gives typed init
|
|
@@ -2087,7 +2016,7 @@ export function lowerResponseNew(L, expr) {
|
|
|
2087
2016
|
loc: value.loc,
|
|
2088
2017
|
};
|
|
2089
2018
|
}
|
|
2090
|
-
const local =
|
|
2019
|
+
const local = lowerer.declareHiddenLocal(name, value.type);
|
|
2091
2020
|
stmts.push({ kind: "varDecl", localId: local.id, init: value, loc: value.loc });
|
|
2092
2021
|
return {
|
|
2093
2022
|
kind: "varRef",
|
|
@@ -2100,8 +2029,8 @@ export function lowerResponseNew(L, expr) {
|
|
|
2100
2029
|
const initRef = capture(init, "%responseInit");
|
|
2101
2030
|
for (const argument of args.slice(2)) {
|
|
2102
2031
|
const discarded = ts.isVoidExpression(argument)
|
|
2103
|
-
?
|
|
2104
|
-
:
|
|
2032
|
+
? lowerer.lowerExpr(argument.expression)
|
|
2033
|
+
: lowerer.lowerExpr(argument);
|
|
2105
2034
|
stmts.push({ kind: "exprStmt", expr: discarded, loc: discarded.loc });
|
|
2106
2035
|
}
|
|
2107
2036
|
const result = {
|
|
@@ -2120,9 +2049,9 @@ export function lowerResponseNew(L, expr) {
|
|
|
2120
2049
|
* transport into the checker's concrete chunk type. An exact chunk type
|
|
2121
2050
|
* preserves ReadableStream.from(array)'s element identity; structural
|
|
2122
2051
|
* widening keeps the compiler's ordinary copy-based width semantics. */
|
|
2123
|
-
export function lowerStaticReadableStreamReaderCall(
|
|
2052
|
+
export function lowerStaticReadableStreamReaderCall(lowerer, call) {
|
|
2124
2053
|
const access = call.expression;
|
|
2125
|
-
if (
|
|
2054
|
+
if (lowerer.dynamic ||
|
|
2126
2055
|
call.questionDotToken ||
|
|
2127
2056
|
call.arguments.length !== 0 ||
|
|
2128
2057
|
(!ts.isPropertyAccessExpression(access) &&
|
|
@@ -2130,23 +2059,23 @@ export function lowerStaticReadableStreamReaderCall(L, call) {
|
|
|
2130
2059
|
access.questionDotToken) {
|
|
2131
2060
|
return null;
|
|
2132
2061
|
}
|
|
2133
|
-
const member = staticResponseMemberName(
|
|
2062
|
+
const member = staticResponseMemberName(lowerer, access);
|
|
2134
2063
|
if (member !== "read")
|
|
2135
2064
|
return null;
|
|
2136
|
-
const receiverTs =
|
|
2065
|
+
const receiverTs = lowerer.typeOf(access.expression);
|
|
2137
2066
|
const symbol = receiverTs.getSymbol();
|
|
2138
2067
|
if (symbol?.name !== "ReadableStreamDefaultReader" ||
|
|
2139
|
-
!
|
|
2140
|
-
|
|
2068
|
+
!lowerer.checker.declarationsOf(symbol).some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2069
|
+
lowerer.isStdlibFile(d.getSourceFile()))) {
|
|
2141
2070
|
return null;
|
|
2142
2071
|
}
|
|
2143
|
-
const type =
|
|
2072
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
2144
2073
|
if (type?.kind !== "promise" ||
|
|
2145
2074
|
type.inner.kind !== "record") {
|
|
2146
2075
|
return null;
|
|
2147
2076
|
}
|
|
2148
|
-
const receiver =
|
|
2149
|
-
return lowerStaticFixedFetchMethodCall(
|
|
2077
|
+
const receiver = lowerer.lowerExprExpecting(access.expression, DYN);
|
|
2078
|
+
return lowerStaticFixedFetchMethodCall(lowerer, call, access, "read", receiver, [], (receiverRef) => ({
|
|
2150
2079
|
kind: "libCall",
|
|
2151
2080
|
fn: "fetch.readerRead",
|
|
2152
2081
|
args: [receiverRef],
|
|
@@ -2167,27 +2096,27 @@ export function lowerStaticReadableStreamReaderCall(L, call) {
|
|
|
2167
2096
|
* graph is a BUILD-time artifact — a runtime-computed name has nothing
|
|
2168
2097
|
* to embed, and the fence says so. Static builds report the per-site
|
|
2169
2098
|
* SC2012. Null for anything that isn't `import(...)`. */
|
|
2170
|
-
export function lowerDynamicImportCall(
|
|
2099
|
+
export function lowerDynamicImportCall(lowerer, call) {
|
|
2171
2100
|
if (call.expression.kind !== ts.SyntaxKind.ImportKeyword)
|
|
2172
2101
|
return null;
|
|
2173
|
-
|
|
2102
|
+
lowerer.requireDynamicApi("'import()'", call);
|
|
2174
2103
|
const loc = locOf(call);
|
|
2175
2104
|
const arg = call.arguments[0];
|
|
2176
2105
|
if (arg === undefined || !ts.isStringLiteralLike(arg)) {
|
|
2177
|
-
|
|
2106
|
+
lowerer.unsupported("SC1090", call, "dynamic import() of computed specifiers (the module graph embeds at " +
|
|
2178
2107
|
"build time — the specifier must be a string literal)");
|
|
2179
2108
|
}
|
|
2180
2109
|
if (call.arguments.length !== 1) {
|
|
2181
|
-
|
|
2110
|
+
lowerer.unsupported("SC1090", call, "dynamic import() with import attributes");
|
|
2182
2111
|
}
|
|
2183
|
-
const res =
|
|
2112
|
+
const res = lowerer.dynImports.get(`${call.getSourceFile().fileName}\u0000${arg.text}`);
|
|
2184
2113
|
if (!res) {
|
|
2185
2114
|
// Collection walks every file before bodies lower, so a missing
|
|
2186
2115
|
// entry is a lowerer bug, not user error.
|
|
2187
|
-
throw new
|
|
2116
|
+
throw new InternalCompilerError(`lowerer bug: unresolved dynamic import '${arg.text}'`);
|
|
2188
2117
|
}
|
|
2189
2118
|
if (res.kind === "program-module") {
|
|
2190
|
-
return lowerOwnModuleImport(
|
|
2119
|
+
return lowerOwnModuleImport(lowerer, call, arg);
|
|
2191
2120
|
}
|
|
2192
2121
|
if (res.kind !== "module") {
|
|
2193
2122
|
throw new PoisonError(); // resolution failed — collection reported it
|
|
@@ -2217,29 +2146,29 @@ export function lowerDynamicImportCall(L, call) {
|
|
|
2217
2146
|
* signatures) cross as trap functions that throw a pointed TypeError
|
|
2218
2147
|
* when USED — the namespace still builds, exactly like Node still
|
|
2219
2148
|
* resolves it. */
|
|
2220
|
-
function lowerOwnModuleImport(
|
|
2149
|
+
function lowerOwnModuleImport(lowerer, call, arg) {
|
|
2221
2150
|
const loc = locOf(call);
|
|
2222
2151
|
let dep = null;
|
|
2223
|
-
const modSym =
|
|
2224
|
-
for (const d of (modSym ?
|
|
2152
|
+
const modSym = lowerer.checker.getSymbolAtLocation(arg);
|
|
2153
|
+
for (const d of (modSym ? lowerer.checker.declarationsOf(modSym) : [])) {
|
|
2225
2154
|
if (ts.isSourceFile(d) && !d.isDeclarationFile) {
|
|
2226
2155
|
dep = d;
|
|
2227
2156
|
break;
|
|
2228
2157
|
}
|
|
2229
2158
|
}
|
|
2230
2159
|
if (dep !== null && (dep.fileName.endsWith(".cts") || isCjsJsFile(dep))) {
|
|
2231
|
-
|
|
2160
|
+
lowerer.unsupported("SC1090", call, `dynamic import of the program's own CommonJS module '${arg.text}' ` +
|
|
2232
2161
|
"(its namespace comes from module.exports through Node's CJS lexer, " +
|
|
2233
2162
|
"which has no compiled story — require it, or import it statically)");
|
|
2234
2163
|
}
|
|
2235
|
-
const builder = dep !== null ? dynNsBuilderOf(
|
|
2164
|
+
const builder = dep !== null ? dynNsBuilderOf(lowerer, dep, loc) : null;
|
|
2236
2165
|
if (builder === null) {
|
|
2237
|
-
|
|
2166
|
+
lowerer.unsupported("SC1090", call, `dynamic import of the program's own module '${arg.text}' ` +
|
|
2238
2167
|
"(this module is not part of the compiled module graph — import it statically)");
|
|
2239
2168
|
}
|
|
2240
2169
|
const promiseCtor = { kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc };
|
|
2241
2170
|
const resolved = { kind: "jsOp", op: "callMethod", name: "resolve", args: [promiseCtor], type: JSVAL, loc };
|
|
2242
|
-
const builderAsync = dep !== null &&
|
|
2171
|
+
const builderAsync = dep !== null && lowerer.asyncInitFiles.has(dep);
|
|
2243
2172
|
const builderFn = {
|
|
2244
2173
|
kind: "func",
|
|
2245
2174
|
params: [],
|
|
@@ -2261,20 +2190,20 @@ function lowerOwnModuleImport(L, call, arg) {
|
|
|
2261
2190
|
* then `return { <sorted exports> }` as an engine object. Null when the
|
|
2262
2191
|
* module never joined the compiled graph (no %init exists — an empty
|
|
2263
2192
|
* preflight order or a cycle the extension refused). */
|
|
2264
|
-
function dynNsBuilderOf(
|
|
2265
|
-
const cached =
|
|
2193
|
+
function dynNsBuilderOf(lowerer, dep, loc) {
|
|
2194
|
+
const cached = lowerer.dynNsBuilders.get(dep);
|
|
2266
2195
|
if (cached !== undefined)
|
|
2267
2196
|
return cached;
|
|
2268
|
-
const initName =
|
|
2197
|
+
const initName = lowerer.initNameOf.get(dep);
|
|
2269
2198
|
if (initName === undefined)
|
|
2270
2199
|
return null;
|
|
2271
|
-
const rawTag =
|
|
2200
|
+
const rawTag = lowerer.fileTag.get(dep) ?? "";
|
|
2272
2201
|
const name = `%dynns.${rawTag === "" ? "e." : rawTag.replace(/^%/, "")}`;
|
|
2273
|
-
|
|
2274
|
-
const isAsync =
|
|
2202
|
+
lowerer.dynNsBuilders.set(dep, name);
|
|
2203
|
+
const isAsync = lowerer.asyncInitFiles.has(dep);
|
|
2275
2204
|
const fnCtx = newFnCtx(true, null, null, JSVAL);
|
|
2276
2205
|
fnCtx.isAsync = isAsync;
|
|
2277
|
-
|
|
2206
|
+
lowerer.fnStack.push(fnCtx);
|
|
2278
2207
|
try {
|
|
2279
2208
|
const body = [];
|
|
2280
2209
|
// A synchronous entry has no run-once guard, so its historical
|
|
@@ -2283,7 +2212,7 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2283
2212
|
// promise is essential for top-level `await import("./self")`,
|
|
2284
2213
|
// which deadlocks (and ultimately exits 13) in Node rather than
|
|
2285
2214
|
// exposing a half-evaluated namespace.
|
|
2286
|
-
if (dep !==
|
|
2215
|
+
if (dep !== lowerer.entry || isAsync) {
|
|
2287
2216
|
const call = {
|
|
2288
2217
|
kind: "call",
|
|
2289
2218
|
callee: initName,
|
|
@@ -2291,7 +2220,7 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2291
2220
|
type: isAsync ? { kind: "promise", inner: VOID } : VOID,
|
|
2292
2221
|
loc,
|
|
2293
2222
|
};
|
|
2294
|
-
const cyclePromiseId =
|
|
2223
|
+
const cyclePromiseId = lowerer.asyncCyclePromiseOf.get(dep);
|
|
2295
2224
|
if (isAsync && cyclePromiseId !== undefined) {
|
|
2296
2225
|
// Starting the REQUESTED member matters for dynamically-only
|
|
2297
2226
|
// cycles: build-time discovery may have encountered another
|
|
@@ -2326,7 +2255,7 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2326
2255
|
// Node sorts module-namespace keys (code-unit order); tsc erases
|
|
2327
2256
|
// type-only exports, so only VALUE exports appear.
|
|
2328
2257
|
const entries = [];
|
|
2329
|
-
const modSym =
|
|
2258
|
+
const modSym = lowerer.checker.getSymbolAtLocation(dep);
|
|
2330
2259
|
modSym?.getExports().forEach((sym, key) => {
|
|
2331
2260
|
const n = String(key);
|
|
2332
2261
|
if (!n.startsWith("__") && n !== "export=")
|
|
@@ -2335,14 +2264,14 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2335
2264
|
entries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
|
|
2336
2265
|
const args = [];
|
|
2337
2266
|
for (const [exportName, sym] of entries) {
|
|
2338
|
-
const value = exportJsvalValue(
|
|
2267
|
+
const value = exportJsvalValue(lowerer, exportName, sym, loc);
|
|
2339
2268
|
if (value === null)
|
|
2340
2269
|
continue;
|
|
2341
2270
|
args.push({ kind: "jsMarshal", value: { kind: "strLit", value: exportName, type: STRING, loc }, type: JSVAL, loc }, value);
|
|
2342
2271
|
}
|
|
2343
2272
|
body.push({ kind: "return", value: { kind: "jsOp", op: "objLit", args, type: JSVAL, loc }, loc });
|
|
2344
|
-
const ctx =
|
|
2345
|
-
|
|
2273
|
+
const ctx = lowerer.ctx;
|
|
2274
|
+
lowerer.liftedFns.push({
|
|
2346
2275
|
name,
|
|
2347
2276
|
params: [],
|
|
2348
2277
|
returnType: JSVAL,
|
|
@@ -2354,7 +2283,7 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2354
2283
|
});
|
|
2355
2284
|
}
|
|
2356
2285
|
finally {
|
|
2357
|
-
|
|
2286
|
+
lowerer.fnStack.pop();
|
|
2358
2287
|
}
|
|
2359
2288
|
return name;
|
|
2360
2289
|
}
|
|
@@ -2366,12 +2295,12 @@ function dynNsBuilderOf(L, dep, loc) {
|
|
|
2366
2295
|
* called or constructed — the namespace still builds (Node resolves it;
|
|
2367
2296
|
* only the USE has no compiled story). Null for exports that do not exist
|
|
2368
2297
|
* at runtime (type-only). */
|
|
2369
|
-
function exportJsvalValue(
|
|
2370
|
-
const trap = (what) => islandTrapFnValue(
|
|
2298
|
+
function exportJsvalValue(lowerer, name, sym, loc) {
|
|
2299
|
+
const trap = (what) => islandTrapFnValue(lowerer, `the '${name}' export is ${what} of the compiled program, which cannot cross into dynamically-executed code yet`, loc);
|
|
2371
2300
|
let resolved = sym;
|
|
2372
2301
|
if (sym.flags & ts.SymbolFlags.Alias) {
|
|
2373
2302
|
// `export type { x }` / `export { type x }`: erased at runtime.
|
|
2374
|
-
for (const d of
|
|
2303
|
+
for (const d of lowerer.checker.declarationsOf(sym)) {
|
|
2375
2304
|
if (ts.isExportSpecifier(d)) {
|
|
2376
2305
|
const exportDecl = d.parent.parent;
|
|
2377
2306
|
if (d.isTypeOnly || (ts.isExportDeclaration(exportDecl) && exportDecl.isTypeOnly))
|
|
@@ -2383,11 +2312,11 @@ function exportJsvalValue(L, name, sym, loc) {
|
|
|
2383
2312
|
return null;
|
|
2384
2313
|
}
|
|
2385
2314
|
}
|
|
2386
|
-
resolved =
|
|
2315
|
+
resolved = lowerer.checker.getAliasedSymbol(sym);
|
|
2387
2316
|
}
|
|
2388
2317
|
if (!(resolved.flags & ts.SymbolFlags.Value))
|
|
2389
2318
|
return null; // pure type surface
|
|
2390
|
-
const g =
|
|
2319
|
+
const g = lowerer.globalsBySymbol.get(resolved);
|
|
2391
2320
|
if (g) {
|
|
2392
2321
|
const ref = { kind: "varRef", localId: g.id, type: g.type, loc };
|
|
2393
2322
|
if (ref.type.kind === "jsval")
|
|
@@ -2396,18 +2325,18 @@ function exportJsvalValue(L, name, sym, loc) {
|
|
|
2396
2325
|
return { kind: "jsOp", op: ref.type.kind === "undefinedT" ? "undefLit" : "nullLit", args: [], type: JSVAL, loc };
|
|
2397
2326
|
}
|
|
2398
2327
|
if (ref.type.kind === "func") {
|
|
2399
|
-
return canMarshalTypedFuncIntoIsland(ref.type, (id) =>
|
|
2328
|
+
return canMarshalTypedFuncIntoIsland(ref.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))
|
|
2400
2329
|
? { kind: "jsMarshal", value: ref, type: JSVAL, loc }
|
|
2401
|
-
: trap(`a function value of type '${
|
|
2330
|
+
: trap(`a function value of type '${lowerer.fmt(ref.type)}'`);
|
|
2402
2331
|
}
|
|
2403
|
-
if (
|
|
2332
|
+
if (lowerer.boundarySafe(ref.type))
|
|
2404
2333
|
return { kind: "jsMarshal", value: ref, type: JSVAL, loc };
|
|
2405
|
-
if (
|
|
2406
|
-
return
|
|
2407
|
-
return trap(`a value of type '${
|
|
2334
|
+
if (lowerer.jsvalLiftable(ref.type))
|
|
2335
|
+
return lowerer.jsvalLiftExpr(ref, loc);
|
|
2336
|
+
return trap(`a value of type '${lowerer.fmt(ref.type)}'`);
|
|
2408
2337
|
}
|
|
2409
|
-
const sig =
|
|
2410
|
-
const decl0 =
|
|
2338
|
+
const sig = lowerer.fnSigsBySymbol.get(resolved);
|
|
2339
|
+
const decl0 = lowerer.checker.declarationsOf(resolved).find((d) => ts.isFunctionDeclaration(d) && (ts.isSourceFile(d.parent) || lowerer.nsBlocks.get(d.parent) === "flattened"));
|
|
2411
2340
|
if (sig && decl0) {
|
|
2412
2341
|
if (!sig.params.every((p) => p.mode === "required")) {
|
|
2413
2342
|
return trap("a function with optional, default, or rest parameters");
|
|
@@ -2417,10 +2346,10 @@ function exportJsvalValue(L, name, sym, loc) {
|
|
|
2417
2346
|
params: sig.params.map((p) => p.type),
|
|
2418
2347
|
ret: sig.returnType,
|
|
2419
2348
|
};
|
|
2420
|
-
if (!canMarshalTypedFuncIntoIsland(funcType, (id) =>
|
|
2421
|
-
return trap(`a function of type '${
|
|
2349
|
+
if (!canMarshalTypedFuncIntoIsland(funcType, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
2350
|
+
return trap(`a function of type '${lowerer.fmt(funcType)}'`);
|
|
2422
2351
|
}
|
|
2423
|
-
|
|
2352
|
+
lowerer.noteEdge(sig.name);
|
|
2424
2353
|
return {
|
|
2425
2354
|
kind: "jsMarshal",
|
|
2426
2355
|
value: { kind: "closure", fnName: sig.name, captures: [], type: funcType, loc },
|
|
@@ -2428,7 +2357,7 @@ function exportJsvalValue(L, name, sym, loc) {
|
|
|
2428
2357
|
loc,
|
|
2429
2358
|
};
|
|
2430
2359
|
}
|
|
2431
|
-
if (
|
|
2360
|
+
if (lowerer.genericFnsBySymbol.has(resolved))
|
|
2432
2361
|
return trap("a generic function");
|
|
2433
2362
|
const flags = resolved.flags;
|
|
2434
2363
|
if (flags & ts.SymbolFlags.Class)
|
|
@@ -2445,8 +2374,8 @@ function exportJsvalValue(L, name, sym, loc) {
|
|
|
2445
2374
|
* namespace holds the value too), property probes answer like a
|
|
2446
2375
|
* function's, and calling or `new`-ing it runs the body, which throws
|
|
2447
2376
|
* the pointed TypeError. */
|
|
2448
|
-
function islandTrapFnValue(
|
|
2449
|
-
void
|
|
2377
|
+
function islandTrapFnValue(lowerer, message, loc) {
|
|
2378
|
+
void lowerer;
|
|
2450
2379
|
const code = `throw new TypeError(${JSON.stringify(message)})`;
|
|
2451
2380
|
return {
|
|
2452
2381
|
kind: "jsOp",
|
|
@@ -2469,7 +2398,7 @@ function islandTrapFnValue(L, message, loc) {
|
|
|
2469
2398
|
* are admitted; engine property names have no identifier restriction. Plain
|
|
2470
2399
|
* spreads copy through the engine's CopyDataProperties operation in
|
|
2471
2400
|
* source order, including nested RequestInit/header dictionaries. */
|
|
2472
|
-
|
|
2401
|
+
function lowerIslandObjectLiteral(lowerer, expr) {
|
|
2473
2402
|
const loc = locOf(expr);
|
|
2474
2403
|
let args = [];
|
|
2475
2404
|
let acc = null;
|
|
@@ -2486,8 +2415,8 @@ export function lowerIslandObjectLiteral(L, expr) {
|
|
|
2486
2415
|
if (ts.isSpreadAssignment(prop)) {
|
|
2487
2416
|
flushFields();
|
|
2488
2417
|
const spread = ts.isObjectLiteralExpression(prop.expression)
|
|
2489
|
-
? lowerIslandObjectLiteral(
|
|
2490
|
-
:
|
|
2418
|
+
? lowerIslandObjectLiteral(lowerer, prop.expression)
|
|
2419
|
+
: lowerer.jsvalIn(lowerer.lowerExpr(prop.expression), prop.expression);
|
|
2491
2420
|
acc ??= { kind: "jsOp", op: "objLit", args: [], type: JSVAL, loc };
|
|
2492
2421
|
acc = { kind: "jsOp", op: "objSpread", args: [acc, spread], type: JSVAL, loc: locOf(prop) };
|
|
2493
2422
|
continue;
|
|
@@ -2495,11 +2424,11 @@ export function lowerIslandObjectLiteral(L, expr) {
|
|
|
2495
2424
|
if (!ts.isPropertyAssignment(prop) &&
|
|
2496
2425
|
!ts.isShorthandPropertyAssignment(prop) &&
|
|
2497
2426
|
!ts.isMethodDeclaration(prop)) {
|
|
2498
|
-
|
|
2427
|
+
lowerer.unsupported("SC1090", prop, "this property form in an island-built object literal (use a spelled or pure const-folded key with a value or method)");
|
|
2499
2428
|
}
|
|
2500
|
-
const propertyName = requestInitLiteralKey(
|
|
2429
|
+
const propertyName = requestInitLiteralKey(lowerer, prop);
|
|
2501
2430
|
if (propertyName === null) {
|
|
2502
|
-
|
|
2431
|
+
lowerer.unsupported("SC1090", prop, "this property key in an island-built object literal (use a spelled or pure const-folded key)");
|
|
2503
2432
|
}
|
|
2504
2433
|
const nameLoc = locOf(prop.name);
|
|
2505
2434
|
args.push({
|
|
@@ -2513,18 +2442,18 @@ export function lowerIslandObjectLiteral(L, expr) {
|
|
|
2513
2442
|
? prop.name
|
|
2514
2443
|
: prop;
|
|
2515
2444
|
if (ts.isObjectLiteralExpression(valueNode)) {
|
|
2516
|
-
args.push(lowerIslandObjectLiteral(
|
|
2445
|
+
args.push(lowerIslandObjectLiteral(lowerer, valueNode));
|
|
2517
2446
|
}
|
|
2518
2447
|
else if (ts.isArrayLiteralExpression(valueNode) &&
|
|
2519
2448
|
!valueNode.elements.some(ts.isSpreadElement)) {
|
|
2520
|
-
const elems = valueNode.elements.map((el) =>
|
|
2449
|
+
const elems = valueNode.elements.map((el) => lowerer.jsvalIn(lowerer.lowerExpr(el), el));
|
|
2521
2450
|
args.push({ kind: "jsOp", op: "arrLit", args: elems, type: JSVAL, loc: locOf(valueNode) });
|
|
2522
2451
|
}
|
|
2523
2452
|
else {
|
|
2524
2453
|
const value = ts.isMethodDeclaration(valueNode)
|
|
2525
|
-
? (
|
|
2526
|
-
:
|
|
2527
|
-
args.push(
|
|
2454
|
+
? (lowerer.rejectThisInObjectMethod(valueNode.body ?? valueNode), lowerer.lowerLambda(valueNode))
|
|
2455
|
+
: lowerer.lowerExpr(valueNode);
|
|
2456
|
+
args.push(lowerer.jsvalIn(value, valueNode));
|
|
2528
2457
|
}
|
|
2529
2458
|
}
|
|
2530
2459
|
flushFields();
|
|
@@ -2540,13 +2469,13 @@ export function lowerIslandObjectLiteral(L, expr) {
|
|
|
2540
2469
|
* receiver, arity, and argument types against ambient/scriptc.d.ts; an
|
|
2541
2470
|
* ambient member missing from ISLAND_SURFACE returns null into the
|
|
2542
2471
|
* existing generic rejections. */
|
|
2543
|
-
export function lowerIslandMethodCall(
|
|
2544
|
-
if (
|
|
2472
|
+
export function lowerIslandMethodCall(lowerer, call, access) {
|
|
2473
|
+
if (lowerer.chainBlocked(access, call))
|
|
2545
2474
|
return null;
|
|
2546
2475
|
const name = access.name.text;
|
|
2547
2476
|
const loc = locOf(call);
|
|
2548
2477
|
const finish = (receiver, entry) => {
|
|
2549
|
-
const args = call.arguments.map((a) =>
|
|
2478
|
+
const args = call.arguments.map((a) => lowerer.jsvalIn(lowerer.lowerExpr(a), a));
|
|
2550
2479
|
const result = {
|
|
2551
2480
|
kind: "jsOp", op: "callMethod", name, args: [receiver, ...args], type: JSVAL, loc,
|
|
2552
2481
|
};
|
|
@@ -2559,11 +2488,11 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2559
2488
|
// RequestInit literal into fetch without a JSON detour. The prelude
|
|
2560
2489
|
// implements all three statics.
|
|
2561
2490
|
{
|
|
2562
|
-
const sigMember =
|
|
2491
|
+
const sigMember = lowerer.stdlibGlobalMember(access, "AbortSignal");
|
|
2563
2492
|
if ((sigMember === "timeout" || sigMember === "abort" || sigMember === "any") &&
|
|
2564
2493
|
call.arguments.every((argument) => !ts.isSpreadElement(argument))) {
|
|
2565
|
-
|
|
2566
|
-
const args = call.arguments.map((a) =>
|
|
2494
|
+
lowerer.requireDynamicApi(`'AbortSignal.${sigMember}'`, call);
|
|
2495
|
+
const args = call.arguments.map((a) => lowerer.jsvalIn(lowerer.lowerExpr(a), a));
|
|
2567
2496
|
const signalGlobal = {
|
|
2568
2497
|
kind: "jsOp", op: "globalGet", name: "AbortSignal", args: [], type: JSVAL, loc,
|
|
2569
2498
|
};
|
|
@@ -2573,9 +2502,9 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2573
2502
|
};
|
|
2574
2503
|
}
|
|
2575
2504
|
}
|
|
2576
|
-
if (
|
|
2505
|
+
if (lowerer.stdlibGlobalMember(access, "ReadableStream") === "from" &&
|
|
2577
2506
|
call.arguments.every((argument) => !ts.isSpreadElement(argument))) {
|
|
2578
|
-
|
|
2507
|
+
lowerer.requireDynamicApi("'ReadableStream.from'", call);
|
|
2579
2508
|
const streamGlobal = {
|
|
2580
2509
|
kind: "jsOp",
|
|
2581
2510
|
op: "globalGet",
|
|
@@ -2590,13 +2519,13 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2590
2519
|
name: "from",
|
|
2591
2520
|
args: [
|
|
2592
2521
|
streamGlobal,
|
|
2593
|
-
...call.arguments.map((argument) =>
|
|
2522
|
+
...call.arguments.map((argument) => lowerer.jsvalIn(lowerer.lowerExpr(argument), argument)),
|
|
2594
2523
|
],
|
|
2595
2524
|
type: JSVAL,
|
|
2596
2525
|
loc,
|
|
2597
2526
|
};
|
|
2598
2527
|
}
|
|
2599
|
-
const isMath =
|
|
2528
|
+
const isMath = lowerer.stdlibGlobalMember(access, "Math") !== null;
|
|
2600
2529
|
// The STATIC Math members (floor/min/max/random): one C call IS the
|
|
2601
2530
|
// JS operation — no island, no --dynamic. Only the tabled arity with
|
|
2602
2531
|
// plain (non-spread) arguments takes this path; other forms fall
|
|
@@ -2617,7 +2546,7 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2617
2546
|
if (call.arguments.length === 0) {
|
|
2618
2547
|
return { kind: "numLit", value: name === "max" ? -Infinity : Infinity, type: F64, loc };
|
|
2619
2548
|
}
|
|
2620
|
-
const args = call.arguments.map((a) =>
|
|
2549
|
+
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, F64));
|
|
2621
2550
|
let acc = args[0];
|
|
2622
2551
|
for (let i = 1; i < args.length; i++) {
|
|
2623
2552
|
acc = { kind: "libCall", fn: staticMath.fn, args: [acc, args[i]], type: F64, loc };
|
|
@@ -2625,7 +2554,7 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2625
2554
|
return acc;
|
|
2626
2555
|
}
|
|
2627
2556
|
if (call.arguments.length === staticMath.arity) {
|
|
2628
|
-
const args = call.arguments.map((a) =>
|
|
2557
|
+
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, F64));
|
|
2629
2558
|
return { kind: "libCall", fn: staticMath.fn, args, type: F64, loc };
|
|
2630
2559
|
}
|
|
2631
2560
|
}
|
|
@@ -2640,9 +2569,9 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2640
2569
|
call.arguments.length === 1 &&
|
|
2641
2570
|
ts.isSpreadElement(call.arguments[0])) {
|
|
2642
2571
|
const spread = call.arguments[0];
|
|
2643
|
-
const src =
|
|
2572
|
+
const src = lowerer.lowerExpr(spread.expression);
|
|
2644
2573
|
if (src.type.kind !== "array" || src.type.elem.kind !== "f64") {
|
|
2645
|
-
|
|
2574
|
+
lowerer.unsupported("SC1090", spread, `spreading '${lowerer.fmt(src.type)}' into Math.${name} (only a number[] spreads)`);
|
|
2646
2575
|
}
|
|
2647
2576
|
return {
|
|
2648
2577
|
kind: "libCall",
|
|
@@ -2654,10 +2583,10 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2654
2583
|
}
|
|
2655
2584
|
const mathFn = isMath ? own(ISLAND_SURFACE.math.fns, name) : undefined;
|
|
2656
2585
|
if (mathFn && call.arguments.length === mathFn.args.length) {
|
|
2657
|
-
|
|
2586
|
+
lowerer.requireDynamicApi(`'Math.${name}'`, call);
|
|
2658
2587
|
return finish({ kind: "jsOp", op: "globalGet", name: "Math", args: [], type: JSVAL, loc }, mathFn);
|
|
2659
2588
|
}
|
|
2660
|
-
const kind =
|
|
2589
|
+
const kind = lowerer.mapTypeOf(lowerer.typeOf(access.expression))?.kind;
|
|
2661
2590
|
const entry = kind === "f64"
|
|
2662
2591
|
? own(ISLAND_SURFACE.number, name)
|
|
2663
2592
|
: kind === "string"
|
|
@@ -2665,30 +2594,35 @@ export function lowerIslandMethodCall(L, call, access) {
|
|
|
2665
2594
|
: undefined;
|
|
2666
2595
|
if (!entry || call.arguments.length !== entry.args.length)
|
|
2667
2596
|
return null;
|
|
2668
|
-
if (!
|
|
2597
|
+
if (!lowerer.isStdlibMember(access))
|
|
2669
2598
|
return null;
|
|
2670
|
-
|
|
2671
|
-
return finish(
|
|
2599
|
+
lowerer.requireDynamicApi(`'.${name}()' on ${kind === "f64" ? "numbers" : "strings"}`, call);
|
|
2600
|
+
return finish(lowerer.jsvalIn(lowerer.lowerExpr(access.expression), access.expression), entry);
|
|
2672
2601
|
}
|
|
2673
|
-
/** `Math.PI` / `Math.E` property
|
|
2674
|
-
*
|
|
2675
|
-
* call are rejected specifically (no value form
|
|
2676
|
-
* not). Null for non-Math receivers (the property chain
|
|
2677
|
-
|
|
2678
|
-
|
|
2602
|
+
/** Canonical `Math.PI` / `Math.E` property reads become typed numeric
|
|
2603
|
+
* literals. Remaining Math properties retain the island/fence path. Math
|
|
2604
|
+
* methods referenced without a call are rejected specifically (no value form
|
|
2605
|
+
* exists, --dynamic or not). Null for non-Math receivers (the property chain
|
|
2606
|
+
* keeps trying). */
|
|
2607
|
+
export function lowerMathProperty(lowerer, expr) {
|
|
2608
|
+
const member = lowerer.stdlibGlobalMember(expr, "Math");
|
|
2679
2609
|
if (member === null)
|
|
2680
2610
|
return null;
|
|
2681
2611
|
const loc = locOf(expr);
|
|
2612
|
+
const staticValue = own(STATIC_MATH_PROPS, member);
|
|
2613
|
+
if (staticValue !== undefined) {
|
|
2614
|
+
return { kind: "numLit", value: staticValue, type: F64, loc };
|
|
2615
|
+
}
|
|
2682
2616
|
const propType = own(ISLAND_SURFACE.math.props, member);
|
|
2683
2617
|
if (propType !== undefined) {
|
|
2684
|
-
|
|
2618
|
+
lowerer.requireDynamicApi(`'Math.${member}'`, expr);
|
|
2685
2619
|
const math = { kind: "jsOp", op: "globalGet", name: "Math", args: [], type: JSVAL, loc };
|
|
2686
2620
|
const read = { kind: "jsOp", op: "getProp", name: member, args: [math], type: JSVAL, loc };
|
|
2687
2621
|
return { kind: "jsExit", value: read, type: propType, loc };
|
|
2688
2622
|
}
|
|
2689
2623
|
if (own(ISLAND_SURFACE.math.fns, member) !== undefined ||
|
|
2690
2624
|
own(STATIC_MATH_FNS, member) !== undefined) {
|
|
2691
|
-
|
|
2625
|
+
lowerer.unsupported("SC1090", expr, `Math methods as values (call '${member}' directly)`);
|
|
2692
2626
|
}
|
|
2693
2627
|
return null; // declared-but-untabled members fall through generically
|
|
2694
2628
|
}
|
|
@@ -2696,13 +2630,13 @@ export function lowerMathProperty(L, expr) {
|
|
|
2696
2630
|
* or null when the type isn't package-declared. Union parts are searched
|
|
2697
2631
|
* too: `string | Command` fails mapping as a whole, but the blame (and
|
|
2698
2632
|
* the --dynamic attribution) belongs to the package-declared part. */
|
|
2699
|
-
export function npmPackageOf(
|
|
2700
|
-
const pkg =
|
|
2633
|
+
export function npmPackageOf(lowerer, type) {
|
|
2634
|
+
const pkg = lowerer.npmPackageOfSymbol(type.getAliasSymbol() ?? type.getSymbol());
|
|
2701
2635
|
if (pkg)
|
|
2702
2636
|
return pkg;
|
|
2703
2637
|
if (type.isUnionType()) {
|
|
2704
2638
|
for (const part of ts.constituentTypes(type)) {
|
|
2705
|
-
const partPkg =
|
|
2639
|
+
const partPkg = lowerer.npmPackageOf(part);
|
|
2706
2640
|
if (partPkg)
|
|
2707
2641
|
return partPkg;
|
|
2708
2642
|
}
|
|
@@ -2715,24 +2649,24 @@ export function npmPackageOf(L, type) {
|
|
|
2715
2649
|
* attribute the site to the package instead of the generic property/
|
|
2716
2650
|
* method rejection. No-op under --dynamic (the island paths claimed
|
|
2717
2651
|
* these) and for non-package receivers, so callers' fallbacks apply. */
|
|
2718
|
-
export function npmMemberFence(
|
|
2719
|
-
if (
|
|
2652
|
+
export function npmMemberFence(lowerer, access) {
|
|
2653
|
+
if (lowerer.dynamic)
|
|
2720
2654
|
return;
|
|
2721
|
-
const pkg =
|
|
2722
|
-
|
|
2655
|
+
const pkg = lowerer.npmPackageOf(lowerer.typeOf(access.expression)) ??
|
|
2656
|
+
lowerer.npmPackageOfSymbol(lowerer.checker.getSymbolAtLocation(access.name));
|
|
2723
2657
|
if (!pkg)
|
|
2724
2658
|
return;
|
|
2725
|
-
|
|
2659
|
+
lowerer.pushDiag(requiresDynamicPackageDiag(pkg, locOf(access)));
|
|
2726
2660
|
throw new PoisonError();
|
|
2727
2661
|
}
|
|
2728
2662
|
/** The npm package a SYMBOL is declared by, or null. The symbol half of
|
|
2729
2663
|
* npmPackageOf, also asked directly for import-alias bindings (whose
|
|
2730
2664
|
* aliased symbol is the package's export). */
|
|
2731
|
-
export function npmPackageOfSymbol(
|
|
2732
|
-
const decls = sym ?
|
|
2665
|
+
export function npmPackageOfSymbol(lowerer, sym) {
|
|
2666
|
+
const decls = sym ? lowerer.checker.declarationsOf(sym) : undefined;
|
|
2733
2667
|
if (!decls || decls.length === 0)
|
|
2734
2668
|
return null;
|
|
2735
|
-
if (!decls.every((d) =>
|
|
2669
|
+
if (!decls.every((d) => lowerer.isNpmFile(d.getSourceFile())))
|
|
2736
2670
|
return null;
|
|
2737
2671
|
return npmPackageNameOf(decls[0].getSourceFile().fileName);
|
|
2738
2672
|
}
|