@scriptc/compiler 0.4.6 → 0.4.7
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/node-fallback/events.d.ts +6 -1
- package/ambient/node-fallback/fs-promises.d.ts +1 -1
- package/ambient/node-fallback/fs.d.ts +54 -10
- package/ambient/node-fallback/http.d.ts +3 -1
- package/ambient/node-fallback/net.d.ts +19 -0
- package/ambient/node-fallback/querystring.d.ts +3 -3
- package/ambient/scriptc-node-fallback.d.ts +58 -13
- package/dist/backend/executable-features.js +13 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +12 -1
- package/dist/backend/immutability.js +50 -4
- package/dist/backend/immutability.js.map +1 -1
- package/dist/backend/immutability.test.js +95 -1
- package/dist/backend/immutability.test.js.map +1 -1
- package/dist/backend/library-pack.js +2 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/linker.d.ts +11 -0
- package/dist/backend/linker.js +31 -3
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/lld.d.ts +7 -2
- package/dist/backend/lld.js +5 -3
- package/dist/backend/lld.js.map +1 -1
- package/dist/backend/lld.test.js +10 -4
- package/dist/backend/lld.test.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +50 -1
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/cpu-dispatch.js +6 -5
- package/dist/backend/llvm/cpu-dispatch.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +53 -1
- package/dist/backend/llvm/dyn.js +221 -9
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +1 -1
- package/dist/backend/llvm/emit-function.js.map +1 -1
- package/dist/backend/llvm/emit-module.js +148 -50
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.js +39 -19
- package/dist/backend/llvm/emit-statements.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +29 -2
- package/dist/backend/llvm/emitter.js +86 -7
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +4 -1
- package/dist/backend/llvm/expr-calls.js +20 -4
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +209 -16
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +94 -11
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +8 -0
- package/dist/backend/llvm/expr-stream-bridges.js +42 -2
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +16 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +206 -20
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/integer-values.d.ts +2 -0
- package/dist/backend/llvm/integer-values.js +6 -0
- package/dist/backend/llvm/integer-values.js.map +1 -1
- package/dist/backend/llvm/js-ic.d.ts +38 -0
- package/dist/backend/llvm/js-ic.js +295 -1
- package/dist/backend/llvm/js-ic.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +20 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +116 -11
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +136 -24
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +70 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +67 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/loop-entry-versions.d.ts +2 -2
- package/dist/backend/llvm/loop-entry-versions.js +43 -21
- package/dist/backend/llvm/loop-entry-versions.js.map +1 -1
- package/dist/backend/llvm/loop-state.d.ts +7 -1
- package/dist/backend/llvm/loop-state.js +20 -2
- package/dist/backend/llvm/loop-state.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +3 -1
- package/dist/backend/llvm/map-number-lookup.js +7 -3
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +52 -11
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/receiver-brackets.test.d.ts +1 -0
- package/dist/backend/llvm/receiver-brackets.test.js +68 -0
- package/dist/backend/llvm/receiver-brackets.test.js.map +1 -0
- package/dist/backend/llvm/record-views.d.ts +22 -2
- package/dist/backend/llvm/record-views.js +139 -10
- package/dist/backend/llvm/record-views.js.map +1 -1
- package/dist/backend/llvm/record-views.test.js +76 -0
- package/dist/backend/llvm/record-views.test.js.map +1 -1
- package/dist/backend/llvm/reference-writes.js +1 -0
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +3 -0
- package/dist/backend/llvm/shapes.js +18 -3
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +4 -0
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +10 -1
- package/dist/backend/llvm/speculative-integers.js +59 -8
- package/dist/backend/llvm/speculative-integers.js.map +1 -1
- package/dist/backend/llvm/unwind-abi.d.ts +3 -3
- package/dist/backend/llvm/unwind-abi.js +8 -3
- package/dist/backend/llvm/unwind-abi.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -1
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +54 -0
- package/dist/backend/native/executable.js +87 -5
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -1
- package/dist/backend/native/library.js.map +1 -1
- package/dist/backend/native/runtime-inputs.js +5 -1
- package/dist/backend/native/runtime-inputs.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-codegen.js +3 -0
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +43 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.js +1 -0
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-profile.d.ts +4 -1
- package/dist/backend/native-profile.js +12 -1
- package/dist/backend/native-profile.js.map +1 -1
- package/dist/backend/native-profile.test.js +10 -0
- package/dist/backend/native-profile.test.js.map +1 -1
- package/dist/backend/publication.d.ts +4 -1
- package/dist/backend/publication.js +4 -2
- package/dist/backend/publication.js.map +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 +31 -7
- package/dist/backend/runtime-pack-core.js +21 -1
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.d.ts +18 -1
- package/dist/backend/runtime-pack-native.js +138 -29
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-native.test.js +166 -4
- package/dist/backend/runtime-pack-native.test.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +3 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +7 -0
- package/dist/backend/runtime-pack.js +25 -3
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +3 -11
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/vendor-archives.d.ts +4 -1
- package/dist/backend/vendor-archives.js +264 -3
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +36 -0
- package/dist/backend/vendor-inputs.js +42 -0
- package/dist/backend/vendor-inputs.js.map +1 -1
- package/dist/backend/vendor-inputs.test.js +28 -1
- package/dist/backend/vendor-inputs.test.js.map +1 -1
- package/dist/backend/warm-cache.js +2 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +7 -1
- package/dist/compat/fetch-profile.js +23 -10
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +7 -0
- package/dist/contracts/check.d.ts +3 -0
- package/dist/contracts/check.js +18 -5
- package/dist/contracts/check.js.map +1 -1
- package/dist/coverage/surface-manifest.js +1 -1
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/codes.d.ts +6 -0
- package/dist/diagnostics/codes.js +6 -0
- package/dist/diagnostics/codes.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +50 -0
- package/dist/diagnostics/diagnostic.js +142 -3
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/dynamic-tier.js +3 -1
- package/dist/diagnostics/dynamic-tier.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +29 -0
- package/dist/executable/executable-cache.js +18 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +5 -1
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +13 -3
- package/dist/executable/prepare.js +271 -18
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/early-errors.d.ts +14 -0
- package/dist/frontend/early-errors.js +305 -0
- package/dist/frontend/early-errors.js.map +1 -0
- package/dist/frontend/early-errors.test.d.ts +1 -0
- package/dist/frontend/early-errors.test.js +42 -0
- package/dist/frontend/early-errors.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +23 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +47 -0
- package/dist/frontend/input-tracker.js +173 -36
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +86 -2
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/js-inference.d.ts +2 -0
- package/dist/frontend/js-inference.js +18 -0
- package/dist/frontend/js-inference.js.map +1 -0
- package/dist/frontend/lowering/binding-analysis.d.ts +2 -1
- package/dist/frontend/lowering/binding-analysis.js +65 -1
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtin-calls.js +9 -0
- package/dist/frontend/lowering/builtin-calls.js.map +1 -1
- package/dist/frontend/lowering/builtin-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/builtin-namespaces.js +19 -2
- package/dist/frontend/lowering/builtin-namespaces.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.d.ts +7 -0
- package/dist/frontend/lowering/builtins/child-process-methods.js +50 -10
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.js +5 -1
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/dates.d.ts +1 -1
- package/dist/frontend/lowering/builtins/dates.js +23 -1
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/environment.d.ts +55 -0
- package/dist/frontend/lowering/builtins/environment.js +213 -2
- package/dist/frontend/lowering/builtins/environment.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js +47 -16
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +25 -7
- package/dist/frontend/lowering/builtins/filesystem.js +185 -16
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +39 -2
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +8 -0
- package/dist/frontend/lowering/builtins/module-resolution.js +31 -5
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.d.ts +3 -2
- package/dist/frontend/lowering/builtins/operating-system.js +5 -4
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +17 -1
- package/dist/frontend/lowering/builtins/process.js +285 -19
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/querystring.d.ts +8 -0
- package/dist/frontend/lowering/builtins/querystring.js +202 -18
- package/dist/frontend/lowering/builtins/querystring.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.js +21 -3
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/reflection.js +60 -1
- package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.js +208 -59
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.js +20 -1
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/v8.d.ts +5 -5
- package/dist/frontend/lowering/builtins/v8.js +7 -5
- package/dist/frontend/lowering/builtins/v8.js.map +1 -1
- package/dist/frontend/lowering/builtins/web-streams-dyn.d.ts +17 -2
- package/dist/frontend/lowering/builtins/web-streams-dyn.js +97 -9
- package/dist/frontend/lowering/builtins/web-streams-dyn.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +77 -0
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/cjs-exports-object.d.ts +3 -0
- package/dist/frontend/lowering/cjs-exports-object.js +1 -1
- package/dist/frontend/lowering/cjs-exports-object.js.map +1 -1
- package/dist/frontend/lowering/cjs-inline-require.js +5 -0
- package/dist/frontend/lowering/cjs-inline-require.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +5 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +114 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.js +59 -10
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js +15 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-views.d.ts +13 -0
- package/dist/frontend/lowering/class-views.js +51 -0
- package/dist/frontend/lowering/class-views.js.map +1 -0
- package/dist/frontend/lowering/coercions/function-adapters.d.ts +15 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +54 -10
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/state.d.ts +7 -0
- package/dist/frontend/lowering/coercions/state.js +7 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +60 -3
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +29 -1
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +8 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +132 -28
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +16 -5
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +16 -0
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +4 -0
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.d.ts +11 -0
- package/dist/frontend/lowering/containers/callback-arguments.js +53 -0
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/filter-predicates.d.ts +10 -0
- package/dist/frontend/lowering/containers/filter-predicates.js +69 -3
- package/dist/frontend/lowering/containers/filter-predicates.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +46 -2
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.d.ts +14 -0
- package/dist/frontend/lowering/expressions/array-literals.js +26 -10
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/binary.js +104 -12
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.js +121 -4
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.js +143 -3
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/keyed-field-targets.d.ts +11 -1
- package/dist/frontend/lowering/expressions/keyed-field-targets.js +22 -1
- package/dist/frontend/lowering/expressions/keyed-field-targets.js.map +1 -1
- package/dist/frontend/lowering/expressions/narrowing.js +25 -1
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +5 -1
- package/dist/frontend/lowering/expressions/object-literals.js +778 -229
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +66 -20
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +31 -0
- package/dist/frontend/lowering/expressions/property-access.js +796 -12
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +29 -1
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/typeof.js +17 -0
- package/dist/frontend/lowering/expressions/typeof.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.js +132 -17
- package/dist/frontend/lowering/expressions/updates.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.d.ts +6 -0
- package/dist/frontend/lowering/frozen-records.js +10 -4
- package/dist/frontend/lowering/frozen-records.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.test.d.ts +1 -0
- package/dist/frontend/lowering/frozen-records.test.js +44 -0
- package/dist/frontend/lowering/frozen-records.test.js.map +1 -0
- package/dist/frontend/lowering/function-names.d.ts +9 -0
- package/dist/frontend/lowering/function-names.js +95 -0
- package/dist/frontend/lowering/function-names.js.map +1 -0
- package/dist/frontend/lowering/function-returns.js +5 -3
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +49 -0
- package/dist/frontend/lowering/generic-functions.js +365 -7
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/global-values.d.ts +9 -0
- package/dist/frontend/lowering/global-values.js +44 -0
- package/dist/frontend/lowering/global-values.js.map +1 -1
- package/dist/frontend/lowering/handle-properties.js +34 -1
- package/dist/frontend/lowering/handle-properties.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.d.ts +54 -0
- package/dist/frontend/lowering/key-order-witness.js +546 -5
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +14 -0
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +110 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +36 -6
- package/dist/frontend/lowering/lower-builtin-values.js +332 -58
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +22 -1
- package/dist/frontend/lowering/lower-calls.js +427 -48
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-calls.test.js +78 -0
- package/dist/frontend/lowering/lower-calls.test.js.map +1 -0
- package/dist/frontend/lowering/lower-classes.d.ts +16 -5
- package/dist/frontend/lowering/lower-classes.js +168 -51
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +9 -0
- package/dist/frontend/lowering/lower-event-emitter.js +383 -41
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +14 -0
- package/dist/frontend/lowering/lower-exprs.js +25 -0
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +2 -0
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +80 -33
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +87 -25
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-node-island.d.ts +35 -4
- package/dist/frontend/lowering/lower-node-island.js +456 -61
- package/dist/frontend/lowering/lower-node-island.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +160 -9
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-shared-modules.js +13 -1
- package/dist/frontend/lowering/lower-shared-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +3 -2
- package/dist/frontend/lowering/lower-stdlib.js +32 -18
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +21 -4
- package/dist/frontend/lowering/lower-stmts.js +580 -103
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +126 -8
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +133 -21
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +139 -3
- package/dist/frontend/lowering/lowerer.js +579 -43
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +1 -1
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.js +15 -0
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/new-target.js +2 -2
- package/dist/frontend/lowering/nullish-empty-pattern.d.ts +17 -0
- package/dist/frontend/lowering/nullish-empty-pattern.js +118 -0
- package/dist/frontend/lowering/nullish-empty-pattern.js.map +1 -0
- package/dist/frontend/lowering/partial-assertions.d.ts +39 -0
- package/dist/frontend/lowering/partial-assertions.js +195 -0
- package/dist/frontend/lowering/partial-assertions.js.map +1 -0
- package/dist/frontend/lowering/primitive-wrappers.d.ts +34 -0
- package/dist/frontend/lowering/primitive-wrappers.js +220 -0
- package/dist/frontend/lowering/primitive-wrappers.js.map +1 -0
- package/dist/frontend/lowering/private-statics.d.ts +46 -0
- package/dist/frontend/lowering/private-statics.js +322 -0
- package/dist/frontend/lowering/private-statics.js.map +1 -0
- package/dist/frontend/lowering/record-sources.d.ts +12 -1
- package/dist/frontend/lowering/record-sources.js +60 -0
- package/dist/frontend/lowering/record-sources.js.map +1 -1
- package/dist/frontend/lowering/strict-equality.d.ts +4 -0
- package/dist/frontend/lowering/strict-equality.js +14 -0
- package/dist/frontend/lowering/strict-equality.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +27 -0
- package/dist/frontend/lowering/surfaces.js +135 -62
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/unit-journal.d.ts +128 -17
- package/dist/frontend/lowering/unit-journal.js +310 -53
- package/dist/frontend/lowering/unit-journal.js.map +1 -1
- package/dist/frontend/lowering/unit-journal.test.js +91 -3
- package/dist/frontend/lowering/unit-journal.test.js.map +1 -1
- package/dist/frontend/lowering/unit-reuse.d.ts +92 -0
- package/dist/frontend/lowering/unit-reuse.js +1008 -0
- package/dist/frontend/lowering/unit-reuse.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +12 -0
- package/dist/frontend/npm-file-import.test.d.ts +1 -0
- package/dist/frontend/npm-file-import.test.js +76 -0
- package/dist/frontend/npm-file-import.test.js.map +1 -0
- package/dist/frontend/npm-static.js +17 -2
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +9 -0
- package/dist/frontend/npm.js +82 -0
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/pipeline-native.js +2 -1
- package/dist/frontend/pipeline-native.js.map +1 -1
- package/dist/frontend/pipeline.d.ts +4 -0
- package/dist/frontend/pipeline.js +68 -7
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/program-node.d.ts +3 -0
- package/dist/frontend/program-node.js +13 -6
- package/dist/frontend/program-node.js.map +1 -1
- package/dist/frontend/program.d.ts +9 -0
- package/dist/frontend/program.js +159 -7
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance-core.js +4 -0
- package/dist/frontend/provenance-core.js.map +1 -1
- package/dist/frontend/services.d.ts +14 -0
- package/dist/frontend/services.js +52 -2
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +61 -1
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/shape-inference/analyze.d.ts +5 -0
- package/dist/frontend/shape-inference/analyze.js +104 -4
- package/dist/frontend/shape-inference/analyze.js.map +1 -1
- package/dist/frontend/shape-inference/domain.js +0 -1
- package/dist/frontend/shape-inference/domain.js.map +1 -1
- package/dist/frontend/shape-inference/index.js +5 -1
- package/dist/frontend/shape-inference/index.js.map +1 -1
- package/dist/frontend/shape-inference/memo.d.ts +2 -1
- package/dist/frontend/shape-inference/memo.js +6 -2
- package/dist/frontend/shape-inference/memo.js.map +1 -1
- package/dist/frontend/shape-inference/overlay.d.ts +1 -1
- package/dist/frontend/shape-inference/overlay.js +116 -2
- package/dist/frontend/shape-inference/overlay.js.map +1 -1
- package/dist/frontend/shape-inference/static-objects.js +11 -6
- package/dist/frontend/shape-inference/static-objects.js.map +1 -1
- package/dist/frontend/source-phase-imports.test.d.ts +1 -0
- package/dist/frontend/source-phase-imports.test.js +37 -0
- package/dist/frontend/source-phase-imports.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +6 -1
- package/dist/frontend/ts7/ast-node.js +12 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-wire-protocols.test.js +11 -3
- package/dist/frontend/ts7/ast-wire-protocols.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.js +3 -5
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +13 -0
- package/dist/frontend/ts7/checker-backend.js +84 -2
- package/dist/frontend/ts7/checker-backend.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.test.js +126 -2
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +22 -1
- package/dist/frontend/ts7/program-host.js +49 -4
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/program-host.test.js +83 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-process.d.ts +16 -1
- package/dist/frontend/ts7/rpc-process.js +170 -92
- package/dist/frontend/ts7/rpc-process.js.map +1 -1
- package/dist/frontend/ts7/rpc-process.test.js +49 -21
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -1
- package/dist/frontend/tsc-codes.js +70 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +7 -2
- package/dist/frontend/type-mapper.js +148 -1
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +152 -8
- 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/build.d.ts +3 -2
- package/dist/ir/build.js +4 -2
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-effects.js +53 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +211 -10
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/codec.d.ts +82 -0
- package/dist/ir/codec.generated.d.ts +13 -0
- package/dist/ir/codec.generated.js +5274 -0
- package/dist/ir/codec.generated.js.map +1 -0
- package/dist/ir/codec.js +325 -0
- package/dist/ir/codec.js.map +1 -0
- package/dist/ir/codec.test.d.ts +1 -0
- package/dist/ir/codec.test.js +225 -0
- package/dist/ir/codec.test.js.map +1 -0
- package/dist/ir/fields.generated.d.ts +20 -10
- package/dist/ir/fields.generated.js +1031 -11
- package/dist/ir/fields.generated.js.map +1 -1
- package/dist/ir/fields.test.js +46 -2
- package/dist/ir/fields.test.js.map +1 -1
- package/dist/ir/function-references.d.ts +5 -4
- package/dist/ir/function-references.js +8 -4
- package/dist/ir/function-references.js.map +1 -1
- package/dist/ir/function-references.test.js +7 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/inline-array-sources.js +4 -1
- package/dist/ir/inline-array-sources.js.map +1 -1
- package/dist/ir/inline-array-views.d.ts +13 -0
- package/dist/ir/inline-array-views.js +944 -0
- package/dist/ir/inline-array-views.js.map +1 -0
- package/dist/ir/inline-arrays.d.ts +7 -0
- package/dist/ir/inline-arrays.js +190 -55
- package/dist/ir/inline-arrays.js.map +1 -1
- package/dist/ir/inline-arrays.test.js +140 -2
- package/dist/ir/inline-arrays.test.js.map +1 -1
- package/dist/ir/integer-ranges.js +16 -6
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +75 -44
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/js-ic.d.ts +10 -9
- package/dist/ir/js-ic.js +28 -20
- package/dist/ir/js-ic.js.map +1 -1
- package/dist/ir/js-ic.test.js +10 -2
- package/dist/ir/js-ic.test.js.map +1 -1
- package/dist/ir/jsval.js +374 -63
- package/dist/ir/jsval.js.map +1 -1
- package/dist/ir/jsval.test.js +96 -2
- package/dist/ir/jsval.test.js.map +1 -1
- package/dist/ir/loop-entry-ranges.js +112 -9
- package/dist/ir/loop-entry-ranges.js.map +1 -1
- package/dist/ir/loop-entry-ranges.test.js +40 -0
- package/dist/ir/loop-entry-ranges.test.js.map +1 -1
- package/dist/ir/parameter-versions.d.ts +2 -1
- package/dist/ir/parameter-versions.js +3 -1
- package/dist/ir/parameter-versions.js.map +1 -1
- package/dist/ir/receiver-readers.js +58 -2
- package/dist/ir/receiver-readers.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +60 -1
- package/dist/ir/runtime-features.js +277 -2
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/runtime-features.test.js +165 -1
- package/dist/ir/runtime-features.test.js.map +1 -1
- package/dist/ir/saturating-loop-jams.d.ts +8 -1
- package/dist/ir/saturating-loop-jams.js +46 -7
- package/dist/ir/saturating-loop-jams.js.map +1 -1
- package/dist/ir/saturating-loop-jams.test.js +39 -1
- package/dist/ir/saturating-loop-jams.test.js.map +1 -1
- package/dist/ir/self-captures.js +8 -1
- package/dist/ir/self-captures.js.map +1 -1
- package/dist/ir/self-captures.test.js +15 -0
- package/dist/ir/self-captures.test.js.map +1 -1
- package/dist/ir/serialize.d.ts +3 -2
- package/dist/ir/serialize.js +6 -2
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.js +82 -4
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +46 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/ir-policy.js +3 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/native/cache.js +2 -0
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cli.js +2 -0
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +8 -2
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/prepare.js +32 -3
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.js +53 -3
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/sanitizer.test.js +88 -2
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/toolchain.js +9 -2
- package/dist/native/toolchain.js.map +1 -1
- package/dist/node-islands/boundary.d.ts +25 -1
- package/dist/node-islands/boundary.js +28 -2
- package/dist/node-islands/boundary.js.map +1 -1
- package/dist/node-islands/detect.d.ts +18 -1
- package/dist/node-islands/detect.js +365 -40
- package/dist/node-islands/detect.js.map +1 -1
- package/dist/node-islands/detect.test.js +151 -4
- package/dist/node-islands/detect.test.js.map +1 -1
- package/dist/node-islands/effect-gate.js +30 -20
- package/dist/node-islands/effect-gate.js.map +1 -1
- package/dist/node-islands/effect-gate.test.js +4 -1
- package/dist/node-islands/effect-gate.test.js.map +1 -1
- package/dist/node-islands/libnode.d.ts +1 -1
- package/dist/node-islands/libnode.js +1 -1
- package/dist/node-islands/libnode.js.map +1 -1
- package/dist/node-islands/modules.d.ts +28 -0
- package/dist/node-islands/modules.js +156 -0
- package/dist/node-islands/modules.js.map +1 -1
- package/dist/node-islands/modules.test.js +105 -1
- package/dist/node-islands/modules.test.js.map +1 -1
- package/dist/node-islands/policy.js +2 -3
- package/dist/node-islands/policy.js.map +1 -1
- package/dist/node-islands/probe-recorder.d.ts +1 -0
- package/dist/node-islands/probe-recorder.js +596 -0
- package/dist/node-islands/probe-recorder.js.map +1 -0
- package/dist/node-islands/probe-recorder.test.d.ts +1 -0
- package/dist/node-islands/probe-recorder.test.js +80 -0
- package/dist/node-islands/probe-recorder.test.js.map +1 -0
- package/dist/node-islands/report.test.js +2 -0
- package/dist/node-islands/report.test.js.map +1 -1
- package/dist/node-islands/rules.js +4 -0
- package/dist/node-islands/rules.js.map +1 -1
- package/dist/node-islands/scan.d.ts +7 -1
- package/dist/node-islands/scan.js +51 -2
- package/dist/node-islands/scan.js.map +1 -1
- package/dist/node-islands/snapshot.d.ts +38 -1
- package/dist/node-islands/snapshot.js +165 -161
- package/dist/node-islands/snapshot.js.map +1 -1
- package/dist/node-islands/snapshot.test.js +63 -2
- package/dist/node-islands/snapshot.test.js.map +1 -1
- package/dist/node-islands/summary.js +8 -0
- package/dist/node-islands/summary.js.map +1 -1
- package/dist/node-islands/type-strip.d.ts +11 -0
- package/dist/node-islands/type-strip.js +157 -0
- package/dist/node-islands/type-strip.js.map +1 -0
- package/dist/node-islands/type-strip.test.d.ts +1 -0
- package/dist/node-islands/type-strip.test.js +31 -0
- package/dist/node-islands/type-strip.test.js.map +1 -0
- package/dist/project-config.d.ts +4 -0
- package/dist/project-config.js +19 -0
- package/dist/project-config.js.map +1 -1
- package/dist/project-config.test.js +10 -0
- package/dist/project-config.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +43 -11
|
@@ -10,15 +10,18 @@ import { NARROW_FIRST } from "../surfaces.js";
|
|
|
10
10
|
import { recordShapeMismatchDiag, unionLiteralMismatchDiag, } from "../../../diagnostics/diagnostic.js";
|
|
11
11
|
import { PoisonError, jsFuncNameOf, neverTaintedJsType } from "../lowerer.js";
|
|
12
12
|
import { lowerIndexMergeHelper } from "../containers/indexed-objects.js";
|
|
13
|
+
import { recordMayKeepSource } from "../record-sources.js";
|
|
13
14
|
import { PERF_ENTRY_MARKER, X509_PUBLIC_KEY_FIELD, isGenericCallableMemberType, jsOpenObjectType, } from "../../type-mapper.js";
|
|
14
15
|
import { isSafeToRepeat } from "./evaluation-safety.js";
|
|
15
16
|
import { tryLowerExpression } from "./try-lower-expression.js";
|
|
16
17
|
import { classSymbolKeyOf, fenceSymbolFieldCopy, symbolFieldDisplayName, } from "../symbol-fields.js";
|
|
17
18
|
import { planUnionRetag } from "../union-retag.js";
|
|
19
|
+
import { literalValues } from "../../literal-values.js";
|
|
18
20
|
import { jsHoldsDynObject, runtimeOptionalStorageOperand } from "../lower-exprs.js";
|
|
19
21
|
import { builtinGlobalValue } from "./property-access.js";
|
|
20
22
|
import { holdsEvolvingArray } from "../lower-stmts.js";
|
|
21
23
|
import { builtinNamespaceValue } from "../builtin-namespaces.js";
|
|
24
|
+
import { tsUntypedGlobalValue } from "../global-values.js";
|
|
22
25
|
/** `{ a: 1, b: "x" }` → recordLit. The record type comes from the
|
|
23
26
|
* contextual type when tsc has one (annotated declarations, arguments,
|
|
24
27
|
* nested literals) and from the literal's own type otherwise — both intern
|
|
@@ -154,6 +157,34 @@ function pureKeyExpr(lowerer, expr) {
|
|
|
154
157
|
return expr.templateSpans.nodes.every((s) => pureKeyExpr(lowerer, s.expression));
|
|
155
158
|
return false;
|
|
156
159
|
}
|
|
160
|
+
/** Whether expr reads no state that evaluating other code could change:
|
|
161
|
+
* literals, `const` bindings, and unary operators over those. */
|
|
162
|
+
function constantInitializer(lowerer, expr) {
|
|
163
|
+
if (ts.isParenthesizedExpression(expr) || ts.isNonNullExpression(expr))
|
|
164
|
+
return constantInitializer(lowerer, expr.expression);
|
|
165
|
+
if (ts.isAsExpression(expr) || ts.isTypeAssertion(expr))
|
|
166
|
+
return constantInitializer(lowerer, expr.expression);
|
|
167
|
+
if (ts.isStringLiteralLike(expr) || ts.isNumericLiteral(expr))
|
|
168
|
+
return true;
|
|
169
|
+
if (expr.kind === ts.SyntaxKind.TrueKeyword ||
|
|
170
|
+
expr.kind === ts.SyntaxKind.FalseKeyword ||
|
|
171
|
+
expr.kind === ts.SyntaxKind.NullKeyword)
|
|
172
|
+
return true;
|
|
173
|
+
if (ts.isPrefixUnaryExpression(expr) &&
|
|
174
|
+
(expr.operator === ts.SyntaxKind.MinusToken ||
|
|
175
|
+
expr.operator === ts.SyntaxKind.PlusToken ||
|
|
176
|
+
expr.operator === ts.SyntaxKind.ExclamationToken ||
|
|
177
|
+
expr.operator === ts.SyntaxKind.TildeToken))
|
|
178
|
+
return constantInitializer(lowerer, expr.operand);
|
|
179
|
+
if (ts.isIdentifier(expr)) {
|
|
180
|
+
const decls = lowerer.checker.getSymbolAtLocation(expr)?.declarations ?? [];
|
|
181
|
+
return (decls.length > 0 &&
|
|
182
|
+
decls.every((d) => ts.isVariableDeclaration(d) &&
|
|
183
|
+
ts.isVariableDeclarationList(d.parent) &&
|
|
184
|
+
(ts.getCombinedNodeFlags(d) & ts.NodeFlags.Const) !== 0));
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
157
188
|
/** A property's field name: identifier/string-literal keys directly,
|
|
158
189
|
* foldable computed keys through literalComputedKey (the syntax pass
|
|
159
190
|
* fenced everything else). */
|
|
@@ -401,8 +432,11 @@ export function lowerDynObjectLiteral(lowerer, expr, boxValue, conditionalArms =
|
|
|
401
432
|
// A PURE member read a JS file cannot lower (a namespace object
|
|
402
433
|
// in an export aggregate): the slot takes a boxed fence closure —
|
|
403
434
|
// the diagnostics defer to the runtime-fence ledger, the object
|
|
404
|
-
// builds, and only USING the member stops the run.
|
|
405
|
-
|
|
435
|
+
// builds, and only USING the member stops the run. A TypeScript
|
|
436
|
+
// source keeps the compile-time refusal: the closure would answer
|
|
437
|
+
// typeof "function" and undefined members where Node reads the
|
|
438
|
+
// value.
|
|
439
|
+
const pureMember = ts.isIdentifier(valueExpr) && isJsSourceFile(ts.getSourceFileOfNode(prop));
|
|
406
440
|
if (!(err instanceof PoisonError) || !pureMember)
|
|
407
441
|
throw err;
|
|
408
442
|
const fence = lowerer.deferToRuntimeFence(propDiagsBefore, prop, {
|
|
@@ -493,9 +527,7 @@ function fenceAccessorSpreadSource(lowerer, prop, srcShape) {
|
|
|
493
527
|
/** Only definitely present later records replace earlier defaults. A
|
|
494
528
|
* callback binding may store undefined despite its checker annotation. */
|
|
495
529
|
function laterSpreadType(lowerer, expr) {
|
|
496
|
-
|
|
497
|
-
while (ts.isParenthesizedExpression(source))
|
|
498
|
-
source = source.expression;
|
|
530
|
+
const source = spreadSourceNode(lowerer, expr);
|
|
499
531
|
if (ts.isIdentifier(source))
|
|
500
532
|
return lowerer.lowerExpr(source).type;
|
|
501
533
|
return lowerer.mapTypeOf(lowerer.typeOf(source));
|
|
@@ -772,7 +804,11 @@ function lowerOptionalIndexSpreadSource(lowerer, source, loc) {
|
|
|
772
804
|
? selected
|
|
773
805
|
: { kind: "seqExpr", stmts: prefix, result: selected, type: recordType, loc };
|
|
774
806
|
}
|
|
775
|
-
export function lowerObjectLiteral(lowerer, expr, expected
|
|
807
|
+
export function lowerObjectLiteral(lowerer, expr, expected,
|
|
808
|
+
/** Build exactly at `expected` (one arm of a distributed union spread,
|
|
809
|
+
* lowerDistributedUnionSpread): the checker types the literal as the
|
|
810
|
+
* whole union, so its contextual type cannot choose the layout. */
|
|
811
|
+
exact = false) {
|
|
776
812
|
// A spread of an untyped (`any`) source into a typed slot: TypeScript
|
|
777
813
|
// types such a literal `any`, and the copy holds whatever own properties
|
|
778
814
|
// the source has at runtime. Build it as a checked-dynamic object, then
|
|
@@ -861,7 +897,7 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
861
897
|
tryLowerExpression(lowerer, property.expression)?.type.kind === "dyn"))) {
|
|
862
898
|
return lowerDynObjectLiteral(lowerer, expr);
|
|
863
899
|
}
|
|
864
|
-
const unionClone = lowerUnionRecordClone(lowerer, expr);
|
|
900
|
+
const unionClone = exact ? null : lowerUnionRecordClone(lowerer, expr);
|
|
865
901
|
if (unionClone !== null)
|
|
866
902
|
return unionClone;
|
|
867
903
|
// The RUNTIME-KEYED literal (JS): a computed key that doesn't fold to a
|
|
@@ -993,7 +1029,7 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
993
1029
|
ts.constituentTypes(tsType).some((t) => ts.symbolNameOf(t.getSymbol()) === "PromiseLike")) {
|
|
994
1030
|
tsType = lowerer.checker.getAwaitedType(tsType) ?? tsType;
|
|
995
1031
|
}
|
|
996
|
-
let mapped = lowerer.mapTypeOf(tsType);
|
|
1032
|
+
let mapped = exact && expected ? expected : lowerer.mapTypeOf(tsType);
|
|
997
1033
|
// A checked-dynamic source has runtime keys even when later explicit
|
|
998
1034
|
// fields make the literal's inferred type look like a fixed record.
|
|
999
1035
|
// Keep a checked-dynamic destination in that representation so copying
|
|
@@ -1193,14 +1229,27 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1193
1229
|
lowerer.unsupported("SC1090", deferredConditionalSpread, CONDITIONAL_SPREAD_FENCE);
|
|
1194
1230
|
}
|
|
1195
1231
|
if (!mapped || mapped.kind !== "record") {
|
|
1232
|
+
// Distribute against the contextual union when there is one (its arms
|
|
1233
|
+
// carry the discriminants), else against the literal's own union.
|
|
1234
|
+
const ctx = lowerer.mapTypeOf(tsType);
|
|
1235
|
+
const unionCtx = ctx?.kind === "union" ? ctx : mapped;
|
|
1236
|
+
const distributed = exact ? null : lowerDistributedUnionSpread(lowerer, expr, unionCtx);
|
|
1237
|
+
if (distributed)
|
|
1238
|
+
return distributed;
|
|
1196
1239
|
// A spread merge over UNION-typed sources (`{ ...base, ...override }`
|
|
1197
1240
|
// with `base`, `override` of arm-union types) has one field set per
|
|
1198
1241
|
// combination of source arms, so its own type is a union of records.
|
|
1199
1242
|
// No single arm of the contextual union can hold that value without
|
|
1200
1243
|
// dropping the fields the other arms contributed (Node keeps them
|
|
1201
1244
|
// all), and a runtime tag would be a guess about which arm the value
|
|
1202
|
-
// "is".
|
|
1245
|
+
// "is". Build the object Node builds instead — the checked-dynamic
|
|
1246
|
+
// copy — and let the union's checked conversion validate it.
|
|
1203
1247
|
if (mapped?.kind === "union") {
|
|
1248
|
+
if (!exact && unionCtx?.kind === "union") {
|
|
1249
|
+
const merged = lowerUnionSpreadMergeDyn(lowerer, expr, unionCtx);
|
|
1250
|
+
if (merged)
|
|
1251
|
+
return merged;
|
|
1252
|
+
}
|
|
1204
1253
|
const members = tsType.isUnionType() ? ts.constituentTypes(tsType) : [tsType];
|
|
1205
1254
|
const arms = [...new Set(members.map((m) => lowerer.checker.typeToString(m)))];
|
|
1206
1255
|
lowerer.pushDiag(unionLiteralMismatchDiag(lowerer.checker.typeToString(tsType), arms, locOf(expr)));
|
|
@@ -1208,7 +1257,20 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1208
1257
|
}
|
|
1209
1258
|
lowerer.badType(expr, tsType);
|
|
1210
1259
|
}
|
|
1211
|
-
|
|
1260
|
+
// An enclosing literal that built at its OWN type (its context had no
|
|
1261
|
+
// layout) asks for the matching own layout of this nested literal. When
|
|
1262
|
+
// this literal's contextual layout cannot reach that slot, build at it:
|
|
1263
|
+
// the enclosing literal's coercion then decides, and the width lifts
|
|
1264
|
+
// (the index-signature overflow capture included) carry the whole tree
|
|
1265
|
+
// into the real destination. Otherwise the two layers disagree and the
|
|
1266
|
+
// SC2002 names the source literal's own type as the expected one.
|
|
1267
|
+
const layout = expected &&
|
|
1268
|
+
!typeEquals(mapped, expected) &&
|
|
1269
|
+
lowerer.widthLiftPlan(mapped, expected) === null &&
|
|
1270
|
+
typeEquals(lowerer.mapTypeOf(lowerer.typeOf(expr)) ?? mapped, expected)
|
|
1271
|
+
? expected
|
|
1272
|
+
: mapped;
|
|
1273
|
+
let type = layout;
|
|
1212
1274
|
// A fresh, plain literal can construct its fields directly for a known
|
|
1213
1275
|
// destination with the same field set. This matters for inferred
|
|
1214
1276
|
// conditional records: an empty array in one arm has no element layout
|
|
@@ -1219,15 +1281,31 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1219
1281
|
expr.properties.nodes.every((p) => ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p))) {
|
|
1220
1282
|
const own = lowerer.shapes.get(type.shapeId);
|
|
1221
1283
|
const target = lowerer.shapes.get(expected.shapeId);
|
|
1222
|
-
|
|
1284
|
+
// The field set to compare is the LITERAL's: its checker type. The
|
|
1285
|
+
// contextual type a few lines up can be wider than what the literal
|
|
1286
|
+
// writes (an unannotated method checked against a generic slot's
|
|
1287
|
+
// signature: `{ content, details }` under a contextual
|
|
1288
|
+
// `AgentToolResult<unknown>` whose optional members the literal never
|
|
1289
|
+
// mentions), and the destination still names the same fields as the
|
|
1290
|
+
// literal, so the build can construct them directly. Only when the
|
|
1291
|
+
// contextual build has no conversion into the destination at all: a
|
|
1292
|
+
// value that converts today keeps its exact construction.
|
|
1293
|
+
const ownType = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
1294
|
+
const ownChecked = ownType?.kind === "record" &&
|
|
1295
|
+
ownType.shapeId !== type.shapeId &&
|
|
1296
|
+
lowerer.widthLiftPlan(type, expected) === null
|
|
1297
|
+
? lowerer.shapes.get(ownType.shapeId)
|
|
1298
|
+
: undefined;
|
|
1299
|
+
const fits = (from) => !from.tuple &&
|
|
1223
1300
|
!target.tuple &&
|
|
1224
|
-
!
|
|
1301
|
+
!from.indexValue &&
|
|
1225
1302
|
!target.indexValue &&
|
|
1226
|
-
!shapeHasAccessorSlots(
|
|
1303
|
+
!shapeHasAccessorSlots(from) &&
|
|
1227
1304
|
!shapeHasAccessorSlots(target) &&
|
|
1228
|
-
target.fields.every((field) =>
|
|
1305
|
+
target.fields.every((field) => from.fields.some((candidate) => candidate.name === field.name) ||
|
|
1229
1306
|
(field.type.kind === "union" && lowerer.armTag(field.type.unionId, UNDEFINED_T) >= 0)) &&
|
|
1230
|
-
|
|
1307
|
+
from.fields.every((field) => target.fields.some((candidate) => candidate.name === field.name));
|
|
1308
|
+
if (fits(own) || (ownChecked !== undefined && fits(ownChecked))) {
|
|
1231
1309
|
type = { kind: "record", shapeId: expected.shapeId };
|
|
1232
1310
|
}
|
|
1233
1311
|
}
|
|
@@ -1357,7 +1435,13 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1357
1435
|
lowerer.badType(valueNode, lowerer.typeOf(valueNode));
|
|
1358
1436
|
overrides.push({ name, value });
|
|
1359
1437
|
}
|
|
1360
|
-
return {
|
|
1438
|
+
return lowerer.keyOrder.clone({
|
|
1439
|
+
kind: "recordClone",
|
|
1440
|
+
source,
|
|
1441
|
+
overrides,
|
|
1442
|
+
type,
|
|
1443
|
+
loc,
|
|
1444
|
+
});
|
|
1361
1445
|
}
|
|
1362
1446
|
leadingSpreadLowered = source;
|
|
1363
1447
|
}
|
|
@@ -1591,6 +1675,16 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1591
1675
|
const droppedNames = new Set();
|
|
1592
1676
|
// The order this literal creates its keys in (key-order-witness.ts).
|
|
1593
1677
|
const orderSegments = [];
|
|
1678
|
+
// The literal's contributors when a spread drops source keys the target
|
|
1679
|
+
// has no slot for (key-order-witness.ts keepWidthSpreads). Conditional
|
|
1680
|
+
// spreads leave the literal to the static copy.
|
|
1681
|
+
const widthSegments = [];
|
|
1682
|
+
let widthDrops = false;
|
|
1683
|
+
let widthBlocked = false;
|
|
1684
|
+
// A checked-dynamic spread source's own keys are a run-time fact: even
|
|
1685
|
+
// when the checker's shape fits the target, the copied object can hold
|
|
1686
|
+
// more (slice 3).
|
|
1687
|
+
let widthDynSource = false;
|
|
1594
1688
|
for (const prop of expr.properties.nodes) {
|
|
1595
1689
|
// A later contributor can mutate an earlier source or overwrite a
|
|
1596
1690
|
// value with effects. Snapshot pending fields at their source position,
|
|
@@ -1604,6 +1698,7 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1604
1698
|
if (ts.isSpreadAssignment(prop)) {
|
|
1605
1699
|
const cs = conditionalSpreadOf(prop.expression) ?? andSpreadOf(lowerer, prop.expression);
|
|
1606
1700
|
if (cs && cs !== "unsupported") {
|
|
1701
|
+
widthBlocked = true;
|
|
1607
1702
|
// `...(c ? { k: v } : {})` — one conditional field per carried
|
|
1608
1703
|
// property at the spread's own position: cond evaluates exactly
|
|
1609
1704
|
// once (into a hidden local when several fields test it), each
|
|
@@ -1676,15 +1771,25 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1676
1771
|
// earlier ones (JS last-write-wins). Evaluate the source exactly
|
|
1677
1772
|
// once, including empty sources and those whose fields are all
|
|
1678
1773
|
// overridden. Field snapshots above preserve the copy order.
|
|
1679
|
-
|
|
1680
|
-
while (ts.isParenthesizedExpression(srcNode))
|
|
1681
|
-
srcNode = srcNode.expression;
|
|
1774
|
+
const srcNode = spreadSourceNode(lowerer, prop.expression);
|
|
1682
1775
|
const condRecord = conditionalRecordSpreadOf(lowerer, prop.expression);
|
|
1683
|
-
|
|
1776
|
+
let srcLowered = capture(condRecord !== null
|
|
1684
1777
|
? lowerConditionalRecordSpread(lowerer, condRecord, locOf(prop))
|
|
1685
1778
|
: prop === expr.properties.nodes[0] && leadingSpreadLowered !== null
|
|
1686
1779
|
? leadingSpreadLowered
|
|
1687
|
-
: lowerer.lowerExpr(srcNode));
|
|
1780
|
+
: (lowerer.spreadArmOverrides.get(srcNode) ?? lowerer.lowerExpr(srcNode)));
|
|
1781
|
+
{
|
|
1782
|
+
const narrowed = checkedSpreadSource(lowerer, srcNode, srcLowered);
|
|
1783
|
+
if (narrowed !== null)
|
|
1784
|
+
srcLowered = capture(narrowed);
|
|
1785
|
+
}
|
|
1786
|
+
if (condRecord !== null || srcLowered.kind !== "varRef")
|
|
1787
|
+
widthBlocked = true;
|
|
1788
|
+
else {
|
|
1789
|
+
widthSegments.push({ kind: "spread", value: srcLowered });
|
|
1790
|
+
if (srcLowered.type.kind === "dyn")
|
|
1791
|
+
widthDynSource = true;
|
|
1792
|
+
}
|
|
1688
1793
|
// Array callbacks can receive a record-or-undefined ABI even when
|
|
1689
1794
|
// TypeScript describes a required record. Select the copy strategy
|
|
1690
1795
|
// from that stored representation so absent sources copy nothing.
|
|
@@ -1704,12 +1809,10 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1704
1809
|
const def = lowerer.unions.get(srcType.unionId);
|
|
1705
1810
|
const recArms = def?.arms.filter((a) => a.kind === "record") ?? [];
|
|
1706
1811
|
if (!def ||
|
|
1707
|
-
recArms.length
|
|
1812
|
+
recArms.length === 0 ||
|
|
1708
1813
|
!def.arms.every((a) => a.kind === "record" || isUnitType(a))) {
|
|
1709
1814
|
lowerer.unsupported("SC1090", prop, `object spread of '${lowerer.fmt(srcType)}' sources (only known record shapes spread — ${NARROW_FIRST})`);
|
|
1710
1815
|
}
|
|
1711
|
-
const recArm = recArms[0];
|
|
1712
|
-
const recTag = def.arms.indexOf(recArm);
|
|
1713
1816
|
// A checked-dynamic VALUE under the union-mapped checker type
|
|
1714
1817
|
// (a JS dyn-holding binding): the present/absent desugar tests
|
|
1715
1818
|
// union tags a dyn box does not carry — fence honestly instead
|
|
@@ -1718,230 +1821,240 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
1718
1821
|
if (probedSrc?.type.kind === "dyn") {
|
|
1719
1822
|
lowerer.unsupported("SC1090", prop, `object spread of a checked-dynamic '${lowerer.fmt(srcType)}' source (${NARROW_FIRST})`);
|
|
1720
1823
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
const
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1824
|
+
// Several record arms: each arm contributes its own fields behind its
|
|
1825
|
+
// tag test, wrapping the earlier contributor, so a key that arm lacks
|
|
1826
|
+
// keeps the earlier value (JS copies only the arm's own keys).
|
|
1827
|
+
for (const recArmCandidate of recArms) {
|
|
1828
|
+
const recArm = recArmCandidate;
|
|
1829
|
+
const recTag = def.arms.indexOf(recArm);
|
|
1830
|
+
const srcShape = lowerer.shapes.get(recArm.shapeId);
|
|
1831
|
+
if (!srcShape)
|
|
1832
|
+
throw new InternalCompilerError(`lowerer bug: spread of unknown shape ${recArm.shapeId}`);
|
|
1833
|
+
fenceAccessorSpreadSource(lowerer, prop, srcShape);
|
|
1834
|
+
if (srcShape.indexValue || shape.indexValue) {
|
|
1835
|
+
const fallback = dynSpreadLiteral(lowerer, expr, type);
|
|
1836
|
+
if (fallback)
|
|
1837
|
+
return fallback;
|
|
1838
|
+
lowerer.unsupported("SC1090", prop, "object spread involving index-signature shapes (overflow keys are runtime state — copy the fields you need explicitly)");
|
|
1839
|
+
}
|
|
1840
|
+
const laterNames = new Set();
|
|
1841
|
+
for (const later of expr.properties.nodes.slice(expr.properties.nodes.indexOf(prop) + 1)) {
|
|
1842
|
+
if (ts.isSpreadAssignment(later)) {
|
|
1843
|
+
if (conditionalSpreadOf(later.expression) || andSpreadOf(lowerer, later.expression))
|
|
1844
|
+
continue;
|
|
1845
|
+
const lt = laterSpreadType(lowerer, later.expression);
|
|
1846
|
+
if (lt?.kind === "record") {
|
|
1847
|
+
// A field the later source may lack defines nothing.
|
|
1848
|
+
for (const lf of lowerer.shapes.get(lt.shapeId)?.fields ?? [])
|
|
1849
|
+
if (!canLackField(lf.type))
|
|
1850
|
+
laterNames.add(lf.name);
|
|
1851
|
+
}
|
|
1735
1852
|
continue;
|
|
1736
|
-
const lt = laterSpreadType(lowerer, later.expression);
|
|
1737
|
-
if (lt?.kind === "record") {
|
|
1738
|
-
// A field the later source may lack defines nothing.
|
|
1739
|
-
for (const lf of lowerer.shapes.get(lt.shapeId)?.fields ?? [])
|
|
1740
|
-
if (!canLackField(lf.type))
|
|
1741
|
-
laterNames.add(lf.name);
|
|
1742
1853
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
laterNames.add(propNameText(lowerer, later.name));
|
|
1752
|
-
}
|
|
1753
|
-
}
|
|
1754
|
-
const srcRef = () => srcLowered ?? lowerer.lowerExpr(srcNode);
|
|
1755
|
-
const srcNarrowed = () => ({
|
|
1756
|
-
kind: "unionNarrow",
|
|
1757
|
-
unionId: srcType.unionId,
|
|
1758
|
-
tag: recTag,
|
|
1759
|
-
value: srcRef(),
|
|
1760
|
-
type: recArm,
|
|
1761
|
-
loc: locOf(prop),
|
|
1762
|
-
});
|
|
1763
|
-
// The source PROVEN present: the checked extraction `x!` lowers to
|
|
1764
|
-
// (narrowedArmHelper + checkedNarrowCall). A required target field
|
|
1765
|
-
// with no earlier contributor has no absent representation, so
|
|
1766
|
-
// `{ ...maybeRecord }` into it must find the record: the unit arm
|
|
1767
|
-
// throws the catchable TypeError instead of leaving the slot unset
|
|
1768
|
-
// (divergence 38's lying-assertion stance — the checker typed the
|
|
1769
|
-
// spread's fields optional, so only a cast or an unchecked indexed
|
|
1770
|
-
// read reaches this shape).
|
|
1771
|
-
const srcPresent = () => {
|
|
1772
|
-
const helper = lowerer.narrowedArmHelper(srcType.unionId, recArm, locOf(prop));
|
|
1773
|
-
return helper
|
|
1774
|
-
? lowerer.checkedNarrowCall(helper, srcRef(), recArm, locOf(prop))
|
|
1775
|
-
: srcNarrowed();
|
|
1776
|
-
};
|
|
1777
|
-
orderSegments.push({ kind: "spread", shapeId: recArm.shapeId, maybeAbsent: true });
|
|
1778
|
-
for (const f of srcShape.fields) {
|
|
1779
|
-
if (laterNames.has(f.name))
|
|
1780
|
-
continue;
|
|
1781
|
-
const targetType = fieldTypes.get(f.name);
|
|
1782
|
-
// No slot on the target shape: the copy DROPS the field
|
|
1783
|
-
// (divergence 36's stance, same as the plain-record spread).
|
|
1784
|
-
if (!targetType)
|
|
1785
|
-
continue;
|
|
1786
|
-
if (conditionalNames.has(f.name)) {
|
|
1787
|
-
const conditionalDyn = conditionalFallback();
|
|
1788
|
-
if (conditionalDyn)
|
|
1789
|
-
return conditionalDyn;
|
|
1790
|
-
lowerer.unsupported("SC1090", prop, `spread of '${f.name}' over an earlier conditional spread (the desugar keeps one entry per name — restructure so each name has one contributor)`);
|
|
1854
|
+
if (later.name &&
|
|
1855
|
+
(ts.isIdentifier(later.name) ||
|
|
1856
|
+
ts.isStringLiteral(later.name) ||
|
|
1857
|
+
ts.isNumericLiteral(later.name) ||
|
|
1858
|
+
(ts.isComputedPropertyName(later.name) &&
|
|
1859
|
+
literalComputedKey(lowerer, later.name) !== null))) {
|
|
1860
|
+
laterNames.add(propNameText(lowerer, later.name));
|
|
1861
|
+
}
|
|
1791
1862
|
}
|
|
1792
|
-
const
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
shapeId: recArm.shapeId,
|
|
1796
|
-
field: f.name,
|
|
1797
|
-
type: f.type,
|
|
1798
|
-
loc: locOf(prop),
|
|
1799
|
-
});
|
|
1800
|
-
let cond = {
|
|
1801
|
-
kind: "unionIsTag",
|
|
1863
|
+
const srcRef = () => srcLowered ?? lowerer.lowerExpr(srcNode);
|
|
1864
|
+
const srcNarrowed = () => ({
|
|
1865
|
+
kind: "unionNarrow",
|
|
1802
1866
|
unionId: srcType.unionId,
|
|
1803
1867
|
tag: recTag,
|
|
1804
|
-
negated: false,
|
|
1805
1868
|
value: srcRef(),
|
|
1806
|
-
type:
|
|
1869
|
+
type: recArm,
|
|
1807
1870
|
loc: locOf(prop),
|
|
1871
|
+
});
|
|
1872
|
+
// The source PROVEN present: the checked extraction `x!` lowers to
|
|
1873
|
+
// (narrowedArmHelper + checkedNarrowCall). A required target field
|
|
1874
|
+
// with no earlier contributor has no absent representation, so
|
|
1875
|
+
// `{ ...maybeRecord }` into it must find the record: the unit arm
|
|
1876
|
+
// throws the catchable TypeError instead of leaving the slot unset
|
|
1877
|
+
// (divergence 38's lying-assertion stance — the checker typed the
|
|
1878
|
+
// spread's fields optional, so only a cast or an unchecked indexed
|
|
1879
|
+
// read reaches this shape).
|
|
1880
|
+
const srcPresent = () => {
|
|
1881
|
+
const helper = lowerer.narrowedArmHelper(srcType.unionId, recArm, locOf(prop));
|
|
1882
|
+
return helper
|
|
1883
|
+
? lowerer.checkedNarrowCall(helper, srcRef(), recArm, locOf(prop))
|
|
1884
|
+
: srcNarrowed();
|
|
1808
1885
|
};
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1886
|
+
orderSegments.push({ kind: "spread", shapeId: recArm.shapeId, maybeAbsent: true });
|
|
1887
|
+
for (const f of srcShape.fields) {
|
|
1888
|
+
if (laterNames.has(f.name))
|
|
1889
|
+
continue;
|
|
1890
|
+
const targetType = fieldTypes.get(f.name);
|
|
1891
|
+
// No slot on the target shape: the static copy skips the field,
|
|
1892
|
+
// and the literal keeps it through a kept source view when the
|
|
1893
|
+
// program can observe it (keepWidthSpreads).
|
|
1894
|
+
if (!targetType) {
|
|
1895
|
+
widthDrops = true;
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
if (conditionalNames.has(f.name)) {
|
|
1899
|
+
const conditionalDyn = conditionalFallback();
|
|
1900
|
+
if (conditionalDyn)
|
|
1901
|
+
return conditionalDyn;
|
|
1902
|
+
lowerer.unsupported("SC1090", prop, `spread of '${f.name}' over an earlier conditional spread (the desugar keeps one entry per name — restructure so each name has one contributor)`);
|
|
1903
|
+
}
|
|
1904
|
+
const fRead = (present = false) => ({
|
|
1905
|
+
kind: "recordGet",
|
|
1906
|
+
obj: present ? srcPresent() : srcNarrowed(),
|
|
1825
1907
|
shapeId: recArm.shapeId,
|
|
1826
1908
|
field: f.name,
|
|
1909
|
+
type: f.type,
|
|
1910
|
+
loc: locOf(prop),
|
|
1911
|
+
});
|
|
1912
|
+
let cond = {
|
|
1913
|
+
kind: "unionIsTag",
|
|
1914
|
+
unionId: srcType.unionId,
|
|
1915
|
+
tag: recTag,
|
|
1916
|
+
negated: false,
|
|
1917
|
+
value: srcRef(),
|
|
1827
1918
|
type: BOOL,
|
|
1828
1919
|
loc: locOf(prop),
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
const canBeAbsent = f.type.kind === "union" && lowerer.armTag(f.type.unionId, UNDEFINED_T) >= 0;
|
|
1834
|
-
if (typeEquals(f.type, targetType)) {
|
|
1835
|
-
thenVal = fRead();
|
|
1836
|
-
if (canBeAbsent)
|
|
1837
|
-
cond = fieldPresent();
|
|
1838
|
-
}
|
|
1839
|
-
else if (f.type.kind === "union" &&
|
|
1840
|
-
lowerer.armTag(f.type.unionId, UNDEFINED_T) >= 0 &&
|
|
1841
|
-
typeEquals(lowerer.stripUndefinedArm(f.type), targetType)) {
|
|
1842
|
-
// Optional source field into a required target slot: present
|
|
1843
|
-
// means the source holds the record AND the field its value
|
|
1844
|
-
// arm — the spread-override completion, union-source form.
|
|
1845
|
-
const ftUndef = lowerer.armTag(f.type.unionId, UNDEFINED_T);
|
|
1846
|
-
cond = {
|
|
1920
|
+
};
|
|
1921
|
+
let thenVal;
|
|
1922
|
+
// A source field that can be absent copies only when present.
|
|
1923
|
+
const fieldPresent = () => ({
|
|
1847
1924
|
kind: "logical",
|
|
1848
1925
|
op: "&&",
|
|
1849
1926
|
left: cond,
|
|
1850
1927
|
right: {
|
|
1851
|
-
kind: "
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1928
|
+
kind: "recordHas",
|
|
1929
|
+
obj: {
|
|
1930
|
+
kind: "unionNarrow",
|
|
1931
|
+
unionId: srcType.unionId,
|
|
1932
|
+
tag: recTag,
|
|
1933
|
+
value: srcRef(),
|
|
1934
|
+
type: recArm,
|
|
1935
|
+
loc: locOf(prop),
|
|
1936
|
+
},
|
|
1937
|
+
shapeId: recArm.shapeId,
|
|
1938
|
+
field: f.name,
|
|
1856
1939
|
type: BOOL,
|
|
1857
1940
|
loc: locOf(prop),
|
|
1858
1941
|
},
|
|
1859
1942
|
type: BOOL,
|
|
1860
1943
|
loc: locOf(prop),
|
|
1861
|
-
};
|
|
1862
|
-
const
|
|
1863
|
-
if (
|
|
1864
|
-
|
|
1865
|
-
if (
|
|
1866
|
-
|
|
1867
|
-
throw new PoisonError();
|
|
1868
|
-
}
|
|
1869
|
-
thenVal = {
|
|
1870
|
-
kind: "call",
|
|
1871
|
-
callee: retag,
|
|
1872
|
-
args: [fRead()],
|
|
1873
|
-
type: targetType,
|
|
1874
|
-
loc: locOf(prop),
|
|
1875
|
-
};
|
|
1944
|
+
});
|
|
1945
|
+
const canBeAbsent = f.type.kind === "union" && lowerer.armTag(f.type.unionId, UNDEFINED_T) >= 0;
|
|
1946
|
+
if (typeEquals(f.type, targetType)) {
|
|
1947
|
+
thenVal = fRead();
|
|
1948
|
+
if (canBeAbsent)
|
|
1949
|
+
cond = fieldPresent();
|
|
1876
1950
|
}
|
|
1877
|
-
else if (
|
|
1878
|
-
|
|
1879
|
-
lowerer.
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1951
|
+
else if (f.type.kind === "union" &&
|
|
1952
|
+
lowerer.armTag(f.type.unionId, UNDEFINED_T) >= 0 &&
|
|
1953
|
+
typeEquals(lowerer.stripUndefinedArm(f.type), targetType)) {
|
|
1954
|
+
// Optional source field into a required target slot: present
|
|
1955
|
+
// means the source holds the record AND the field its value
|
|
1956
|
+
// arm — the spread-override completion, union-source form.
|
|
1957
|
+
const ftUndef = lowerer.armTag(f.type.unionId, UNDEFINED_T);
|
|
1958
|
+
cond = {
|
|
1959
|
+
kind: "logical",
|
|
1960
|
+
op: "&&",
|
|
1961
|
+
left: cond,
|
|
1962
|
+
right: {
|
|
1963
|
+
kind: "unionIsTag",
|
|
1964
|
+
unionId: f.type.unionId,
|
|
1965
|
+
tag: ftUndef,
|
|
1966
|
+
negated: true,
|
|
1967
|
+
value: fRead(),
|
|
1968
|
+
type: BOOL,
|
|
1969
|
+
loc: locOf(prop),
|
|
1970
|
+
},
|
|
1971
|
+
type: BOOL,
|
|
1886
1972
|
loc: locOf(prop),
|
|
1887
1973
|
};
|
|
1974
|
+
const ftDef = lowerer.unions.get(f.type.unionId);
|
|
1975
|
+
if (targetType.kind === "union") {
|
|
1976
|
+
const retag = lowerer.unionRetagHelper(f.type.unionId, targetType.unionId, locOf(prop));
|
|
1977
|
+
if (!retag) {
|
|
1978
|
+
lowerer.pushDiag(recordShapeMismatchDiag(lowerer.fmt(type), lowerer.fmt(recArm), locOf(prop), `spread field '${f.name}': '${lowerer.fmt(f.type)}' cannot re-tag into '${lowerer.fmt(targetType)}' behind the present-test`));
|
|
1979
|
+
throw new PoisonError();
|
|
1980
|
+
}
|
|
1981
|
+
thenVal = {
|
|
1982
|
+
kind: "call",
|
|
1983
|
+
callee: retag,
|
|
1984
|
+
args: [fRead()],
|
|
1985
|
+
type: targetType,
|
|
1986
|
+
loc: locOf(prop),
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
else if (ftDef &&
|
|
1990
|
+
ftDef.arms.length === 2 &&
|
|
1991
|
+
lowerer.armTag(f.type.unionId, targetType) >= 0) {
|
|
1992
|
+
thenVal = {
|
|
1993
|
+
kind: "unionNarrow",
|
|
1994
|
+
unionId: f.type.unionId,
|
|
1995
|
+
tag: lowerer.armTag(f.type.unionId, targetType),
|
|
1996
|
+
value: fRead(),
|
|
1997
|
+
type: targetType,
|
|
1998
|
+
loc: locOf(prop),
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
else {
|
|
2002
|
+
lowerer.pushDiag(recordShapeMismatchDiag(lowerer.fmt(type), lowerer.fmt(recArm), locOf(prop), `spread field '${f.name}': '${lowerer.fmt(f.type)}' cannot narrow into '${lowerer.fmt(targetType)}' behind the present-test`));
|
|
2003
|
+
throw new PoisonError();
|
|
2004
|
+
}
|
|
1888
2005
|
}
|
|
1889
2006
|
else {
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
// The width-lift fallback (arm wrap, re-tag, nested
|
|
1896
|
-
// reshape) — the same per-field rule the slot coercion
|
|
1897
|
-
// applies. Runs AFTER the optional-completion branch: a
|
|
1898
|
-
// present-test has its own semantics a re-tag's stranded
|
|
1899
|
-
// undefined trap must not shadow.
|
|
1900
|
-
const lift = lowerer.widthLiftPlan(f.type, targetType);
|
|
1901
|
-
if (!lift) {
|
|
1902
|
-
lowerer.pushDiag(recordShapeMismatchDiag(lowerer.fmt(type), lowerer.fmt(recArm), locOf(prop), `spread field '${f.name}': '${lowerer.fmt(f.type)}' does not lift into '${lowerer.fmt(targetType)}'`));
|
|
1903
|
-
throw new PoisonError();
|
|
1904
|
-
}
|
|
1905
|
-
thenVal = lowerer.applyWidthLift(lift, fRead(), targetType, locOf(prop));
|
|
1906
|
-
if (canBeAbsent)
|
|
1907
|
-
cond = fieldPresent();
|
|
1908
|
-
}
|
|
1909
|
-
const at = fields.findIndex((x) => x.name === f.name);
|
|
1910
|
-
const elseVal = at >= 0 ? fields[at].value : lowerer.absentFieldValue(targetType, locOf(prop));
|
|
1911
|
-
if (!elseVal) {
|
|
1912
|
-
if (canBeAbsent) {
|
|
1913
|
-
// The FIELD itself can be missing from a present source:
|
|
1914
|
-
// no extraction makes it exist.
|
|
1915
|
-
lowerer.unsupported("SC1090", prop, `object spread of '${lowerer.fmt(srcType)}' sources where '${f.name}' has no earlier contributor (the absent arm leaves the required field unset — spread defaults first: { ...defaults, ...overrides })`);
|
|
1916
|
-
}
|
|
1917
|
-
// No earlier contributor and the target slot cannot be absent:
|
|
1918
|
-
// the source must be here. Copy through the checked extraction
|
|
1919
|
-
// (the absent unit arm throws) — the same read the width lift
|
|
1920
|
-
// below wraps, so a lift still applies.
|
|
1921
|
-
let strict = fRead(true);
|
|
1922
|
-
if (!typeEquals(f.type, targetType)) {
|
|
2007
|
+
// The width-lift fallback (arm wrap, re-tag, nested
|
|
2008
|
+
// reshape) — the same per-field rule the slot coercion
|
|
2009
|
+
// applies. Runs AFTER the optional-completion branch: a
|
|
2010
|
+
// present-test has its own semantics a re-tag's stranded
|
|
2011
|
+
// undefined trap must not shadow.
|
|
1923
2012
|
const lift = lowerer.widthLiftPlan(f.type, targetType);
|
|
1924
2013
|
if (!lift) {
|
|
1925
2014
|
lowerer.pushDiag(recordShapeMismatchDiag(lowerer.fmt(type), lowerer.fmt(recArm), locOf(prop), `spread field '${f.name}': '${lowerer.fmt(f.type)}' does not lift into '${lowerer.fmt(targetType)}'`));
|
|
1926
2015
|
throw new PoisonError();
|
|
1927
2016
|
}
|
|
1928
|
-
|
|
2017
|
+
thenVal = lowerer.applyWidthLift(lift, fRead(), targetType, locOf(prop));
|
|
2018
|
+
if (canBeAbsent)
|
|
2019
|
+
cond = fieldPresent();
|
|
1929
2020
|
}
|
|
1930
|
-
fields.
|
|
1931
|
-
|
|
2021
|
+
const at = fields.findIndex((x) => x.name === f.name);
|
|
2022
|
+
const elseVal = at >= 0 ? fields[at].value : lowerer.absentFieldValue(targetType, locOf(prop));
|
|
2023
|
+
if (!elseVal) {
|
|
2024
|
+
if (canBeAbsent) {
|
|
2025
|
+
// The FIELD itself can be missing from a present source:
|
|
2026
|
+
// no extraction makes it exist.
|
|
2027
|
+
lowerer.unsupported("SC1090", prop, `object spread of '${lowerer.fmt(srcType)}' sources where '${f.name}' has no earlier contributor (the absent arm leaves the required field unset — spread defaults first: { ...defaults, ...overrides })`);
|
|
2028
|
+
}
|
|
2029
|
+
// No earlier contributor and the target slot cannot be absent:
|
|
2030
|
+
// the source must be here. Copy through the checked extraction
|
|
2031
|
+
// (the absent unit arm throws) — the same read the width lift
|
|
2032
|
+
// below wraps, so a lift still applies.
|
|
2033
|
+
let strict = fRead(true);
|
|
2034
|
+
if (!typeEquals(f.type, targetType)) {
|
|
2035
|
+
const lift = lowerer.widthLiftPlan(f.type, targetType);
|
|
2036
|
+
if (!lift) {
|
|
2037
|
+
lowerer.pushDiag(recordShapeMismatchDiag(lowerer.fmt(type), lowerer.fmt(recArm), locOf(prop), `spread field '${f.name}': '${lowerer.fmt(f.type)}' does not lift into '${lowerer.fmt(targetType)}'`));
|
|
2038
|
+
throw new PoisonError();
|
|
2039
|
+
}
|
|
2040
|
+
strict = lowerer.applyWidthLift(lift, strict, targetType, locOf(prop));
|
|
2041
|
+
}
|
|
2042
|
+
fields.push({ name: f.name, value: strict });
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
const merged = {
|
|
2046
|
+
kind: "ternary",
|
|
2047
|
+
cond,
|
|
2048
|
+
then: thenVal,
|
|
2049
|
+
else_: elseVal,
|
|
2050
|
+
type: targetType,
|
|
2051
|
+
loc: locOf(prop),
|
|
2052
|
+
};
|
|
2053
|
+
if (at >= 0)
|
|
2054
|
+
fields[at] = { name: f.name, value: merged };
|
|
2055
|
+
else
|
|
2056
|
+
fields.push({ name: f.name, value: merged });
|
|
1932
2057
|
}
|
|
1933
|
-
const merged = {
|
|
1934
|
-
kind: "ternary",
|
|
1935
|
-
cond,
|
|
1936
|
-
then: thenVal,
|
|
1937
|
-
else_: elseVal,
|
|
1938
|
-
type: targetType,
|
|
1939
|
-
loc: locOf(prop),
|
|
1940
|
-
};
|
|
1941
|
-
if (at >= 0)
|
|
1942
|
-
fields[at] = { name: f.name, value: merged };
|
|
1943
|
-
else
|
|
1944
|
-
fields.push({ name: f.name, value: merged });
|
|
1945
2058
|
}
|
|
1946
2059
|
continue;
|
|
1947
2060
|
}
|
|
@@ -2006,13 +2119,15 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
2006
2119
|
if (laterNames.has(f.name))
|
|
2007
2120
|
continue;
|
|
2008
2121
|
let targetType = fieldTypes.get(f.name);
|
|
2009
|
-
// A source field with NO slot on the target shape: the
|
|
2010
|
-
//
|
|
2011
|
-
//
|
|
2012
|
-
//
|
|
2013
|
-
|
|
2014
|
-
|
|
2122
|
+
// A source field with NO slot on the target shape: the static
|
|
2123
|
+
// copy skips it (the read is pure, so skipping evaluates nothing),
|
|
2124
|
+
// and the literal keeps it through a kept source view when the
|
|
2125
|
+
// program can observe the target (keepWidthSpreads).
|
|
2126
|
+
if (!targetType) {
|
|
2127
|
+
if (srcLowered.type.kind !== "dyn")
|
|
2128
|
+
widthDrops = true;
|
|
2015
2129
|
continue;
|
|
2130
|
+
}
|
|
2016
2131
|
// A runtime-optional source field (an unchecked indexed read the
|
|
2017
2132
|
// checker calls present) keeps its undefined arm in the copy, as a
|
|
2018
2133
|
// property initialized from that read would.
|
|
@@ -2251,7 +2366,8 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
2251
2366
|
lowerer.diags.slice(propDiagsBefore).some((d) => d.code === "SC9001")) {
|
|
2252
2367
|
throw err;
|
|
2253
2368
|
}
|
|
2254
|
-
|
|
2369
|
+
for (const d of lowerer.diags.splice(propDiagsBefore))
|
|
2370
|
+
lowerer.runtimeFences.push(d);
|
|
2255
2371
|
droppedNames.add(name);
|
|
2256
2372
|
continue;
|
|
2257
2373
|
}
|
|
@@ -2297,6 +2413,7 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
2297
2413
|
fields.splice(at, 1);
|
|
2298
2414
|
fields.push({ name, value });
|
|
2299
2415
|
orderSegments.push({ kind: "key", name, definite: true });
|
|
2416
|
+
widthSegments.push({ kind: "key", name });
|
|
2300
2417
|
}
|
|
2301
2418
|
// Optional fields may be omitted: the field holds its absent state.
|
|
2302
2419
|
// tsc rejects omission of required fields before lowering.
|
|
@@ -2323,10 +2440,46 @@ export function lowerObjectLiteral(lowerer, expr, expected) {
|
|
|
2323
2440
|
}
|
|
2324
2441
|
}
|
|
2325
2442
|
const result = lowerer.keyOrder.literal({ kind: "recordLit", fields, type, loc }, orderSegments);
|
|
2443
|
+
if (!widthBlocked &&
|
|
2444
|
+
spreadStmts.length > 0 &&
|
|
2445
|
+
type.kind === "record" &&
|
|
2446
|
+
recordMayKeepSource(lowerer, type))
|
|
2447
|
+
lowerer.keyOrder.width(result, widthSegments, widthDrops || widthDynSource);
|
|
2326
2448
|
return spreadStmts.length === 0
|
|
2327
2449
|
? result
|
|
2328
2450
|
: { kind: "seqExpr", stmts: spreadStmts, result, type, loc };
|
|
2329
2451
|
}
|
|
2452
|
+
/** A spread source whose stored union holds several record arms while the
|
|
2453
|
+
* checker narrowed this site to fewer (`if (b?.type === "tool") ({ ...b })`
|
|
2454
|
+
* on an element read, or a type predicate's arm): extract the narrowed
|
|
2455
|
+
* value through the CHECKED narrowing, so every arm the checker excludes,
|
|
2456
|
+
* including a hidden absence arm, throws the catchable TypeError instead of
|
|
2457
|
+
* being copied. Null when the stored union has at most one record arm (the
|
|
2458
|
+
* present-test desugar owns that case), when the site type is not a
|
|
2459
|
+
* narrowing of the stored union, or in JavaScript files. */
|
|
2460
|
+
function checkedSpreadSource(lowerer, node, stored) {
|
|
2461
|
+
if (stored.type.kind !== "union")
|
|
2462
|
+
return null;
|
|
2463
|
+
if (isJsSourceFile(ts.getSourceFileOfNode(node)))
|
|
2464
|
+
return null;
|
|
2465
|
+
const def = lowerer.unions.get(stored.type.unionId);
|
|
2466
|
+
if (!def || def.arms.filter((arm) => arm.kind === "record").length < 2)
|
|
2467
|
+
return null;
|
|
2468
|
+
const site = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
2469
|
+
if (!site || typeEquals(site, stored.type))
|
|
2470
|
+
return null;
|
|
2471
|
+
const loc = stored.loc;
|
|
2472
|
+
if (site.kind === "record") {
|
|
2473
|
+
if (lowerer.armTag(stored.type.unionId, site) < 0)
|
|
2474
|
+
return null;
|
|
2475
|
+
const helper = lowerer.narrowedArmHelper(stored.type.unionId, site, loc);
|
|
2476
|
+
return helper ? lowerer.checkedNarrowCall(helper, stored, site, loc) : null;
|
|
2477
|
+
}
|
|
2478
|
+
if (site.kind !== "union")
|
|
2479
|
+
return null;
|
|
2480
|
+
const helper = lowerer.narrowedRetagHelper(node, stored.type.unionId, site.unionId, loc);
|
|
2481
|
+
return helper ? { kind: "call", callee: helper, args: [stored], type: site, loc } : null;
|
|
2482
|
+
}
|
|
2330
2483
|
/** The field type is an array, or a union with exactly one array arm. */
|
|
2331
2484
|
function singleArrayArm(lowerer, type) {
|
|
2332
2485
|
if (type.kind === "array")
|
|
@@ -2342,6 +2495,269 @@ function isEmptyArrayLiteral(node) {
|
|
|
2342
2495
|
inner = inner.expression;
|
|
2343
2496
|
return ts.isArrayLiteralExpression(inner) && inner.elements.nodes.length === 0;
|
|
2344
2497
|
}
|
|
2498
|
+
/** `{ ...u, k: v }` where the spread source `u` is a union of records (and
|
|
2499
|
+
* unit arms): TypeScript types the literal as the union of one spread per
|
|
2500
|
+
* source arm, so it is built that way. The source evaluates once into a
|
|
2501
|
+
* hidden local; a tag dispatch builds the running arm's literal with that
|
|
2502
|
+
* arm as the source, at the destination arm chosen for it:
|
|
2503
|
+
* 1. the arms the discriminant's last writer selects (an explicit
|
|
2504
|
+
* property, or the source arm when it carries the field);
|
|
2505
|
+
* 2. among those, the source arm itself (`{ ...command, id }`);
|
|
2506
|
+
* 3. else the one arm whose keys are exactly the keys the literal writes.
|
|
2507
|
+
* Every key a contributor may write must be a field of the destination:
|
|
2508
|
+
* the record path's width copy would drop the others, and Node keeps them.
|
|
2509
|
+
* So a genuine merge (`{ ...http, ...patch }` where `patch` may carry a
|
|
2510
|
+
* stdio-only key) stays refused. A stored source the checker narrowed
|
|
2511
|
+
* converts through the checked re-tag first, so an excluded arm (a hidden
|
|
2512
|
+
* absence arm included) throws the catchable TypeError. Null when the
|
|
2513
|
+
* literal is not this shape, before anything is lowered except the
|
|
2514
|
+
* source; the caller keeps its refusal. */
|
|
2515
|
+
function lowerDistributedUnionSpread(lowerer, expr, mapped) {
|
|
2516
|
+
if (isJsSourceFile(ts.getSourceFileOfNode(expr)))
|
|
2517
|
+
return null;
|
|
2518
|
+
if (mapped?.kind !== "union")
|
|
2519
|
+
return null;
|
|
2520
|
+
const target = lowerer.unions.get(mapped.unionId);
|
|
2521
|
+
if (!target)
|
|
2522
|
+
return null;
|
|
2523
|
+
const props = expr.properties.nodes;
|
|
2524
|
+
// Exactly one distributed source: a plain spread whose checker type maps
|
|
2525
|
+
// to a union of records and unit arms. Several would be a product.
|
|
2526
|
+
let spreadIndex = -1;
|
|
2527
|
+
let srcNode = null;
|
|
2528
|
+
for (let i = 0; i < props.length; i++) {
|
|
2529
|
+
const prop = props[i];
|
|
2530
|
+
if (!ts.isSpreadAssignment(prop))
|
|
2531
|
+
continue;
|
|
2532
|
+
if (conditionalSpreadOf(prop.expression) !== null ||
|
|
2533
|
+
andSpreadOf(lowerer, prop.expression) !== null ||
|
|
2534
|
+
conditionalRecordSpreadOf(lowerer, prop.expression) !== null)
|
|
2535
|
+
continue;
|
|
2536
|
+
let node = prop.expression;
|
|
2537
|
+
while (ts.isParenthesizedExpression(node))
|
|
2538
|
+
node = node.expression;
|
|
2539
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(node))?.kind !== "union")
|
|
2540
|
+
continue;
|
|
2541
|
+
if (srcNode !== null)
|
|
2542
|
+
return null;
|
|
2543
|
+
spreadIndex = i;
|
|
2544
|
+
srcNode = node;
|
|
2545
|
+
}
|
|
2546
|
+
if (srcNode === null)
|
|
2547
|
+
return null;
|
|
2548
|
+
const site = srcNode;
|
|
2549
|
+
// The source evaluates before the dispatch, so everything written before
|
|
2550
|
+
// it must be free of effects. When the source itself may have effects, an
|
|
2551
|
+
// earlier property may also not read a value they could change: those
|
|
2552
|
+
// properties must be constants.
|
|
2553
|
+
const sourcePure = pureKeyExpr(lowerer, site);
|
|
2554
|
+
for (const prop of props.slice(0, spreadIndex)) {
|
|
2555
|
+
if (sourcePure && ts.isShorthandPropertyAssignment(prop))
|
|
2556
|
+
continue;
|
|
2557
|
+
if (ts.isPropertyAssignment(prop) &&
|
|
2558
|
+
(sourcePure
|
|
2559
|
+
? pureKeyExpr(lowerer, prop.initializer)
|
|
2560
|
+
: constantInitializer(lowerer, prop.initializer)))
|
|
2561
|
+
continue;
|
|
2562
|
+
return null;
|
|
2563
|
+
}
|
|
2564
|
+
const siteType = lowerer.mapTypeOf(lowerer.typeOf(site));
|
|
2565
|
+
if (siteType?.kind !== "union")
|
|
2566
|
+
return null;
|
|
2567
|
+
const siteDef = lowerer.unions.get(siteType.unionId);
|
|
2568
|
+
if (!siteDef || !siteDef.arms.every((arm) => arm.kind === "record" || isUnitType(arm)))
|
|
2569
|
+
return null;
|
|
2570
|
+
const discField = target.discriminant?.field;
|
|
2571
|
+
// The discriminant values the literal's LAST writer of that field gives
|
|
2572
|
+
// this source arm; null when unknown.
|
|
2573
|
+
const discriminantOf = (tag, arm) => {
|
|
2574
|
+
if (discField === undefined)
|
|
2575
|
+
return null;
|
|
2576
|
+
for (let i = props.length - 1; i >= 0; i--) {
|
|
2577
|
+
const prop = props[i];
|
|
2578
|
+
if (i === spreadIndex) {
|
|
2579
|
+
if (arm.kind !== "record")
|
|
2580
|
+
continue;
|
|
2581
|
+
if (!lowerer.shapes.get(arm.shapeId)?.fields.some((f) => f.name === discField))
|
|
2582
|
+
continue;
|
|
2583
|
+
const own = siteDef.discriminant;
|
|
2584
|
+
return own?.field === discField
|
|
2585
|
+
? (own.cases.find((c) => c.tag === tag)?.values ?? null)
|
|
2586
|
+
: null;
|
|
2587
|
+
}
|
|
2588
|
+
if (ts.isSpreadAssignment(prop))
|
|
2589
|
+
return null;
|
|
2590
|
+
if ((ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop)) &&
|
|
2591
|
+
propNameText(lowerer, prop.name) === discField)
|
|
2592
|
+
return ts.isPropertyAssignment(prop)
|
|
2593
|
+
? literalValues(lowerer.typeOf(prop.initializer))
|
|
2594
|
+
: literalValues(lowerer.typeOf(prop.name));
|
|
2595
|
+
}
|
|
2596
|
+
return null;
|
|
2597
|
+
};
|
|
2598
|
+
// Every key some contributor may write for this source arm; null when a
|
|
2599
|
+
// contributor has no fixed key set (an index signature, a non-record).
|
|
2600
|
+
const writtenKeys = (arm) => {
|
|
2601
|
+
const names = new Set();
|
|
2602
|
+
for (let i = 0; i < props.length; i++) {
|
|
2603
|
+
const prop = props[i];
|
|
2604
|
+
if (ts.isSpreadAssignment(prop)) {
|
|
2605
|
+
let node = prop.expression;
|
|
2606
|
+
while (ts.isParenthesizedExpression(node))
|
|
2607
|
+
node = node.expression;
|
|
2608
|
+
const t = i === spreadIndex ? arm : lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
2609
|
+
if (t !== null && isUnitType(t))
|
|
2610
|
+
continue;
|
|
2611
|
+
if (t?.kind !== "record")
|
|
2612
|
+
return null;
|
|
2613
|
+
const shape = lowerer.shapes.get(t.shapeId);
|
|
2614
|
+
if (!shape || shape.indexValue || shape.tuple)
|
|
2615
|
+
return null;
|
|
2616
|
+
for (const f of shape.fields)
|
|
2617
|
+
names.add(f.name);
|
|
2618
|
+
}
|
|
2619
|
+
else if (ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop)) {
|
|
2620
|
+
names.add(propNameText(lowerer, prop.name));
|
|
2621
|
+
}
|
|
2622
|
+
else {
|
|
2623
|
+
return null;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
return names;
|
|
2627
|
+
};
|
|
2628
|
+
const destinationOf = (tag, arm) => {
|
|
2629
|
+
const keys = writtenKeys(arm);
|
|
2630
|
+
if (keys === null)
|
|
2631
|
+
return null;
|
|
2632
|
+
let candidates = target.arms
|
|
2633
|
+
.map((a, t) => ({ a, t }))
|
|
2634
|
+
.filter((c) => c.a.kind === "record")
|
|
2635
|
+
.filter((c) => {
|
|
2636
|
+
const fields = lowerer.shapes.get(c.a.shapeId).fields;
|
|
2637
|
+
return [...keys].every((k) => fields.some((f) => f.name === k));
|
|
2638
|
+
});
|
|
2639
|
+
const values = discriminantOf(tag, arm);
|
|
2640
|
+
if (values && values.length > 0 && target.discriminant) {
|
|
2641
|
+
const cases = target.discriminant.cases;
|
|
2642
|
+
candidates = candidates.filter((c) => (cases.find((k) => k.tag === c.t)?.values ?? []).some((v) => values.includes(v)));
|
|
2643
|
+
}
|
|
2644
|
+
if (candidates.length === 1)
|
|
2645
|
+
return candidates[0].a;
|
|
2646
|
+
if (arm.kind === "record") {
|
|
2647
|
+
const same = candidates.find((c) => c.a.shapeId === arm.shapeId);
|
|
2648
|
+
if (same)
|
|
2649
|
+
return same.a;
|
|
2650
|
+
}
|
|
2651
|
+
const exactKeys = candidates.filter((c) => lowerer.shapes.get(c.a.shapeId).fields.length === keys.size);
|
|
2652
|
+
return exactKeys.length === 1 ? exactKeys[0].a : null;
|
|
2653
|
+
};
|
|
2654
|
+
// Plan every arm before lowering anything.
|
|
2655
|
+
const plan = [];
|
|
2656
|
+
for (let tag = 0; tag < siteDef.arms.length; tag++) {
|
|
2657
|
+
const arm = siteDef.arms[tag];
|
|
2658
|
+
const destination = destinationOf(tag, arm);
|
|
2659
|
+
if (destination === null)
|
|
2660
|
+
return null;
|
|
2661
|
+
plan.push({ tag, arm, destination });
|
|
2662
|
+
}
|
|
2663
|
+
const loc = locOf(expr);
|
|
2664
|
+
let source = lowerer.lowerExpr(site);
|
|
2665
|
+
if (source.type.kind === "union" && !typeEquals(source.type, siteType)) {
|
|
2666
|
+
const helper = lowerer.narrowedRetagHelper(site, source.type.unionId, siteType.unionId, source.loc);
|
|
2667
|
+
if (helper)
|
|
2668
|
+
source = { kind: "call", callee: helper, args: [source], type: siteType, loc: source.loc };
|
|
2669
|
+
}
|
|
2670
|
+
if (!typeEquals(source.type, siteType))
|
|
2671
|
+
return null;
|
|
2672
|
+
const saved = lowerer.declareHiddenLocal("%spreadArms", siteType);
|
|
2673
|
+
const ref = varRef(saved.id, siteType, loc);
|
|
2674
|
+
let result = null;
|
|
2675
|
+
for (let i = plan.length - 1; i >= 0; i--) {
|
|
2676
|
+
const { tag, arm, destination } = plan[i];
|
|
2677
|
+
const armValue = arm.kind === "record"
|
|
2678
|
+
? { kind: "unionNarrow", value: ref, unionId: siteType.unionId, tag, type: arm, loc }
|
|
2679
|
+
: {
|
|
2680
|
+
kind: "recordLit",
|
|
2681
|
+
fields: [],
|
|
2682
|
+
type: { kind: "record", shapeId: lowerer.shapes.intern([]) },
|
|
2683
|
+
loc,
|
|
2684
|
+
};
|
|
2685
|
+
lowerer.spreadArmOverrides.set(site, armValue);
|
|
2686
|
+
let built;
|
|
2687
|
+
try {
|
|
2688
|
+
built = lowerObjectLiteral(lowerer, expr, destination, true);
|
|
2689
|
+
}
|
|
2690
|
+
finally {
|
|
2691
|
+
lowerer.spreadArmOverrides.delete(site);
|
|
2692
|
+
}
|
|
2693
|
+
const wrapped = lowerer.coerceToExpected(built, mapped);
|
|
2694
|
+
if (!typeEquals(wrapped.type, mapped))
|
|
2695
|
+
return null;
|
|
2696
|
+
result =
|
|
2697
|
+
result === null
|
|
2698
|
+
? wrapped
|
|
2699
|
+
: {
|
|
2700
|
+
kind: "ternary",
|
|
2701
|
+
cond: {
|
|
2702
|
+
kind: "unionIsTag",
|
|
2703
|
+
value: ref,
|
|
2704
|
+
unionId: siteType.unionId,
|
|
2705
|
+
tag,
|
|
2706
|
+
negated: false,
|
|
2707
|
+
type: BOOL,
|
|
2708
|
+
loc,
|
|
2709
|
+
},
|
|
2710
|
+
then: wrapped,
|
|
2711
|
+
else_: result,
|
|
2712
|
+
type: mapped,
|
|
2713
|
+
loc,
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
if (result === null)
|
|
2717
|
+
return null;
|
|
2718
|
+
return {
|
|
2719
|
+
kind: "seqExpr",
|
|
2720
|
+
stmts: [{ kind: "varDecl", localId: saved.id, init: source, loc }],
|
|
2721
|
+
result,
|
|
2722
|
+
type: mapped,
|
|
2723
|
+
loc,
|
|
2724
|
+
};
|
|
2725
|
+
}
|
|
2726
|
+
/** `{ ...a, ...b }` over union-typed sources that lowerDistributedUnionSpread
|
|
2727
|
+
* declined: no single destination arm holds every key the contributors may
|
|
2728
|
+
* write (`provider-composer`'s two all-optional compat unions, an aggregate
|
|
2729
|
+
* config merged from a http|stdio union plus a patch naming both). Node
|
|
2730
|
+
* builds ONE plain object: each source's own enumerable keys copy in source
|
|
2731
|
+
* order (later writers win), then the explicit fields write in their own
|
|
2732
|
+
* positions. Build exactly that object — the checked-dynamic literal — and
|
|
2733
|
+
* validate it into the declared union at the slot. The value keeps its
|
|
2734
|
+
* runtime keys (reflection, JSON, and inspection see what Node sees); a
|
|
2735
|
+
* value the union cannot hold throws the catchable TypeError at the
|
|
2736
|
+
* conversion instead of being reinterpreted as one arm.
|
|
2737
|
+
*
|
|
2738
|
+
* Null when the shape is not the SC2003 one (no union-typed spread source),
|
|
2739
|
+
* when the build must not demote (inside a capture buffer, or under
|
|
2740
|
+
* `--tier=static-only`, which keeps today's refusal), or when the union has
|
|
2741
|
+
* no checked extraction. The caller then keeps its refusal. */
|
|
2742
|
+
function lowerUnionSpreadMergeDyn(lowerer, expr, target) {
|
|
2743
|
+
if (isJsSourceFile(ts.getSourceFileOfNode(expr)))
|
|
2744
|
+
return null;
|
|
2745
|
+
const spreadsUnion = expr.properties.nodes.some((prop) => {
|
|
2746
|
+
if (!ts.isSpreadAssignment(prop))
|
|
2747
|
+
return false;
|
|
2748
|
+
let node = prop.expression;
|
|
2749
|
+
while (ts.isParenthesizedExpression(node))
|
|
2750
|
+
node = node.expression;
|
|
2751
|
+
return lowerer.mapTypeOf(lowerer.typeOf(node))?.kind === "union";
|
|
2752
|
+
});
|
|
2753
|
+
if (!spreadsUnion)
|
|
2754
|
+
return null;
|
|
2755
|
+
if (lowerer.tierMode !== "auto" || lowerer.diagSink !== null)
|
|
2756
|
+
return null;
|
|
2757
|
+
if (!canDynCheckTo(target, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
2758
|
+
return null;
|
|
2759
|
+
return lowerer.coerceToExpected(lowerDynObjectLiteral(lowerer, expr), target);
|
|
2760
|
+
}
|
|
2345
2761
|
/** A union of plain records can preserve its existing variant while
|
|
2346
2762
|
* replacing shared fields. Dispatch before constructing the copy: only
|
|
2347
2763
|
* the selected arm evaluates overrides, and recordClone snapshots fields
|
|
@@ -2446,6 +2862,15 @@ function lowerUnionRecordClone(lowerer, expr) {
|
|
|
2446
2862
|
};
|
|
2447
2863
|
}
|
|
2448
2864
|
}
|
|
2865
|
+
// Any other source (a capture, a runtime-optional binding, a member
|
|
2866
|
+
// read) converts through the same checked re-tag: the arms the site's
|
|
2867
|
+
// checker type excludes, a hidden absence arm included, throw the
|
|
2868
|
+
// catchable TypeError instead of being cloned.
|
|
2869
|
+
if (!typeEquals(source.type, sourceType) && source.type.kind === "union") {
|
|
2870
|
+
const helper = lowerer.narrowedRetagHelper(spread.expression, source.type.unionId, sourceType.unionId, source.loc);
|
|
2871
|
+
if (helper)
|
|
2872
|
+
source = { kind: "call", callee: helper, args: [source], type: sourceType, loc: source.loc };
|
|
2873
|
+
}
|
|
2449
2874
|
if (!typeEquals(source.type, sourceType)) {
|
|
2450
2875
|
lowerer.unsupported("SC1090", spread, "a union record clone whose stored source still includes absence");
|
|
2451
2876
|
}
|
|
@@ -2632,15 +3057,50 @@ function lowerConditionalRecordSpread(lowerer, spread, loc) {
|
|
|
2632
3057
|
loc,
|
|
2633
3058
|
};
|
|
2634
3059
|
}
|
|
3060
|
+
/** A spread's source expression with parentheses stripped, seeing through
|
|
3061
|
+
* an empty-object default: `...(x ?? {})` and `...(x || {})` spread exactly
|
|
3062
|
+
* what `...x` spreads (a nullish or other falsy value is a primitive with
|
|
3063
|
+
* no own keys, and x evaluates once either way). Only where `x` is a plain
|
|
3064
|
+
* record or a record-or-unit union, which the field copy and the
|
|
3065
|
+
* optional-spread desugar handle; index-signature and other sources keep
|
|
3066
|
+
* their paths. */
|
|
3067
|
+
function spreadSourceNode(lowerer, expr) {
|
|
3068
|
+
let e = expr;
|
|
3069
|
+
while (ts.isParenthesizedExpression(e))
|
|
3070
|
+
e = e.expression;
|
|
3071
|
+
if (!ts.isBinaryExpression(e) ||
|
|
3072
|
+
(e.operatorToken.kind !== ts.SyntaxKind.QuestionQuestionToken &&
|
|
3073
|
+
e.operatorToken.kind !== ts.SyntaxKind.BarBarToken))
|
|
3074
|
+
return e;
|
|
3075
|
+
let right = e.right;
|
|
3076
|
+
while (ts.isParenthesizedExpression(right))
|
|
3077
|
+
right = right.expression;
|
|
3078
|
+
if (!ts.isObjectLiteralExpression(right) || right.properties.nodes.length !== 0)
|
|
3079
|
+
return e;
|
|
3080
|
+
let left = e.left;
|
|
3081
|
+
while (ts.isParenthesizedExpression(left))
|
|
3082
|
+
left = left.expression;
|
|
3083
|
+
const plainRecord = (t) => t?.kind === "record" && lowerer.shapes.get(t.shapeId)?.indexValue === undefined;
|
|
3084
|
+
const source = lowerer.mapTypeOf(lowerer.typeOf(left));
|
|
3085
|
+
if (plainRecord(source ?? undefined))
|
|
3086
|
+
return left;
|
|
3087
|
+
if (source?.kind === "union") {
|
|
3088
|
+
const arms = lowerer.unions.get(source.unionId)?.arms ?? [];
|
|
3089
|
+
const records = arms.filter((arm) => arm.kind === "record");
|
|
3090
|
+
if (records.length === 1 &&
|
|
3091
|
+
plainRecord(records[0]) &&
|
|
3092
|
+
arms.every((arm) => arm.kind === "record" || isUnitType(arm)))
|
|
3093
|
+
return left;
|
|
3094
|
+
}
|
|
3095
|
+
return e;
|
|
3096
|
+
}
|
|
2635
3097
|
/** A spread source the record desugar cannot enumerate: an untyped
|
|
2636
3098
|
* (`unknown`) value, or one whose shape carries an index signature
|
|
2637
3099
|
* (`Record<string, unknown>`, `{ [key: string]: T }`) so its keys are
|
|
2638
3100
|
* runtime state. Node copies own enumerable keys in insertion order, which
|
|
2639
3101
|
* the checked-dynamic object reproduces. */
|
|
2640
3102
|
function dynSpreadSource(lowerer, node) {
|
|
2641
|
-
|
|
2642
|
-
while (ts.isParenthesizedExpression(e))
|
|
2643
|
-
e = e.expression;
|
|
3103
|
+
const e = spreadSourceNode(lowerer, node);
|
|
2644
3104
|
if ((lowerer.typeOf(e).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
|
|
2645
3105
|
return true;
|
|
2646
3106
|
const indexed = (t) => {
|
|
@@ -2770,6 +3230,28 @@ export function conditionalSpreadOf(expr) {
|
|
|
2770
3230
|
}
|
|
2771
3231
|
return { cond: e.condition, props, whenTrue: trueCarries };
|
|
2772
3232
|
}
|
|
3233
|
+
/** The record arms of a union spread source of the declared-shape merge,
|
|
3234
|
+
* or null unless every arm is a non-tuple record or the null/undefined
|
|
3235
|
+
* unit and at least one arm is a record. Unit arms contribute nothing:
|
|
3236
|
+
* CopyDataProperties skips nullish sources. */
|
|
3237
|
+
function declaredMergeUnionArms(lowerer, unionId) {
|
|
3238
|
+
const def = lowerer.unions.get(unionId);
|
|
3239
|
+
if (!def)
|
|
3240
|
+
return null;
|
|
3241
|
+
const arms = [];
|
|
3242
|
+
for (let tag = 0; tag < def.arms.length; tag++) {
|
|
3243
|
+
const arm = def.arms[tag];
|
|
3244
|
+
if (arm.kind === "undefinedT" || arm.kind === "nullT")
|
|
3245
|
+
continue;
|
|
3246
|
+
if (arm.kind !== "record")
|
|
3247
|
+
return null;
|
|
3248
|
+
const armShape = lowerer.shapes.get(arm.shapeId);
|
|
3249
|
+
if (!armShape || armShape.tuple)
|
|
3250
|
+
return null;
|
|
3251
|
+
arms.push({ tag, shapeId: arm.shapeId, shape: armShape });
|
|
3252
|
+
}
|
|
3253
|
+
return arms.length > 0 ? arms : null;
|
|
3254
|
+
}
|
|
2773
3255
|
/** `{ ...idx, ...idx2 }` typed a DECLARED shape (no index signature) — the
|
|
2774
3256
|
* defaults-merge idiom over runtime-keyed sources (`{ ...fromEntries(a),
|
|
2775
3257
|
* ...fromEntries(b) }` typed AppConfig). Lowers to ONE interned helper
|
|
@@ -2785,7 +3267,12 @@ export function conditionalSpreadOf(expr) {
|
|
|
2785
3267
|
* untyped copy would store the lie) — and a key naming NO declared field
|
|
2786
3268
|
* is DROPPED (the shape cannot represent it; Node keeps it invisibly —
|
|
2787
3269
|
* divergence 68). Later contributors overwrite earlier ones
|
|
2788
|
-
* (last-write-wins). Fixed, hybrid, and pure index records may contribute
|
|
3270
|
+
* (last-write-wins). Fixed, hybrid, and pure index records may contribute,
|
|
3271
|
+
* and so may a union of those records with the null/undefined unit: each
|
|
3272
|
+
* record arm copies through its own shape's helper behind its tag test,
|
|
3273
|
+
* a unit arm copies nothing (CopyDataProperties skips nullish sources),
|
|
3274
|
+
* and the union is held in a hidden local, so it still evaluates once, in
|
|
3275
|
+
* order. */
|
|
2789
3276
|
function lowerDeclaredSpreadMerge(lowerer, expr, type, shape, loc) {
|
|
2790
3277
|
const srcs = [];
|
|
2791
3278
|
for (const prop of expr.properties.nodes) {
|
|
@@ -2795,6 +3282,15 @@ function lowerDeclaredSpreadMerge(lowerer, expr, type, shape, loc) {
|
|
|
2795
3282
|
srcs.push({ value, shapeId: "dyn" });
|
|
2796
3283
|
continue;
|
|
2797
3284
|
}
|
|
3285
|
+
if (value.type.kind === "union") {
|
|
3286
|
+
const arms = declaredMergeUnionArms(lowerer, value.type.unionId);
|
|
3287
|
+
if (arms) {
|
|
3288
|
+
for (const arm of arms)
|
|
3289
|
+
fenceAccessorSpreadSource(lowerer, prop, arm.shape);
|
|
3290
|
+
srcs.push({ value, shapeId: "union", arms });
|
|
3291
|
+
continue;
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
2798
3294
|
const srcShape = value.type.kind === "record" ? lowerer.shapes.get(value.type.shapeId) : undefined;
|
|
2799
3295
|
if (value.type.kind !== "record" || !srcShape || srcShape.tuple) {
|
|
2800
3296
|
lowerer.unsupported("SC1090", prop, `object spread of '${lowerer.fmt(value.type)}' into '${lowerer.fmt(type)}' (only records spread into a declared shape)`);
|
|
@@ -2932,12 +3428,11 @@ function lowerDeclaredSpreadMerge(lowerer, expr, type, shape, loc) {
|
|
|
2932
3428
|
loc,
|
|
2933
3429
|
},
|
|
2934
3430
|
];
|
|
2935
|
-
|
|
3431
|
+
const mergeHelper = (source, sourceType) => {
|
|
2936
3432
|
const key = `declmerge-source:${type.shapeId}:${source.shapeId}`;
|
|
2937
3433
|
let helper = lowerer.valueHelpers.get(key);
|
|
2938
3434
|
if (!helper) {
|
|
2939
3435
|
helper = keyedHelperName(lowerer, "%rec.declmerge", key);
|
|
2940
|
-
const sourceType = source.value.type;
|
|
2941
3436
|
const destination = varRef("out.0", type, loc);
|
|
2942
3437
|
const receiver = varRef("source.0", sourceType, loc);
|
|
2943
3438
|
const locals = [
|
|
@@ -3112,6 +3607,59 @@ function lowerDeclaredSpreadMerge(lowerer, expr, type, shape, loc) {
|
|
|
3112
3607
|
// leave an entry that a later literal could reuse without a body.
|
|
3113
3608
|
lowerer.valueHelpers.set(key, helper);
|
|
3114
3609
|
}
|
|
3610
|
+
return helper;
|
|
3611
|
+
};
|
|
3612
|
+
for (const source of srcs) {
|
|
3613
|
+
if (source.arms && source.value.type.kind === "union") {
|
|
3614
|
+
// Evaluate the union once, then copy the running arm's own keys.
|
|
3615
|
+
const unionType = source.value.type;
|
|
3616
|
+
const held = lowerer.declareHiddenLocal("%declMergeSource", unionType);
|
|
3617
|
+
const heldRef = varRef(held.id, unionType, loc);
|
|
3618
|
+
stmts.push({ kind: "varDecl", localId: held.id, init: source.value, loc });
|
|
3619
|
+
for (const arm of source.arms) {
|
|
3620
|
+
const armType = { kind: "record", shapeId: arm.shapeId };
|
|
3621
|
+
const helper = mergeHelper({ value: heldRef, shapeId: arm.shapeId, shape: arm.shape }, armType);
|
|
3622
|
+
stmts.push({
|
|
3623
|
+
kind: "if",
|
|
3624
|
+
cond: {
|
|
3625
|
+
kind: "unionIsTag",
|
|
3626
|
+
unionId: unionType.unionId,
|
|
3627
|
+
tag: arm.tag,
|
|
3628
|
+
negated: false,
|
|
3629
|
+
value: heldRef,
|
|
3630
|
+
type: BOOL,
|
|
3631
|
+
loc,
|
|
3632
|
+
},
|
|
3633
|
+
then: [
|
|
3634
|
+
{
|
|
3635
|
+
kind: "exprStmt",
|
|
3636
|
+
expr: {
|
|
3637
|
+
kind: "call",
|
|
3638
|
+
callee: helper,
|
|
3639
|
+
args: [
|
|
3640
|
+
outRef,
|
|
3641
|
+
{
|
|
3642
|
+
kind: "unionNarrow",
|
|
3643
|
+
unionId: unionType.unionId,
|
|
3644
|
+
tag: arm.tag,
|
|
3645
|
+
value: heldRef,
|
|
3646
|
+
type: armType,
|
|
3647
|
+
loc,
|
|
3648
|
+
},
|
|
3649
|
+
],
|
|
3650
|
+
type,
|
|
3651
|
+
loc,
|
|
3652
|
+
},
|
|
3653
|
+
loc,
|
|
3654
|
+
},
|
|
3655
|
+
],
|
|
3656
|
+
else_: null,
|
|
3657
|
+
loc,
|
|
3658
|
+
});
|
|
3659
|
+
}
|
|
3660
|
+
continue;
|
|
3661
|
+
}
|
|
3662
|
+
const helper = mergeHelper(source, source.value.type);
|
|
3115
3663
|
stmts.push({
|
|
3116
3664
|
kind: "exprStmt",
|
|
3117
3665
|
expr: { kind: "call", callee: helper, args: [outRef, source.value], type, loc },
|
|
@@ -3134,7 +3682,8 @@ function shorthandBuiltinValue(lowerer, prop) {
|
|
|
3134
3682
|
const js = isJsSourceFile(ts.getSourceFileOfNode(prop));
|
|
3135
3683
|
const name = ts.symbolName(symbol);
|
|
3136
3684
|
return ((js ? builtinNamespaceValue(lowerer, name, locOf(prop.name)) : null) ??
|
|
3137
|
-
builtinGlobalValue(name, locOf(prop.name), js)
|
|
3685
|
+
builtinGlobalValue(name, locOf(prop.name), js) ??
|
|
3686
|
+
tsUntypedGlobalValue(lowerer, prop.name, name, locOf(prop.name)));
|
|
3138
3687
|
}
|
|
3139
3688
|
export function lowerShorthandValue(lowerer, prop) {
|
|
3140
3689
|
// 7 types the shorthand's name as PropertyName; it is always an
|