@scriptc/compiler 0.2.9 → 0.3.0
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 +2 -36
- package/ambient/scriptc-overrides.d.ts +1 -25
- package/ambient/scriptc.d.ts +1 -9
- package/dist/backend/cycle-analysis.d.ts +56 -0
- package/dist/backend/cycle-analysis.js +175 -14
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +95 -2
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +3 -7
- package/dist/backend/cycle-mutability.js +4 -30
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.d.ts +1 -1
- package/dist/backend/executable-features.js +3 -8
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +57 -0
- package/dist/backend/immutability.js +178 -0
- package/dist/backend/immutability.js.map +1 -0
- package/dist/backend/immutability.test.js +131 -0
- package/dist/backend/immutability.test.js.map +1 -0
- package/dist/backend/library-pack.js +0 -2
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/linker.js +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/llvm/borrowed-inputs.d.ts +9 -2
- package/dist/backend/llvm/borrowed-inputs.js +31 -3
- package/dist/backend/llvm/borrowed-inputs.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.test.js +1 -1
- package/dist/backend/llvm/classes.d.ts +28 -0
- package/dist/backend/llvm/classes.js +48 -14
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +134 -6
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +13 -0
- package/dist/backend/llvm/common.js +13 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +1 -1
- package/dist/backend/llvm/constant-callbacks.js +3 -3
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +1 -1
- package/dist/backend/llvm/dense-array-access.js +5 -4
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +10 -2
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +2 -1
- package/dist/backend/llvm/dyn.js +3 -76
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +67 -19
- package/dist/backend/llvm/emitter.js +443 -226
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +21 -3
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.js +1 -1
- package/dist/backend/llvm/expr-calls.js +14 -6
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +41 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +4 -107
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -2
- package/dist/backend/llvm/expr-dispatch.js +0 -41
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.d.ts +1 -1
- package/dist/backend/llvm/expr-dynamic.js +13 -27
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +30 -3
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +55 -2
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
- package/dist/backend/llvm/lib-dispatch.js +0 -1
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +0 -13
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +0 -8
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +3 -3
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +1 -1
- package/dist/backend/llvm/loop-array-borrows.d.ts +5 -2
- package/dist/backend/llvm/loop-array-borrows.js +27 -8
- package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +14 -0
- package/dist/backend/llvm/map-number-lookup.js +33 -2
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.d.ts +5 -0
- package/dist/backend/llvm/map-read-lifetimes.js +20 -4
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +25 -3
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +124 -0
- package/dist/backend/llvm/reference-writes.js +1090 -0
- package/dist/backend/llvm/reference-writes.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +8 -5
- package/dist/backend/llvm/shapes.js +37 -13
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +3 -3
- package/dist/backend/llvm/stack-unions.test.js +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +40 -11
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +3 -0
- package/dist/backend/llvm/string-reads.js +31 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.d.ts +2 -2
- package/dist/backend/llvm/switch-dispatch.js +35 -22
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +29 -11
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.d.ts +8 -1
- package/dist/backend/llvm/walk-borrows.js +15 -4
- package/dist/backend/llvm/walk-borrows.js.map +1 -1
- package/dist/backend/may-throw.d.ts +36 -2
- package/dist/backend/may-throw.js +308 -21
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +147 -2
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native/artifact-stamps.js +0 -2
- package/dist/backend/native/artifact-stamps.js.map +1 -1
- package/dist/backend/native/cache-warm.d.ts +1 -1
- package/dist/backend/native/cache-warm.js +2 -3
- package/dist/backend/native/cache-warm.js.map +1 -1
- package/dist/backend/native/compiler-fingerprint.d.ts +1 -1
- package/dist/backend/native/compiler-fingerprint.js +4 -7
- package/dist/backend/native/compiler-fingerprint.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +3 -28
- package/dist/backend/native/driver.js +1 -3
- package/dist/backend/native/driver.js.map +1 -1
- package/dist/backend/native/executable.d.ts +0 -15
- package/dist/backend/native/executable.js +17 -172
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/tool-identity.js +0 -1
- package/dist/backend/native/tool-identity.js.map +1 -1
- package/dist/backend/native/vendor.d.ts +1 -1
- package/dist/backend/native/vendor.js +1 -1
- package/dist/backend/native/vendor.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +0 -2
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +23 -33
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/publication.d.ts +5 -0
- package/dist/backend/publication.js +10 -0
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/publication.test.js +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +1 -2
- package/dist/backend/runtime-pack-core.js +5 -14
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +3 -8
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +22 -19
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +0 -5
- package/dist/backend/target-diagnostics.js +1 -11
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/vendor-archives.d.ts +1 -7
- package/dist/backend/vendor-archives.js +9 -189
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +0 -1
- package/dist/backend/vendor-inputs.js +0 -1
- package/dist/backend/vendor-inputs.js.map +1 -1
- package/dist/backend/warm-cache.js +3 -5
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +4 -8
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +1 -1
- package/dist/cli/usage.d.ts +1 -5
- package/dist/cli/usage.js +4 -9
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +2 -2
- package/dist/compat/fetch-profile.js +16 -25
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +2 -17
- package/dist/contracts/check.d.ts +8 -0
- package/dist/contracts/check.js +1573 -0
- package/dist/contracts/check.js.map +1 -0
- package/dist/coverage/report.d.ts +5 -22
- package/dist/coverage/report.js +12 -76
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.d.ts +3 -3
- package/dist/coverage/surface-manifest.js +22 -27
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +1 -3
- package/dist/coverage/verdict-cache.js +2 -7
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -60
- package/dist/diagnostics/diagnostic.js +39 -118
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +3 -4
- package/dist/diagnostics/envelope.js +0 -9
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/diagnostics/envelope.test.js +1 -1
- package/dist/diagnostics/envelope.test.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +0 -3
- package/dist/executable/executable-cache.js +2 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +0 -4
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +14 -2
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +10 -10
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/cjs-syntax.js +0 -88
- package/dist/frontend/cjs-syntax.js.map +1 -1
- package/dist/frontend/contract-types.d.ts +50 -0
- package/dist/frontend/contract-types.js +232 -0
- package/dist/frontend/contract-types.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +1 -1
- package/dist/frontend/dts-paths.js +1 -1
- package/dist/frontend/lowering/abstract-equality.js +1 -4
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-values.js +4 -11
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/arguments.js +0 -13
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +0 -4
- package/dist/frontend/lowering/builtins/crypto.js +0 -4
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +1 -39
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +0 -15
- package/dist/frontend/lowering/builtins/module-resolution.js +5 -44
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.d.ts +0 -6
- package/dist/frontend/lowering/builtins/numbers.js +6 -57
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.js +4 -67
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.js +1 -1
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.d.ts +1 -37
- package/dist/frontend/lowering/call-arguments.js +11 -94
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.d.ts +1 -6
- package/dist/frontend/lowering/call-signatures.js +16 -68
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +19 -4
- package/dist/frontend/lowering/class-dynamic-dispatch.js +168 -98
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +44 -4
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.js +0 -2
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.js +1 -1
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +5 -35
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/state.d.ts +0 -1
- package/dist/frontend/lowering/coercions/state.js +0 -1
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +2 -4
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +2 -12
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +12 -0
- package/dist/frontend/lowering/coercions/unions.js +63 -1
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +9 -28
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +2 -3
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +10 -54
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +0 -1
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +2 -10
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +1 -6
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +0 -2
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +0 -6
- package/dist/frontend/lowering/containers/string-and-regexp.js +2 -10
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/expressions/evaluation-safety.js +0 -3
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/native-proxy.js +1 -1
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +0 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +0 -8
- package/dist/frontend/lowering/expressions/object-literals.js +8 -35
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +0 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +7 -67
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/function-context.js +0 -1
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.js +0 -1
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +10 -77
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.js +1 -10
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.js +2 -2
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +2 -3
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +2 -27
- package/dist/frontend/lowering/lower-calls.js +56 -465
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +11 -49
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.js +2 -3
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.js +5 -8
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +3 -4
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.js +3 -5
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +0 -8
- package/dist/frontend/lowering/lower-exprs.js +133 -908
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +2 -5
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +1 -50
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +0 -43
- package/dist/frontend/lowering/lower-modules.js +25 -329
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +5 -5
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +0 -30
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +98 -0
- package/dist/frontend/lowering/{lower-island.js → lower-stdlib.js} +97 -1160
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -0
- package/dist/frontend/lowering/lower-stmts.d.ts +0 -16
- package/dist/frontend/lowering/lower-stmts.js +58 -1016
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +1 -3
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +26 -151
- package/dist/frontend/lowering/lowerer.js +120 -770
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +4 -51
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.d.ts +100 -0
- package/dist/frontend/lowering/narrowing-stability.js +1174 -0
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -0
- package/dist/frontend/lowering/narrowing-stability.test.js +150 -0
- package/dist/frontend/lowering/narrowing-stability.test.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +0 -2
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/strict-equality.js +1 -1
- package/dist/frontend/lowering/strict-equality.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +6 -45
- package/dist/frontend/lowering/surfaces.js +5 -65
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/module-syntax.d.ts +0 -3
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/npm-node.d.ts +0 -7
- package/dist/frontend/npm-node.js +0 -7
- package/dist/frontend/npm-node.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +6 -82
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +1 -1
- package/dist/frontend/npm-static.js +6 -71
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +3 -319
- package/dist/frontend/npm.js +6 -1007
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -197
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.js +1 -2
- package/dist/frontend/pipeline-native.js.map +1 -1
- package/dist/frontend/pipeline.d.ts +3 -11
- package/dist/frontend/pipeline.js +37 -56
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/pipeline.test.js +12 -6
- package/dist/frontend/pipeline.test.js.map +1 -1
- package/dist/frontend/program.d.ts +0 -34
- package/dist/frontend/program.js +13 -98
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance-core.d.ts +0 -4
- package/dist/frontend/provenance-core.js +4 -37
- package/dist/frontend/provenance-core.js.map +1 -1
- package/dist/frontend/provenance-registry.d.ts +0 -4
- package/dist/frontend/provenance-registry.js +0 -20
- package/dist/frontend/provenance-registry.js.map +1 -1
- package/dist/frontend/resolve.d.ts +0 -12
- package/dist/frontend/resolve.js +0 -34
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.js +2 -2
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/services-node.js +2 -3
- package/dist/frontend/services-node.js.map +1 -1
- package/dist/frontend/services.d.ts +1 -8
- package/dist/frontend/services.js +2 -22
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +0 -38
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/tsc-codes.js +0 -11
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +2 -27
- package/dist/frontend/type-mapper.js +85 -153
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/api.d.ts +1 -1
- package/dist/ir/api.js +1 -1
- package/dist/ir/api.js.map +1 -1
- package/dist/ir/builtin-effects.js +0 -5
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +1 -55
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/constant-globals.test.js +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/final-fields.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/int32-slots.d.ts +29 -3
- package/dist/ir/int32-slots.js +152 -66
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +1 -1
- package/dist/ir/integer-loops.js +3 -0
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +26 -1
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +20 -0
- package/dist/ir/integer-ranges.js +178 -21
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +148 -3
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +44 -284
- package/dist/ir/ir.js +10 -259
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +2 -7
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +3 -30
- package/dist/ir/runtime-features.js +5 -41
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +6 -2
- package/dist/ir/serialize.js +11 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +0 -21
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/unshare.d.ts +14 -0
- package/dist/ir/unshare.js +60 -0
- package/dist/ir/unshare.js.map +1 -0
- package/dist/ir/unshare.test.js +115 -0
- package/dist/ir/unshare.test.js.map +1 -0
- package/dist/ir/validate.js +9 -207
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +6 -6
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/prepare.js +14 -20
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/cli.js +0 -2
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.test.js +2 -4
- package/dist/native/compiler.test.js.map +1 -1
- package/dist/native/prepare.js +2 -4
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.js +2 -16
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/sanitizer.test.js +0 -3
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/startup-cache.js +0 -2
- package/dist/startup-cache.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +80 -88
- package/dist/backend/llvm/expr-island.d.ts +0 -15
- package/dist/backend/llvm/expr-island.js +0 -709
- package/dist/backend/llvm/expr-island.js.map +0 -1
- package/dist/frontend/lowering/coercions/island.d.ts +0 -37
- package/dist/frontend/lowering/coercions/island.js +0 -350
- package/dist/frontend/lowering/coercions/island.js.map +0 -1
- package/dist/frontend/lowering/lower-island.d.ts +0 -229
- package/dist/frontend/lowering/lower-island.js.map +0 -1
- package/dist/frontend/lowering/lower-island.test.js +0 -56
- package/dist/frontend/lowering/lower-island.test.js.map +0 -1
- package/dist/frontend/npm-fetch-analysis.d.ts +0 -17
- package/dist/frontend/npm-fetch-analysis.js +0 -109
- package/dist/frontend/npm-fetch-analysis.js.map +0 -1
- package/dist/frontend/npm-fetch-analysis.test.js +0 -130
- package/dist/frontend/npm-fetch-analysis.test.js.map +0 -1
- package/dist/frontend/npm-fetch-node.d.ts +0 -2
- package/dist/frontend/npm-fetch-node.js +0 -12
- package/dist/frontend/npm-fetch-node.js.map +0 -1
- package/dist/frontend/npm-fetch-syntax.d.ts +0 -6
- package/dist/frontend/npm-fetch-syntax.js +0 -202
- package/dist/frontend/npm-fetch-syntax.js.map +0 -1
- package/dist/native/runtime-typescript.d.ts +0 -4
- package/dist/native/runtime-typescript.js +0 -74
- package/dist/native/runtime-typescript.js.map +0 -1
- package/dist/native/runtime-typescript.test.js +0 -41
- package/dist/native/runtime-typescript.test.js.map +0 -1
- /package/dist/{frontend/lowering/lower-island.test.d.ts → backend/immutability.test.d.ts} +0 -0
- /package/dist/frontend/{npm-fetch-analysis.test.d.ts → lowering/narrowing-stability.test.d.ts} +0 -0
- /package/dist/{native/runtime-typescript.test.d.ts → ir/unshare.test.d.ts} +0 -0
|
@@ -19,15 +19,16 @@ import { constituentTypes } from "../ts7/checker.js";
|
|
|
19
19
|
import { dirname } from "node:path";
|
|
20
20
|
import * as posix from "node:path/posix";
|
|
21
21
|
import { checkedClassAssertion, checkedClassUnionAssertion } from "./class-assertions.js";
|
|
22
|
+
import { checkedArmExtraction } from "./coercions/unions.js";
|
|
22
23
|
import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
|
|
23
24
|
import { lowerUnionFieldRead, lowerUnionFieldWrite } from "./expressions/union-fields.js";
|
|
24
25
|
import { captureContextArguments } from "./function-context.js";
|
|
25
26
|
import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
|
|
26
27
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
27
|
-
import { BIGINT_T, BYTES_ELEMENT_NAME, BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64,
|
|
28
|
+
import { BIGINT_T, BYTES_ELEMENT_NAME, BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, NULL_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_ERROR_CLASSES, SEARCH_PARAMS_T, STRING, UNDEFINED_T, VOID, arrayOf, canAdaptDynFuncTo, canDynCheckTo, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isSupportedArrayElem, isUnitType, shapeHasAccessorSlots, typeEquals, typeKey, unionContainerArmsOk, } from "../../ir/ir.js";
|
|
28
29
|
import { cjsClassExprWholeExportOf, cjsExportAssignmentOf, cjsExportDiscardReason, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeEsmFile, locOf, } from "../program.js";
|
|
29
|
-
import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, COMPOUND_ASSIGN_OPS,
|
|
30
|
-
import { UNSUPPORTED, blockedBindingUseDiag,
|
|
30
|
+
import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, COMPOUND_ASSIGN_OPS, STDLIB_SURFACE, isChildSurfaceMember, MAP_METHODS, NARROW_FIRST, SET_METHODS, STRING_INDEX_METHODS, STR_METHODS, UNSUPPORTED_EXPR, sideEffectFreeOptionValue, stdlibGlobalNameOf, } from "./surfaces.js";
|
|
31
|
+
import { UNSUPPORTED, blockedBindingUseDiag, unsupportedPackageValueDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
31
32
|
import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
|
|
32
33
|
import { lowerCollectionSpread } from "./containers/collection-methods.js";
|
|
33
34
|
import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, lowerSafeBytesRead, } from "./array-values.js";
|
|
@@ -52,11 +53,11 @@ import { lowerYield } from "./lower-generators.js";
|
|
|
52
53
|
import { errorPropertyRead, errorPropertyWrite, errorToStringCall } from "./error-methods.js";
|
|
53
54
|
import { lowerStreamProperty, lowerStreamStateProperty, streamSidesOf } from "./lower-stream.js";
|
|
54
55
|
import { unionWideningTags } from "../../ir/analysis.js";
|
|
55
|
-
import { isSafeToDiscard,
|
|
56
|
+
import { isSafeToDiscard, isSafeToRepeat } from "./expressions/evaluation-safety.js";
|
|
56
57
|
import { globalSymbolKey } from "./expressions/global-symbols.js";
|
|
57
58
|
import { lowerShortCircuitAssignment } from "./expressions/nullish-assignment.js";
|
|
58
59
|
import { hasOptionalChainGuard, isOptionalChainTail, isRequireMainFilename, } from "./expressions/optional-chains.js";
|
|
59
|
-
import {
|
|
60
|
+
import { foldedStringKeyOf } from "./expressions/object-literals.js";
|
|
60
61
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
61
62
|
import { fenceNodeModuleMutation, isNodeModuleValue, lowerNodeModuleIdentifier, lowerNodeModuleProperty, lowerRequireCacheElement, lowerRequireCacheHas, lowerRequireMainProperty, } from "./lower-node-module.js";
|
|
62
63
|
import { lowerAbstractEquality } from "./abstract-equality.js";
|
|
@@ -377,335 +378,6 @@ function lowerExprInner(lowerer, expr) {
|
|
|
377
378
|
}
|
|
378
379
|
lowerer.unsupported("SC1090", expr, "'void' with an effectful operand in value position (hoist the operand to its own statement — statement-position 'void e' and void-returning arrow bodies compile)");
|
|
379
380
|
}
|
|
380
|
-
// Literals in an `any`-typed slot (the CONTEXTUAL type is what the
|
|
381
|
-
// record/array lowerings would consult) build natively in the island:
|
|
382
|
-
// each value lowers statically and marshals in. An UNMAPPABLE
|
|
383
|
-
// contextual type falls back to the literal's own type, exactly like
|
|
384
|
-
// lowerObjectLiteral's fallback — a package call's options parameter
|
|
385
|
-
// is often an unmappable intersection while the literal's own type
|
|
386
|
-
// absorbs to jsval (a bare-jsval field, an npm-typed member).
|
|
387
|
-
if ((ts.isObjectLiteralExpression(expr) || ts.isArrayLiteralExpression(expr)) &&
|
|
388
|
-
(() => {
|
|
389
|
-
const ctxTs = lowerer.checker.getContextualType(expr);
|
|
390
|
-
const mapped = (ctxTs ? lowerer.mapTypeOf(ctxTs) : null) ?? lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
391
|
-
if (mapped?.kind !== "jsval")
|
|
392
|
-
return false;
|
|
393
|
-
// The tsgo readonly-[] panic repair (see lowerArrayLiteral): an
|
|
394
|
-
// EMPTY array literal under a const assertion is the empty tuple —
|
|
395
|
-
// its `any` answer is a panicked query, not an island slot.
|
|
396
|
-
if (ts.isArrayLiteralExpression(expr) &&
|
|
397
|
-
expr.elements.length === 0 &&
|
|
398
|
-
underConstAssertion(expr)) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
// A JS variable INITIALIZER whose BINDING registered as a
|
|
402
|
-
// checked-dynamic module global (the typedef-annotated
|
|
403
|
-
// doc-builder consts whose JSDoc types degraded — DYN slots):
|
|
404
|
-
// the island build could never land (no engine→dyn crossing
|
|
405
|
-
// exists), so the literal takes its own world's path instead —
|
|
406
|
-
// the dyn literal, or a static record the slot converts.
|
|
407
|
-
if (isJsSourceFile(expr.getSourceFile()) &&
|
|
408
|
-
ts.isVariableDeclaration(expr.parent) &&
|
|
409
|
-
expr.parent.initializer === expr &&
|
|
410
|
-
ts.isIdentifier(expr.parent.name)) {
|
|
411
|
-
const bindSym = lowerer.checker.getSymbolAtLocation(expr.parent.name);
|
|
412
|
-
const g = bindSym ? lowerer.globalsBySymbol.get(bindSym) : undefined;
|
|
413
|
-
if (g?.type.kind === "dyn")
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
// A PROJECT-DECLARED contextual type that only ABSORBED to the
|
|
417
|
-
// island (a doc-builder typedef whose field's JSDoc type
|
|
418
|
-
// reference degraded to checker-`any` — the tsgo multi-file
|
|
419
|
-
// value-as-type residue) is not an npm slot: when the literal's
|
|
420
|
-
// OWN type maps statically, it builds that way — the binding's
|
|
421
|
-
// checked-dynamic slot takes the dyn conversion. Genuinely
|
|
422
|
-
// island slots (npm .d.ts provenance, plain `any`) keep the
|
|
423
|
-
// native build.
|
|
424
|
-
if (ctxTs !== undefined && (ctxTs.flags & ts.TypeFlags.Any) === 0) {
|
|
425
|
-
// Intersection/tuple typedefs (`Line & {readonly soft: true}`)
|
|
426
|
-
// carry provenance on the ALIAS symbol.
|
|
427
|
-
const sym = ctxTs.getSymbol() ?? ctxTs.getAliasSymbol();
|
|
428
|
-
const decls = sym ? lowerer.checker.declarationsOf(sym) : [];
|
|
429
|
-
const projectDeclared = decls.length > 0 &&
|
|
430
|
-
decls.every((d) => {
|
|
431
|
-
const sf = d.getSourceFile();
|
|
432
|
-
return !sf.isDeclarationFile && !sf.fileName.includes("/node_modules/");
|
|
433
|
-
});
|
|
434
|
-
if (projectDeclared) {
|
|
435
|
-
// A spread already stored in the island must copy there too.
|
|
436
|
-
// Later overrides can make the literal's own inferred shape
|
|
437
|
-
// appear static without making that source a native record.
|
|
438
|
-
if (ts.isObjectLiteralExpression(expr) &&
|
|
439
|
-
expr.properties.some((p) => ts.isSpreadAssignment(p) &&
|
|
440
|
-
lowerer.mapTypeOf(lowerer.typeOf(p.expression))?.kind === "jsval")) {
|
|
441
|
-
return true;
|
|
442
|
-
}
|
|
443
|
-
const own = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
444
|
-
if (own?.kind === "record" || own?.kind === "array")
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
return true;
|
|
449
|
-
})()) {
|
|
450
|
-
if (ts.isObjectLiteralExpression(expr)) {
|
|
451
|
-
// Two engine literals when a CONDITIONAL spread participates
|
|
452
|
-
// (`{ a, ...(c ? { k: v } : {}) }` — the optional-key idiom): the
|
|
453
|
-
// whole literal becomes `c ? objLit(with) : objLit(without)`. The
|
|
454
|
-
// shared properties' nodes ride BOTH arms (exactly one arm
|
|
455
|
-
// evaluates, so each property still evaluates once); the reorder
|
|
456
|
-
// of `c` before earlier properties is unobservable because the
|
|
457
|
-
// condition must be a side-effect-free read. The spread arm's keys
|
|
458
|
-
// are truly ABSENT when the empty arm is taken — engine-exact
|
|
459
|
-
// (`"k" in o` is false), which the static record path can't say.
|
|
460
|
-
const argsWithout = [];
|
|
461
|
-
const argsWith = [];
|
|
462
|
-
const getters = [];
|
|
463
|
-
let spread = null;
|
|
464
|
-
// A MEMBER a JS file cannot lower or marshal: defer like a
|
|
465
|
-
// statement fence, shaped by what the member IS. A FUNCTION-shaped
|
|
466
|
-
// member (a generic function as a value, a signature with
|
|
467
|
-
// checked-dynamic parameters — the doc-builder public aggregate's
|
|
468
|
-
// degraded pieces) becomes a host closure that THROWS the captured
|
|
469
|
-
// diagnostic when invoked — building the aggregate compiles and
|
|
470
|
-
// only a CALL through the island stops the run. A DATA-shaped
|
|
471
|
-
// member must NOT become a callable (the retired fence box's
|
|
472
|
-
// silent wrong answers: typeof said "function", downstream errors
|
|
473
|
-
// blamed the wrong thing — the withPlugins `plugins:` slot), so it
|
|
474
|
-
// defines through the engine's getter machinery instead: READING
|
|
475
|
-
// the member throws the diagnostic — the honest granularity, since
|
|
476
|
-
// using the value is exactly what cannot be answered. `getterName`
|
|
477
|
-
// null keeps the closure shape (function-shaped members, and the
|
|
478
|
-
// conditional-spread arms where getters cannot combine).
|
|
479
|
-
const islandMemberFence = (diagsBefore, err, valueNode, getterName = null) => {
|
|
480
|
-
if (!isJsSourceFile(expr.getSourceFile()))
|
|
481
|
-
throw err;
|
|
482
|
-
const fence = lowerer.deferToRuntimeFence(diagsBefore, valueNode, {
|
|
483
|
-
kind: "closure",
|
|
484
|
-
name: () => `%fn${lowerer.lambdaCounter++}_islfence`,
|
|
485
|
-
returnType: VOID,
|
|
486
|
-
type: { kind: "func", params: [], ret: VOID },
|
|
487
|
-
});
|
|
488
|
-
if (!fence)
|
|
489
|
-
throw err;
|
|
490
|
-
if (getterName !== null) {
|
|
491
|
-
getters.push({
|
|
492
|
-
name: getterName,
|
|
493
|
-
fn: lowerer.jsvalIn(fence, valueNode),
|
|
494
|
-
loc: locOf(valueNode),
|
|
495
|
-
});
|
|
496
|
-
return null;
|
|
497
|
-
}
|
|
498
|
-
return lowerer.jsvalIn(fence, valueNode);
|
|
499
|
-
};
|
|
500
|
-
// The member's SHAPE decides the fence's granularity: syntactic
|
|
501
|
-
// functions and checker-callable values keep the call-time
|
|
502
|
-
// closure; everything else (call results, awaits, data reads —
|
|
503
|
-
// the withPlugins `plugins:` shape) fences at the READ.
|
|
504
|
-
const funcShapedMember = (p) => {
|
|
505
|
-
if (ts.isMethodDeclaration(p))
|
|
506
|
-
return true;
|
|
507
|
-
const src = ts.isPropertyAssignment(p)
|
|
508
|
-
? p.initializer
|
|
509
|
-
: ts.isShorthandPropertyAssignment(p)
|
|
510
|
-
? p.name
|
|
511
|
-
: null;
|
|
512
|
-
if (!src || !ts.isExpression(src))
|
|
513
|
-
return true; // unknown form: keep the closure shape
|
|
514
|
-
let inner = src;
|
|
515
|
-
while (ts.isParenthesizedExpression(inner))
|
|
516
|
-
inner = inner.expression;
|
|
517
|
-
if (ts.isArrowFunction(inner) || ts.isFunctionExpression(inner))
|
|
518
|
-
return true;
|
|
519
|
-
return lowerer.checker.getCallSignatures(lowerer.typeOf(src)).length > 0;
|
|
520
|
-
};
|
|
521
|
-
const pushProp = (name, value, valueNode, into) => {
|
|
522
|
-
const diagsBefore = lowerer.diags.length;
|
|
523
|
-
let marshaled;
|
|
524
|
-
try {
|
|
525
|
-
marshaled = lowerer.jsvalIn(value, valueNode);
|
|
526
|
-
}
|
|
527
|
-
catch (err) {
|
|
528
|
-
// A value that LOWERED but cannot cross (a promise, a class
|
|
529
|
-
// instance): func-typed values keep the call-time closure;
|
|
530
|
-
// data-shaped values fence at the read (the getter), unless a
|
|
531
|
-
// conditional spread owns the literal (getters cannot combine).
|
|
532
|
-
if (!(err instanceof PoisonError))
|
|
533
|
-
throw err;
|
|
534
|
-
const asGetter = value.type.kind !== "func" && spread === null;
|
|
535
|
-
const fence = islandMemberFence(diagsBefore, err, valueNode, asGetter ? name.text : null);
|
|
536
|
-
if (fence === null)
|
|
537
|
-
return; // registered as a fence getter — no data property
|
|
538
|
-
marshaled = fence;
|
|
539
|
-
}
|
|
540
|
-
for (const args of into) {
|
|
541
|
-
args.push({
|
|
542
|
-
kind: "jsMarshal",
|
|
543
|
-
value: { kind: "strLit", value: name.text, type: STRING, loc: locOf(name) },
|
|
544
|
-
type: JSVAL,
|
|
545
|
-
loc: locOf(name),
|
|
546
|
-
});
|
|
547
|
-
args.push(marshaled);
|
|
548
|
-
}
|
|
549
|
-
};
|
|
550
|
-
const spreadSrcs = [];
|
|
551
|
-
let sawPlainProp = false;
|
|
552
|
-
for (const prop of expr.properties) {
|
|
553
|
-
if (ts.isSpreadAssignment(prop)) {
|
|
554
|
-
const cs = conditionalSpreadOf(prop.expression);
|
|
555
|
-
if (cs && cs !== "unsupported" && !spread) {
|
|
556
|
-
if (spreadSrcs.length > 0) {
|
|
557
|
-
lowerer.unsupported("SC1090", prop, "a conditional spread mixed with plain spreads in an 'any'-typed object literal");
|
|
558
|
-
}
|
|
559
|
-
const cond = lowerer.lowerCondition(cs.cond);
|
|
560
|
-
if (!isSafeToMoveConditionEarlier(cond)) {
|
|
561
|
-
lowerer.unsupported("SC1090", prop, "conditional spreads with effectful conditions in an 'any'-typed object literal (bind the condition to a const first)");
|
|
562
|
-
}
|
|
563
|
-
spread = { cond, whenTrue: cs.whenTrue };
|
|
564
|
-
for (const p of cs.props) {
|
|
565
|
-
const v = ts.isPropertyAssignment(p)
|
|
566
|
-
? lowerer.lowerExpr(p.initializer)
|
|
567
|
-
: lowerer.lowerShorthandValue(p);
|
|
568
|
-
pushProp(p.name, v, p, [argsWith]);
|
|
569
|
-
}
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
// A PLAIN spread (`{ ...options, plugins }` — the withPlugins
|
|
573
|
-
// argument-rebuild shape): the source copies into the fresh
|
|
574
|
-
// engine object through the spec's CopyDataProperties (the
|
|
575
|
-
// objSpread op). Spreads must precede explicit properties
|
|
576
|
-
// (the composition applies explicit keys AFTER the copies —
|
|
577
|
-
// JS's later-wins — which a spread after them would invert);
|
|
578
|
-
// mixing with a conditional spread keeps the fence.
|
|
579
|
-
if (cs === undefined || cs === null) {
|
|
580
|
-
if (sawPlainProp || spread) {
|
|
581
|
-
lowerer.unsupported("SC1090", prop, "object spread after explicit properties (or mixed with a conditional spread) in an 'any'-typed object literal — spreads must come first");
|
|
582
|
-
}
|
|
583
|
-
spreadSrcs.push(lowerer.jsvalIn(lowerer.lowerExpr(prop.expression), prop.expression));
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
lowerer.unsupported("SC1090", prop, "this spread form in an 'any'-typed object literal (one `...(c ? { k: v } : {})` conditional spread is supported — bind other shapes to a const and set keys explicitly)");
|
|
587
|
-
}
|
|
588
|
-
sawPlainProp = true;
|
|
589
|
-
// `name: value`, the shorthand `{ name }` (the value is the
|
|
590
|
-
// identifier itself, resolved through the shorthand VALUE symbol
|
|
591
|
-
// like the static record path), and METHODS — `{ load() {...} }`
|
|
592
|
-
// is a function expression under a shorthand name, marshaled
|
|
593
|
-
// like any closure value (this-uses keep the static path's
|
|
594
|
-
// rejection); everything else keeps the fence. Identifier and
|
|
595
|
-
// string-literal keys — engine property names have no
|
|
596
|
-
// identifier restriction ("content-type").
|
|
597
|
-
const name = prop.name;
|
|
598
|
-
// A GET accessor (`get root() { return ROOT_INDENT; }` — the
|
|
599
|
-
// doc-printer's self-referential root-indent shape): the body
|
|
600
|
-
// lowers as a zero-param closure marshaled into the engine, and
|
|
601
|
-
// the property defines through the engine's own getter
|
|
602
|
-
// machinery AFTER the literal builds (the defineGetter op) —
|
|
603
|
-
// reads through the handle invoke it natively. `this` in the
|
|
604
|
-
// body keeps the object-method rejection; setters stay fenced.
|
|
605
|
-
if (ts.isGetAccessorDeclaration(prop) &&
|
|
606
|
-
prop.body &&
|
|
607
|
-
name &&
|
|
608
|
-
(ts.isIdentifier(name) || ts.isStringLiteral(name))) {
|
|
609
|
-
lowerer.rejectThisInObjectMethod(prop.body);
|
|
610
|
-
getters.push({
|
|
611
|
-
name: name.text,
|
|
612
|
-
fn: lowerer.jsvalIn(lowerer.lowerLambda(prop), prop),
|
|
613
|
-
loc: locOf(prop),
|
|
614
|
-
});
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
// A member VALUE that cannot lower at all (a generic function
|
|
618
|
-
// referenced as a value — the aggregate's `align`): the same
|
|
619
|
-
// call-time fence deferral pushProp applies to marshal failures.
|
|
620
|
-
let value = null;
|
|
621
|
-
const valueDiagsBefore = lowerer.diags.length;
|
|
622
|
-
try {
|
|
623
|
-
value = ts.isPropertyAssignment(prop)
|
|
624
|
-
? lowerer.lowerExpr(prop.initializer)
|
|
625
|
-
: ts.isShorthandPropertyAssignment(prop)
|
|
626
|
-
? lowerer.lowerShorthandValue(prop)
|
|
627
|
-
: ts.isMethodDeclaration(prop) && prop.body
|
|
628
|
-
? (lowerer.rejectThisInObjectMethod(prop.body), lowerer.lowerLambda(prop))
|
|
629
|
-
: null;
|
|
630
|
-
}
|
|
631
|
-
catch (err) {
|
|
632
|
-
if (!(err instanceof PoisonError))
|
|
633
|
-
throw err;
|
|
634
|
-
const nameText = name && (ts.isIdentifier(name) || ts.isStringLiteral(name)) ? name.text : null;
|
|
635
|
-
const asGetter = nameText !== null && spread === null && !funcShapedMember(prop);
|
|
636
|
-
value = islandMemberFence(valueDiagsBefore, err, prop, asGetter ? nameText : null);
|
|
637
|
-
if (value === null)
|
|
638
|
-
continue; // registered as a fence getter — no data property
|
|
639
|
-
}
|
|
640
|
-
if (value && name && (ts.isIdentifier(name) || ts.isStringLiteral(name))) {
|
|
641
|
-
pushProp(name, value, prop, [argsWithout, argsWith]);
|
|
642
|
-
}
|
|
643
|
-
else {
|
|
644
|
-
lowerer.unsupported("SC1090", prop, "this property form in an 'any'-typed object literal (only `name: value`, shorthand names, methods, and get accessors are supported)");
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
const withGetters = (obj) => getters.reduce((acc, g) => ({
|
|
648
|
-
kind: "jsOp",
|
|
649
|
-
op: "defineGetter",
|
|
650
|
-
args: [
|
|
651
|
-
acc,
|
|
652
|
-
{
|
|
653
|
-
kind: "jsMarshal",
|
|
654
|
-
value: { kind: "strLit", value: g.name, type: STRING, loc: g.loc },
|
|
655
|
-
type: JSVAL,
|
|
656
|
-
loc: g.loc,
|
|
657
|
-
},
|
|
658
|
-
g.fn,
|
|
659
|
-
],
|
|
660
|
-
type: JSVAL,
|
|
661
|
-
loc: g.loc,
|
|
662
|
-
}), obj);
|
|
663
|
-
if (!spread) {
|
|
664
|
-
if (spreadSrcs.length === 0) {
|
|
665
|
-
return withGetters({ kind: "jsOp", op: "objLit", args: argsWithout, type: JSVAL, loc });
|
|
666
|
-
}
|
|
667
|
-
// Plain spreads compose left to right onto a fresh object, the
|
|
668
|
-
// explicit properties merging LAST (JS's later-wins): spread
|
|
669
|
-
// sources evaluate before later property values by nesting
|
|
670
|
-
// order, exactly the source order.
|
|
671
|
-
let acc = { kind: "jsOp", op: "objLit", args: [], type: JSVAL, loc };
|
|
672
|
-
for (const src of spreadSrcs) {
|
|
673
|
-
acc = { kind: "jsOp", op: "objSpread", args: [acc, src], type: JSVAL, loc };
|
|
674
|
-
}
|
|
675
|
-
if (argsWithout.length > 0) {
|
|
676
|
-
acc = {
|
|
677
|
-
kind: "jsOp",
|
|
678
|
-
op: "objSpread",
|
|
679
|
-
args: [acc, { kind: "jsOp", op: "objLit", args: argsWithout, type: JSVAL, loc }],
|
|
680
|
-
type: JSVAL,
|
|
681
|
-
loc,
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
return withGetters(acc);
|
|
685
|
-
}
|
|
686
|
-
if (getters.length > 0) {
|
|
687
|
-
lowerer.unsupported("SC1090", expr, "get accessors combined with conditional spreads in an 'any'-typed object literal");
|
|
688
|
-
}
|
|
689
|
-
const withLit = { kind: "jsOp", op: "objLit", args: argsWith, type: JSVAL, loc };
|
|
690
|
-
const withoutLit = {
|
|
691
|
-
kind: "jsOp",
|
|
692
|
-
op: "objLit",
|
|
693
|
-
args: argsWithout,
|
|
694
|
-
type: JSVAL,
|
|
695
|
-
loc,
|
|
696
|
-
};
|
|
697
|
-
return {
|
|
698
|
-
kind: "ternary",
|
|
699
|
-
cond: spread.cond,
|
|
700
|
-
then: spread.whenTrue ? withLit : withoutLit,
|
|
701
|
-
else_: spread.whenTrue ? withoutLit : withLit,
|
|
702
|
-
type: JSVAL,
|
|
703
|
-
loc,
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
const args = expr.elements.map((el) => lowerer.jsvalIn(lowerer.lowerExpr(el), el));
|
|
707
|
-
return { kind: "jsOp", op: "arrLit", args, type: JSVAL, loc };
|
|
708
|
-
}
|
|
709
381
|
if (ts.isTypeOfExpression(expr)) {
|
|
710
382
|
if (lowerer.isStdlibGlobal(expr.expression, "process"))
|
|
711
383
|
return { kind: "strLit", value: "object", type: STRING, loc };
|
|
@@ -759,7 +431,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
759
431
|
tested = tested.expression;
|
|
760
432
|
if (ts.isIdentifier(tested)) {
|
|
761
433
|
const sym = lowerer.checker.getSymbolAtLocation(tested);
|
|
762
|
-
if (!sym
|
|
434
|
+
if (!sym) {
|
|
763
435
|
return { kind: "strLit", value: "undefined", type: STRING, loc };
|
|
764
436
|
}
|
|
765
437
|
if (lowerer.isStdlibSymbol(sym)) {
|
|
@@ -774,9 +446,6 @@ function lowerExprInner(lowerer, expr) {
|
|
|
774
446
|
// still evaluates: calls, getters, and checked reads can have effects
|
|
775
447
|
// or throw. Only trivial operands may disappear.
|
|
776
448
|
let operand = deferredSlotOr(lowerer, runtimeOptionalStorageOperand(lowerer, expr.expression) ?? lowerer.lowerExpr(expr.expression));
|
|
777
|
-
if (operand.type.kind === "jsval") {
|
|
778
|
-
return { kind: "jsOp", op: "typeof", args: [operand], type: STRING, loc };
|
|
779
|
-
}
|
|
780
449
|
// A checker-narrowed dyn read arrives as a VALIDATED extraction
|
|
781
450
|
// (maybeNarrow's dynCheck bridge). typeof needs no extraction — the
|
|
782
451
|
// dyn kind table answers the question directly, and answers it even
|
|
@@ -825,6 +494,13 @@ function lowerExprInner(lowerer, expr) {
|
|
|
825
494
|
// tests, so only side-effect-free reads compose — and when every arm
|
|
826
495
|
// agrees the whole expression folds to that one string (dropping only
|
|
827
496
|
// the pure read, the trust-the-checker bet lowerUnitComparison makes).
|
|
497
|
+
// An effectful producer (a getter) evaluates once into a hidden local.
|
|
498
|
+
const prelude = [];
|
|
499
|
+
if (operand.type.kind === "union" && !isSafeToRepeat(operand)) {
|
|
500
|
+
const local = lowerer.declareHiddenLocal("%typeofOperand", operand.type);
|
|
501
|
+
prelude.push({ kind: "varDecl", localId: local.id, init: operand, loc });
|
|
502
|
+
operand = varRef(local.id, operand.type, loc);
|
|
503
|
+
}
|
|
828
504
|
if (operand.type.kind === "union" && isSafeToRepeat(operand)) {
|
|
829
505
|
const def = lowerer.unions.get(operand.type.unionId);
|
|
830
506
|
const answers = def?.arms.map(typeofAnswer);
|
|
@@ -875,7 +551,9 @@ function lowerExprInner(lowerer, expr) {
|
|
|
875
551
|
loc,
|
|
876
552
|
};
|
|
877
553
|
}
|
|
878
|
-
return
|
|
554
|
+
return prelude.length > 0
|
|
555
|
+
? { kind: "seqExpr", stmts: prelude, result, type: STRING, loc }
|
|
556
|
+
: result;
|
|
879
557
|
}
|
|
880
558
|
}
|
|
881
559
|
if (operand.type.kind === "dyn") {
|
|
@@ -1236,19 +914,14 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1236
914
|
if (lowerer.cjsLocalModuleBindingOf(expr)) {
|
|
1237
915
|
lowerer.unsupported("SC1090", expr, `module namespace objects as values (access '${expr.text}' members directly)`);
|
|
1238
916
|
}
|
|
1239
|
-
if (lowerer.
|
|
1240
|
-
// Island-backed functions have no closure representation (they
|
|
1241
|
-
// lower to engine ops at call sites only).
|
|
917
|
+
if (lowerer.stdlibGlobalFnOf(expr)) {
|
|
1242
918
|
lowerer.unsupported("SC1090", expr, `library functions as values (call '${expr.text}' directly)`);
|
|
1243
919
|
}
|
|
1244
|
-
//
|
|
1245
|
-
|
|
1246
|
-
// diagnostic, not the generic fallthrough. (Under --dynamic these
|
|
1247
|
-
// resolve as jsval globals above.)
|
|
1248
|
-
if (!lowerer.dynamic) {
|
|
920
|
+
// A declaration-only npm binding has no compiled runtime value.
|
|
921
|
+
{
|
|
1249
922
|
const pkg = lowerer.npmPackageOfSymbol(lowerer.resolveValueSymbol(expr) ?? undefined);
|
|
1250
923
|
if (pkg) {
|
|
1251
|
-
lowerer.pushDiag(
|
|
924
|
+
lowerer.pushDiag(unsupportedPackageValueDiag(pkg, loc));
|
|
1252
925
|
throw new PoisonError();
|
|
1253
926
|
}
|
|
1254
927
|
}
|
|
@@ -1346,13 +1019,13 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1346
1019
|
}
|
|
1347
1020
|
return { kind: "closure", fnName: name, captures: [], type, loc };
|
|
1348
1021
|
}
|
|
1349
|
-
if (
|
|
1022
|
+
if (lowerer.isStdlibGlobal(expr, "crypto"))
|
|
1350
1023
|
return { kind: "libCall", fn: "crypto.native", args: [], type: DYN, loc };
|
|
1351
1024
|
const nativeAlias = stdlibGlobalNameOf(lowerer, expr);
|
|
1352
1025
|
if (nativeAlias === "Buffer" && expr.text !== "Buffer") {
|
|
1353
1026
|
return { kind: "strLit", value: "[builtin Buffer]", type: STRING, loc };
|
|
1354
1027
|
}
|
|
1355
|
-
if (
|
|
1028
|
+
if (lowerer.isStdlibGlobal(expr, "fetch")) {
|
|
1356
1029
|
return { kind: "libCall", fn: "fetch.function", args: [], type: DYN, loc };
|
|
1357
1030
|
}
|
|
1358
1031
|
// The lib fence's IDENTIFIER chokepoint: the real standard library
|
|
@@ -1368,7 +1041,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1368
1041
|
// global, one token; what a token cannot do (be called, answer
|
|
1369
1042
|
// typeof "function") meets per-site fences/divergences, and
|
|
1370
1043
|
// SEMANTICS.md documents the stance.
|
|
1371
|
-
if (
|
|
1044
|
+
if (stdlibGlobalNameOf(lowerer, expr) === "globalThis") {
|
|
1372
1045
|
return lowerGlobalValue(lowerer, expr);
|
|
1373
1046
|
}
|
|
1374
1047
|
{
|
|
@@ -1378,13 +1051,6 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1378
1051
|
const canonical = stdlibGlobalNameOf(lowerer, expr) ?? expr.text;
|
|
1379
1052
|
return { kind: "strLit", value: `[builtin ${canonical}]`, type: STRING, loc };
|
|
1380
1053
|
}
|
|
1381
|
-
// In a dynamic TypeScript build, the real global object is the
|
|
1382
|
-
// escape hatch for host capabilities without static lowering.
|
|
1383
|
-
// Direct globalThis.member uses still take their static surface
|
|
1384
|
-
// paths; an explicit `as any` or `: any` can reach engine ops.
|
|
1385
|
-
if (lowerer.dynamic && expr.text === "globalThis") {
|
|
1386
|
-
return { kind: "jsOp", op: "globalGet", name: "globalThis", args: [], type: JSVAL, loc };
|
|
1387
|
-
}
|
|
1388
1054
|
// The families with a WHY: each hint states what makes the
|
|
1389
1055
|
// surface genuinely non-static (or what to use instead).
|
|
1390
1056
|
const globalHints = {
|
|
@@ -1633,9 +1299,8 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1633
1299
|
const promiseArm = def.arms[promiseTag];
|
|
1634
1300
|
const inner = promiseArm.kind === "promise" ? promiseArm.inner : VOID;
|
|
1635
1301
|
const units = def.arms.filter(isUnitType);
|
|
1636
|
-
if (inner.kind === "union" || inner.kind === "dyn"
|
|
1302
|
+
if (inner.kind === "union" || inner.kind === "dyn") {
|
|
1637
1303
|
// A union inner would need an arm-wise re-tag into the result
|
|
1638
|
-
// union; dyn/jsval inners have their own boundary stories.
|
|
1639
1304
|
lowerer.unsupported("SC1090", expr, `awaiting '${lowerer.fmt(value.type)}' (the promise's inner type has no combined result union — await the promise arm after narrowing instead)`);
|
|
1640
1305
|
}
|
|
1641
1306
|
let type;
|
|
@@ -1665,27 +1330,6 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1665
1330
|
if (value.type.kind === "dyn") {
|
|
1666
1331
|
return { kind: "libCall", fn: "async.awaitDyn", args: [value], type: DYN, loc };
|
|
1667
1332
|
}
|
|
1668
|
-
// A jsval whose CHECKER type is a promise is a package-returned
|
|
1669
|
-
// promise: the value lives in the engine. Bridge it — a static
|
|
1670
|
-
// promise the engine promise settles (fulfillment = the retained
|
|
1671
|
-
// handle or void, rejection = the bridged reason) — and await
|
|
1672
|
-
// THAT: the fiber parks like any await, resumes with the settled
|
|
1673
|
-
// jsval, or re-throws the crossed rejection.
|
|
1674
|
-
if (value.type.kind === "jsval") {
|
|
1675
|
-
// ANY island value bridges — the runtime's Promise.resolve(v)
|
|
1676
|
-
// .then(...) wiring awaits thenables and non-thenables exactly
|
|
1677
|
-
// like JS (`await reg.load()` where the checker only knows
|
|
1678
|
-
// 'any' must still park on the returned engine promise).
|
|
1679
|
-
const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
|
|
1680
|
-
const inner = mapped?.kind === "promise" && mapped.inner.kind === "void" ? VOID : JSVAL;
|
|
1681
|
-
const bridged = {
|
|
1682
|
-
kind: "jsBridgePromise",
|
|
1683
|
-
value,
|
|
1684
|
-
type: { kind: "promise", inner },
|
|
1685
|
-
loc,
|
|
1686
|
-
};
|
|
1687
|
-
return { kind: "awaitExpr", value: bridged, type: inner, loc };
|
|
1688
|
-
}
|
|
1689
1333
|
// A TYPED non-promise operand (`await 42`, an awaited record):
|
|
1690
1334
|
// JS awaits non-thenables through exactly one microtask turn and
|
|
1691
1335
|
// yields the value itself — evaluate the operand, hop, answer it.
|
|
@@ -1755,9 +1399,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1755
1399
|
return lowerer.lowerBinary(expr);
|
|
1756
1400
|
if (ts.isCallExpression(expr)) {
|
|
1757
1401
|
// The tail of an optional chain whose `?.` sits deeper
|
|
1758
|
-
// (`x?.trim().toLowerCase()`): the whole tail short-circuits
|
|
1759
|
-
// the guard, so it lowers as one chain (dyn/island receivers keep
|
|
1760
|
-
// their own undefined-propagating reads — see isOptionalChainTail).
|
|
1402
|
+
// (`x?.trim().toLowerCase()`): the whole tail short-circuits together.
|
|
1761
1403
|
if (isOptionalChainTail(lowerer, expr))
|
|
1762
1404
|
return lowerer.lowerOptionalChain(expr);
|
|
1763
1405
|
return lowerer.lowerCall(expr);
|
|
@@ -1799,7 +1441,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1799
1441
|
return lowerer.lowerSuperAccessorRead(expr);
|
|
1800
1442
|
}
|
|
1801
1443
|
// Enum member reads (`E.A`) fold to their compile-time constants —
|
|
1802
|
-
// claimed FIRST so no receiver-shaped path (records,
|
|
1444
|
+
// claimed FIRST so no receiver-shaped path (records, the
|
|
1803
1445
|
// identifier fence on the enum object) sees them. lower-enums.ts.
|
|
1804
1446
|
{
|
|
1805
1447
|
const en = lowerEnumAccess(lowerer, expr);
|
|
@@ -1858,7 +1500,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1858
1500
|
loc,
|
|
1859
1501
|
};
|
|
1860
1502
|
}
|
|
1861
|
-
if (
|
|
1503
|
+
if (lowerer.stdlibGlobalMember(expr, "Object") === "freeze") {
|
|
1862
1504
|
const name = "%builtin.Object.freeze";
|
|
1863
1505
|
if (!lowerer.liftedFns.some((fn) => fn.name === name))
|
|
1864
1506
|
lowerer.liftedFns.push({
|
|
@@ -1899,8 +1541,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1899
1541
|
// in a native program. Declared globals retain their own lowering;
|
|
1900
1542
|
// arbitrary global-object mutation remains fenced. Preserve a dyn
|
|
1901
1543
|
// undefined value so stored probes compose with optional calls.
|
|
1902
|
-
if (
|
|
1903
|
-
stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
|
|
1544
|
+
if (stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
|
|
1904
1545
|
!lowerer.checker.getPropertyOfType(lowerer.typeOf(expr.expression), expr.name.text)) {
|
|
1905
1546
|
return dynUndefinedExpr(loc);
|
|
1906
1547
|
}
|
|
@@ -1926,63 +1567,11 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1926
1567
|
lowerer.fenceStaticResponseMember(expr, "read");
|
|
1927
1568
|
lowerer.fenceStaticHeadersMember(expr, "read");
|
|
1928
1569
|
lowerer.fenceStaticReadableStreamMember(expr, "read");
|
|
1929
|
-
// Island receiver: o.x is an engine property read (getProp may throw
|
|
1930
1570
|
// — reading off null/undefined — bridged catchably like everything
|
|
1931
1571
|
// at the boundary). `o?.x` arrives here too, through the chain
|
|
1932
1572
|
// lowering's re-dispatch (a questionDotToken past the gate above is
|
|
1933
1573
|
// always chain-handled; the receiver reads back as the chain's
|
|
1934
1574
|
// bound handle).
|
|
1935
|
-
if (lowerer.isIslandExpr(expr.expression)) {
|
|
1936
|
-
const receiver = lowerer.lowerExpr(expr.expression);
|
|
1937
|
-
// The checker said 'any' but the VALUE lives in the checked-dynamic tree (`this`
|
|
1938
|
-
// in a plain JS function — dyn.this — or a checked-dynamic local
|
|
1939
|
-
// behind an any-typed spelling): the property read is the checked-dynamic tree's
|
|
1940
|
-
// own keyed read, dyn results and dyn chains exactly like every
|
|
1941
|
-
// checked-dynamic member access (a nullish receiver throws V8's
|
|
1942
|
-
// catchable TypeError, exactly Node). Never a jsOp over a dyn —
|
|
1943
|
-
// the two dynamic worlds don't share a value representation.
|
|
1944
|
-
if (receiver.type.kind === "dyn") {
|
|
1945
|
-
return {
|
|
1946
|
-
kind: "dynKeyGet",
|
|
1947
|
-
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
1948
|
-
value: receiver,
|
|
1949
|
-
type: DYN,
|
|
1950
|
-
loc,
|
|
1951
|
-
};
|
|
1952
|
-
}
|
|
1953
|
-
const read = {
|
|
1954
|
-
kind: "jsOp",
|
|
1955
|
-
op: "getProp",
|
|
1956
|
-
name: expr.name.text,
|
|
1957
|
-
args: [receiver],
|
|
1958
|
-
type: JSVAL,
|
|
1959
|
-
loc,
|
|
1960
|
-
};
|
|
1961
|
-
// A member the .d.ts DECLARES as a primitive exits eagerly to that
|
|
1962
|
-
// static type (`f.mediaType` on a package handle IS a string):
|
|
1963
|
-
// primitives copy by value across the boundary — no aliasing, no
|
|
1964
|
-
// cost — and every static consumer (intrinsics, templates,
|
|
1965
|
-
// comparisons) works on the result. Trust-but-verify: a lying
|
|
1966
|
-
// declaration throws the catchable TypeError instead of smuggling
|
|
1967
|
-
// a mistyped handle into string ops. A Uint8Array member exits the
|
|
1968
|
-
// same way (`result.audio.uint8Array` — the generated-media
|
|
1969
|
-
// payload) as a validated u8 COPY, the boundary's aliasing stance
|
|
1970
|
-
// (divergences 44/45; engine Buffers pass — they ARE Uint8Arrays).
|
|
1971
|
-
// Other composites stay handles (eager JSON copies would change
|
|
1972
|
-
// aliasing), and chain-handled reads stay jsval (the chain's unit
|
|
1973
|
-
// path is the engine's undefined — see lowerOptionalChain).
|
|
1974
|
-
if (!expr.questionDotToken) {
|
|
1975
|
-
const declared = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
1976
|
-
if (declared &&
|
|
1977
|
-
(declared.kind === "f64" ||
|
|
1978
|
-
declared.kind === "bool" ||
|
|
1979
|
-
declared.kind === "string" ||
|
|
1980
|
-
(declared.kind === "bytes" && declared.elem === "u8"))) {
|
|
1981
|
-
return { kind: "jsExit", value: read, type: declared, loc };
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
return read;
|
|
1985
|
-
}
|
|
1986
1575
|
// `m.index` on a for-of-over-matchAll binding reads the companion-
|
|
1987
1576
|
// index array at this iteration's cursor — always a number: every
|
|
1988
1577
|
// drained row matched, so the lib's `.index` is never undefined
|
|
@@ -2258,13 +1847,13 @@ function lowerExprInner(lowerer, expr) {
|
|
|
2258
1847
|
isJsSourceFile(expr.getSourceFile())) {
|
|
2259
1848
|
const canonical = stdlibGlobalNameOf(lowerer, expr);
|
|
2260
1849
|
if (canonical !== null) {
|
|
2261
|
-
if (
|
|
1850
|
+
if (canonical === "globalThis")
|
|
2262
1851
|
return lowerGlobalValue(lowerer, expr);
|
|
2263
|
-
if (
|
|
1852
|
+
if (canonical === "ArrayBuffer")
|
|
2264
1853
|
return { kind: "libCall", fn: "arrayBuffer.constructor", args: [], type: DYN, loc };
|
|
2265
|
-
if (
|
|
1854
|
+
if (canonical === "fetch")
|
|
2266
1855
|
return { kind: "libCall", fn: "fetch.function", args: [], type: DYN, loc };
|
|
2267
|
-
if (
|
|
1856
|
+
if (Object.values(BYTES_ELEMENT_NAME).includes(canonical))
|
|
2268
1857
|
return {
|
|
2269
1858
|
kind: "libCall",
|
|
2270
1859
|
fn: "bytes.constructor",
|
|
@@ -2919,7 +2508,7 @@ export function lowerTernary(lowerer, expr, expected) {
|
|
|
2919
2508
|
(lowerer.typeOf(expr).flags & ts.TypeFlags.Any) !== 0) {
|
|
2920
2509
|
const a = thenRaw.type;
|
|
2921
2510
|
const b = elseRaw.type;
|
|
2922
|
-
const staticArm = (t) => t.kind !== "dyn" && t.kind !== "caught" && t.kind !== "
|
|
2511
|
+
const staticArm = (t) => t.kind !== "dyn" && t.kind !== "caught" && t.kind !== "void";
|
|
2923
2512
|
if (staticArm(a) && staticArm(b)) {
|
|
2924
2513
|
if (typeEquals(a, b)) {
|
|
2925
2514
|
anyJoin = a;
|
|
@@ -3149,6 +2738,11 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3149
2738
|
if (narrowed?.kind === "object" &&
|
|
3150
2739
|
narrowed.className !== expr.type.className &&
|
|
3151
2740
|
lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
|
|
2741
|
+
if (lowerer.narrowing.untrusted(node, narrowed)) {
|
|
2742
|
+
const checked = checkedClassAssertion(lowerer, expr, narrowed, expr.loc);
|
|
2743
|
+
if (checked)
|
|
2744
|
+
return checked;
|
|
2745
|
+
}
|
|
3152
2746
|
return { kind: "downcast", value: expr, type: narrowed, loc: expr.loc };
|
|
3153
2747
|
}
|
|
3154
2748
|
return expr;
|
|
@@ -3181,9 +2775,8 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3181
2775
|
const narrowedTs = lowerer.typeOf(node);
|
|
3182
2776
|
const narrowed = lowerer.mapTypeOf(narrowedTs);
|
|
3183
2777
|
// `Array.isArray(u)` on a union with one readonly array/tuple arm: the
|
|
3184
|
-
// lib predicate narrows to `any[]`,
|
|
3185
|
-
//
|
|
3186
|
-
// array-of-handles, nothing, or a synthetic intersection record — but
|
|
2778
|
+
// lib predicate narrows to `any[]`, possibly intersected with another
|
|
2779
|
+
// type. That mapping may be a checked value or a synthetic record, but
|
|
3187
2780
|
// the tag test proved the union's one array-valued arm, so bridge to it
|
|
3188
2781
|
// with the same trusted unionNarrow the mapped case below builds.
|
|
3189
2782
|
if (lowerer.checkerAnyArrayType(narrowedTs)) {
|
|
@@ -3191,6 +2784,9 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3191
2784
|
const arrayTags = lowerer.arrayValueTags(expr.type.unionId);
|
|
3192
2785
|
if (arrayTags.length === 1) {
|
|
3193
2786
|
const arm = def.arms[arrayTags[0]];
|
|
2787
|
+
const checked = checkedStaleArm(lowerer, node, expr, arrayTags[0], arm);
|
|
2788
|
+
if (checked)
|
|
2789
|
+
return checked;
|
|
3194
2790
|
return {
|
|
3195
2791
|
kind: "unionNarrow",
|
|
3196
2792
|
unionId: expr.type.unionId,
|
|
@@ -3224,6 +2820,9 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3224
2820
|
const values = literalValues(lowerer.checker.getTypeOfSymbol(property));
|
|
3225
2821
|
const arm = values && literalUnionArm(def, values, (id) => lowerer.shapes.get(id));
|
|
3226
2822
|
if (arm) {
|
|
2823
|
+
const checked = checkedStaleArm(lowerer, node, expr, lowerer.armTag(expr.type.unionId, arm), arm);
|
|
2824
|
+
if (checked)
|
|
2825
|
+
return checked;
|
|
3227
2826
|
return {
|
|
3228
2827
|
kind: "unionNarrow",
|
|
3229
2828
|
unionId: expr.type.unionId,
|
|
@@ -3249,6 +2848,10 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3249
2848
|
arm.kind !== "object" ||
|
|
3250
2849
|
!lowerer.isSubclassOf(narrowed.className, arm.className)) &&
|
|
3251
2850
|
lowerer.isSubclassOf(narrowed.className, valueType.className)) {
|
|
2851
|
+
const checked = checkedStaleArm(lowerer, node, expr, valueTag, valueType, narrowed);
|
|
2852
|
+
if (checked) {
|
|
2853
|
+
return checkedClassAssertion(lowerer, checked, narrowed, expr.loc) ?? checked;
|
|
2854
|
+
}
|
|
3252
2855
|
return {
|
|
3253
2856
|
kind: "downcast",
|
|
3254
2857
|
value: {
|
|
@@ -3265,6 +2868,9 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3265
2868
|
}
|
|
3266
2869
|
return expr;
|
|
3267
2870
|
}
|
|
2871
|
+
const checked = checkedStaleArm(lowerer, node, expr, tag, narrowed);
|
|
2872
|
+
if (checked)
|
|
2873
|
+
return checked;
|
|
3268
2874
|
return {
|
|
3269
2875
|
kind: "unionNarrow",
|
|
3270
2876
|
unionId: expr.type.unionId,
|
|
@@ -3274,6 +2880,60 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3274
2880
|
loc: expr.loc,
|
|
3275
2881
|
};
|
|
3276
2882
|
}
|
|
2883
|
+
/** The checked form of maybeNarrow's arm extraction for a narrowing the
|
|
2884
|
+
* checker may hold past code that replaced the value (a call clearing the
|
|
2885
|
+
* property; see NarrowingStability). Every other arm throws the TypeError
|
|
2886
|
+
* Node raises for the operation consuming the read (`Cannot read
|
|
2887
|
+
* properties of undefined (reading 'x')`, `o.f is not a function`), or the
|
|
2888
|
+
* stranded-value TypeError where Node would carry the value on. Null when
|
|
2889
|
+
* the narrowing is provably current. `narrowed` is the checker's type when
|
|
2890
|
+
* it refines the arm (a subclass view). */
|
|
2891
|
+
function checkedStaleArm(lowerer, node, value, tag, arm, narrowed = arm) {
|
|
2892
|
+
if (value.type.kind !== "union" || tag < 0)
|
|
2893
|
+
return null;
|
|
2894
|
+
if (!lowerer.narrowing.untrusted(node, narrowed))
|
|
2895
|
+
return null;
|
|
2896
|
+
const inPlace = checkedArmExtraction(lowerer, value, tag, arm, (found) => staleReadMessage(node, found));
|
|
2897
|
+
if (inPlace)
|
|
2898
|
+
return inPlace;
|
|
2899
|
+
const helper = lowerer.narrowedArmHelper(value.type.unionId, arm, value.loc);
|
|
2900
|
+
return helper ? lowerer.checkedNarrowCall(helper, value, arm, value.loc) : null;
|
|
2901
|
+
}
|
|
2902
|
+
/** Node's TypeError for the operation consuming `node` when it holds a
|
|
2903
|
+
* value of type `found`, or null where Node would not throw. */
|
|
2904
|
+
function staleReadMessage(node, found) {
|
|
2905
|
+
let child = node;
|
|
2906
|
+
let parent = node.parent;
|
|
2907
|
+
while (ts.isParenthesizedExpression(parent)) {
|
|
2908
|
+
child = parent;
|
|
2909
|
+
parent = parent.parent;
|
|
2910
|
+
}
|
|
2911
|
+
if (ts.isCallExpression(parent) && parent.expression === child && !parent.questionDotToken) {
|
|
2912
|
+
return found.kind === "func" ? null : `${node.getText()} is not a function`;
|
|
2913
|
+
}
|
|
2914
|
+
const unit = found.kind === "undefinedT" ? "undefined" : found.kind === "nullT" ? "null" : null;
|
|
2915
|
+
if (unit === null)
|
|
2916
|
+
return null;
|
|
2917
|
+
if (!(ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) ||
|
|
2918
|
+
parent.expression !== child ||
|
|
2919
|
+
parent.questionDotToken)
|
|
2920
|
+
return null;
|
|
2921
|
+
let key = null;
|
|
2922
|
+
if (ts.isPropertyAccessExpression(parent))
|
|
2923
|
+
key = parent.name.text;
|
|
2924
|
+
else if (ts.isStringLiteral(parent.argumentExpression))
|
|
2925
|
+
key = parent.argumentExpression.text;
|
|
2926
|
+
else if (ts.isNumericLiteral(parent.argumentExpression))
|
|
2927
|
+
key = String(Number(parent.argumentExpression.text));
|
|
2928
|
+
if (key === null)
|
|
2929
|
+
return null;
|
|
2930
|
+
const store = parent.parent;
|
|
2931
|
+
return ts.isBinaryExpression(store) &&
|
|
2932
|
+
store.left === parent &&
|
|
2933
|
+
store.operatorToken.kind === ts.SyntaxKind.EqualsToken
|
|
2934
|
+
? `Cannot set properties of ${unit} (setting '${key}')`
|
|
2935
|
+
: `Cannot read properties of ${unit} (reading '${key}')`;
|
|
2936
|
+
}
|
|
3277
2937
|
/** A runtime-optional slot can be assigned while a truthy guard is in
|
|
3278
2938
|
* force. TypeScript then types a direct member receiver as the plain arm,
|
|
3279
2939
|
* even though an OOB-safe assignment may have restored undefined. Check
|
|
@@ -3661,18 +3321,6 @@ function volatileEnvRead(e) {
|
|
|
3661
3321
|
}
|
|
3662
3322
|
return null;
|
|
3663
3323
|
}
|
|
3664
|
-
/** `x == null` / `x != null` — JS's idiomatic null-OR-undefined test, the
|
|
3665
|
-
* ONE loose comparison with static semantics: `== null` matches exactly
|
|
3666
|
-
* null and undefined (0, "", and false do not). Requires a syntactic
|
|
3667
|
-
* null LITERAL on either side; the other operand's unit arms become a
|
|
3668
|
-
* runtime tag test — one `unionIsTag` when the union has a single unit
|
|
3669
|
-
* arm, a short-circuit pair over both tags otherwise (that shape re-emits
|
|
3670
|
-
* the operand, so only side-effect-free reads compose; anything else
|
|
3671
|
-
* keeps the fence). A unit-literal operand folds (null and undefined are
|
|
3672
|
-
* mutually loose-equal), and a non-nullable operand folds statically —
|
|
3673
|
-
* the same trust-the-checker bet as lowerUnitComparison. Null (fence)
|
|
3674
|
-
* when this isn't a null-literal comparison or the operand has no
|
|
3675
|
-
* lowering here (dyn/jsval/void). */
|
|
3676
3324
|
function lowerLooseNullCompare(lowerer, expr, loc) {
|
|
3677
3325
|
const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
|
|
3678
3326
|
const unwrap = (e) => ts.isParenthesizedExpression(e) ? unwrap(e.expression) : e;
|
|
@@ -3737,7 +3385,7 @@ function lowerLooseNullCompare(lowerer, expr, loc) {
|
|
|
3737
3385
|
loc,
|
|
3738
3386
|
};
|
|
3739
3387
|
}
|
|
3740
|
-
if (other.type.kind === "
|
|
3388
|
+
if (other.type.kind === "void") {
|
|
3741
3389
|
return null; // no static tag to test — keep the fence
|
|
3742
3390
|
}
|
|
3743
3391
|
// The env-volatility escape (see lowerUnitComparison): a narrowed
|
|
@@ -3894,10 +3542,8 @@ function isMemberReceiver(node) {
|
|
|
3894
3542
|
function lowerNullishPair(lowerer, expr, loc, left) {
|
|
3895
3543
|
if (left.type.kind === "dyn") {
|
|
3896
3544
|
// `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
|
|
3897
|
-
// runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default
|
|
3898
|
-
//
|
|
3899
|
-
// the wrap constructor scalar-normalizes engine null/undefined
|
|
3900
|
-
// away). Both sides live in the checked-dynamic tree — the right converts through
|
|
3545
|
+
// runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default).
|
|
3546
|
+
// Both sides live in the checked-dynamic tree — the right converts through
|
|
3901
3547
|
// the usual boundary and evaluates lazily in its branch; a default
|
|
3902
3548
|
// with no dyn representation keeps the fence.
|
|
3903
3549
|
const right = lowerer.coerceToExpected(lowerer.lowerExpr(expr.right), DYN);
|
|
@@ -3906,13 +3552,6 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3906
3552
|
}
|
|
3907
3553
|
return { kind: "nullish", left, right, type: DYN, loc };
|
|
3908
3554
|
}
|
|
3909
|
-
if (left.type.kind === "jsval") {
|
|
3910
|
-
// `a ?? b` on an ISLAND value: the engine's own nullish test — the
|
|
3911
|
-
// left evaluates once, the right runs lazily in its branch and
|
|
3912
|
-
// marshals in (the emitter's jsval nullish arm).
|
|
3913
|
-
const right = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
|
|
3914
|
-
return { kind: "nullish", left, right, type: JSVAL, loc };
|
|
3915
|
-
}
|
|
3916
3555
|
if (left.type.kind !== "union")
|
|
3917
3556
|
return left;
|
|
3918
3557
|
const def = lowerer.unions.get(left.type.unionId);
|
|
@@ -4356,10 +3995,6 @@ export function ensureBool(lowerer, e, node) {
|
|
|
4356
3995
|
// tag (plus the scalar payload for number/string).
|
|
4357
3996
|
return { kind: "dynTest", test: "truthy", value: e, type: BOOL, loc: e.loc };
|
|
4358
3997
|
}
|
|
4359
|
-
if (e.type.kind === "jsval") {
|
|
4360
|
-
// ToBoolean of an island value — the engine answers (never throws).
|
|
4361
|
-
return { kind: "jsOp", op: "truthy", args: [e], type: BOOL, loc: e.loc };
|
|
4362
|
-
}
|
|
4363
3998
|
if (e.type.kind === "union") {
|
|
4364
3999
|
lowerer.requireTruthyUnion(e.type.unionId, node);
|
|
4365
4000
|
return { kind: "toBool", operand: e, type: BOOL, loc: e.loc };
|
|
@@ -4377,23 +4012,15 @@ export function ensureBool(lowerer, e, node) {
|
|
|
4377
4012
|
}
|
|
4378
4013
|
lowerer.badType(node, lowerer.typeOf(node));
|
|
4379
4014
|
}
|
|
4380
|
-
/** Truthiness needs a ToBoolean per arm: dyn/caught arms have none (a
|
|
4381
|
-
* dynamic ToBoolean over the checked-dynamic tree / the snapshot box) — fence those
|
|
4382
|
-
* unions; every other arm kind is answerable (units false, scalars and
|
|
4383
|
-
* strings by value, refs true, jsval by the engine). */
|
|
4384
4015
|
export function requireTruthyUnion(lowerer, unionId, node) {
|
|
4385
4016
|
const def = lowerer.unions.get(unionId);
|
|
4386
4017
|
if (def && def.arms.every((a) => a.kind !== "dyn" && a.kind !== "caught"))
|
|
4387
4018
|
return;
|
|
4388
4019
|
lowerer.unsupported("SC1090", node, `union-typed conditions with 'unknown' arms (${NARROW_FIRST})`);
|
|
4389
4020
|
}
|
|
4390
|
-
/** Strict equality needs a per-arm comparison: units, scalars, strings,
|
|
4391
|
-
* and ref kinds (pointer identity) all have one; dyn/caught arms have no
|
|
4392
|
-
* static equality and jsval arms would need the engine's `===` — those
|
|
4393
|
-
* unions keep the narrow-first fence. */
|
|
4394
4021
|
export function eqComparableUnion(lowerer, unionId) {
|
|
4395
4022
|
const def = lowerer.unions.get(unionId);
|
|
4396
|
-
return
|
|
4023
|
+
return !!def && def.arms.every((a) => a.kind !== "dyn" && a.kind !== "caught");
|
|
4397
4024
|
}
|
|
4398
4025
|
/** Property access on a string or array receiver: `.length` lowers to the
|
|
4399
4026
|
* matching intrinsic; a bare method reference (`const f = s.slice` — a
|
|
@@ -4801,9 +4428,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4801
4428
|
return null;
|
|
4802
4429
|
}
|
|
4803
4430
|
if (kind === "f64") {
|
|
4804
|
-
|
|
4805
|
-
// bare reference has no value form regardless of --dynamic.
|
|
4806
|
-
if (own(ISLAND_SURFACE.number, name) !== undefined) {
|
|
4431
|
+
if (own(STDLIB_SURFACE.number, name) !== undefined) {
|
|
4807
4432
|
lowerer.unsupported("SC1090", expr, `number methods as values (call '${name}' directly)`);
|
|
4808
4433
|
}
|
|
4809
4434
|
return null;
|
|
@@ -4847,22 +4472,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4847
4472
|
? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
|
|
4848
4473
|
: lowerer.maybeNarrow(receiver, expr.expression);
|
|
4849
4474
|
}
|
|
4850
|
-
// An island handle behind a typed-array .d.ts surface: the engine
|
|
4851
4475
|
// property read, exiting at the declared number type (the array
|
|
4852
|
-
// .length rule). Chain-handled reads stay jsval.
|
|
4853
|
-
if (receiver.type.kind === "jsval") {
|
|
4854
|
-
const read = {
|
|
4855
|
-
kind: "jsOp",
|
|
4856
|
-
op: "getProp",
|
|
4857
|
-
name,
|
|
4858
|
-
args: [receiver],
|
|
4859
|
-
type: JSVAL,
|
|
4860
|
-
loc,
|
|
4861
|
-
};
|
|
4862
|
-
if (expr.questionDotToken)
|
|
4863
|
-
return read;
|
|
4864
|
-
return { kind: "jsExit", value: read, type: F64, loc };
|
|
4865
|
-
}
|
|
4866
4476
|
return { kind: "bytesIntrinsic", method: name, receiver, args: [], type: F64, loc };
|
|
4867
4477
|
}
|
|
4868
4478
|
if (name === "byteOffset") {
|
|
@@ -4941,24 +4551,6 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4941
4551
|
? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
|
|
4942
4552
|
: lowerer.maybeNarrow(receiver, expr.expression);
|
|
4943
4553
|
}
|
|
4944
|
-
// An island handle behind an array-typed .d.ts surface
|
|
4945
|
-
// (`parts().length` on a declared `string[]` return — arrays never
|
|
4946
|
-
// exit eagerly, so the value stays jsval): an engine property read,
|
|
4947
|
-
// exiting at the declared number type. Chain-handled reads stay
|
|
4948
|
-
// jsval (the island chain's body must be a handle).
|
|
4949
|
-
if (receiver.type.kind === "jsval") {
|
|
4950
|
-
const read = {
|
|
4951
|
-
kind: "jsOp",
|
|
4952
|
-
op: "getProp",
|
|
4953
|
-
name: "length",
|
|
4954
|
-
args: [receiver],
|
|
4955
|
-
type: JSVAL,
|
|
4956
|
-
loc: locOf(expr),
|
|
4957
|
-
};
|
|
4958
|
-
if (expr.questionDotToken)
|
|
4959
|
-
return read;
|
|
4960
|
-
return { kind: "jsExit", value: read, type: F64, loc: locOf(expr) };
|
|
4961
|
-
}
|
|
4962
4554
|
// A CHECKED-DYNAMIC value behind an array-typed checker spelling
|
|
4963
4555
|
// (`Object.keys(u).length` — the dyn walk answers a dyn array while
|
|
4964
4556
|
// tsc spells string[]): the runtime-world dispatch — a dyn keyed
|
|
@@ -4984,7 +4576,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4984
4576
|
if (kind === "string"
|
|
4985
4577
|
? own(STR_METHODS, name) !== undefined ||
|
|
4986
4578
|
STRING_INDEX_METHODS.has(name) ||
|
|
4987
|
-
own(
|
|
4579
|
+
own(STDLIB_SURFACE.string, name) !== undefined
|
|
4988
4580
|
: ARRAY_METHODS.has(name)) {
|
|
4989
4581
|
lowerer.unsupported("SC1090", expr, `${kind} methods as values (call '${name}' directly)`);
|
|
4990
4582
|
}
|
|
@@ -5089,11 +4681,8 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5089
4681
|
!(ts.isIdentifier(el) && el.text === "undefined"));
|
|
5090
4682
|
const ownUnhelpful = mapped === null ||
|
|
5091
4683
|
mapped.kind === "dyn" ||
|
|
5092
|
-
// The checker
|
|
5093
|
-
// own type decides nothing either — nor does an island ('any')
|
|
5094
|
-
// residue under a STATIC union slot.
|
|
4684
|
+
// The checker may echo the context union rather than infer this literal.
|
|
5095
4685
|
mapped.kind === "union" ||
|
|
5096
|
-
mapped.kind === "jsval" ||
|
|
5097
4686
|
(mapped.kind === "array" && nonUnitElems && lowerer.unitOnlyElem(mapped.elem));
|
|
5098
4687
|
if (ownUnhelpful) {
|
|
5099
4688
|
const def = lowerer.unions.get(ctxUnion.unionId);
|
|
@@ -5141,11 +4730,9 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5141
4730
|
tryLowerExpression(lowerer, element.expression)?.type.kind === "dyn"))
|
|
5142
4731
|
mapped = DYN;
|
|
5143
4732
|
// An EMPTY literal under a CONST ASSERTION whose type queries panicked
|
|
5144
|
-
// (tsgo's readonly-[] TupleType conversion
|
|
5145
|
-
//
|
|
5146
|
-
|
|
5147
|
-
// unit-element array, mapType's own `[] as const` rule.
|
|
5148
|
-
if ((mapped === null || mapped.kind === "jsval") &&
|
|
4733
|
+
// (tsgo's readonly-[] TupleType conversion) uses a unit-element array,
|
|
4734
|
+
// mapType's own `[] as const` rule.
|
|
4735
|
+
if (mapped === null &&
|
|
5149
4736
|
expr.elements.length === 0 &&
|
|
5150
4737
|
(tsType.flags & ts.TypeFlags.Any) !== 0 &&
|
|
5151
4738
|
underConstAssertion(expr)) {
|
|
@@ -5175,22 +4762,7 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5175
4762
|
// tsc padded an UNDER-LENGTH literal against an optional-element
|
|
5176
4763
|
// tuple context (`options || []` with `options?: [string?,
|
|
5177
4764
|
// number?]` — the instantiated type spells every position, the
|
|
5178
|
-
// literal spells fewer): no fixed shape holds it
|
|
5179
|
-
// engine's real arrays do — under --dynamic the literal builds
|
|
5180
|
-
// island-native with its ACTUAL elements, length exact. Static
|
|
5181
|
-
// builds keep the type fence (badType's dynamic probe tells the
|
|
5182
|
-
// --dynamic story).
|
|
5183
|
-
if (lowerer.dynamic &&
|
|
5184
|
-
expr.elements.length < shape.fields.length &&
|
|
5185
|
-
expr.elements.every((el) => !ts.isOmittedExpression(el))) {
|
|
5186
|
-
return {
|
|
5187
|
-
kind: "jsOp",
|
|
5188
|
-
op: "arrLit",
|
|
5189
|
-
args: expr.elements.map((el) => lowerer.jsvalIn(lowerer.lowerExpr(el), el)),
|
|
5190
|
-
type: JSVAL,
|
|
5191
|
-
loc,
|
|
5192
|
-
};
|
|
5193
|
-
}
|
|
4765
|
+
// literal spells fewer): no fixed shape holds it.
|
|
5194
4766
|
lowerer.badType(expr, tsType);
|
|
5195
4767
|
}
|
|
5196
4768
|
const byName = new Map(shape.fields.map((f) => [f.name, f.type]));
|
|
@@ -5293,10 +4865,9 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5293
4865
|
while (ts.isParenthesizedExpression(srcNode))
|
|
5294
4866
|
srcNode = srcNode.expression;
|
|
5295
4867
|
lowerer.fenceStaticHeadersIteration(el.expression);
|
|
5296
|
-
let src =
|
|
5297
|
-
(
|
|
5298
|
-
|
|
5299
|
-
: lowerer.lowerExpr(el.expression));
|
|
4868
|
+
let src = ts.isConditionalExpression(srcNode)
|
|
4869
|
+
? lowerTernary(lowerer, srcNode, type)
|
|
4870
|
+
: lowerer.lowerExpr(el.expression);
|
|
5300
4871
|
src = lowerCollectionSpread(lowerer, src, el.expression) ?? src;
|
|
5301
4872
|
// `[...new SymbolIterator]`: a CLASS ITERABLE drains through its
|
|
5302
4873
|
// own protocol into a fresh element array (classIteratorDrainCall
|
|
@@ -5851,33 +5422,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5851
5422
|
return lowerer.maybeNarrow({ kind: "dynKeyGet", value: receiver, key, type: DYN, loc: locOf(expr) }, expr);
|
|
5852
5423
|
}
|
|
5853
5424
|
}
|
|
5854
|
-
if (receiverIr?.kind === "jsval") {
|
|
5855
|
-
// Dispatch follows the RUNTIME world (383(d)): a checker-'any'
|
|
5856
|
-
// receiver whose value LOWERED checked-dynamic (`bag.list[0]` where
|
|
5857
|
-
// bag.list is a routed keyed read off a wrapped island value) takes
|
|
5858
|
-
// the dyn keyed read below — the routed JSVAL arm reads the real
|
|
5859
|
-
// engine element; a jsval-lowered receiver keeps the island read.
|
|
5860
|
-
const recv = lowerer.lowerExpr(expr.expression);
|
|
5861
|
-
if (recv.type.kind !== "dyn")
|
|
5862
|
-
return islandElementRead(lowerer, expr, recv);
|
|
5863
|
-
const rawKey = lowerer.lowerExpr(expr.argumentExpression);
|
|
5864
|
-
const key = rawKey.type.kind === "string"
|
|
5865
|
-
? rawKey
|
|
5866
|
-
: rawKey.type.kind === "f64"
|
|
5867
|
-
? { kind: "toString", operand: rawKey, type: STRING, loc: rawKey.loc }
|
|
5868
|
-
: null;
|
|
5869
|
-
if (key) {
|
|
5870
|
-
const opt = hasOptionalChainGuard(expr.expression);
|
|
5871
|
-
return lowerer.maybeNarrow({
|
|
5872
|
-
kind: "dynKeyGet",
|
|
5873
|
-
key,
|
|
5874
|
-
...(opt ? { optional: true } : {}),
|
|
5875
|
-
value: recv,
|
|
5876
|
-
type: DYN,
|
|
5877
|
-
loc: locOf(expr),
|
|
5878
|
-
}, expr);
|
|
5879
|
-
}
|
|
5880
|
-
}
|
|
5881
5425
|
// Typed-array element read `b[i]` — like arrayGet with a scalar
|
|
5882
5426
|
// result; any invalid index traps (the array discipline; JS would
|
|
5883
5427
|
// read undefined — divergence 4's policy).
|
|
@@ -5894,12 +5438,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5894
5438
|
? lowerer.checkedNarrowCall(helper, recv, present, locOf(expr.expression))
|
|
5895
5439
|
: lowerer.maybeNarrow(recv, expr.expression);
|
|
5896
5440
|
}
|
|
5897
|
-
// A typed-array .d.ts surface whose VALUE is an island handle
|
|
5898
|
-
// (`data()[0]` on a declared Uint8Array return — call results only
|
|
5899
|
-
// exit primitives eagerly): the engine element read, exiting at the
|
|
5900
|
-
// declared number type.
|
|
5901
|
-
if (recv.type.kind === "jsval")
|
|
5902
|
-
return islandElementRead(lowerer, expr, recv);
|
|
5903
5441
|
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5904
5442
|
if (isJsSourceFile(expr.getSourceFile()) && recv.type.kind === "bytes") {
|
|
5905
5443
|
return {
|
|
@@ -5951,14 +5489,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5951
5489
|
const shape = lowerer.shapes.get(receiverIr.shapeId);
|
|
5952
5490
|
if (shape?.tuple) {
|
|
5953
5491
|
let obj = lowerer.lowerExpr(expr.expression);
|
|
5954
|
-
// A tuple-typed .d.ts surface whose VALUE is an island handle
|
|
5955
|
-
// (`pair()[0]` on a declared `[number, string]` return — the
|
|
5956
|
-
// anonymous tuple type has no npm symbol, so the checker maps it
|
|
5957
|
-
// structurally while the call result stays an engine array): the
|
|
5958
|
-
// read rides engine ops, exiting at the declared per-index type
|
|
5959
|
-
// like the array path.
|
|
5960
|
-
if (obj.type.kind === "jsval")
|
|
5961
|
-
return islandElementRead(lowerer, expr, obj);
|
|
5962
5492
|
if (obj.type.kind === "dyn") {
|
|
5963
5493
|
// Object.entries over a checked value stores each pair in the
|
|
5964
5494
|
// dynamic tree even when the checker names a tuple type.
|
|
@@ -6009,14 +5539,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
6009
5539
|
: lowerer.maybeNarrow(get, expr);
|
|
6010
5540
|
}
|
|
6011
5541
|
if (shape && !shape.tuple) {
|
|
6012
|
-
// A record-typed .d.ts surface whose VALUE is an island handle
|
|
6013
|
-
// (`headers()["x-id"]` on a declared `Record<string, string>`
|
|
6014
|
-
// return — the stdlib alias maps structurally while the call
|
|
6015
|
-
// result stays an engine object): the read rides engine ops with
|
|
6016
|
-
// the declared-value exit, never a recordKeyGet over a jsval.
|
|
6017
|
-
const obj = lowerer.lowerExpr(expr.expression);
|
|
6018
|
-
if (obj.type.kind === "jsval")
|
|
6019
|
-
return islandElementRead(lowerer, expr, obj);
|
|
6020
5542
|
return lowerer.lowerRecordKeyRead(expr, receiverIr.shapeId, shape);
|
|
6021
5543
|
}
|
|
6022
5544
|
}
|
|
@@ -6243,14 +5765,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
6243
5765
|
? lowerer.checkedNarrowCall(helper, arr, present, locOf(expr.expression))
|
|
6244
5766
|
: lowerer.maybeNarrow(arr, expr.expression);
|
|
6245
5767
|
}
|
|
6246
|
-
// The checker sees an array but the VALUE is an island handle (an
|
|
6247
|
-
// array-typed .d.ts surface: `parts()[0]` on a declared `string[]`
|
|
6248
|
-
// return, `issue.path[0]` on a declared member — arrays never exit
|
|
6249
|
-
// eagerly, so the call/member read stays jsval): the read rides
|
|
6250
|
-
// engine ops with the declared-element exit, never a static arrayGet
|
|
6251
|
-
// over a jsval (the validator ICE).
|
|
6252
|
-
if (arr.type.kind === "jsval")
|
|
6253
|
-
return islandElementRead(lowerer, expr, arr);
|
|
6254
5768
|
// The checker sees an array but the VALUE lowered checked-dynamic (a
|
|
6255
5769
|
// jsdoc-typed default export from a .js module — signature 14): the
|
|
6256
5770
|
// read rides the dynCheck boundary when the array shape is one the checked-dynamic tree
|
|
@@ -6328,33 +5842,6 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
6328
5842
|
// narrows literal-index element accesses).
|
|
6329
5843
|
return lowerer.maybeNarrow({ kind: "arrayGet", arr, index, type: elemT, loc: locOf(expr) }, expr);
|
|
6330
5844
|
}
|
|
6331
|
-
/** `o[k]` where the RECEIVER is an island value — a jsval-mapped checker
|
|
6332
|
-
* type, or an array/tuple-typed .d.ts surface whose lowered value is a
|
|
6333
|
-
* handle. The key marshals in (any JS key kind — the engine does its
|
|
6334
|
-
* own ToPropertyKey) and the result stays island, EXCEPT when the
|
|
6335
|
-
* checker declares the element a primitive (`parts()[0]` on a declared
|
|
6336
|
-
* `string[]`): those exit eagerly to the static type, exactly the
|
|
6337
|
-
* island property-read rule (trust-but-verify — a lying declaration
|
|
6338
|
-
* throws the catchable TypeError; tsc puts the `| undefined` of a
|
|
6339
|
-
* short-circuiting chain on the OUTERMOST expression, so chain tails
|
|
6340
|
-
* never map primitive here). Chain-handled reads (`v?.[0]`) stay jsval
|
|
6341
|
-
* — the chain's unit path is the engine's undefined. */
|
|
6342
|
-
function islandElementRead(lowerer, expr, obj) {
|
|
6343
|
-
const loc = locOf(expr);
|
|
6344
|
-
const key = lowerer.jsvalIn(lowerer.lowerExpr(expr.argumentExpression), expr.argumentExpression);
|
|
6345
|
-
const read = { kind: "jsOp", op: "getIdx", args: [obj, key], type: JSVAL, loc };
|
|
6346
|
-
if (!expr.questionDotToken) {
|
|
6347
|
-
const declared = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
6348
|
-
if (declared &&
|
|
6349
|
-
(declared.kind === "f64" ||
|
|
6350
|
-
declared.kind === "bool" ||
|
|
6351
|
-
declared.kind === "string" ||
|
|
6352
|
-
(declared.kind === "bytes" && declared.elem === "u8"))) {
|
|
6353
|
-
return { kind: "jsExit", value: read, type: declared, loc };
|
|
6354
|
-
}
|
|
6355
|
-
}
|
|
6356
|
-
return read;
|
|
6357
|
-
}
|
|
6358
5845
|
/** `r[k]` over a (non-tuple) record shape. A LITERAL key naming a declared
|
|
6359
5846
|
* field is the bracket spelling of field access (the ONLY spelling tsc
|
|
6360
5847
|
* permits for signature-declared fields under
|
|
@@ -7108,39 +6595,6 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7108
6595
|
if (receiver?.type.kind === "array")
|
|
7109
6596
|
receiverIr = receiver.type;
|
|
7110
6597
|
}
|
|
7111
|
-
if (receiverIr?.kind === "jsval") {
|
|
7112
|
-
const obj = lowerer.lowerExpr(target.expression);
|
|
7113
|
-
// Dispatch follows the RUNTIME world (383(d)): a checker-'any'
|
|
7114
|
-
// receiver whose value LOWERED checked-dynamic takes the dyn keyed
|
|
7115
|
-
// write — the routed JSVAL arm lands it on the real engine object.
|
|
7116
|
-
if (obj.type.kind === "dyn") {
|
|
7117
|
-
const loc = locOf(expr);
|
|
7118
|
-
const rawKey = lowerer.lowerExpr(target.argumentExpression);
|
|
7119
|
-
const key = rawKey.type.kind === "f64" || rawKey.type.kind === "bool" || rawKey.type.kind === "dyn"
|
|
7120
|
-
? { kind: "toString", operand: rawKey, type: STRING, loc: rawKey.loc }
|
|
7121
|
-
: rawKey;
|
|
7122
|
-
if (key.type.kind !== "string") {
|
|
7123
|
-
lowerer.unsupported("SC1090", target.argumentExpression, `'${lowerer.fmt(key.type)}'-typed keys in keyed writes through 'unknown' values`);
|
|
7124
|
-
}
|
|
7125
|
-
const value = lowerer.coerceToExpected(lowerer.lowerExpr(expr.right), DYN);
|
|
7126
|
-
if (value.type.kind !== "dyn") {
|
|
7127
|
-
lowerer.unsupported("SC1100", expr.right, `assigning '${lowerer.fmt(value.type)}' values through 'unknown' receivers`);
|
|
7128
|
-
}
|
|
7129
|
-
return {
|
|
7130
|
-
kind: "exprStmt",
|
|
7131
|
-
expr: { kind: "libCall", fn: "dyn.keySet", args: [obj, key, value], type: VOID, loc },
|
|
7132
|
-
loc,
|
|
7133
|
-
};
|
|
7134
|
-
}
|
|
7135
|
-
const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
|
|
7136
|
-
const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
|
|
7137
|
-
const loc = locOf(expr);
|
|
7138
|
-
return {
|
|
7139
|
-
kind: "exprStmt",
|
|
7140
|
-
expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc },
|
|
7141
|
-
loc,
|
|
7142
|
-
};
|
|
7143
|
-
}
|
|
7144
6598
|
// A checked-dynamic receiver TYPE (`unknown[]` and the collapsed
|
|
7145
6599
|
// `(string | object)[]` map to DYN wholesale now): the dyn keyed
|
|
7146
6600
|
// write — dyn.keySet. Number keys canonicalize through the JS-exact
|
|
@@ -7194,18 +6648,6 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7194
6648
|
// the runtime coerces JS-exactly; invalid indices are ignored.
|
|
7195
6649
|
if (receiverIr?.kind === "bytes") {
|
|
7196
6650
|
const recv = lowerer.lowerExpr(target.expression);
|
|
7197
|
-
// The write twin: a typed-array .d.ts surface whose VALUE is a
|
|
7198
|
-
// handle takes the engine keyed write.
|
|
7199
|
-
if (recv.type.kind === "jsval") {
|
|
7200
|
-
const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
|
|
7201
|
-
const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
|
|
7202
|
-
const loc = locOf(expr);
|
|
7203
|
-
return {
|
|
7204
|
-
kind: "exprStmt",
|
|
7205
|
-
expr: { kind: "jsOp", op: "setIdx", args: [recv, key, value], type: VOID, loc },
|
|
7206
|
-
loc,
|
|
7207
|
-
};
|
|
7208
|
-
}
|
|
7209
6651
|
const index = lowerer.lowerExpr(target.argumentExpression);
|
|
7210
6652
|
if (index.type.kind === "dyn" && recv.type.kind === "bytes") {
|
|
7211
6653
|
return {
|
|
@@ -7224,24 +6666,11 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7224
6666
|
// — literal indices only, like the read.
|
|
7225
6667
|
if (receiverIr?.kind === "record") {
|
|
7226
6668
|
const shape = lowerer.shapes.get(receiverIr.shapeId);
|
|
7227
|
-
// A record/tuple-typed .d.ts surface whose VALUE is an island
|
|
7228
|
-
// handle: the engine keyed write (the read dispatch's twin), never
|
|
7229
|
-
// a recordSet/recordKeySet over a jsval.
|
|
7230
6669
|
if (shape) {
|
|
7231
6670
|
const obj = lowerer.lowerExpr(target.expression);
|
|
7232
6671
|
if (hasClassPayload(lowerer, obj.type)) {
|
|
7233
6672
|
lowerer.unsupported("SC1090", target, "computed property writes through structural views of class instances (use a declared literal key)");
|
|
7234
6673
|
}
|
|
7235
|
-
if (obj.type.kind === "jsval") {
|
|
7236
|
-
const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
|
|
7237
|
-
const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
|
|
7238
|
-
const loc = locOf(expr);
|
|
7239
|
-
return {
|
|
7240
|
-
kind: "exprStmt",
|
|
7241
|
-
expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc },
|
|
7242
|
-
loc,
|
|
7243
|
-
};
|
|
7244
|
-
}
|
|
7245
6674
|
// A record-mapped CHECKER type over a VALUE living in the checked-dynamic tree (a
|
|
7246
6675
|
// JS file-scope object-literal global): the checked-dynamic keyed
|
|
7247
6676
|
// write — dyn.keySet (later writes win, insertion order; Node's
|
|
@@ -7406,9 +6835,8 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7406
6835
|
// arm above — later writes win in insertion order, number keys
|
|
7407
6836
|
// canonicalize through the JS-exact formatter (ToPropertyKey's string
|
|
7408
6837
|
// side), index keys on dyn arrays set/extend elements, and non-object
|
|
7409
|
-
// receivers throw Node's TypeErrors at runtime. An
|
|
7410
|
-
//
|
|
7411
|
-
// probes the receiver's own lowered world: a dyn value takes the same
|
|
6838
|
+
// receivers throw Node's TypeErrors at runtime. An unmapped checker type
|
|
6839
|
+
// probes the receiver's lowered representation: a dyn value takes the same
|
|
7412
6840
|
// write, anything else falls through to the fences.
|
|
7413
6841
|
if (receiverIr?.kind === "dyn" || receiverIr?.kind === "object" || receiverIr === null) {
|
|
7414
6842
|
const obj = receiverIr !== null
|
|
@@ -7448,19 +6876,6 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7448
6876
|
lowerer.unsupported("SC1090", target, "assignment to non-array elements");
|
|
7449
6877
|
}
|
|
7450
6878
|
let arr = lowerer.lowerExpr(target.expression);
|
|
7451
|
-
// The write twin of the island element read: an array-typed .d.ts
|
|
7452
|
-
// surface whose VALUE is a handle takes the engine keyed write, never
|
|
7453
|
-
// a static arraySet over a jsval.
|
|
7454
|
-
if (arr.type.kind === "jsval") {
|
|
7455
|
-
const key = lowerer.jsvalIn(lowerer.lowerExpr(target.argumentExpression), target.argumentExpression);
|
|
7456
|
-
const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.right), expr.right);
|
|
7457
|
-
const loc = locOf(expr);
|
|
7458
|
-
return {
|
|
7459
|
-
kind: "exprStmt",
|
|
7460
|
-
expr: { kind: "jsOp", op: "setIdx", args: [arr, key, value], type: VOID, loc },
|
|
7461
|
-
loc,
|
|
7462
|
-
};
|
|
7463
|
-
}
|
|
7464
6879
|
if (arr.type.kind === "union" &&
|
|
7465
6880
|
lowerer.armTag(arr.type.unionId, UNDEFINED_T) >= 0 &&
|
|
7466
6881
|
receiverIr.kind === "array") {
|
|
@@ -7548,10 +6963,6 @@ export function ensureString(lowerer, e, node) {
|
|
|
7548
6963
|
const boxed = { kind: "dynFrom", value: e, type: DYN, loc: e.loc };
|
|
7549
6964
|
return { kind: "toString", operand: boxed, type: STRING, loc: e.loc };
|
|
7550
6965
|
}
|
|
7551
|
-
if (e.type.kind === "jsval") {
|
|
7552
|
-
// String(v) in the engine — JS-exact (and Node-exact in templates).
|
|
7553
|
-
return { kind: "jsOp", op: "toStr", args: [e], type: STRING, loc: e.loc };
|
|
7554
|
-
}
|
|
7555
6966
|
if (e.type.kind === "object") {
|
|
7556
6967
|
// String(err) / `${err}` uses the same dispatch as err.toString().
|
|
7557
6968
|
for (let c = lowerer.classes.get(e.type.className) ?? null; c; c = c.base) {
|
|
@@ -7793,12 +7204,8 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7793
7204
|
const use = runtimeOptionalUseOf(expr);
|
|
7794
7205
|
if (inner.type.kind === "union" && runtimeOptionalAssertionErases(lowerer, expr, inner, use))
|
|
7795
7206
|
return inner;
|
|
7796
|
-
if (inner.type.kind !== "dyn"
|
|
7797
|
-
// A STATIC value cast `as any` is the explicit island entrance.
|
|
7207
|
+
if (inner.type.kind !== "dyn") {
|
|
7798
7208
|
const targetTs0 = lowerer.checker.getTypeFromTypeNode(expr.type);
|
|
7799
|
-
if (targetTs0.flags & ts.TypeFlags.Any && lowerer.dynamic) {
|
|
7800
|
-
return lowerer.jsvalIn(inner, expr.expression);
|
|
7801
|
-
}
|
|
7802
7209
|
const target = lowerer.mapTypeOf(targetTs0);
|
|
7803
7210
|
if (target?.kind === "object") {
|
|
7804
7211
|
const asserted = checkedClassAssertion(lowerer, inner, target, locOf(expr));
|
|
@@ -7876,25 +7283,6 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7876
7283
|
}
|
|
7877
7284
|
return inner; // erasure, unchanged
|
|
7878
7285
|
}
|
|
7879
|
-
if (inner.type.kind === "jsval") {
|
|
7880
|
-
// The island exit. `as any` on an island value is erasure; a static
|
|
7881
|
-
// target compiles to a VALIDATED extraction (strict primitives; the
|
|
7882
|
-
// JSON round-trip + dynCheck walker for composites) that throws a
|
|
7883
|
-
// catchable TypeError on mismatch — same trust-but-verify rule as
|
|
7884
|
-
// the dyn boundary. Targets with no extraction are rejected.
|
|
7885
|
-
const targetTs = lowerer.checker.getTypeFromTypeNode(expr.type);
|
|
7886
|
-
if (targetTs.flags & ts.TypeFlags.Any)
|
|
7887
|
-
return inner;
|
|
7888
|
-
const target = lowerer.mapTypeOf(targetTs);
|
|
7889
|
-
if (!target)
|
|
7890
|
-
lowerer.badType(expr.type, targetTs);
|
|
7891
|
-
if (!lowerer.boundarySafe(target)) {
|
|
7892
|
-
lowerer.unsupported("SC1090", expr, `a checked cast of 'any' to '${lowerer.fmt(target)}' ` +
|
|
7893
|
-
`(an 'any' value can only be validated against JSON-representable types: ` +
|
|
7894
|
-
`number, string, boolean, records, arrays, and unions of those)`);
|
|
7895
|
-
}
|
|
7896
|
-
return { kind: "jsExit", value: inner, type: target, loc: locOf(expr) };
|
|
7897
|
-
}
|
|
7898
7286
|
const targetTs = lowerer.checker.getTypeFromTypeNode(expr.type);
|
|
7899
7287
|
const target = lowerer.mapTypeOf(targetTs) ?? dynFallbackType(lowerer, expr.type, targetTs);
|
|
7900
7288
|
if (!target)
|
|
@@ -7963,9 +7351,6 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
7963
7351
|
switch (expr.operator) {
|
|
7964
7352
|
case ts.SyntaxKind.MinusToken: {
|
|
7965
7353
|
const raw = lowerer.lowerExpr(expr.operand);
|
|
7966
|
-
if (raw.type.kind === "jsval") {
|
|
7967
|
-
return { kind: "jsOp", op: "neg", args: [raw], type: JSVAL, loc };
|
|
7968
|
-
}
|
|
7969
7354
|
if (raw.type.kind === "bigint") {
|
|
7970
7355
|
return { kind: "libCall", fn: "bigint.neg", args: [raw], type: BIGINT_T, loc };
|
|
7971
7356
|
}
|
|
@@ -7987,9 +7372,6 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
7987
7372
|
// Unary + is ToNumber; on an already-number operand it's identity,
|
|
7988
7373
|
// and a STRING operand runs the runtime's ECMA-exact StringToNumber
|
|
7989
7374
|
// (num.fromString — Number(aString)'s lowering, scr_string.c).
|
|
7990
|
-
if (raw.type.kind === "jsval") {
|
|
7991
|
-
return { kind: "jsOp", op: "plus", args: [raw], type: JSVAL, loc };
|
|
7992
|
-
}
|
|
7993
7375
|
if (raw.type.kind === "string") {
|
|
7994
7376
|
return { kind: "libCall", fn: "num.fromString", args: [raw], type: F64, loc };
|
|
7995
7377
|
}
|
|
@@ -8281,38 +7663,6 @@ function seqExprSafeStmt(s) {
|
|
|
8281
7663
|
return false;
|
|
8282
7664
|
}
|
|
8283
7665
|
}
|
|
8284
|
-
/** Run one supported `any` binary operation in the island. Checked-dynamic
|
|
8285
|
-
* operands marshal in only after lowerBinary's identity-preserving native
|
|
8286
|
-
* cases have had their chance (notably dyn strict equality). */
|
|
8287
|
-
function lowerAnyBinaryInIsland(lowerer, expr, left, right, loc) {
|
|
8288
|
-
const op = expr.operatorToken.kind;
|
|
8289
|
-
const JS_BIN = {
|
|
8290
|
-
[ts.SyntaxKind.PlusToken]: "add",
|
|
8291
|
-
[ts.SyntaxKind.MinusToken]: "sub",
|
|
8292
|
-
[ts.SyntaxKind.AsteriskToken]: "mul",
|
|
8293
|
-
[ts.SyntaxKind.SlashToken]: "div",
|
|
8294
|
-
[ts.SyntaxKind.PercentToken]: "mod",
|
|
8295
|
-
[ts.SyntaxKind.AsteriskAsteriskToken]: "pow",
|
|
8296
|
-
[ts.SyntaxKind.LessThanToken]: "lt",
|
|
8297
|
-
[ts.SyntaxKind.LessThanEqualsToken]: "le",
|
|
8298
|
-
[ts.SyntaxKind.GreaterThanToken]: "gt",
|
|
8299
|
-
[ts.SyntaxKind.GreaterThanEqualsToken]: "ge",
|
|
8300
|
-
[ts.SyntaxKind.EqualsEqualsEqualsToken]: "eq",
|
|
8301
|
-
[ts.SyntaxKind.ExclamationEqualsEqualsToken]: "neq",
|
|
8302
|
-
};
|
|
8303
|
-
const jop = JS_BIN[op];
|
|
8304
|
-
if (jop === undefined) {
|
|
8305
|
-
lowerer.unsupported("SC1090", expr, `operator '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}' on 'any' values`);
|
|
8306
|
-
}
|
|
8307
|
-
const type = jsOpResultKind(jop) === "bool" ? BOOL : JSVAL;
|
|
8308
|
-
return {
|
|
8309
|
-
kind: "jsOp",
|
|
8310
|
-
op: jop,
|
|
8311
|
-
args: [lowerer.jsvalIn(left, expr.left), lowerer.jsvalIn(right, expr.right)],
|
|
8312
|
-
type,
|
|
8313
|
-
loc,
|
|
8314
|
-
};
|
|
8315
|
-
}
|
|
8316
7666
|
export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
|
|
8317
7667
|
const loc = locOf(expr);
|
|
8318
7668
|
const read = {
|
|
@@ -8324,27 +7674,6 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
|
|
|
8324
7674
|
const rhs = lowerer.lowerExpr(expr.right);
|
|
8325
7675
|
const numericRead = lowerOptionalNumber(lowerer, read, loc);
|
|
8326
7676
|
const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
|
|
8327
|
-
if (target.type.kind === "jsval" || rhs.type.kind === "jsval") {
|
|
8328
|
-
const JS_COMPOUND = {
|
|
8329
|
-
"+": "add",
|
|
8330
|
-
"-": "sub",
|
|
8331
|
-
"*": "mul",
|
|
8332
|
-
"/": "div",
|
|
8333
|
-
"%": "mod",
|
|
8334
|
-
"**": "pow",
|
|
8335
|
-
};
|
|
8336
|
-
const jop = JS_COMPOUND[compound];
|
|
8337
|
-
if (jop === undefined)
|
|
8338
|
-
lowerer.unsupported("SC1043", expr);
|
|
8339
|
-
const wrapped = {
|
|
8340
|
-
kind: "jsOp",
|
|
8341
|
-
op: jop,
|
|
8342
|
-
args: [lowerer.jsvalIn(read, expr.left), lowerer.jsvalIn(rhs, expr.right)],
|
|
8343
|
-
type: JSVAL,
|
|
8344
|
-
loc,
|
|
8345
|
-
};
|
|
8346
|
-
return lowerer.coerceInto(expr, wrapped, target.type);
|
|
8347
|
-
}
|
|
8348
7677
|
if (compound === "+" &&
|
|
8349
7678
|
(target.type.kind === "string" ||
|
|
8350
7679
|
(target.type.kind === "union" &&
|
|
@@ -8622,49 +7951,6 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8622
7951
|
};
|
|
8623
7952
|
}
|
|
8624
7953
|
}
|
|
8625
|
-
// `h.k = v` on an ISLAND receiver in VALUE position: the engine
|
|
8626
|
-
// property write (setProp throws the engine's TypeErrors on
|
|
8627
|
-
// nullish receivers, bridged catchably), the RHS value threaded
|
|
8628
|
-
// through as the expression's value.
|
|
8629
|
-
if (ts.isPropertyAccessExpression(expr.left) &&
|
|
8630
|
-
!expr.left.questionDotToken &&
|
|
8631
|
-
lowerer.isIslandExpr(expr.left.expression)) {
|
|
8632
|
-
const recv = lowerer.lowerExpr(expr.left.expression);
|
|
8633
|
-
const recvTmp = lowerer.declareHiddenLocal("%setRecv", recv.type);
|
|
8634
|
-
const rhsVal = lowerer.lowerExpr(expr.right);
|
|
8635
|
-
const valTmp = lowerer.declareHiddenLocal("%setVal", rhsVal.type);
|
|
8636
|
-
const valRef = () => ({
|
|
8637
|
-
kind: "varRef",
|
|
8638
|
-
localId: valTmp.id,
|
|
8639
|
-
type: rhsVal.type,
|
|
8640
|
-
loc,
|
|
8641
|
-
});
|
|
8642
|
-
return {
|
|
8643
|
-
kind: "seqExpr",
|
|
8644
|
-
stmts: [
|
|
8645
|
-
{ kind: "varDecl", localId: recvTmp.id, init: recv, loc },
|
|
8646
|
-
{ kind: "varDecl", localId: valTmp.id, init: rhsVal, loc },
|
|
8647
|
-
{
|
|
8648
|
-
kind: "exprStmt",
|
|
8649
|
-
expr: {
|
|
8650
|
-
kind: "jsOp",
|
|
8651
|
-
op: "setProp",
|
|
8652
|
-
name: expr.left.name.text,
|
|
8653
|
-
args: [
|
|
8654
|
-
{ kind: "varRef", localId: recvTmp.id, type: recv.type, loc },
|
|
8655
|
-
lowerer.jsvalIn(valRef(), expr.right),
|
|
8656
|
-
],
|
|
8657
|
-
type: VOID,
|
|
8658
|
-
loc,
|
|
8659
|
-
},
|
|
8660
|
-
loc,
|
|
8661
|
-
},
|
|
8662
|
-
],
|
|
8663
|
-
result: valRef(),
|
|
8664
|
-
type: rhsVal.type,
|
|
8665
|
-
loc,
|
|
8666
|
-
};
|
|
8667
|
-
}
|
|
8668
7954
|
// `h.k = v` on a CHECKED-DYNAMIC receiver in VALUE position
|
|
8669
7955
|
// (`var _ = module.exports = foo`): receiver first, then RHS
|
|
8670
7956
|
// (JS's reference-before-value order), the keyed write, and the
|
|
@@ -8980,34 +8266,20 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8980
8266
|
}
|
|
8981
8267
|
}
|
|
8982
8268
|
}
|
|
8983
|
-
// `any`-origin
|
|
8984
|
-
//
|
|
8985
|
-
// here): JS's full coercion semantics (ToPrimitive, NaN, string +)
|
|
8986
|
-
// live in the engine — the dynamic-family fence, so the island
|
|
8987
|
-
// retry lifts the site. Genuine unknown keeps the SC1100 story.
|
|
8269
|
+
// Unsupported `any`-origin operations get their specific diagnostic;
|
|
8270
|
+
// unknown retains the narrowing diagnostic below.
|
|
8988
8271
|
if ((left.type.kind === "dyn" && lowerer.anyOrigin(expr.left)) ||
|
|
8989
8272
|
(right.type.kind === "dyn" && lowerer.anyOrigin(expr.right))) {
|
|
8990
8273
|
// `JSON.parse` and other checked-dynamic producers deliberately
|
|
8991
8274
|
// remain dyn when assigned to an `any` local: eagerly converting
|
|
8992
8275
|
// the binding would deep-copy its data and sever aliases. At an
|
|
8993
|
-
// operator
|
|
8994
|
-
// the engine apply JS's exact coercion semantics. Static builds
|
|
8995
|
-
// retain the SC2011 promise that --dynamic lifts this site.
|
|
8996
|
-
if (lowerer.dynamic)
|
|
8997
|
-
return lowerAnyBinaryInIsland(lowerer, expr, left, right, loc);
|
|
8276
|
+
// unsupported operator, require an explicit represented type.
|
|
8998
8277
|
lowerer.anyOpFence(`the '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}' operator`, expr);
|
|
8999
8278
|
}
|
|
9000
8279
|
// tsc allows ===/!== on unknown (arithmetic/comparisons it rejects
|
|
9001
8280
|
// itself); a dynamic equality would need a dyn walk — validate first.
|
|
9002
8281
|
lowerer.unsupported("SC1100", expr, "operators on 'unknown' values");
|
|
9003
8282
|
}
|
|
9004
|
-
// Operators over 'any' execute in the island with JS-exact semantics
|
|
9005
|
-
// (ToPrimitive, NaN, string +): both operands marshal in, the engine
|
|
9006
|
-
// computes. Comparisons come back as static bools; arithmetic stays
|
|
9007
|
-
// an island value ('1 as any + "x"' is a string over there).
|
|
9008
|
-
if (left.type.kind === "jsval" || right.type.kind === "jsval") {
|
|
9009
|
-
return lowerAnyBinaryInIsland(lowerer, expr, left, right, loc);
|
|
9010
|
-
}
|
|
9011
8283
|
if (left.type.kind === "bigint" && right.type.kind === "bigint") {
|
|
9012
8284
|
const binary = {
|
|
9013
8285
|
[ts.SyntaxKind.PlusToken]: "bigint.add",
|
|
@@ -9705,16 +8977,6 @@ function lowerLogicalPair(lowerer, expr, left) {
|
|
|
9705
8977
|
loc,
|
|
9706
8978
|
};
|
|
9707
8979
|
}
|
|
9708
|
-
if (left.type.kind === "jsval" || right.type.kind === "jsval") {
|
|
9709
|
-
return {
|
|
9710
|
-
kind: "logical",
|
|
9711
|
-
op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
|
|
9712
|
-
left: lowerer.jsvalIn(left, expr.left),
|
|
9713
|
-
right: lowerer.jsvalIn(right, expr.right),
|
|
9714
|
-
type: JSVAL,
|
|
9715
|
-
loc,
|
|
9716
|
-
};
|
|
9717
|
-
}
|
|
9718
8980
|
if (isJsSourceFile(expr.getSourceFile()) &&
|
|
9719
8981
|
op === ts.SyntaxKind.AmpersandAmpersandToken &&
|
|
9720
8982
|
left.type.kind === "union" &&
|
|
@@ -9765,10 +9027,7 @@ function lowerLogicalPair(lowerer, expr, left) {
|
|
|
9765
9027
|
left.type.kind === "union") {
|
|
9766
9028
|
const leftArms = lowerer.unions.get(left.type.unionId)?.arms;
|
|
9767
9029
|
const rightArms = right.type.kind === "union" ? lowerer.unions.get(right.type.unionId)?.arms : [right.type];
|
|
9768
|
-
const rightIsStatic = rightArms?.every((arm) => arm.kind !== "dyn" &&
|
|
9769
|
-
arm.kind !== "caught" &&
|
|
9770
|
-
arm.kind !== "jsval" &&
|
|
9771
|
-
arm.kind !== "void") ?? false;
|
|
9030
|
+
const rightIsStatic = rightArms?.every((arm) => arm.kind !== "dyn" && arm.kind !== "caught" && arm.kind !== "void") ?? false;
|
|
9772
9031
|
if (leftArms &&
|
|
9773
9032
|
rightArms &&
|
|
9774
9033
|
rightIsStatic &&
|
|
@@ -10105,12 +9364,6 @@ export function lowerCaughtTypeofTest(lowerer, expr, loc) {
|
|
|
10105
9364
|
}
|
|
10106
9365
|
return null;
|
|
10107
9366
|
}
|
|
10108
|
-
/** The static `typeof` answer for a union ARM's IR type, or null when the
|
|
10109
|
-
* arm has no fixed answer. Unit arms are known (`typeof undefined` is
|
|
10110
|
-
* "undefined", `typeof null` is "object" — JS's oldest wart, preserved
|
|
10111
|
-
* exactly); every ref kind is a JS object ("object"), func arms would be
|
|
10112
|
-
* "function" (unions never carry them — defensive), and the jsval/dyn/
|
|
10113
|
-
* caught/void/union kinds cannot appear as arms. */
|
|
10114
9367
|
function typeofAnswer(arm) {
|
|
10115
9368
|
switch (arm.kind) {
|
|
10116
9369
|
case "f64":
|
|
@@ -10675,22 +9928,7 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10675
9928
|
const sockTest = lowerSocketInstanceOf(lowerer, expr, loc);
|
|
10676
9929
|
if (sockTest !== null)
|
|
10677
9930
|
return sockTest;
|
|
10678
|
-
|
|
10679
|
-
// exported class — the safeParse-style error narrowing): the spec's
|
|
10680
|
-
// InstanceofOperator runs in the engine (Symbol.hasInstance included;
|
|
10681
|
-
// a non-object RHS throws the engine's own TypeError, catchably).
|
|
10682
|
-
// The LHS marshals in — island handles pass through, static
|
|
10683
|
-
// primitives answer false exactly like the spec's non-object rule,
|
|
10684
|
-
// and unmarshalable statics (class instances, catch bindings — the
|
|
10685
|
-
// payload is a name/message snapshot, never the engine object) keep
|
|
10686
|
-
// jsvalIn's honest fences.
|
|
10687
|
-
if (lowerer.isIslandExpr(expr.right) && !lowerer.caughtLocalOf(expr.left)) {
|
|
10688
|
-
const left = lowerer.jsvalIn(lowerer.lowerExpr(expr.left), expr.left);
|
|
10689
|
-
const right = lowerer.lowerExpr(expr.right);
|
|
10690
|
-
return { kind: "jsOp", op: "instanceOf", args: [left, right], type: BOOL, loc };
|
|
10691
|
-
}
|
|
10692
|
-
if (!lowerer.dynamic &&
|
|
10693
|
-
(lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map"))) {
|
|
9931
|
+
if (lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map")) {
|
|
10694
9932
|
const collection = lowerer.isStdlibGlobal(expr.right, "Map") ? "map" : "set";
|
|
10695
9933
|
const value = lowerer.lowerExpr(expr.left);
|
|
10696
9934
|
if (value.type.kind === "union") {
|
|
@@ -10751,18 +9989,6 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10751
9989
|
}
|
|
10752
9990
|
if (lowerer.isStdlibGlobal(expr.right, "WeakMap") ||
|
|
10753
9991
|
lowerer.isStdlibGlobal(expr.right, "WeakSet")) {
|
|
10754
|
-
if (lowerer.dynamic) {
|
|
10755
|
-
const value = lowerer.jsvalIn(lowerer.lowerExpr(expr.left), expr.left);
|
|
10756
|
-
const ctor = {
|
|
10757
|
-
kind: "jsOp",
|
|
10758
|
-
op: "globalGet",
|
|
10759
|
-
name: lowerer.isStdlibGlobal(expr.right, "WeakMap") ? "WeakMap" : "WeakSet",
|
|
10760
|
-
args: [],
|
|
10761
|
-
type: JSVAL,
|
|
10762
|
-
loc,
|
|
10763
|
-
};
|
|
10764
|
-
return { kind: "jsOp", op: "instanceOf", args: [value, ctor], type: BOOL, loc };
|
|
10765
|
-
}
|
|
10766
9992
|
const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
|
|
10767
9993
|
return {
|
|
10768
9994
|
kind: "libCall",
|
|
@@ -12619,12 +11845,11 @@ function lowerUnionKeyedRead(lowerer, expr, unionId, value, key, literalField) {
|
|
|
12619
11845
|
}
|
|
12620
11846
|
if (joinArms.length === 0)
|
|
12621
11847
|
return null;
|
|
12622
|
-
// The join must
|
|
12623
|
-
//
|
|
12624
|
-
// siblings). The caller owns the diagnostic for a refused join.
|
|
11848
|
+
// The join must satisfy native union invariants. The caller owns the
|
|
11849
|
+
// diagnostic when a container or opaque arm prevents that join.
|
|
12625
11850
|
if (joinArms.length > 1 &&
|
|
12626
11851
|
(!unionContainerArmsOk(joinArms) ||
|
|
12627
|
-
joinArms.some((a) => a.kind === "dyn" || a.kind === "
|
|
11852
|
+
joinArms.some((a) => a.kind === "dyn" || a.kind === "generator" || a.kind === "caught"))) {
|
|
12628
11853
|
return null;
|
|
12629
11854
|
}
|
|
12630
11855
|
joinArms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|