@scriptc/compiler 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +960 -82
- package/ambient/scriptc.d.ts +134 -0
- package/dist/backend/cycle-analysis.d.ts +1 -1
- package/dist/backend/cycle-analysis.js +1 -0
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +13 -1
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.js +16 -5
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +13 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.test.js +1 -1
- package/dist/backend/library-pack.js +6 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +41 -4
- package/dist/backend/llvm/alloc.js +138 -7
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/alloc.test.js +30 -1
- package/dist/backend/llvm/alloc.test.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.test.js +1 -1
- package/dist/backend/llvm/array-search.test.js +1 -1
- package/dist/backend/llvm/blocks.d.ts +8 -0
- package/dist/backend/llvm/blocks.js +43 -1
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.js +22 -1
- package/dist/backend/llvm/blocks.test.js.map +1 -1
- package/dist/backend/llvm/byte-numbers.js +15 -5
- package/dist/backend/llvm/byte-numbers.js.map +1 -1
- package/dist/backend/llvm/bytes-alias.d.ts +14 -0
- package/dist/backend/llvm/bytes-alias.js +20 -0
- package/dist/backend/llvm/bytes-alias.js.map +1 -0
- package/dist/backend/llvm/bytes-loop-versions.d.ts +86 -0
- package/dist/backend/llvm/bytes-loop-versions.js +506 -0
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -0
- package/dist/backend/llvm/bytes-loop-versions.test.d.ts +1 -0
- package/dist/backend/llvm/bytes-loop-versions.test.js +244 -0
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.js +50 -1
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +34 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.test.js +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.js +4 -1
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +11 -0
- package/dist/backend/llvm/classes.js +71 -14
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +58 -8
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.js +1 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +5 -1
- package/dist/backend/llvm/constant-callbacks.js +55 -12
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +88 -1
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +4 -0
- package/dist/backend/llvm/counted-loops.js +37 -0
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +12 -3
- package/dist/backend/llvm/dense-array-access.js +72 -14
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +59 -3
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.d.ts +51 -0
- package/dist/backend/llvm/dense-array-loops.js +162 -0
- package/dist/backend/llvm/dense-array-loops.js.map +1 -0
- package/dist/backend/llvm/dense-array-loops.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-loops.test.js +128 -0
- package/dist/backend/llvm/dense-array-loops.test.js.map +1 -0
- package/dist/backend/llvm/dyn-handle-tags.test.d.ts +1 -0
- package/dist/backend/llvm/dyn-handle-tags.test.js +38 -0
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +28 -4
- package/dist/backend/llvm/dyn.js +324 -179
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.d.ts +64 -0
- package/dist/backend/llvm/emit-function.js +1190 -0
- package/dist/backend/llvm/emit-function.js.map +1 -0
- package/dist/backend/llvm/emit-module.d.ts +24 -0
- package/dist/backend/llvm/emit-module.js +1535 -0
- package/dist/backend/llvm/emit-module.js.map +1 -0
- package/dist/backend/llvm/emit-statements.d.ts +58 -0
- package/dist/backend/llvm/emit-statements.js +1964 -0
- package/dist/backend/llvm/emit-statements.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +576 -268
- package/dist/backend/llvm/emitter.js +801 -4447
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +57 -3
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +73 -46
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.js +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -0
- package/dist/backend/llvm/expr-bytes.js +76 -29
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +6 -2
- package/dist/backend/llvm/expr-callbacks.js +48 -11
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +1 -1
- package/dist/backend/llvm/expr-calls.js +71 -53
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-calls.test.js +1 -1
- package/dist/backend/llvm/expr-containers.js +39 -15
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +16 -16
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +1 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.d.ts +3 -0
- package/dist/backend/llvm/expr-dynamic.js +92 -63
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +132 -25
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +2 -2
- package/dist/backend/llvm/expr-records.d.ts +1 -1
- package/dist/backend/llvm/expr-records.js +32 -11
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +54 -12
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +22 -1
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/int32-abi.test.js +2 -2
- package/dist/backend/llvm/integer-clones.test.js +3 -3
- package/dist/backend/llvm/integer-remainder.d.ts +34 -13
- package/dist/backend/llvm/integer-remainder.js +156 -22
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/intern-tables.test.js +1 -1
- package/dist/backend/llvm/jsval-encoding.d.ts +21 -0
- package/dist/backend/llvm/jsval-encoding.js +20 -0
- package/dist/backend/llvm/jsval-encoding.js.map +1 -0
- package/dist/backend/llvm/jsval.d.ts +12 -0
- package/dist/backend/llvm/jsval.js +488 -0
- package/dist/backend/llvm/jsval.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.d.ts +12 -2
- package/dist/backend/llvm/lazy-captures.js +39 -17
- package/dist/backend/llvm/lazy-captures.js.map +1 -1
- package/dist/backend/llvm/lib-abi.js +1 -1
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-connect.js +1 -1
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +14 -8
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +217 -24
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +102 -13
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +3 -3
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +2 -2
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +77 -25
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +100 -50
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.d.ts +12 -0
- package/dist/backend/llvm/lib-shared.js +229 -5
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +46 -16
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +57 -8
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/lib-tls.js +4 -9
- package/dist/backend/llvm/lib-tls.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +2 -2
- package/dist/backend/llvm/local-array-reads.test.js +1 -1
- package/dist/backend/llvm/local-extents.d.ts +19 -0
- package/dist/backend/llvm/local-extents.js +169 -0
- package/dist/backend/llvm/local-extents.js.map +1 -0
- package/dist/backend/llvm/local-extents.test.d.ts +1 -0
- package/dist/backend/llvm/local-extents.test.js +92 -0
- package/dist/backend/llvm/local-extents.test.js.map +1 -0
- package/dist/backend/llvm/local-union-storage.js +7 -7
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +2 -2
- package/dist/backend/llvm/map-entry-fusion.test.js +1 -1
- package/dist/backend/llvm/map-number-lookup.js +2 -2
- package/dist/backend/llvm/map-number-lookup.test.js +2 -2
- package/dist/backend/llvm/map-read-lifetimes.test.js +2 -2
- package/dist/backend/llvm/narrow-guards.d.ts +38 -0
- package/dist/backend/llvm/narrow-guards.js +151 -0
- package/dist/backend/llvm/narrow-guards.js.map +1 -0
- package/dist/backend/llvm/nullable-unions.d.ts +70 -9
- package/dist/backend/llvm/nullable-unions.js +105 -6
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-unions.test.js +65 -0
- package/dist/backend/llvm/nullable-unions.test.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +4 -0
- package/dist/backend/llvm/publish.js +14 -2
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/publish.test.js +1 -1
- package/dist/backend/llvm/receivers.d.ts +31 -0
- package/dist/backend/llvm/receivers.js +395 -0
- package/dist/backend/llvm/receivers.js.map +1 -0
- package/dist/backend/llvm/record-results.d.ts +13 -2
- package/dist/backend/llvm/record-results.js +66 -6
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-effects.js +9 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +4 -0
- package/dist/backend/llvm/reference-writes.js +143 -6
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/reference-writes.test.d.ts +1 -0
- package/dist/backend/llvm/reference-writes.test.js +88 -0
- package/dist/backend/llvm/reference-writes.test.js.map +1 -0
- package/dist/backend/llvm/regex-matchers.d.ts +8 -0
- package/dist/backend/llvm/regex-matchers.js +33 -0
- package/dist/backend/llvm/regex-matchers.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.test.js +23 -1
- package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +1 -1
- package/dist/backend/llvm/regions.js +9 -6
- package/dist/backend/llvm/regions.js.map +1 -1
- package/dist/backend/llvm/regions.test.js +1 -1
- package/dist/backend/llvm/shapes.d.ts +69 -43
- package/dist/backend/llvm/shapes.js +285 -21
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +37 -3
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +74 -0
- package/dist/backend/llvm/speculative-integers.js +571 -0
- package/dist/backend/llvm/speculative-integers.js.map +1 -0
- package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
- package/dist/backend/llvm/speculative-integers.test.js +148 -0
- package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
- package/dist/backend/llvm/split-loops.js +2 -2
- package/dist/backend/llvm/split-loops.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +26 -6
- package/dist/backend/llvm/stack-objects.js +133 -10
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/stack-objects.test.js +55 -1
- package/dist/backend/llvm/stack-objects.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +15 -14
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-slices.d.ts +25 -0
- package/dist/backend/llvm/string-slices.js +207 -1
- package/dist/backend/llvm/string-slices.js.map +1 -1
- package/dist/backend/llvm/string-slices.test.js +139 -2
- package/dist/backend/llvm/string-slices.test.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +2 -2
- package/dist/backend/llvm/thread-slots.d.ts +5 -0
- package/dist/backend/llvm/thread-slots.js +142 -0
- package/dist/backend/llvm/thread-slots.js.map +1 -0
- package/dist/backend/llvm/thread-slots.test.d.ts +1 -0
- package/dist/backend/llvm/thread-slots.test.js +110 -0
- package/dist/backend/llvm/thread-slots.test.js.map +1 -0
- package/dist/backend/llvm/union-repr.d.ts +7 -7
- package/dist/backend/llvm/union-repr.js +18 -2
- package/dist/backend/llvm/union-repr.js.map +1 -1
- package/dist/backend/llvm/union-retype.test.js +17 -3
- package/dist/backend/llvm/union-retype.test.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -2
- package/dist/backend/llvm/walkers.js +51 -26
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wasm-modules.d.ts +16 -0
- package/dist/backend/llvm/wasm-modules.js +66 -0
- package/dist/backend/llvm/wasm-modules.js.map +1 -0
- package/dist/backend/llvm/wrapping-sums.d.ts +7 -0
- package/dist/backend/llvm/wrapping-sums.js +11 -3
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/mangle.d.ts +7 -0
- package/dist/backend/mangle.js +11 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.d.ts +3 -0
- package/dist/backend/may-throw.js +6 -2
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +1 -1
- package/dist/backend/native/contracts.d.ts +37 -0
- package/dist/backend/native/executable.js +192 -134
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -0
- package/dist/backend/native/library.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +2 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +30 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/publication.test.js +1 -1
- package/dist/backend/runtime-pack-core.d.ts +9 -1
- package/dist/backend/runtime-pack-core.js +10 -1
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.js +1 -1
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-native.test.d.ts +1 -0
- package/dist/backend/runtime-pack-native.test.js +31 -0
- package/dist/backend/runtime-pack-native.test.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +5 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +7 -3
- package/dist/backend/runtime-pack.js +12 -6
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +20 -6
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/stack-observations.d.ts +22 -0
- package/dist/backend/stack-observations.js +382 -0
- package/dist/backend/stack-observations.js.map +1 -0
- package/dist/backend/stack-observations.test.d.ts +1 -0
- package/dist/backend/stack-observations.test.js +233 -0
- package/dist/backend/stack-observations.test.js.map +1 -0
- package/dist/backend/target-diagnostics.js +8 -0
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/warm-cache.js +5 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/backend/young-nursery.d.ts +7 -0
- package/dist/backend/young-nursery.js +10 -0
- package/dist/backend/young-nursery.js.map +1 -0
- package/dist/cli/command.js +44 -4
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +11 -1
- package/dist/cli/usage.js +20 -1
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.js +10 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +13 -0
- package/dist/contracts/check.js +25 -6
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.d.ts +115 -0
- package/dist/contracts/int32-elements.js +1179 -0
- package/dist/contracts/int32-elements.js.map +1 -0
- package/dist/coverage/report.d.ts +16 -0
- package/dist/coverage/report.js +182 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +19 -6
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +2 -0
- package/dist/coverage/verdict-cache.js +12 -0
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/coverage/verdict-cache.test.js +2 -1
- package/dist/coverage/verdict-cache.test.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -7
- package/dist/diagnostics/diagnostic.js +35 -23
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +39 -2
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/diagnostics/render.d.ts +7 -0
- package/dist/diagnostics/render.js +50 -13
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/diagnostics/render.test.d.ts +1 -0
- package/dist/diagnostics/render.test.js +49 -0
- package/dist/diagnostics/render.test.js.map +1 -0
- package/dist/executable/executable-cache.d.ts +17 -0
- package/dist/executable/executable-cache.js +13 -1
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +7 -1
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +6 -1
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +16 -2
- package/dist/frontend/builtin-modules.js +40 -7
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-syntax.js +52 -51
- package/dist/frontend/cjs-syntax.js.map +1 -1
- package/dist/frontend/contract-types.d.ts +3 -0
- package/dist/frontend/contract-types.js +36 -7
- package/dist/frontend/contract-types.js.map +1 -1
- package/dist/frontend/experimental-import.d.ts +5 -1
- package/dist/frontend/experimental-import.js +26 -7
- package/dist/frontend/experimental-import.js.map +1 -1
- package/dist/frontend/fork-target.js +20 -22
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/fork-target.test.js +2 -1
- package/dist/frontend/fork-target.test.js.map +1 -1
- package/dist/frontend/function-completion.js +6 -6
- package/dist/frontend/function-completion.js.map +1 -1
- package/dist/frontend/helper-tokens.js +15 -3
- package/dist/frontend/helper-tokens.js.map +1 -1
- package/dist/frontend/helper-tokens.test.js +7 -1
- package/dist/frontend/helper-tokens.test.js.map +1 -1
- package/dist/frontend/inferred-js-diagnostics.js +14 -17
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +3 -0
- package/dist/frontend/input-tracker.js +32 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/lib-contract.js +36 -32
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lib-exports.js +3 -3
- package/dist/frontend/lib-exports.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +8 -3
- package/dist/frontend/lowering/array-values.js +60 -11
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/assert-instances.js +4 -4
- package/dist/frontend/lowering/assert-instances.js.map +1 -1
- package/dist/frontend/lowering/assertion-identity.d.ts +12 -0
- package/dist/frontend/lowering/assertion-identity.js +70 -0
- package/dist/frontend/lowering/assertion-identity.js.map +1 -0
- package/dist/frontend/lowering/assertion-members.d.ts +28 -0
- package/dist/frontend/lowering/assertion-members.js +185 -0
- package/dist/frontend/lowering/assertion-members.js.map +1 -0
- package/dist/frontend/lowering/binding-analysis.js +27 -20
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtin-calls.js +72 -4
- package/dist/frontend/lowering/builtin-calls.js.map +1 -1
- package/dist/frontend/lowering/builtin-function-fences.d.ts +14 -0
- package/dist/frontend/lowering/builtin-function-fences.js +42 -0
- package/dist/frontend/lowering/builtin-function-fences.js.map +1 -0
- package/dist/frontend/lowering/builtins/arguments.js +1 -1
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/async-context.js +53 -52
- package/dist/frontend/lowering/builtins/async-context.js.map +1 -1
- package/dist/frontend/lowering/builtins/atomics.js +6 -6
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
- package/dist/frontend/lowering/builtins/blob.js +8 -6
- package/dist/frontend/lowering/builtins/blob.js.map +1 -1
- package/dist/frontend/lowering/builtins/builtin-class-dyn.d.ts +23 -0
- package/dist/frontend/lowering/builtins/builtin-class-dyn.js +156 -0
- package/dist/frontend/lowering/builtins/builtin-class-dyn.js.map +1 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js +45 -6
- package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-async.js +7 -7
- package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.d.ts +6 -4
- package/dist/frontend/lowering/builtins/child-process-methods.js +310 -57
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js +16 -10
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.d.ts +6 -4
- package/dist/frontend/lowering/builtins/child-process.js +85 -61
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/class-values.d.ts +60 -0
- package/dist/frontend/lowering/builtins/class-values.js +226 -0
- package/dist/frontend/lowering/builtins/class-values.js.map +1 -0
- package/dist/frontend/lowering/builtins/compression.d.ts +18 -0
- package/dist/frontend/lowering/builtins/compression.js +230 -52
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/constants.d.ts +9 -1
- package/dist/frontend/lowering/builtins/constants.js +28 -7
- package/dist/frontend/lowering/builtins/constants.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +19 -0
- package/dist/frontend/lowering/builtins/crypto.js +223 -38
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/dates.d.ts +7 -1
- package/dist/frontend/lowering/builtins/dates.js +92 -16
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/disposable-stack.d.ts +18 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js +137 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -0
- package/dist/frontend/lowering/builtins/environment.js +3 -3
- package/dist/frontend/lowering/builtins/environment.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.d.ts +14 -10
- package/dist/frontend/lowering/builtins/errors.js +174 -6
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +4 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +136 -113
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
- package/dist/frontend/lowering/builtins/filesystem.js +213 -76
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-glob.js +3 -3
- package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-streams.js +10 -11
- package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -1
- package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
- package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
- package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
- package/dist/frontend/lowering/builtins/ipc.js +45 -8
- package/dist/frontend/lowering/builtins/ipc.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +232 -24
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/key-object.js +4 -4
- package/dist/frontend/lowering/builtins/key-object.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-bindings.d.ts +8 -0
- package/dist/frontend/lowering/builtins/module-bindings.js +71 -22
- package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +67 -46
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +4 -3
- package/dist/frontend/lowering/builtins/module-resolution.js +24 -23
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
- package/dist/frontend/lowering/builtins/navigator.d.ts +13 -0
- package/dist/frontend/lowering/builtins/navigator.js +40 -0
- package/dist/frontend/lowering/builtins/navigator.js.map +1 -0
- package/dist/frontend/lowering/builtins/net-address.d.ts +19 -0
- package/dist/frontend/lowering/builtins/net-address.js +156 -0
- package/dist/frontend/lowering/builtins/net-address.js.map +1 -0
- package/dist/frontend/lowering/builtins/numbers.js +25 -9
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.d.ts +4 -0
- package/dist/frontend/lowering/builtins/operating-system.js +25 -12
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/performance.d.ts +12 -0
- package/dist/frontend/lowering/builtins/performance.js +259 -8
- package/dist/frontend/lowering/builtins/performance.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +32 -1
- package/dist/frontend/lowering/builtins/process.js +468 -99
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +5 -1
- package/dist/frontend/lowering/builtins/promises.js +326 -43
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/promisify-callback.d.ts +37 -0
- package/dist/frontend/lowering/builtins/promisify-callback.js +320 -0
- package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -0
- package/dist/frontend/lowering/builtins/properties.js +37 -1
- package/dist/frontend/lowering/builtins/properties.js.map +1 -1
- package/dist/frontend/lowering/builtins/querystring.js +14 -14
- package/dist/frontend/lowering/builtins/querystring.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +55 -13
- package/dist/frontend/lowering/builtins/readline.js +931 -69
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/receiver-types.js +3 -5
- package/dist/frontend/lowering/builtins/receiver-types.js.map +1 -1
- package/dist/frontend/lowering/builtins/reflection.js +16 -14
- package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
- package/dist/frontend/lowering/builtins/runtime-constructor.d.ts +26 -0
- package/dist/frontend/lowering/builtins/runtime-constructor.js +165 -0
- package/dist/frontend/lowering/builtins/runtime-constructor.js.map +1 -0
- package/dist/frontend/lowering/builtins/strings.js +101 -12
- package/dist/frontend/lowering/builtins/strings.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.js +41 -38
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/timers.js +75 -30
- package/dist/frontend/lowering/builtins/timers.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.d.ts +3 -0
- package/dist/frontend/lowering/builtins/url.js +120 -17
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/util-types.js +20 -4
- package/dist/frontend/lowering/builtins/util-types.js.map +1 -1
- package/dist/frontend/lowering/builtins/v8.d.ts +11 -0
- package/dist/frontend/lowering/builtins/v8.js +105 -0
- package/dist/frontend/lowering/builtins/v8.js.map +1 -0
- package/dist/frontend/lowering/builtins/webassembly.d.ts +33 -0
- package/dist/frontend/lowering/builtins/webassembly.js +388 -0
- package/dist/frontend/lowering/builtins/webassembly.js.map +1 -0
- package/dist/frontend/lowering/builtins/webcrypto.d.ts +20 -0
- package/dist/frontend/lowering/builtins/webcrypto.js +112 -0
- package/dist/frontend/lowering/builtins/webcrypto.js.map +1 -0
- package/dist/frontend/lowering/builtins/workers.d.ts +16 -0
- package/dist/frontend/lowering/builtins/workers.js +246 -3
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +69 -14
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.d.ts +19 -1
- package/dist/frontend/lowering/call-signatures.js +254 -47
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/checked-promise-all.d.ts +3 -0
- package/dist/frontend/lowering/checked-promise-all.js +1 -1
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
- package/dist/frontend/lowering/cjs-exports-object.d.ts +53 -0
- package/dist/frontend/lowering/cjs-exports-object.js +528 -0
- package/dist/frontend/lowering/cjs-exports-object.js.map +1 -0
- package/dist/frontend/lowering/cjs-inline-require.d.ts +86 -0
- package/dist/frontend/lowering/cjs-inline-require.js +314 -0
- package/dist/frontend/lowering/cjs-inline-require.js.map +1 -0
- package/dist/frontend/lowering/cjs-tsc-interop.d.ts +28 -0
- package/dist/frontend/lowering/cjs-tsc-interop.js +208 -0
- package/dist/frontend/lowering/cjs-tsc-interop.js.map +1 -0
- package/dist/frontend/lowering/class-attributes.d.ts +19 -0
- package/dist/frontend/lowering/class-attributes.js +378 -0
- package/dist/frontend/lowering/class-attributes.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -1
- package/dist/frontend/lowering/class-callbacks.js +21 -10
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.js +49 -4
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.d.ts +2 -0
- package/dist/frontend/lowering/class-descriptors.js +8 -8
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +64 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1115 -89
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-iterables.d.ts +11 -0
- package/dist/frontend/lowering/class-iterables.js +31 -0
- package/dist/frontend/lowering/class-iterables.js.map +1 -0
- package/dist/frontend/lowering/class-method-mutations.js +73 -35
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.js +56 -10
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocol-dispatch.js +24 -22
- package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +55 -0
- package/dist/frontend/lowering/class-protocols.js +738 -22
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +6 -0
- package/dist/frontend/lowering/class-prototypes.js +80 -18
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.js +2 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/class-to-primitive.d.ts +25 -0
- package/dist/frontend/lowering/class-to-primitive.js +261 -0
- package/dist/frontend/lowering/class-to-primitive.js.map +1 -0
- package/dist/frontend/lowering/class-unions.d.ts +25 -0
- package/dist/frontend/lowering/class-unions.js +102 -1
- package/dist/frontend/lowering/class-unions.js.map +1 -1
- package/dist/frontend/lowering/code-generation.d.ts +14 -0
- package/dist/frontend/lowering/code-generation.js +127 -0
- package/dist/frontend/lowering/code-generation.js.map +1 -0
- package/dist/frontend/lowering/coercions/function-adapters.d.ts +16 -2
- package/dist/frontend/lowering/coercions/function-adapters.js +145 -3
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +25 -3
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +35 -3
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +15 -0
- package/dist/frontend/lowering/coercions/unions.js +57 -1
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.js +2 -2
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
- package/dist/frontend/lowering/collection-narrowing.js +2 -4
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -1
- package/dist/frontend/lowering/construction-escapes.js +8 -8
- package/dist/frontend/lowering/construction-escapes.js.map +1 -1
- package/dist/frontend/lowering/construction-escapes.test.js +4 -4
- package/dist/frontend/lowering/construction-escapes.test.js.map +1 -1
- package/dist/frontend/lowering/constructor-returns.d.ts +61 -0
- package/dist/frontend/lowering/constructor-returns.js +477 -0
- package/dist/frontend/lowering/constructor-returns.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +1 -1
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +9 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +266 -100
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +1 -1
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.d.ts +0 -1
- package/dist/frontend/lowering/containers/array-construction.js +51 -13
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-from-async.d.ts +19 -0
- package/dist/frontend/lowering/containers/array-from-async.js +427 -0
- package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
- package/dist/frontend/lowering/containers/array-methods.js +89 -77
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +1 -0
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +161 -101
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.d.ts +9 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +55 -5
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-grouping.d.ts +7 -8
- package/dist/frontend/lowering/containers/collection-grouping.js +219 -27
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +81 -48
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/dynamic-receivers.js +1 -1
- package/dist/frontend/lowering/containers/dynamic-receivers.js.map +1 -1
- package/dist/frontend/lowering/containers/exec-result-uses.js +2 -2
- package/dist/frontend/lowering/containers/exec-result-uses.js.map +1 -1
- package/dist/frontend/lowering/containers/for-of.d.ts +6 -0
- package/dist/frontend/lowering/containers/for-of.js +19 -19
- package/dist/frontend/lowering/containers/for-of.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +142 -57
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/iterator-helpers.d.ts +53 -4
- package/dist/frontend/lowering/containers/iterator-helpers.js +1581 -462
- package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
- package/dist/frontend/lowering/containers/match-row-uses.d.ts +17 -0
- package/dist/frontend/lowering/containers/match-row-uses.js +264 -0
- package/dist/frontend/lowering/containers/match-row-uses.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +14 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +419 -30
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +4 -0
- package/dist/frontend/lowering/cycle-initialization.js +39 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +47 -43
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/devirtualize.d.ts +1 -1
- package/dist/frontend/lowering/devirtualize.js +27 -7
- package/dist/frontend/lowering/devirtualize.js.map +1 -1
- package/dist/frontend/lowering/divergences.d.ts +0 -5
- package/dist/frontend/lowering/divergences.js +238 -128
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/dyn-streams.d.ts +25 -0
- package/dist/frontend/lowering/dyn-streams.js +257 -0
- package/dist/frontend/lowering/dyn-streams.js.map +1 -0
- package/dist/frontend/lowering/error-methods.js +4 -1
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/error-name-order.d.ts +19 -0
- package/dist/frontend/lowering/error-name-order.js +93 -0
- package/dist/frontend/lowering/error-name-order.js.map +1 -0
- package/dist/frontend/lowering/expressions/array-literals.d.ts +21 -0
- package/dist/frontend/lowering/expressions/array-literals.js +703 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -0
- package/dist/frontend/lowering/expressions/binary.d.ts +35 -0
- package/dist/frontend/lowering/expressions/binary.js +2483 -0
- package/dist/frontend/lowering/expressions/binary.js.map +1 -0
- package/dist/frontend/lowering/expressions/element-access.d.ts +31 -0
- package/dist/frontend/lowering/expressions/element-access.js +1797 -0
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -3
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/hosted-narrowing.d.ts +38 -0
- package/dist/frontend/lowering/expressions/hosted-narrowing.js +160 -0
- package/dist/frontend/lowering/expressions/hosted-narrowing.js.map +1 -0
- package/dist/frontend/lowering/expressions/identifiers.d.ts +4 -0
- package/dist/frontend/lowering/expressions/identifiers.js +830 -0
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.d.ts +40 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.js +226 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.js.map +1 -0
- package/dist/frontend/lowering/expressions/narrowing.d.ts +37 -0
- package/dist/frontend/lowering/expressions/narrowing.js +1322 -0
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +4 -4
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +45 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -0
- package/dist/frontend/lowering/expressions/object-literals.js +253 -85
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +2 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +91 -14
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +110 -0
- package/dist/frontend/lowering/expressions/property-access.js +3544 -0
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -0
- package/dist/frontend/lowering/expressions/relational.d.ts +28 -0
- package/dist/frontend/lowering/expressions/relational.js +1679 -0
- package/dist/frontend/lowering/expressions/relational.js.map +1 -0
- package/dist/frontend/lowering/expressions/typeof.d.ts +22 -0
- package/dist/frontend/lowering/expressions/typeof.js +538 -0
- package/dist/frontend/lowering/expressions/typeof.js.map +1 -0
- package/dist/frontend/lowering/expressions/union-fields.js +1 -1
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.d.ts +21 -0
- package/dist/frontend/lowering/expressions/updates.js +780 -0
- package/dist/frontend/lowering/expressions/updates.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +10 -0
- package/dist/frontend/lowering/function-context.js +11 -1
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/function-returns.js +52 -28
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/general-streams.d.ts +25 -0
- package/dist/frontend/lowering/general-streams.js +108 -0
- package/dist/frontend/lowering/general-streams.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +7 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +172 -69
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +39 -0
- package/dist/frontend/lowering/generic-functions.js +393 -75
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/import-meta.js +2 -2
- package/dist/frontend/lowering/import-meta.js.map +1 -1
- package/dist/frontend/lowering/intern-tables.js +10 -9
- package/dist/frontend/lowering/intern-tables.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.d.ts +19 -0
- package/dist/frontend/lowering/iterator-adapters.js +331 -3
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/js-class-fields.d.ts +28 -0
- package/dist/frontend/lowering/js-class-fields.js +170 -0
- package/dist/frontend/lowering/js-class-fields.js.map +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.d.ts +15 -0
- package/dist/frontend/lowering/js-dynamic-objects.js +299 -0
- package/dist/frontend/lowering/js-dynamic-objects.js.map +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.d.ts +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.js +35 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.js.map +1 -0
- package/dist/frontend/lowering/json-require.d.ts +22 -0
- package/dist/frontend/lowering/json-require.js +131 -0
- package/dist/frontend/lowering/json-require.js.map +1 -0
- package/dist/frontend/lowering/key-order-witness.d.ts +44 -0
- package/dist/frontend/lowering/key-order-witness.js +641 -0
- package/dist/frontend/lowering/key-order-witness.js.map +1 -0
- package/dist/frontend/lowering/key-order-witness.test.d.ts +1 -0
- package/dist/frontend/lowering/key-order-witness.test.js +239 -0
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -0
- package/dist/frontend/lowering/lifetime-regions.js +7 -7
- package/dist/frontend/lowering/lifetime-regions.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +61 -60
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +10 -1
- package/dist/frontend/lowering/lower-async-iteration.js +34 -6
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +5 -0
- package/dist/frontend/lowering/lower-builtin-values.js +32 -3
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +1298 -452
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +50 -3
- package/dist/frontend/lowering/lower-classes.js +1499 -456
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +4 -2
- package/dist/frontend/lowering/lower-comptime.js +111 -13
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-console.js +13 -11
- package/dist/frontend/lowering/lower-console.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +10 -0
- package/dist/frontend/lowering/lower-dgram.js +179 -8
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.js +113 -14
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +16 -7
- package/dist/frontend/lowering/lower-event-emitter.js +268 -71
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-event-target.js +2 -2
- package/dist/frontend/lowering/lower-event-target.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.js +17 -13
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +188 -186
- package/dist/frontend/lowering/lower-exprs.js +1493 -12407
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +68 -22
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +6 -0
- package/dist/frontend/lowering/lower-generators.js +29 -16
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +5 -1
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +354 -99
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +23 -20
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.d.ts +19 -2
- package/dist/frontend/lowering/lower-mock.js +557 -74
- package/dist/frontend/lowering/lower-mock.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +268 -61
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +6 -0
- package/dist/frontend/lowering/lower-namespaces.js +45 -33
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +16 -0
- package/dist/frontend/lowering/lower-node-module.js +147 -14
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +6 -6
- package/dist/frontend/lowering/lower-server.js +638 -105
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +4 -0
- package/dist/frontend/lowering/lower-stdlib.js +151 -109
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +28 -2
- package/dist/frontend/lowering/lower-stmts.js +1589 -398
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +4 -3
- package/dist/frontend/lowering/lower-stream.js +714 -75
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +3 -0
- package/dist/frontend/lowering/lower-test.js +574 -100
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +80 -32
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lower-url.js +1 -1
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +409 -26
- package/dist/frontend/lowering/lowerer.js +1918 -305
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +10 -4
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/maybe-promise.d.ts +46 -0
- package/dist/frontend/lowering/maybe-promise.js +249 -0
- package/dist/frontend/lowering/maybe-promise.js.map +1 -0
- package/dist/frontend/lowering/module-member-this.d.ts +3 -0
- package/dist/frontend/lowering/module-member-this.js +262 -0
- package/dist/frontend/lowering/module-member-this.js.map +1 -0
- package/dist/frontend/lowering/module-namespace-elements.js +1 -1
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/nan-coded-reads.d.ts +3 -0
- package/dist/frontend/lowering/nan-coded-reads.js +45 -32
- package/dist/frontend/lowering/nan-coded-reads.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.d.ts +18 -3
- package/dist/frontend/lowering/narrowing-stability.js +104 -32
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +11 -11
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/null-prototype.d.ts +13 -0
- package/dist/frontend/lowering/null-prototype.js +33 -0
- package/dist/frontend/lowering/null-prototype.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.js +6 -8
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/private-brands.d.ts +46 -0
- package/dist/frontend/lowering/private-brands.js +265 -0
- package/dist/frontend/lowering/private-brands.js.map +1 -0
- package/dist/frontend/lowering/promise-executor-adapter.d.ts +11 -0
- package/dist/frontend/lowering/promise-executor-adapter.js +87 -0
- package/dist/frontend/lowering/promise-executor-adapter.js.map +1 -0
- package/dist/frontend/lowering/require-initialization.d.ts +32 -0
- package/dist/frontend/lowering/require-initialization.js +246 -0
- package/dist/frontend/lowering/require-initialization.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js +7 -7
- package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-elements.js +12 -12
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.js +10 -10
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-ownership.js +10 -9
- package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js +2 -2
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.d.ts +35 -0
- package/dist/frontend/lowering/runtime-optional-records.js +205 -32
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.test.js +19 -1
- package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -1
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/split-consumers.js +4 -4
- package/dist/frontend/lowering/split-consumers.js.map +1 -1
- package/dist/frontend/lowering/static-function-names.d.ts +28 -0
- package/dist/frontend/lowering/static-function-names.js +212 -0
- package/dist/frontend/lowering/static-function-names.js.map +1 -0
- package/dist/frontend/lowering/static-this.js +6 -6
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/strict-mode.d.ts +5 -0
- package/dist/frontend/lowering/strict-mode.js +31 -0
- package/dist/frontend/lowering/strict-mode.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.js +10 -10
- package/dist/frontend/lowering/string-index-bounds.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +12 -0
- package/dist/frontend/lowering/string-index.js +72 -1
- package/dist/frontend/lowering/string-index.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +15 -6
- package/dist/frontend/lowering/surfaces.js +278 -45
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +7 -0
- package/dist/frontend/lowering/symbol-fields.js +204 -36
- package/dist/frontend/lowering/symbol-fields.js.map +1 -1
- package/dist/frontend/lowering/symbol-methods.d.ts +2 -1
- package/dist/frontend/lowering/symbol-methods.js +24 -6
- package/dist/frontend/lowering/symbol-methods.js.map +1 -1
- package/dist/frontend/lowering/thread-slots.d.ts +13 -0
- package/dist/frontend/lowering/thread-slots.js +208 -0
- package/dist/frontend/lowering/thread-slots.js.map +1 -0
- package/dist/frontend/lowering/typed-arguments.d.ts +74 -0
- package/dist/frontend/lowering/typed-arguments.js +472 -0
- package/dist/frontend/lowering/typed-arguments.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +8 -0
- package/dist/frontend/lowering/union-retag.js +27 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -1
- package/dist/frontend/lowering/union-retag.test.js +24 -1
- package/dist/frontend/lowering/union-retag.test.js.map +1 -1
- package/dist/frontend/lowering/var-hoisting.js +6 -6
- package/dist/frontend/lowering/var-hoisting.js.map +1 -1
- package/dist/frontend/lowering/width-lift.d.ts +4 -0
- package/dist/frontend/mock-shapes.d.ts +5 -0
- package/dist/frontend/mock-shapes.js +39 -7
- package/dist/frontend/mock-shapes.js.map +1 -1
- package/dist/frontend/module-source-candidates.js +1 -1
- package/dist/frontend/module-source-candidates.js.map +1 -1
- package/dist/frontend/module-source-candidates.test.js +2 -1
- package/dist/frontend/module-source-candidates.test.js.map +1 -1
- package/dist/frontend/module-syntax.js +8 -8
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/npm-static-bundled-chunks.d.ts +51 -0
- package/dist/frontend/npm-static-bundled-chunks.js +810 -0
- package/dist/frontend/npm-static-bundled-chunks.js.map +1 -0
- package/dist/frontend/npm-static-bundled-chunks.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-chunks.test.js +287 -0
- package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.js +24 -23
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -1
- package/dist/frontend/npm-static-bundled-esm.d.ts +9 -0
- package/dist/frontend/npm-static-bundled-esm.js +768 -0
- package/dist/frontend/npm-static-bundled-esm.js.map +1 -0
- package/dist/frontend/npm-static-bundled-esm.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-esm.test.js +207 -0
- package/dist/frontend/npm-static-bundled-esm.test.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.d.ts +2 -0
- package/dist/frontend/npm-static-cjs-exports-alias.js +186 -0
- package/dist/frontend/npm-static-cjs-exports-alias.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.d.ts +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.js +73 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-var.d.ts +2 -0
- package/dist/frontend/npm-static-cjs-exports-var.js +236 -0
- package/dist/frontend/npm-static-cjs-exports-var.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.js +102 -101
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -1
- package/dist/frontend/npm-static-prune.js +36 -24
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -1
- package/dist/frontend/npm-static-rewrite-host.js +14 -3
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +19 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +274 -101
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.js +7 -9
- package/dist/frontend/npm-static-subtyping.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +17 -1
- package/dist/frontend/npm-static.js +167 -16
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm-static.test.js +22 -1
- package/dist/frontend/npm-static.test.js.map +1 -1
- package/dist/frontend/pipeline.js +164 -26
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/pipeline.test.js +22 -1
- package/dist/frontend/pipeline.test.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +6 -1
- package/dist/frontend/program-analysis.js +7 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +92 -2
- package/dist/frontend/program.js +1557 -254
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +76 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.js +36 -2
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +49 -0
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/services.d.ts +20 -1
- package/dist/frontend/services.js +40 -3
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +2 -1
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/threads-import.js +1 -1
- package/dist/frontend/threads-import.js.map +1 -1
- package/dist/frontend/tier-analysis.d.ts +71 -0
- package/dist/frontend/tier-analysis.js +522 -0
- package/dist/frontend/tier-analysis.js.map +1 -0
- package/dist/frontend/ts7/api-conformance.d.ts +234 -0
- package/dist/frontend/ts7/api-conformance.js +7 -0
- package/dist/frontend/ts7/api-conformance.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.js +2 -1
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +47 -25
- package/dist/frontend/ts7/ast-node.js +64 -18
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +36 -12
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-types.d.ts +10 -3
- package/dist/frontend/ts7/ast-types.generated.d.ts +39 -39
- package/dist/frontend/ts7/ast.d.ts +1 -0
- package/dist/frontend/ts7/ast.js +3 -2
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +23 -0
- package/dist/frontend/ts7/checker-backend.js +88 -0
- package/dist/frontend/ts7/checker-backend.js.map +1 -0
- package/dist/frontend/ts7/checker-backend.test.d.ts +1 -0
- package/dist/frontend/ts7/checker-backend.test.js +63 -0
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -0
- package/dist/frontend/ts7/checker-cache.d.ts +0 -3
- package/dist/frontend/ts7/checker-cache.js +0 -6
- package/dist/frontend/ts7/checker-cache.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +18 -11
- package/dist/frontend/ts7/checker.js +42 -55
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +10 -7
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/diagnostic.d.ts +19 -0
- package/dist/frontend/ts7/diagnostic.js +22 -0
- package/dist/frontend/ts7/diagnostic.js.map +1 -0
- package/dist/frontend/ts7/node-functions.d.ts +8 -0
- package/dist/frontend/ts7/node-functions.js +18 -0
- package/dist/frontend/ts7/node-functions.js.map +1 -0
- package/dist/frontend/ts7/program-host.d.ts +5 -1
- package/dist/frontend/ts7/program-host.js +12 -0
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/rpc-api.d.ts +5 -1
- package/dist/frontend/ts7/rpc-api.js +8 -1
- package/dist/frontend/ts7/rpc-api.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.d.ts +13 -6
- package/dist/frontend/ts7/semantic-checker.js +26 -8
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.test.js +12 -9
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +54 -24
- package/dist/frontend/ts7/semantic-model.js +88 -16
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +4 -4
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-types.d.ts +7 -3
- package/dist/frontend/ts7/semantic-types.js +1 -1
- package/dist/frontend/ts7/semantic-types.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +11 -11
- package/dist/frontend/ts7/session.js +8 -5
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/ts7/session.test.js +9 -5
- package/dist/frontend/ts7/session.test.js.map +1 -1
- package/dist/frontend/ts7/source-parser.d.ts +6 -2
- package/dist/frontend/ts7/source-parser.js +24 -3
- package/dist/frontend/ts7/source-parser.js.map +1 -1
- package/dist/frontend/ts7/source-parser.test.js +38 -17
- package/dist/frontend/ts7/source-parser.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +122 -2
- package/dist/frontend/type-mapper.js +2612 -695
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-only-imports.d.ts +28 -0
- package/dist/frontend/type-only-imports.js +122 -0
- package/dist/frontend/type-only-imports.js.map +1 -0
- package/dist/frontend/worker-target.js +8 -8
- package/dist/frontend/worker-target.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +47 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +4 -2
- package/dist/ir/analysis.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/array-length-stability.d.ts +30 -0
- package/dist/ir/array-length-stability.js +236 -0
- package/dist/ir/array-length-stability.js.map +1 -0
- package/dist/ir/array-length-stability.test.d.ts +1 -0
- package/dist/ir/array-length-stability.test.js +113 -0
- package/dist/ir/array-length-stability.test.js.map +1 -0
- package/dist/ir/build.d.ts +2 -2
- package/dist/ir/build.js +1 -1
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-effects.js +139 -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 +655 -25
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/byte-numbers.js +3 -0
- package/dist/ir/byte-numbers.js.map +1 -1
- package/dist/ir/callback-specialization.d.ts +37 -0
- package/dist/ir/callback-specialization.js +459 -0
- package/dist/ir/callback-specialization.js.map +1 -0
- package/dist/ir/callback-specialization.test.d.ts +1 -0
- package/dist/ir/callback-specialization.test.js +208 -0
- package/dist/ir/callback-specialization.test.js.map +1 -0
- package/dist/ir/capture-values.d.ts +0 -1
- package/dist/ir/capture-values.js +51 -40
- package/dist/ir/capture-values.js.map +1 -1
- package/dist/ir/constant-globals.test.js +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/field-values.test.js +1 -1
- package/dist/ir/final-fields.test.js +1 -1
- package/dist/ir/function-references.test.js +10 -1
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/init-only-globals.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/int32-slots.d.ts +14 -0
- package/dist/ir/int32-slots.js +119 -14
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +29 -1
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loop-facts.d.ts +16 -6
- package/dist/ir/integer-loop-facts.js +143 -38
- package/dist/ir/integer-loop-facts.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +1 -1
- package/dist/ir/integer-loops.js +39 -9
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +104 -0
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +3 -0
- package/dist/ir/integer-ranges.js +4 -6
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +142 -1
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/intrinsic-signatures.js +6 -0
- package/dist/ir/intrinsic-signatures.js.map +1 -1
- package/dist/ir/ir.d.ts +234 -58
- package/dist/ir/ir.js +123 -12
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +10 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/jsval.d.ts +8 -0
- package/dist/ir/jsval.js +365 -0
- package/dist/ir/jsval.js.map +1 -0
- package/dist/ir/jsval.test.d.ts +1 -0
- package/dist/ir/jsval.test.js +239 -0
- package/dist/ir/jsval.test.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +150 -33
- package/dist/ir/runtime-features.js +672 -339
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/runtime-features.test.js +62 -0
- package/dist/ir/runtime-features.test.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/self-captures.d.ts +33 -0
- package/dist/ir/self-captures.js +245 -0
- package/dist/ir/self-captures.js.map +1 -0
- package/dist/ir/self-captures.test.d.ts +1 -0
- package/dist/ir/self-captures.test.js +135 -0
- package/dist/ir/self-captures.test.js.map +1 -0
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +7 -4
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/tiers.d.ts +26 -0
- package/dist/ir/tiers.js +101 -0
- package/dist/ir/tiers.js.map +1 -0
- package/dist/ir/tiers.test.d.ts +1 -0
- package/dist/ir/tiers.test.js +140 -0
- package/dist/ir/tiers.test.js.map +1 -0
- package/dist/ir/traverse.js +107 -94
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/traverse.test.js +33 -30
- package/dist/ir/traverse.test.js.map +1 -1
- package/dist/ir/unshare.js +65 -3
- package/dist/ir/unshare.js.map +1 -1
- package/dist/ir/unshare.test.js +1 -1
- package/dist/ir/validate.js +220 -71
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +64 -9
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/ir-policy.js +18 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-cache.d.ts +1 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +4 -4
- package/dist/library/library-profile.js +35 -7
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.js +13 -1
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/cli.js +5 -0
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +2 -2
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +2 -2
- package/dist/native/prepare.js +7 -0
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.test.js +12 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/toolchain.d.ts +2 -0
- package/dist/native/toolchain.js +10 -1
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +39 -1
- package/dist/native/toolchain.test.js.map +1 -1
- package/dist/startup-cache.d.ts +1 -0
- package/dist/startup-cache.js +1 -0
- package/dist/startup-cache.js.map +1 -1
- package/dist/wasm/base64.d.ts +5 -0
- package/dist/wasm/base64.js +62 -0
- package/dist/wasm/base64.js.map +1 -0
- package/dist/wasm/binary.d.ts +36 -0
- package/dist/wasm/binary.js +1976 -0
- package/dist/wasm/binary.js.map +1 -0
- package/dist/wasm/binary.test.d.ts +1 -0
- package/dist/wasm/binary.test.js +190 -0
- package/dist/wasm/binary.test.js.map +1 -0
- package/dist/wasm/discover.d.ts +38 -0
- package/dist/wasm/discover.js +377 -0
- package/dist/wasm/discover.js.map +1 -0
- package/dist/wasm/discover.test.d.ts +1 -0
- package/dist/wasm/discover.test.js +24 -0
- package/dist/wasm/discover.test.js.map +1 -0
- package/dist/wasm/module.d.ts +151 -0
- package/dist/wasm/module.js +575 -0
- package/dist/wasm/module.js.map +1 -0
- package/dist/wasm/translate.d.ts +48 -0
- package/dist/wasm/translate.js +2129 -0
- package/dist/wasm/translate.js.map +1 -0
- package/dist/wasm/translate.test.d.ts +1 -0
- package/dist/wasm/translate.test.js +207 -0
- package/dist/wasm/translate.test.js.map +1 -0
- package/package.json +21 -20
- package/surface-manifest.json +332 -36
|
@@ -2,7 +2,7 @@ import { InternalCompilerError } from "../errors.js";
|
|
|
2
2
|
import { mockCallRecordType, mockContextType } from "./mock-shapes.js";
|
|
3
3
|
import * as ts from "./ts7/adapter.js";
|
|
4
4
|
import { bodyReadsArguments } from "./arguments-usage.js";
|
|
5
|
-
import { BYTES_ELEMENT_NAME, arrayOf, BOOL, bytesOf, canConvertToDyn, CHILD_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DYN, F64, funcOf, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, mapOf, NULL_T, PROCSTREAM_T, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, ZLIB_STREAM_MODES, setOf, STRING, SYMBOL_T, typeEquals, typeKey, unionContainerArmsOk, UNDEFINED_T, VOID, } from "../ir/ir.js";
|
|
5
|
+
import { BYTES_ELEMENT_NAME, arrayOf, isDynTypedRefType, BOOL, bytesOf, canConvertToDyn, canDynCheckTo, CHILD_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DYN, F64, funcOf, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, mapOf, NULL_T, PROCSTREAM_T, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, ZLIB_STREAM_MODES, setOf, STRING, SYMBOL_T, typeEquals, typeKey, maybePromiseUnionArmsOk, unionContainerArmsOk, UNDEFINED_T, VOID, } from "../ir/ir.js";
|
|
6
6
|
import { BIGINT_T } from "../ir/ir.js";
|
|
7
7
|
import { literalValues } from "./literal-values.js";
|
|
8
8
|
import { remapUnionDiscriminant } from "./union-discriminants.js";
|
|
@@ -21,7 +21,7 @@ function runtimeParameterCount(parameters) {
|
|
|
21
21
|
/** Empty JS object inference describes no fixed layout. Keep these values
|
|
22
22
|
* in checked storage across fields, parameters and function signatures. */
|
|
23
23
|
export function jsOpenObjectType(decl, type, shapes, unions) {
|
|
24
|
-
if (!decl || !isJsSourceFile(
|
|
24
|
+
if (!decl || !isJsSourceFile(ts.getSourceFileOfNode(decl)))
|
|
25
25
|
return type;
|
|
26
26
|
const arms = type.kind === "union" ? unions.get(type.unionId)?.arms : [type];
|
|
27
27
|
const present = arms?.filter((arm) => arm.kind !== "undefinedT");
|
|
@@ -67,6 +67,25 @@ export function jsOpenObjectType(decl, type, shapes, unions) {
|
|
|
67
67
|
? DYN
|
|
68
68
|
: type;
|
|
69
69
|
}
|
|
70
|
+
/** The modules whose RequestOptions interface maps to the checked dynamic. */
|
|
71
|
+
const HTTP_REQUEST_OPTION_MODULES = new Set([
|
|
72
|
+
"http",
|
|
73
|
+
"node:http",
|
|
74
|
+
"https",
|
|
75
|
+
"node:https",
|
|
76
|
+
]);
|
|
77
|
+
/** The WebCrypto interfaces whose values are checked-dynamic: the crypto
|
|
78
|
+
* global, SubtleCrypto, CryptoKey handles and the algorithm dictionaries
|
|
79
|
+
* (scr_webcrypto.c). */
|
|
80
|
+
export const WEBCRYPTO_DYN_TYPES = new Set([
|
|
81
|
+
"Crypto",
|
|
82
|
+
"SubtleCrypto",
|
|
83
|
+
"CryptoKey",
|
|
84
|
+
"Algorithm",
|
|
85
|
+
"KeyAlgorithm",
|
|
86
|
+
"HmacImportParams",
|
|
87
|
+
"HmacKeyAlgorithm",
|
|
88
|
+
]);
|
|
70
89
|
export const FETCH_AMBIENT_TYPES = [
|
|
71
90
|
"Response",
|
|
72
91
|
"Request",
|
|
@@ -74,6 +93,7 @@ export const FETCH_AMBIENT_TYPES = [
|
|
|
74
93
|
"RequestInit",
|
|
75
94
|
"Event",
|
|
76
95
|
"CustomEvent",
|
|
96
|
+
"MessageEvent",
|
|
77
97
|
"EventTarget",
|
|
78
98
|
"AddEventListenerOptions",
|
|
79
99
|
"EventListenerOptions",
|
|
@@ -232,7 +252,7 @@ export class ShapeRegistry {
|
|
|
232
252
|
comparePriority(previous, this.currentDeclaredOrderPriority) <= 0) {
|
|
233
253
|
return;
|
|
234
254
|
}
|
|
235
|
-
shape.declaredOrder = declaredOrder;
|
|
255
|
+
shape.declaredOrder = this.withExtendedNames(shape.id, declaredOrder);
|
|
236
256
|
this.declaredOrderPriority.set(shape.id, this.currentDeclaredOrderPriority);
|
|
237
257
|
}
|
|
238
258
|
/** Mutable generic-instance ranks settle only after reachability closes.
|
|
@@ -250,7 +270,7 @@ export class ShapeRegistry {
|
|
|
250
270
|
const shape = this.byId.get(shapeId);
|
|
251
271
|
if (!shape)
|
|
252
272
|
continue;
|
|
253
|
-
shape.declaredOrder = best.order;
|
|
273
|
+
shape.declaredOrder = this.withExtendedNames(shapeId, best.order);
|
|
254
274
|
this.declaredOrderPriority.set(shapeId, best.priority);
|
|
255
275
|
}
|
|
256
276
|
for (const finalize of this.derivedDeclaredOrderFinalizers)
|
|
@@ -274,7 +294,7 @@ export class ShapeRegistry {
|
|
|
274
294
|
return;
|
|
275
295
|
const next = order();
|
|
276
296
|
if (next !== undefined)
|
|
277
|
-
shape.declaredOrder = next;
|
|
297
|
+
shape.declaredOrder = this.withExtendedNames(shape.id, next);
|
|
278
298
|
};
|
|
279
299
|
}
|
|
280
300
|
/** The shape id a back-reference to an in-progress type resolves to:
|
|
@@ -367,6 +387,52 @@ export class ShapeRegistry {
|
|
|
367
387
|
get(shapeId) {
|
|
368
388
|
return this.byId.get(shapeId);
|
|
369
389
|
}
|
|
390
|
+
/** Names extendShape added to a shape, which every key-order table the
|
|
391
|
+
* shape adopts lists after its declared names. */
|
|
392
|
+
extendedNames = new Map();
|
|
393
|
+
/** The members extendShape attached to a shape (empty for most). */
|
|
394
|
+
attachedNames(shapeId) {
|
|
395
|
+
return this.extendedNames.get(shapeId) ?? [];
|
|
396
|
+
}
|
|
397
|
+
withExtendedNames(shapeId, order) {
|
|
398
|
+
const extra = this.extendedNames.get(shapeId);
|
|
399
|
+
if (!extra)
|
|
400
|
+
return order;
|
|
401
|
+
const missing = extra.filter((name) => !order.includes(name));
|
|
402
|
+
return missing.length === 0 ? order : [...order, ...missing];
|
|
403
|
+
}
|
|
404
|
+
/** Adds optional fields to an interned shape in place: members a type
|
|
405
|
+
* assertion attaches to the shape's values (`r as R & { tag: string }`
|
|
406
|
+
* followed by `view.tag = ...`; see assertion-members.ts). Every value
|
|
407
|
+
* of the shape holds them absent until a write through such a view, so
|
|
408
|
+
* the shape keeps its id, both structural keys resolve to it, and its
|
|
409
|
+
* key-order table lists the new names after the declared ones. Runs
|
|
410
|
+
* before any body lowers; existing layouts change, so the revision
|
|
411
|
+
* advances like a closing recursive placeholder. */
|
|
412
|
+
extendShape(shapeId, extra) {
|
|
413
|
+
const shape = this.byId.get(shapeId);
|
|
414
|
+
if (!shape || shape.tuple || extra.length === 0)
|
|
415
|
+
return;
|
|
416
|
+
const fresh = extra.filter((f) => !shape.fields.some((x) => x.name === f.name));
|
|
417
|
+
if (fresh.length === 0)
|
|
418
|
+
return;
|
|
419
|
+
shape.fields = [...shape.fields, ...fresh].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
420
|
+
this.extendedNames.set(shapeId, [
|
|
421
|
+
...(this.extendedNames.get(shapeId) ?? []),
|
|
422
|
+
...fresh.map((f) => f.name),
|
|
423
|
+
]);
|
|
424
|
+
if (shape.declaredOrder)
|
|
425
|
+
shape.declaredOrder = this.withExtendedNames(shapeId, shape.declaredOrder);
|
|
426
|
+
const candidates = this.declaredOrderCandidates.get(shapeId);
|
|
427
|
+
if (candidates) {
|
|
428
|
+
for (const c of candidates)
|
|
429
|
+
c.order = this.withExtendedNames(shapeId, c.order);
|
|
430
|
+
}
|
|
431
|
+
this.revision++;
|
|
432
|
+
const key = this.keyOf(shape.fields, false, shape.indexValue);
|
|
433
|
+
if (!this.byKey.has(key))
|
|
434
|
+
this.byKey.set(key, shapeId);
|
|
435
|
+
}
|
|
370
436
|
}
|
|
371
437
|
/** The frontend's union interner — mirrors ShapeRegistry. A union's
|
|
372
438
|
* canonical identity includes its typeKey-sorted arms and literal
|
|
@@ -527,6 +593,7 @@ export function formatIrType(t, shapes, unions, seen = new Set()) {
|
|
|
527
593
|
case "bool":
|
|
528
594
|
return append("boolean");
|
|
529
595
|
case "dyn":
|
|
596
|
+
case "jsval":
|
|
530
597
|
return append("unknown");
|
|
531
598
|
case "caught":
|
|
532
599
|
// What tsc calls the binding; the fence messages carry the real story.
|
|
@@ -793,7 +860,7 @@ function isDeclaredInAmbientModule(d, name) {
|
|
|
793
860
|
/** True when the declaration's nearest enclosing namespace is `name`
|
|
794
861
|
* (`declare global { namespace NodeJS { ... } }` — the NodeJS-global
|
|
795
862
|
* interfaces @types/node declares outside any ambient module). */
|
|
796
|
-
function isDeclaredInAmbientNamespace(d, name) {
|
|
863
|
+
export function isDeclaredInAmbientNamespace(d, name) {
|
|
797
864
|
let node = d.parent;
|
|
798
865
|
while (node) {
|
|
799
866
|
if (ts.isModuleDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
@@ -803,6 +870,39 @@ function isDeclaredInAmbientNamespace(d, name) {
|
|
|
803
870
|
}
|
|
804
871
|
return false;
|
|
805
872
|
}
|
|
873
|
+
/** Whether `type` is one of the stream spellings the general stream
|
|
874
|
+
* representation (TypeMapperCtx.generalNodeStreams) maps differently:
|
|
875
|
+
* NodeJS.ReadableStream / NodeJS.WritableStream, @types/node's
|
|
876
|
+
* stream.Readable / stream.Writable, or the fallback declarations'
|
|
877
|
+
* ChildStdin. */
|
|
878
|
+
export function isGeneralNodeStreamInterface(type, ctx) {
|
|
879
|
+
const psym = type.getSymbol() ?? type.getAliasSymbol();
|
|
880
|
+
if (psym === undefined)
|
|
881
|
+
return false;
|
|
882
|
+
return psym.declarations.some((d) => {
|
|
883
|
+
if (!(ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)))
|
|
884
|
+
return false;
|
|
885
|
+
if (!ctx.isStdlibFile(ts.getSourceFileOfNode(d)))
|
|
886
|
+
return false;
|
|
887
|
+
if (ts.symbolName(psym) === "ReadableStream" || ts.symbolName(psym) === "WritableStream")
|
|
888
|
+
return ts.isInterfaceDeclaration(d) && isDeclaredInAmbientNamespace(d, "NodeJS");
|
|
889
|
+
if (ts.symbolName(psym) === "ChildStdin")
|
|
890
|
+
return isDeclaredInAmbientModule(d, "child_process");
|
|
891
|
+
return ((ts.symbolName(psym) === "Readable" || ts.symbolName(psym) === "Writable") &&
|
|
892
|
+
isNodeTypesPath(ts.getSourceFileOfNode(d).fileName) &&
|
|
893
|
+
isDeclaredInAmbientModule(d, "stream"));
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
/** A type declared in the shipped WebAssembly namespace (scriptc.d.ts):
|
|
897
|
+
* its modules, instances, memories, tables, globals, error classes and the
|
|
898
|
+
* Exports/Imports records. */
|
|
899
|
+
export function isWebAssemblyType(type, ctx) {
|
|
900
|
+
const symbol = type.getAliasSymbol() ?? type.getSymbol();
|
|
901
|
+
if (!symbol)
|
|
902
|
+
return false;
|
|
903
|
+
return symbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
904
|
+
isDeclaredInAmbientNamespace(d, "WebAssembly"));
|
|
905
|
+
}
|
|
806
906
|
/** True when a type contains a record anywhere (the trigger for the
|
|
807
907
|
* shape-mismatch diagnostic SC2002 — non-record mismatches are tsc's or
|
|
808
908
|
* the validator's business). */
|
|
@@ -928,8 +1028,8 @@ export function isLegacyUrlType(type, ctx) {
|
|
|
928
1028
|
export function isLegacyUrlSymbol(symbol, ctx) {
|
|
929
1029
|
if (!symbol)
|
|
930
1030
|
return false;
|
|
931
|
-
for (const d of
|
|
932
|
-
if (!ctx.isStdlibFile(
|
|
1031
|
+
for (const d of symbol.declarations) {
|
|
1032
|
+
if (!ctx.isStdlibFile(ts.getSourceFileOfNode(d)))
|
|
933
1033
|
continue;
|
|
934
1034
|
let family = false;
|
|
935
1035
|
for (let n = d; n; n = n.parent) {
|
|
@@ -958,10 +1058,11 @@ export function isOsConstantsType(type, ctx) {
|
|
|
958
1058
|
export function isOsConstantsSymbol(symbol, ctx, types = false) {
|
|
959
1059
|
if (!symbol)
|
|
960
1060
|
return false;
|
|
961
|
-
for (const d of
|
|
1061
|
+
for (const d of symbol.declarations) {
|
|
962
1062
|
const alias = types && ts.isTypeAliasDeclaration(d) && d.name.text === "SignalConstants";
|
|
963
1063
|
const signals = !types && ts.isVariableDeclaration(d) && ts.isIdentifier(d.name) && d.name.text === "signals";
|
|
964
|
-
if (!(alias || signals || ts.isModuleDeclaration(d)) ||
|
|
1064
|
+
if (!(alias || signals || ts.isModuleDeclaration(d)) ||
|
|
1065
|
+
!ctx.isStdlibFile(ts.getSourceFileOfNode(d)))
|
|
965
1066
|
continue;
|
|
966
1067
|
let inConstants = ts.isModuleDeclaration(d) && d.name.text === "constants";
|
|
967
1068
|
for (let n = d.parent; n; n = n.parent) {
|
|
@@ -981,13 +1082,163 @@ export function isOsConstantsSymbol(symbol, ctx, types = false) {
|
|
|
981
1082
|
/** worker_threads' Worker and MessagePort: owned runtime handles that keep
|
|
982
1083
|
* their live object representation (DYN) wherever they are stored. */
|
|
983
1084
|
function isWorkerHandleSymbol(symbol, ctx) {
|
|
984
|
-
return ((symbol
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1085
|
+
return (((symbol !== undefined && ts.symbolName(symbol) === "Worker") ||
|
|
1086
|
+
(symbol !== undefined && ts.symbolName(symbol) === "MessagePort") ||
|
|
1087
|
+
(symbol !== undefined && ts.symbolName(symbol) === "MessageChannel") ||
|
|
1088
|
+
(symbol !== undefined && ts.symbolName(symbol) === "BroadcastChannel")) &&
|
|
1089
|
+
symbol.declarations.some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
1090
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
989
1091
|
isDeclaredInAmbientModule(d, "worker_threads")));
|
|
990
1092
|
}
|
|
1093
|
+
/** The `{ message: any }` object type (or its union with undefined) that
|
|
1094
|
+
* worker_threads declares as receiveMessageOnPort's result. */
|
|
1095
|
+
/** A union of dns lookup option bags with numbers and nullish values that
|
|
1096
|
+
* includes LookupAllOptions (whose `all: true` arm has no record form). */
|
|
1097
|
+
function isLookupOptionsUnion(type, ctx) {
|
|
1098
|
+
if (!type.isUnionType())
|
|
1099
|
+
return false;
|
|
1100
|
+
let all = false;
|
|
1101
|
+
for (const member of ts.constituentTypes(type)) {
|
|
1102
|
+
if (member.flags & (ts.TypeFlags.NumberLike | ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
1103
|
+
continue;
|
|
1104
|
+
const symbol = member.getSymbol();
|
|
1105
|
+
if (symbol === undefined ||
|
|
1106
|
+
!/^Lookup(One|All)?Options$/.test(ts.symbolName(symbol)) ||
|
|
1107
|
+
!symbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
1108
|
+
return false;
|
|
1109
|
+
if (ts.symbolName(symbol) === "LookupAllOptions")
|
|
1110
|
+
all = true;
|
|
1111
|
+
}
|
|
1112
|
+
return all;
|
|
1113
|
+
}
|
|
1114
|
+
/** The binary and stream members of fetch's BodyInit (undici-types):
|
|
1115
|
+
* NodeJS.ArrayBufferView expands to the typed arrays and DataView. */
|
|
1116
|
+
const FETCH_BODY_MEMBERS = new Set([
|
|
1117
|
+
"ArrayBuffer",
|
|
1118
|
+
"SharedArrayBuffer",
|
|
1119
|
+
"AsyncIterable",
|
|
1120
|
+
"Iterable",
|
|
1121
|
+
"Blob",
|
|
1122
|
+
"FormData",
|
|
1123
|
+
"URLSearchParams",
|
|
1124
|
+
"ReadableStream",
|
|
1125
|
+
"DataView",
|
|
1126
|
+
"Buffer",
|
|
1127
|
+
"Int8Array",
|
|
1128
|
+
"Uint8Array",
|
|
1129
|
+
"Uint8ClampedArray",
|
|
1130
|
+
"Int16Array",
|
|
1131
|
+
"Uint16Array",
|
|
1132
|
+
"Int32Array",
|
|
1133
|
+
"Uint32Array",
|
|
1134
|
+
"Float16Array",
|
|
1135
|
+
"Float32Array",
|
|
1136
|
+
"Float64Array",
|
|
1137
|
+
"BigInt64Array",
|
|
1138
|
+
"BigUint64Array",
|
|
1139
|
+
]);
|
|
1140
|
+
/** fetch's request body type, BodyInit, however TypeScript spells it
|
|
1141
|
+
* (`RequestInit["body"]`, `NonNullable<...>`, an optional member): a
|
|
1142
|
+
* union of strings, the stdlib binary and stream types and nullish
|
|
1143
|
+
* values that includes both FormData and URLSearchParams. Native fetch
|
|
1144
|
+
* reads such a body at run time, so it rides checked-dynamic storage. */
|
|
1145
|
+
function isFetchBodyUnion(type, ctx) {
|
|
1146
|
+
if (!type.isUnionType())
|
|
1147
|
+
return false;
|
|
1148
|
+
let formData = false;
|
|
1149
|
+
let searchParams = false;
|
|
1150
|
+
for (const member of ts.constituentTypes(type)) {
|
|
1151
|
+
if (member.flags & (ts.TypeFlags.StringLike | ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
1152
|
+
continue;
|
|
1153
|
+
const symbol = member.getSymbol();
|
|
1154
|
+
if (symbol === undefined ||
|
|
1155
|
+
!FETCH_BODY_MEMBERS.has(ts.symbolName(symbol)) ||
|
|
1156
|
+
!symbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
1157
|
+
return false;
|
|
1158
|
+
if (ts.symbolName(symbol) === "FormData")
|
|
1159
|
+
formData = true;
|
|
1160
|
+
if (ts.symbolName(symbol) === "URLSearchParams")
|
|
1161
|
+
searchParams = true;
|
|
1162
|
+
}
|
|
1163
|
+
return formData && searchParams;
|
|
1164
|
+
}
|
|
1165
|
+
/** A mapped object type (Omit, Pick, Partial) whose members all come from
|
|
1166
|
+
* one stdlib interface that maps to the checked dynamic. */
|
|
1167
|
+
function isDynInterfaceSubset(type, ctx) {
|
|
1168
|
+
if (!(type.flags & ts.TypeFlags.Object) || type.isClassOrInterface())
|
|
1169
|
+
return false;
|
|
1170
|
+
const alias = type.getAliasSymbol();
|
|
1171
|
+
if (alias === undefined)
|
|
1172
|
+
return false;
|
|
1173
|
+
const props = ctx.checker.getPropertiesOfType(type);
|
|
1174
|
+
if (props.length === 0)
|
|
1175
|
+
return false;
|
|
1176
|
+
let owner;
|
|
1177
|
+
for (const prop of props) {
|
|
1178
|
+
const decl = prop.declarations[0];
|
|
1179
|
+
const parent = decl?.parent;
|
|
1180
|
+
if (parent === undefined ||
|
|
1181
|
+
!ts.isInterfaceDeclaration(parent) ||
|
|
1182
|
+
!ctx.isStdlibFile(ts.getSourceFileOfNode(parent)) ||
|
|
1183
|
+
(owner !== undefined && owner !== parent))
|
|
1184
|
+
return false;
|
|
1185
|
+
owner = parent;
|
|
1186
|
+
}
|
|
1187
|
+
return (owner !== undefined && mapType(ctx.checker.getTypeAtLocation(owner.name), ctx)?.kind === "dyn");
|
|
1188
|
+
}
|
|
1189
|
+
/** fetch's HeadersInit (undici-types): a union of the stdlib Headers
|
|
1190
|
+
* class with header-pair arrays and/or a header record, plus nullish
|
|
1191
|
+
* values. Native fetch reads it at run time like the init around it. */
|
|
1192
|
+
function isFetchHeadersUnion(type, ctx) {
|
|
1193
|
+
if (!type.isUnionType())
|
|
1194
|
+
return false;
|
|
1195
|
+
let headers = false;
|
|
1196
|
+
let other = false;
|
|
1197
|
+
for (const member of ts.constituentTypes(type)) {
|
|
1198
|
+
if (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
1199
|
+
continue;
|
|
1200
|
+
const symbol = member.getSymbol();
|
|
1201
|
+
if (symbol !== undefined &&
|
|
1202
|
+
ts.symbolName(symbol) === "Headers" &&
|
|
1203
|
+
symbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1204
|
+
headers = true;
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
const alias = ts.symbolNameOf(member.getAliasSymbol());
|
|
1208
|
+
if ((symbol !== undefined && ts.symbolName(symbol) === "Array") ||
|
|
1209
|
+
(symbol !== undefined && ts.symbolName(symbol) === "ReadonlyArray") ||
|
|
1210
|
+
alias === "Record" ||
|
|
1211
|
+
alias === "HeaderRecord") {
|
|
1212
|
+
other = true;
|
|
1213
|
+
continue;
|
|
1214
|
+
}
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
return headers && other;
|
|
1218
|
+
}
|
|
1219
|
+
function isReceiveMessageResult(type, ctx) {
|
|
1220
|
+
const members = type.isUnionType() ? ts.constituentTypes(type) : [type];
|
|
1221
|
+
let found = false;
|
|
1222
|
+
for (const member of members) {
|
|
1223
|
+
if (member.flags & ts.TypeFlags.Undefined)
|
|
1224
|
+
continue;
|
|
1225
|
+
const decl = member.getSymbol() ? member.getSymbol().declarations[0] : undefined;
|
|
1226
|
+
let fn = decl?.parent;
|
|
1227
|
+
while (fn && ts.isUnionTypeNode(fn))
|
|
1228
|
+
fn = fn.parent;
|
|
1229
|
+
if (!decl ||
|
|
1230
|
+
!ts.isTypeLiteralNode(decl) ||
|
|
1231
|
+
!fn ||
|
|
1232
|
+
!ts.isFunctionDeclaration(fn) ||
|
|
1233
|
+
fn.name?.text !== "receiveMessageOnPort" ||
|
|
1234
|
+
!ctx.isStdlibFile(ts.getSourceFileOfNode(decl)) ||
|
|
1235
|
+
!isDeclaredInAmbientModule(fn, "worker_threads")) {
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
found = true;
|
|
1239
|
+
}
|
|
1240
|
+
return found;
|
|
1241
|
+
}
|
|
991
1242
|
/** True for a type built only from worker handles, null/undefined, and
|
|
992
1243
|
* arrays of those: values that keep the live DYN representation. */
|
|
993
1244
|
export function isWorkerHandleType(type, ctx) {
|
|
@@ -1008,6 +1259,57 @@ export function isWorkerHandleType(type, ctx) {
|
|
|
1008
1259
|
}
|
|
1009
1260
|
return handle;
|
|
1010
1261
|
}
|
|
1262
|
+
/** The return annotation of an `async *` declaration spelled with the
|
|
1263
|
+
* protocol interfaces the generator object implements —
|
|
1264
|
+
* `AsyncIterator<T>`, `AsyncIterableIterator<T>` or `AsyncIterable<T>` (pi's
|
|
1265
|
+
* `async *[Symbol.asyncIterator](): AsyncIterator<T>`): the body always
|
|
1266
|
+
* produces an async generator, so the declaration maps exactly like an
|
|
1267
|
+
* `AsyncGenerator<T, TReturn, TNext>` annotation. Values of these types
|
|
1268
|
+
* elsewhere stay unmapped (they can hold any object implementing the
|
|
1269
|
+
* protocol). Null when the annotation is not one of them. */
|
|
1270
|
+
export function mapAsyncGeneratorAnnotation(type, ctx) {
|
|
1271
|
+
const { checker } = ctx;
|
|
1272
|
+
const symbol = type.getSymbol();
|
|
1273
|
+
if (!symbol ||
|
|
1274
|
+
!["AsyncIterator", "AsyncIterableIterator", "AsyncIterable"].includes(ts.symbolName(symbol)) ||
|
|
1275
|
+
!symbol.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
1276
|
+
return null;
|
|
1277
|
+
const args = checker.getTypeArguments(type);
|
|
1278
|
+
const channels = genChannels(args[0], args[1], args[2], ctx);
|
|
1279
|
+
if (!channels)
|
|
1280
|
+
return null;
|
|
1281
|
+
if (!genResultRecord(channels.yieldT, channels.retT, ctx.shapes, ctx.unions))
|
|
1282
|
+
return null;
|
|
1283
|
+
return { kind: "generator", async: true, ...channels };
|
|
1284
|
+
}
|
|
1285
|
+
/** The native fetch handles (Headers, Request, Response), optionally in
|
|
1286
|
+
* arrays or with null/undefined: checked-dynamic handles wherever they are
|
|
1287
|
+
* stored, like the worker handles above. */
|
|
1288
|
+
export function isFetchHandleType(type, ctx) {
|
|
1289
|
+
const members = type.isUnionType() ? ts.constituentTypes(type) : [type];
|
|
1290
|
+
let handle = false;
|
|
1291
|
+
for (const member of members) {
|
|
1292
|
+
if (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
1293
|
+
continue;
|
|
1294
|
+
if (ctx.checker.isArrayType(member)) {
|
|
1295
|
+
const element = ctx.checker.getTypeArguments(member)[0];
|
|
1296
|
+
if (element === undefined || !isFetchHandleType(element, ctx))
|
|
1297
|
+
return false;
|
|
1298
|
+
}
|
|
1299
|
+
else {
|
|
1300
|
+
const symbol = member.getSymbol();
|
|
1301
|
+
if (!symbol ||
|
|
1302
|
+
(ts.symbolName(symbol) !== "Headers" &&
|
|
1303
|
+
ts.symbolName(symbol) !== "Request" &&
|
|
1304
|
+
ts.symbolName(symbol) !== "Response") ||
|
|
1305
|
+
!symbol.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
1306
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
handle = true;
|
|
1310
|
+
}
|
|
1311
|
+
return handle;
|
|
1312
|
+
}
|
|
1011
1313
|
export function mapType(type, ctx) {
|
|
1012
1314
|
if (mapTypeDepth >= MAP_TYPE_MAX_DEPTH)
|
|
1013
1315
|
return null;
|
|
@@ -1035,7 +1337,18 @@ export function mapType(type, ctx) {
|
|
|
1035
1337
|
const sensitivityAtEntry = contextResolutions;
|
|
1036
1338
|
mapTypeDepth++;
|
|
1037
1339
|
try {
|
|
1038
|
-
|
|
1340
|
+
let mapped;
|
|
1341
|
+
try {
|
|
1342
|
+
mapped = mapTypeInner(type, ctx);
|
|
1343
|
+
}
|
|
1344
|
+
catch (e) {
|
|
1345
|
+
// typescript-go's API can panic serializing a union's members (an
|
|
1346
|
+
// empty tuple cloned as an array literal, `s.match(re) || []`): a
|
|
1347
|
+
// union the checker cannot describe has no representation.
|
|
1348
|
+
if (!topLevel || !ts.isUnreadableConstituentsPanic(e))
|
|
1349
|
+
throw e;
|
|
1350
|
+
mapped = null;
|
|
1351
|
+
}
|
|
1039
1352
|
if (mapped !== null &&
|
|
1040
1353
|
memoKey !== null &&
|
|
1041
1354
|
topLevel &&
|
|
@@ -1058,34 +1371,135 @@ function classExprNeedsContext(decl) {
|
|
|
1058
1371
|
}
|
|
1059
1372
|
return false;
|
|
1060
1373
|
}
|
|
1374
|
+
/** True for the type of a TypeScript object literal with no contextual
|
|
1375
|
+
* type (`const options = { ...location, path }`) that spreads a value
|
|
1376
|
+
* mapping to the checked dynamic (a stdlib options type such as
|
|
1377
|
+
* http.RequestOptions). A literal with a contextual type is built in that
|
|
1378
|
+
* type's representation instead, and JavaScript literals keep their own
|
|
1379
|
+
* rules. */
|
|
1380
|
+
function spreadsCheckedDynamic(symbol, ctx) {
|
|
1381
|
+
if (symbol === undefined || (symbol.flags & ts.SymbolFlags.ObjectLiteral) === 0)
|
|
1382
|
+
return false;
|
|
1383
|
+
const decl = symbol.declarations[0];
|
|
1384
|
+
if (decl === undefined || !ts.isObjectLiteralExpression(decl))
|
|
1385
|
+
return false;
|
|
1386
|
+
if (isJsSourceFile(ts.getSourceFileOfNode(decl)))
|
|
1387
|
+
return false;
|
|
1388
|
+
if (ctx.checker.getContextualType(decl))
|
|
1389
|
+
return false;
|
|
1390
|
+
return decl.properties.nodes.some((prop) => ts.isSpreadAssignment(prop) &&
|
|
1391
|
+
mapType(ctx.checker.getTypeAtLocation(prop.expression), ctx)?.kind === "dyn");
|
|
1392
|
+
}
|
|
1061
1393
|
function mapTypeInner(type, ctx) {
|
|
1062
1394
|
const { checker, unions, classNamer, resolveTypeParam } = ctx;
|
|
1063
1395
|
// TypeScript's intrinsic globalThis symbol has no declaration. A stored
|
|
1064
1396
|
// reference needs native object identity, including var's undefined state.
|
|
1065
1397
|
const intrinsic = type.getSymbol();
|
|
1066
|
-
if (intrinsic
|
|
1398
|
+
if (intrinsic !== undefined &&
|
|
1399
|
+
ts.symbolName(intrinsic) === "globalThis" &&
|
|
1400
|
+
intrinsic.declarations.length === 0)
|
|
1067
1401
|
return DYN;
|
|
1402
|
+
if (ctx.jsDynamicDeclaration !== undefined && intrinsic !== undefined) {
|
|
1403
|
+
const objectLiteral = (intrinsic.flags & ts.SymbolFlags.ObjectLiteral) !== 0;
|
|
1404
|
+
const classInstance = (intrinsic.flags & ts.SymbolFlags.Class) !== 0 && type.isClassOrInterface();
|
|
1405
|
+
if ((objectLiteral || classInstance) &&
|
|
1406
|
+
intrinsic.declarations.some((decl) => ctx.jsDynamicDeclaration(decl)))
|
|
1407
|
+
return DYN;
|
|
1408
|
+
}
|
|
1068
1409
|
{
|
|
1069
1410
|
const moduleId = ctx.moduleNamespaceId?.(type) ?? null;
|
|
1070
1411
|
if (moduleId !== null)
|
|
1071
1412
|
return { kind: "moduleNs", moduleId };
|
|
1072
1413
|
}
|
|
1414
|
+
// A TypeScript object literal that spreads a checked-dynamic value
|
|
1415
|
+
// (`{ ...requestOptions, path, timeout }`): its keys are the source's
|
|
1416
|
+
// runtime keys, which no record shape holds, so the literal rides
|
|
1417
|
+
// checked-dynamic storage like its source.
|
|
1418
|
+
if (spreadsCheckedDynamic(intrinsic, ctx))
|
|
1419
|
+
return DYN;
|
|
1420
|
+
// worker_threads.receiveMessageOnPort's `{ message: any } | undefined`:
|
|
1421
|
+
// the runtime's { message } object, a checked-dynamic value.
|
|
1422
|
+
if (isReceiveMessageResult(type, ctx))
|
|
1423
|
+
return DYN;
|
|
1424
|
+
if (isFetchBodyUnion(type, ctx) || isFetchHeadersUnion(type, ctx))
|
|
1425
|
+
return DYN;
|
|
1426
|
+
// Omit/Pick/Partial of a stdlib interface that rides checked-dynamic
|
|
1427
|
+
// storage (`Omit<RequestInit, "body" | "headers">`): every member comes
|
|
1428
|
+
// from that interface, so the value is a subset of the same runtime-read
|
|
1429
|
+
// options object and rides the same storage.
|
|
1430
|
+
if (isDynInterfaceSubset(type, ctx))
|
|
1431
|
+
return DYN;
|
|
1432
|
+
// The lookup-function option union (`LookupOneOptions | LookupAllOptions
|
|
1433
|
+
// | number | undefined`): with a LookupAllOptions arm it is an option bag
|
|
1434
|
+
// dns.lookup reads at run time, so it rides checked-dynamic storage.
|
|
1435
|
+
if (isLookupOptionsUnion(type, ctx))
|
|
1436
|
+
return DYN;
|
|
1073
1437
|
// @types/node spells child_process.ExecFileException as an intersection
|
|
1074
1438
|
// type alias over two Error-derived metadata interfaces. The value is
|
|
1075
1439
|
// still one ordinary Error; recognize the owned alias before generic
|
|
1076
1440
|
// intersection mapping decomposes it into unsupported utility types.
|
|
1077
1441
|
const directAlias = type.getAliasSymbol();
|
|
1078
|
-
if (directAlias
|
|
1079
|
-
|
|
1442
|
+
if (directAlias !== undefined &&
|
|
1443
|
+
ts.symbolName(directAlias) === "ExecFileException" &&
|
|
1444
|
+
directAlias.declarations.some((decl) => ctx.isStdlibFile(ts.getSourceFileOfNode(decl)))) {
|
|
1445
|
+
return { kind: "object", className: "%Error" };
|
|
1446
|
+
}
|
|
1447
|
+
// child_process.ExecException, exec's callback error, is an interface
|
|
1448
|
+
// extending Error with optional metadata members; the value is one
|
|
1449
|
+
// ordinary Error as well.
|
|
1450
|
+
const execException = type.getSymbol();
|
|
1451
|
+
if (execException !== undefined &&
|
|
1452
|
+
ts.symbolName(execException) === "ExecException" &&
|
|
1453
|
+
execException.declarations.some((decl) => ts.isInterfaceDeclaration(decl) &&
|
|
1454
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(decl)) &&
|
|
1455
|
+
isDeclaredInAmbientModule(decl, "child_process"))) {
|
|
1080
1456
|
return { kind: "object", className: "%Error" };
|
|
1081
1457
|
}
|
|
1082
1458
|
if (isOsConstantsType(type, ctx) || isLegacyUrlType(type, ctx))
|
|
1083
1459
|
return DYN;
|
|
1460
|
+
// The WebAssembly API's values have the checked-dynamic representation, so
|
|
1461
|
+
// declarations that merely mention them compile; each reached use of the
|
|
1462
|
+
// API itself is refused at its site (builtins/webassembly.ts).
|
|
1463
|
+
if (isWebAssemblyType(type, ctx))
|
|
1464
|
+
return DYN;
|
|
1465
|
+
// A union over one of them (quickjs-wasi's `BufferSource | WebAssembly.Module`
|
|
1466
|
+
// option) holds that dynamic value too, so the whole union is dynamic.
|
|
1467
|
+
if (type.isUnionType() && ts.constituentTypes(type).some((t) => isWebAssemblyType(t, ctx)))
|
|
1468
|
+
return DYN;
|
|
1469
|
+
// JavaScript inference merges WebAssembly.instantiate's overloads into
|
|
1470
|
+
// `Promise<WebAssemblyInstantiatedSource> & Promise<Instance>`: a promise
|
|
1471
|
+
// of a WebAssembly value either way.
|
|
1472
|
+
if (type.isIntersectionType() &&
|
|
1473
|
+
ts.constituentTypes(type).every((t) => {
|
|
1474
|
+
if (ts.symbolNameOf(t.getSymbol()) !== "Promise")
|
|
1475
|
+
return false;
|
|
1476
|
+
const arg = ctx.checker.getTypeArguments(t)[0];
|
|
1477
|
+
return arg !== undefined && isWebAssemblyType(arg, ctx);
|
|
1478
|
+
}))
|
|
1479
|
+
return { kind: "promise", inner: DYN };
|
|
1084
1480
|
// Immutable<T> (@scriptc/types) is a deep-readonly view: the value is
|
|
1085
1481
|
// still the T it maps.
|
|
1086
1482
|
const immutableSource = immutableSourceType(type, ctx);
|
|
1087
1483
|
if (immutableSource !== null)
|
|
1088
1484
|
return mapType(immutableSource, ctx);
|
|
1485
|
+
// Inside an erased generic signature or body, every type that mentions
|
|
1486
|
+
// an erased type parameter is `unknown` (`T[]`, `Map<string, T>`,
|
|
1487
|
+
// `[A, B]`, `T[K]`, callbacks over `T`): its values cross through the
|
|
1488
|
+
// checked-dynamic boundary, as JavaScript sees them. The erased
|
|
1489
|
+
// signature itself maps its parameters and result this way.
|
|
1490
|
+
if ((ctx.erasingSignature || ctx.isErasing?.()) &&
|
|
1491
|
+
!(type.flags & ts.TypeFlags.TypeParameter) &&
|
|
1492
|
+
!checker.getCallSignatures(type).some((sig) => sig === ctx.erasingSignature) &&
|
|
1493
|
+
!ERASURE_KEPT_CONTAINERS.has(ts.symbolNameOf(type.getSymbol()) ?? "") &&
|
|
1494
|
+
mentionsErasedTypeParam(type, ctx, 0)) {
|
|
1495
|
+
contextResolutions++;
|
|
1496
|
+
return DYN;
|
|
1497
|
+
}
|
|
1498
|
+
// Readonly<C> over a program class (Object.freeze's result type) is the
|
|
1499
|
+
// same instance.
|
|
1500
|
+
const readonlyClass = readonlyClassType(type, ctx);
|
|
1501
|
+
if (readonlyClass !== null)
|
|
1502
|
+
return readonlyClass;
|
|
1089
1503
|
if (resolveTypeParam && type.flags & ts.TypeFlags.TypeParameter) {
|
|
1090
1504
|
const bound = resolveTypeParam(type);
|
|
1091
1505
|
if (bound) {
|
|
@@ -1124,6 +1538,27 @@ function mapTypeInner(type, ctx) {
|
|
|
1124
1538
|
contextResolutions++;
|
|
1125
1539
|
return viaIndexed;
|
|
1126
1540
|
}
|
|
1541
|
+
// `Parameters<F>` / `ReturnType<F>` over a bound function-typed
|
|
1542
|
+
// parameter (variadic higher-order wrappers): the checker keeps both
|
|
1543
|
+
// conditionals symbolic inside the body, and their `infer` positions
|
|
1544
|
+
// match a call signature, which matchInferReference cannot decide.
|
|
1545
|
+
const viaSignature = mapBoundSignatureAlias(type, ctx) ?? mapBoundKeyofNeverConditional(type, ctx);
|
|
1546
|
+
if (viaSignature !== null) {
|
|
1547
|
+
contextResolutions++;
|
|
1548
|
+
return viaSignature;
|
|
1549
|
+
}
|
|
1550
|
+
// A conditional type over a bound parameter (`Infer<S["left"]>`, a
|
|
1551
|
+
// mapped type's member): evaluate it against the bindings.
|
|
1552
|
+
if (type.isConditionalType()) {
|
|
1553
|
+
const evaluated = evalMappedTemplate(type, new Map(), new Map(), ctx);
|
|
1554
|
+
if (evaluated && evaluated !== type) {
|
|
1555
|
+
const viaConditional = mapType(evaluated, ctx);
|
|
1556
|
+
if (viaConditional !== null) {
|
|
1557
|
+
contextResolutions++;
|
|
1558
|
+
return viaConditional;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1127
1562
|
}
|
|
1128
1563
|
const widened = checker.getBaseTypeOfLiteralType(type);
|
|
1129
1564
|
const flags = widened.flags;
|
|
@@ -1138,8 +1573,9 @@ function mapTypeInner(type, ctx) {
|
|
|
1138
1573
|
// checked-dynamic object retains that distinction through forwarding
|
|
1139
1574
|
// constructors. Only the standard library's interface gets this ABI.
|
|
1140
1575
|
const errorOptionsSymbol = widened.getSymbol();
|
|
1141
|
-
if (errorOptionsSymbol
|
|
1142
|
-
|
|
1576
|
+
if (errorOptionsSymbol !== undefined &&
|
|
1577
|
+
ts.symbolName(errorOptionsSymbol) === "ErrorOptions" &&
|
|
1578
|
+
errorOptionsSymbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1143
1579
|
return DYN;
|
|
1144
1580
|
}
|
|
1145
1581
|
// node:util.parseArgs config/results are declaration-heavy conditional
|
|
@@ -1153,7 +1589,7 @@ function mapTypeInner(type, ctx) {
|
|
|
1153
1589
|
{
|
|
1154
1590
|
const parseArgsSym = widened.getAliasSymbol() ?? widened.getSymbol();
|
|
1155
1591
|
const belongs = (declaration) => {
|
|
1156
|
-
if (!ctx.isStdlibFile(
|
|
1592
|
+
if (!ctx.isStdlibFile(ts.getSourceFileOfNode(declaration)))
|
|
1157
1593
|
return false;
|
|
1158
1594
|
let family = false;
|
|
1159
1595
|
for (let node = declaration; node; node = node.parent) {
|
|
@@ -1167,15 +1603,14 @@ function mapTypeInner(type, ctx) {
|
|
|
1167
1603
|
return false;
|
|
1168
1604
|
};
|
|
1169
1605
|
if (parseArgsSym &&
|
|
1170
|
-
PARSE_ARGS_DYN_TYPES.has(parseArgsSym
|
|
1171
|
-
|
|
1606
|
+
PARSE_ARGS_DYN_TYPES.has(ts.symbolName(parseArgsSym)) &&
|
|
1607
|
+
parseArgsSym.declarations.some(belongs))
|
|
1172
1608
|
return DYN;
|
|
1173
1609
|
// ReturnType and instantiated conditional types can erase the alias.
|
|
1174
1610
|
// Require every member to retain the util declaration provenance so
|
|
1175
1611
|
// unrelated records with similar property names keep their own layout.
|
|
1176
1612
|
const members = checker.getPropertiesOfType(widened);
|
|
1177
|
-
if (members.length > 0 &&
|
|
1178
|
-
members.every((member) => checker.declarationsOf(member).some(belongs)))
|
|
1613
|
+
if (members.length > 0 && members.every((member) => member.declarations.some(belongs)))
|
|
1179
1614
|
return DYN;
|
|
1180
1615
|
}
|
|
1181
1616
|
// The lib's BOXED wrapper interfaces used as TYPES (`const n: Number =
|
|
@@ -1186,9 +1621,15 @@ function mapTypeInner(type, ctx) {
|
|
|
1186
1621
|
{
|
|
1187
1622
|
const boxSym = widened.getSymbol();
|
|
1188
1623
|
if (boxSym &&
|
|
1189
|
-
(boxSym
|
|
1190
|
-
|
|
1191
|
-
|
|
1624
|
+
(ts.symbolName(boxSym) === "Number" ||
|
|
1625
|
+
ts.symbolName(boxSym) === "String" ||
|
|
1626
|
+
ts.symbolName(boxSym) === "Boolean") &&
|
|
1627
|
+
boxSym.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1628
|
+
return ts.symbolName(boxSym) === "Number"
|
|
1629
|
+
? F64
|
|
1630
|
+
: ts.symbolName(boxSym) === "String"
|
|
1631
|
+
? STRING
|
|
1632
|
+
: BOOL;
|
|
1192
1633
|
}
|
|
1193
1634
|
}
|
|
1194
1635
|
// The lib's PRIMITIVE-CONSTRUCTOR interfaces as TYPES (`typeof String`,
|
|
@@ -1205,13 +1646,13 @@ function mapTypeInner(type, ctx) {
|
|
|
1205
1646
|
{
|
|
1206
1647
|
const ctorSym = widened.getSymbol();
|
|
1207
1648
|
if (ctorSym &&
|
|
1208
|
-
(ctorSym
|
|
1209
|
-
ctorSym
|
|
1210
|
-
ctorSym
|
|
1211
|
-
|
|
1212
|
-
return funcOf([STRING], ctorSym
|
|
1649
|
+
(ts.symbolName(ctorSym) === "StringConstructor" ||
|
|
1650
|
+
ts.symbolName(ctorSym) === "NumberConstructor" ||
|
|
1651
|
+
ts.symbolName(ctorSym) === "BooleanConstructor") &&
|
|
1652
|
+
ctorSym.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1653
|
+
return funcOf([STRING], ts.symbolName(ctorSym) === "StringConstructor"
|
|
1213
1654
|
? STRING
|
|
1214
|
-
: ctorSym
|
|
1655
|
+
: ts.symbolName(ctorSym) === "NumberConstructor"
|
|
1215
1656
|
? F64
|
|
1216
1657
|
: BOOL);
|
|
1217
1658
|
}
|
|
@@ -1315,16 +1756,21 @@ function mapTypeInner(type, ctx) {
|
|
|
1315
1756
|
return hasStr ? STRING : F64;
|
|
1316
1757
|
}
|
|
1317
1758
|
}
|
|
1318
|
-
// @scriptc/experimental's LifetimeRegion and
|
|
1319
|
-
// program classes, provenance-checked by the package's
|
|
1759
|
+
// @scriptc/experimental's LifetimeRegion, InternTable and ThreadSlots:
|
|
1760
|
+
// synthetic program classes, provenance-checked by the package's
|
|
1761
|
+
// declaration file.
|
|
1320
1762
|
{
|
|
1321
1763
|
const classSym = widened.getSymbol();
|
|
1322
|
-
const name = classSym
|
|
1323
|
-
if (name === "LifetimeRegion" || name === "InternTable") {
|
|
1324
|
-
for (const d of
|
|
1764
|
+
const name = ts.symbolNameOf(classSym);
|
|
1765
|
+
if (name === "LifetimeRegion" || name === "InternTable" || name === "ThreadSlots") {
|
|
1766
|
+
for (const d of classSym.declarations) {
|
|
1325
1767
|
if (!ts.isClassDeclaration(d))
|
|
1326
1768
|
continue;
|
|
1327
|
-
const synthetic = name === "LifetimeRegion"
|
|
1769
|
+
const synthetic = name === "LifetimeRegion"
|
|
1770
|
+
? ctx.lifetimeRegionClass?.(d)
|
|
1771
|
+
: name === "InternTable"
|
|
1772
|
+
? ctx.internTableClass?.(d)
|
|
1773
|
+
: ctx.threadSlotsClass?.(d);
|
|
1328
1774
|
if (synthetic)
|
|
1329
1775
|
return synthetic;
|
|
1330
1776
|
}
|
|
@@ -1333,15 +1779,33 @@ function mapTypeInner(type, ctx) {
|
|
|
1333
1779
|
// Declaration-only package types have no compiled implementation.
|
|
1334
1780
|
// Primitive and container types retain their structural mappings; types
|
|
1335
1781
|
// owned by the standard library or explicit host mappings are handled
|
|
1336
|
-
// by their dedicated native rules.
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1782
|
+
// by their dedicated native rules. Pure type shapes — interfaces, type
|
|
1783
|
+
// aliases, and object or mapped type literals with no value declaration
|
|
1784
|
+
// merged in — describe data, not an implementation: a program value of
|
|
1785
|
+
// such a type is one the program built itself (`import type` from a
|
|
1786
|
+
// types-only package), so it maps structurally like a local declaration.
|
|
1787
|
+
// Values the package itself would produce stay refused at their import.
|
|
1788
|
+
const packageOnly = (sym) => {
|
|
1789
|
+
const decls = sym ? sym.declarations : undefined;
|
|
1790
|
+
return decls &&
|
|
1791
|
+
decls.length > 0 &&
|
|
1792
|
+
decls.every((d) => {
|
|
1793
|
+
const sf = ts.getSourceFileOfNode(d);
|
|
1794
|
+
return sf.isDeclarationFile && !ctx.isStdlibFile(sf) && !ctx.isExternalTypeFile(sf);
|
|
1795
|
+
})
|
|
1796
|
+
? decls
|
|
1797
|
+
: null;
|
|
1798
|
+
};
|
|
1799
|
+
const pureTypeShape = (decls) => decls === null ||
|
|
1800
|
+
decls.every((d) => packageTypeFile(ts.getSourceFileOfNode(d), ctx) &&
|
|
1801
|
+
(ts.isInterfaceDeclaration(d) ||
|
|
1802
|
+
ts.isTypeAliasDeclaration(d) ||
|
|
1803
|
+
ts.isTypeLiteralNode(d) ||
|
|
1804
|
+
ts.isMappedTypeNode(d)));
|
|
1805
|
+
const aliasDecls = packageOnly(widened.getAliasSymbol());
|
|
1806
|
+
const ownDecls = packageOnly(widened.getSymbol());
|
|
1807
|
+
if ((aliasDecls !== null || (widened.getAliasSymbol() === undefined && ownDecls !== null)) &&
|
|
1808
|
+
!(pureTypeShape(aliasDecls) && pureTypeShape(ownDecls))) {
|
|
1345
1809
|
return null;
|
|
1346
1810
|
}
|
|
1347
1811
|
// Module namespaces were claimed above when they name compiled source
|
|
@@ -1534,19 +1998,24 @@ function mapTypeInner(type, ctx) {
|
|
|
1534
1998
|
// Class instances name a program class. The same symbol with construct
|
|
1535
1999
|
// signatures names its static side, mapped to classval below.
|
|
1536
2000
|
const widenedSym = widened.getSymbol();
|
|
1537
|
-
const classDecl = widenedSym ?
|
|
2001
|
+
const classDecl = widenedSym ? widenedSym.valueDeclaration : undefined;
|
|
1538
2002
|
if (classDecl &&
|
|
1539
2003
|
(ts.isClassDeclaration(classDecl) || ts.isClassExpression(classDecl)) &&
|
|
1540
2004
|
// Nameless class DECLARATIONS are legal only as `export default class
|
|
1541
2005
|
// {}` — classNamer spells them "%anon" (unique per file), the same
|
|
1542
2006
|
// name their collection registered.
|
|
1543
|
-
!
|
|
1544
|
-
checker.getConstructSignatures(widened).length === 0
|
|
1545
|
-
//
|
|
1546
|
-
//
|
|
1547
|
-
//
|
|
1548
|
-
//
|
|
1549
|
-
|
|
2007
|
+
!ts.getSourceFileOfNode(classDecl).isDeclarationFile &&
|
|
2008
|
+
checker.getConstructSignatures(widened).length === 0 &&
|
|
2009
|
+
// A TypeScript class declared OUTSIDE the lowered program (reached
|
|
2010
|
+
// through `import type` alone) never registers, and the program can
|
|
2011
|
+
// hold no instance of it: its instance type maps below as the
|
|
2012
|
+
// structural type it describes, like an interface.
|
|
2013
|
+
(ctx.isProgramFile(ts.getSourceFileOfNode(classDecl)) ||
|
|
2014
|
+
isJsSourceFile(ts.getSourceFileOfNode(classDecl)))) {
|
|
2015
|
+
// A JavaScript class outside the lowered program (jsdoc `typeof
|
|
2016
|
+
// import()` over a never-required module) stays unmappable: JSDoc
|
|
2017
|
+
// types are not checked, so its slots fall back to the dynamic value.
|
|
2018
|
+
if (!ctx.isProgramFile(ts.getSourceFileOfNode(classDecl)))
|
|
1550
2019
|
return null;
|
|
1551
2020
|
// The class inside a MIXIN function: per-call-site instantiations
|
|
1552
2021
|
// share this one node — the CURRENT instantiation (collecting or
|
|
@@ -1560,7 +2029,7 @@ function mapTypeInner(type, ctx) {
|
|
|
1560
2029
|
}
|
|
1561
2030
|
}
|
|
1562
2031
|
if (classExprNeedsContext(classDecl)) {
|
|
1563
|
-
const local = ctx.localClassInstance?.(classDecl);
|
|
2032
|
+
const local = ctx.localClassInstance?.(classDecl, widened);
|
|
1564
2033
|
if (local)
|
|
1565
2034
|
contextResolutions++;
|
|
1566
2035
|
return local ?? null;
|
|
@@ -1568,7 +2037,7 @@ function mapTypeInner(type, ctx) {
|
|
|
1568
2037
|
// A GENERIC class's instance type (`Box<number>`) maps to the concrete
|
|
1569
2038
|
// INSTANTIATION's class (`Box%0`), registered on demand — the Lowerer
|
|
1570
2039
|
// hook owns the instance table (monomorphization by flow).
|
|
1571
|
-
if (classDecl.typeParameters) {
|
|
2040
|
+
if (classDecl.typeParameters?.nodes) {
|
|
1572
2041
|
const instance = ctx.genericClassInstance?.(classDecl, widened, (argument) => mapType(argument, ctx)) ??
|
|
1573
2042
|
null;
|
|
1574
2043
|
// Before the generic declaration's collection turn, the hook can only
|
|
@@ -1580,14 +2049,21 @@ function mapTypeInner(type, ctx) {
|
|
|
1580
2049
|
}
|
|
1581
2050
|
return { kind: "object", className: classNamer(classDecl) };
|
|
1582
2051
|
}
|
|
2052
|
+
// A runtime-provided class's static side (`typeof EventEmitter`,
|
|
2053
|
+
// `typeof Readable`, `ErrorConstructor`): that class's value.
|
|
2054
|
+
{
|
|
2055
|
+
const runtimeClass = ctx.runtimeClassValue?.(widened);
|
|
2056
|
+
if (runtimeClass)
|
|
2057
|
+
return { kind: "classval", className: runtimeClass };
|
|
2058
|
+
}
|
|
1583
2059
|
// The class STATIC side (`typeof C` — the class name as a value): the
|
|
1584
2060
|
// same symbol WITH its construct signatures. Program classes only; lib
|
|
1585
2061
|
// and package statics keep their fences.
|
|
1586
2062
|
if (classDecl &&
|
|
1587
2063
|
(ts.isClassDeclaration(classDecl) || ts.isClassExpression(classDecl)) &&
|
|
1588
|
-
!
|
|
2064
|
+
!ts.getSourceFileOfNode(classDecl).isDeclarationFile &&
|
|
1589
2065
|
checker.getConstructSignatures(widened).length > 0) {
|
|
1590
|
-
if (!ctx.isProgramFile(
|
|
2066
|
+
if (!ctx.isProgramFile(ts.getSourceFileOfNode(classDecl)))
|
|
1591
2067
|
return null;
|
|
1592
2068
|
// The MIXIN class node's static side (`typeof C` inside the mixin):
|
|
1593
2069
|
// the current instantiation's classval, like the instance type above.
|
|
@@ -1599,7 +2075,8 @@ function mapTypeInner(type, ctx) {
|
|
|
1599
2075
|
}
|
|
1600
2076
|
}
|
|
1601
2077
|
if (classExprNeedsContext(classDecl)) {
|
|
1602
|
-
const
|
|
2078
|
+
const ctorSigs = checker.getConstructSignatures(widened);
|
|
2079
|
+
const local = ctx.localClassInstance?.(classDecl, ctorSigs.length === 1 ? checker.getReturnTypeOfSignature(ctorSigs[0]) : undefined);
|
|
1603
2080
|
if (local?.kind === "object") {
|
|
1604
2081
|
contextResolutions++;
|
|
1605
2082
|
return { kind: "classval", className: local.className };
|
|
@@ -1612,7 +2089,7 @@ function mapTypeInner(type, ctx) {
|
|
|
1612
2089
|
// the instantiation's classval. Uninstantiated `typeof Box` keeps the
|
|
1613
2090
|
// type parameter in the construct signature's return — unmapped (the
|
|
1614
2091
|
// family has no thunk and no single constructor ABI).
|
|
1615
|
-
if (classDecl.typeParameters) {
|
|
2092
|
+
if (classDecl.typeParameters?.nodes) {
|
|
1616
2093
|
const ctorSigs = checker.getConstructSignatures(widened);
|
|
1617
2094
|
if (ctorSigs.length !== 1)
|
|
1618
2095
|
return null;
|
|
@@ -1648,10 +2125,9 @@ function mapTypeInner(type, ctx) {
|
|
|
1648
2125
|
// outside stays unmapped — callers report the component fence (SC2009)
|
|
1649
2126
|
// naming the offending half, as does the `new Map` lowering per site.
|
|
1650
2127
|
const psym = widened.getSymbol();
|
|
1651
|
-
const isStdlibInterface = (name) => psym
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()));
|
|
2128
|
+
const isStdlibInterface = (name) => psym !== undefined &&
|
|
2129
|
+
ts.symbolName(psym) === name &&
|
|
2130
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)));
|
|
1655
2131
|
// The builtin Error classes: references to the lib's Error interfaces map to the runtime-provided class
|
|
1656
2132
|
// hierarchy (provenance, not the name — a user's own `class Error`
|
|
1657
2133
|
// resolved through the class-instance branch above, and a user
|
|
@@ -1664,10 +2140,9 @@ function mapTypeInner(type, ctx) {
|
|
|
1664
2140
|
}
|
|
1665
2141
|
// node:assert's AssertionError is declared as a class (in the shipped
|
|
1666
2142
|
// fallback and in @types/node), not as a lib interface.
|
|
1667
|
-
if (psym
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
.some((d) => ts.isClassDeclaration(d) && ctx.isStdlibFile(d.getSourceFile())))
|
|
2143
|
+
if (psym !== undefined &&
|
|
2144
|
+
ts.symbolName(psym) === "AssertionError" &&
|
|
2145
|
+
psym.declarations.some((d) => ts.isClassDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
1671
2146
|
return { kind: "object", className: "%AssertionError" };
|
|
1672
2147
|
// The lib's `Object` interface is a TOP type: tsc admits every
|
|
1673
2148
|
// non-nullish value into an `Object` slot (`const x: Object = "s"`), so
|
|
@@ -1683,12 +2158,11 @@ function mapTypeInner(type, ctx) {
|
|
|
1683
2158
|
// module lowering before generic number operations can observe the
|
|
1684
2159
|
// representation. The node:module class's merged instance interface is
|
|
1685
2160
|
// included, while unrelated user interfaces named Module stay structural.
|
|
1686
|
-
if ((psym
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
.
|
|
1690
|
-
|
|
1691
|
-
(psym.name === "ScriptcModule" ||
|
|
2161
|
+
if (((psym !== undefined && ts.symbolName(psym) === "ScriptcModule") ||
|
|
2162
|
+
(psym !== undefined && ts.symbolName(psym) === "Module")) &&
|
|
2163
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2164
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2165
|
+
(ts.symbolName(psym) === "ScriptcModule" ||
|
|
1692
2166
|
isDeclaredInAmbientNamespace(d, "NodeJS") ||
|
|
1693
2167
|
isDeclaredInAmbientModule(d, "module")))) {
|
|
1694
2168
|
return F64;
|
|
@@ -1700,11 +2174,10 @@ function mapTypeInner(type, ctx) {
|
|
|
1700
2174
|
// (generic) class plus a same-named interface — and @types/node's
|
|
1701
2175
|
// NodeJS.EventEmitter interface (the structural surface net.Socket
|
|
1702
2176
|
// et al. extend) is the same runtime value. Provenance-checked.
|
|
1703
|
-
if (psym
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
.
|
|
1707
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2177
|
+
if (psym !== undefined &&
|
|
2178
|
+
ts.symbolName(psym) === "EventEmitter" &&
|
|
2179
|
+
psym.declarations.some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
2180
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
1708
2181
|
(isDeclaredInAmbientModule(d, "events") || isDeclaredInAmbientNamespace(d, "NodeJS")))) {
|
|
1709
2182
|
return { kind: "object", className: RUNTIME_EMITTER_CLASS };
|
|
1710
2183
|
}
|
|
@@ -1712,54 +2185,69 @@ function mapTypeInner(type, ctx) {
|
|
|
1712
2185
|
// value is an f64 handle into the runtime's registry (the Timeout-id
|
|
1713
2186
|
// precedent). The NAME is generic, so the provenance check adds the
|
|
1714
2187
|
// enclosing ambient module, like net.Server.
|
|
1715
|
-
if (psym
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
.
|
|
1719
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2188
|
+
if (psym !== undefined &&
|
|
2189
|
+
ts.symbolName(psym) === "Interface" &&
|
|
2190
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2191
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
1720
2192
|
(isDeclaredInAmbientModule(d, "readline") ||
|
|
1721
2193
|
isDeclaredInAmbientModule(d, "readline/promises")))) {
|
|
1722
2194
|
return F64;
|
|
1723
2195
|
}
|
|
2196
|
+
// readline.Key: emitKeys' key object stays a checked-dynamic value, so
|
|
2197
|
+
// it keeps Node's own shape (an undefined name, the escape sequences'
|
|
2198
|
+
// code member).
|
|
2199
|
+
if (psym !== undefined &&
|
|
2200
|
+
ts.symbolName(psym) === "Key" &&
|
|
2201
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2202
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2203
|
+
(isDeclaredInAmbientModule(d, "readline") ||
|
|
2204
|
+
isDeclaredInAmbientModule(d, "readline/promises")))) {
|
|
2205
|
+
return DYN;
|
|
2206
|
+
}
|
|
2207
|
+
// readline/promises.Readline: an f64 handle the same way.
|
|
2208
|
+
if (psym !== undefined &&
|
|
2209
|
+
ts.symbolName(psym) === "Readline" &&
|
|
2210
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2211
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2212
|
+
isDeclaredInAmbientModule(d, "readline/promises"))) {
|
|
2213
|
+
return F64;
|
|
2214
|
+
}
|
|
1724
2215
|
// diagnostics_channel.Channel: the channel value is an f64 handle into
|
|
1725
2216
|
// the runtime's channel registry (the readline.Interface precedent —
|
|
1726
2217
|
// Node's channels are process-lived too, its WeakRef machinery aside).
|
|
1727
2218
|
// Provenance: the name is specific enough that stdlib-file provenance
|
|
1728
2219
|
// plus the ambient module suffices for both the fallback declarations
|
|
1729
2220
|
// and @types/node's class Channel<StoreType, ContextType>.
|
|
1730
|
-
if (psym
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
.
|
|
1734
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2221
|
+
if (psym !== undefined &&
|
|
2222
|
+
ts.symbolName(psym) === "Channel" &&
|
|
2223
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2224
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
1735
2225
|
isDeclaredInAmbientModule(d, "diagnostics_channel"))) {
|
|
1736
2226
|
return F64;
|
|
1737
2227
|
}
|
|
1738
2228
|
// async_hooks.AsyncLocalStorage: the store value is an f64 handle into
|
|
1739
2229
|
// the runtime's store id space (the Channel story — stores are
|
|
1740
2230
|
// process-lived; contexts ride the fiber machinery).
|
|
1741
|
-
if (psym
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
.
|
|
1745
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2231
|
+
if (psym !== undefined &&
|
|
2232
|
+
ts.symbolName(psym) === "AsyncLocalStorage" &&
|
|
2233
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2234
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
1746
2235
|
isDeclaredInAmbientModule(d, "async_hooks"))) {
|
|
1747
2236
|
return F64;
|
|
1748
2237
|
}
|
|
1749
2238
|
// diagnostics_channel.TracingChannel: the same f64-handle story over the
|
|
1750
2239
|
// runtime's tracing registry (five event channels per entry).
|
|
1751
|
-
if (psym
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
.
|
|
1755
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2240
|
+
if (psym !== undefined &&
|
|
2241
|
+
ts.symbolName(psym) === "TracingChannel" &&
|
|
2242
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2243
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
1756
2244
|
isDeclaredInAmbientModule(d, "diagnostics_channel"))) {
|
|
1757
2245
|
return F64;
|
|
1758
2246
|
}
|
|
1759
2247
|
// Node names this result; the ambient WHATWG declaration uses a type literal.
|
|
1760
2248
|
const encodeResult = psym &&
|
|
1761
|
-
|
|
1762
|
-
if (!ctx.isStdlibFile(
|
|
2249
|
+
psym.declarations.some((decl) => {
|
|
2250
|
+
if (!ctx.isStdlibFile(ts.getSourceFileOfNode(decl)))
|
|
1763
2251
|
return false;
|
|
1764
2252
|
if (ts.isInterfaceDeclaration(decl) && decl.name.text === "EncodeIntoResult")
|
|
1765
2253
|
return true;
|
|
@@ -1783,16 +2271,15 @@ function mapTypeInner(type, ctx) {
|
|
|
1783
2271
|
};
|
|
1784
2272
|
// WHATWG codec instances have ordinary reference identity and ownership.
|
|
1785
2273
|
// Their private encoding slot is omitted from enumeration and JSON.
|
|
1786
|
-
if ((psym
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
.
|
|
1790
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2274
|
+
if (((psym !== undefined && ts.symbolName(psym) === "TextEncoder") ||
|
|
2275
|
+
(psym !== undefined && ts.symbolName(psym) === "TextDecoder")) &&
|
|
2276
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2277
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1791
2278
|
return {
|
|
1792
2279
|
kind: "record",
|
|
1793
2280
|
shapeId: ctx.shapes.intern([
|
|
1794
|
-
{ name: `%${psym
|
|
1795
|
-
...(psym
|
|
2281
|
+
{ name: `%${ts.symbolName(psym)}`, type: F64 },
|
|
2282
|
+
...(ts.symbolName(psym) === "TextDecoder"
|
|
1796
2283
|
? [
|
|
1797
2284
|
{ name: "%fatal", type: BOOL },
|
|
1798
2285
|
{ name: "%ignoreBOM", type: BOOL },
|
|
@@ -1809,11 +2296,10 @@ function mapTypeInner(type, ctx) {
|
|
|
1809
2296
|
// checked like Stats; construction and the write/end methods are
|
|
1810
2297
|
// special-cased in lowerNew / lowerStringDecoderMethodCall, so the
|
|
1811
2298
|
// record shape never surfaces.
|
|
1812
|
-
if (psym
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
.
|
|
1816
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2299
|
+
if (psym !== undefined &&
|
|
2300
|
+
ts.symbolName(psym) === "StringDecoder" &&
|
|
2301
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2302
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1817
2303
|
return {
|
|
1818
2304
|
kind: "record",
|
|
1819
2305
|
shapeId: ctx.shapes.intern([
|
|
@@ -1832,14 +2318,14 @@ function mapTypeInner(type, ctx) {
|
|
|
1832
2318
|
// record-holding binding forms compile. User-declared literals with
|
|
1833
2319
|
// these member names keep the ordinary record path (their declarations
|
|
1834
2320
|
// are not in declaration files).
|
|
1835
|
-
const promiseDeclarations = psym ?
|
|
2321
|
+
const promiseDeclarations = psym ? psym.declarations : [];
|
|
1836
2322
|
if (flags & ts.TypeFlags.Object &&
|
|
1837
2323
|
promiseDeclarations.length > 0 &&
|
|
1838
|
-
promiseDeclarations.every((d) =>
|
|
2324
|
+
promiseDeclarations.every((d) => ts.getSourceFileOfNode(d).isDeclarationFile)) {
|
|
1839
2325
|
const props = checker.getPropertiesOfType(widened);
|
|
1840
2326
|
if (props.length === 3 &&
|
|
1841
|
-
["promise", "resolve", "reject"].every((n) => props.some((p) => p
|
|
1842
|
-
const promProp = props.find((p) => p
|
|
2327
|
+
["promise", "resolve", "reject"].every((n) => props.some((p) => ts.symbolName(p) === n))) {
|
|
2328
|
+
const promProp = props.find((p) => ts.symbolName(p) === "promise");
|
|
1843
2329
|
const promT = mapType(checker.getTypeOfSymbol(promProp), ctx);
|
|
1844
2330
|
if (promT?.kind === "promise") {
|
|
1845
2331
|
const inner = promT.inner;
|
|
@@ -1876,6 +2362,27 @@ function mapTypeInner(type, ctx) {
|
|
|
1876
2362
|
// stdio and env values. Keep it checked-dynamic for native normalization.
|
|
1877
2363
|
if (isStdlibInterface("SpawnOptions"))
|
|
1878
2364
|
return DYN;
|
|
2365
|
+
// dns.LookupAllOptions (`all: true`, the overload whose callback takes
|
|
2366
|
+
// an address list): a lookup option bag dns.lookup reads at run time.
|
|
2367
|
+
// It rides checked-dynamic storage, so the lookup function type that
|
|
2368
|
+
// takes `LookupOneOptions | LookupAllOptions | number` compiles.
|
|
2369
|
+
if (isStdlibInterface("LookupAllOptions"))
|
|
2370
|
+
return DYN;
|
|
2371
|
+
// http.RequestOptions / https.RequestOptions as a declared type: an
|
|
2372
|
+
// option record whose members include functions, agents and signals.
|
|
2373
|
+
// Values ride checked-dynamic storage, like SpawnOptions.
|
|
2374
|
+
if (psym !== undefined &&
|
|
2375
|
+
ts.symbolName(psym) === "RequestOptions" &&
|
|
2376
|
+
psym.declarations.some((d) => {
|
|
2377
|
+
if (!ts.isInterfaceDeclaration(d) || !ctx.isStdlibFile(ts.getSourceFileOfNode(d)))
|
|
2378
|
+
return false;
|
|
2379
|
+
for (let p = d.parent; p !== undefined; p = p.parent) {
|
|
2380
|
+
if (ts.isModuleDeclaration(p) && ts.isStringLiteral(p.name))
|
|
2381
|
+
return HTTP_REQUEST_OPTION_MODULES.has(p.name.text);
|
|
2382
|
+
}
|
|
2383
|
+
return false;
|
|
2384
|
+
}))
|
|
2385
|
+
return DYN;
|
|
1879
2386
|
// exactly like npm-declared types. Static fetch has one deliberately
|
|
1880
2387
|
// narrower native representation: Response is an opaque checked-
|
|
1881
2388
|
// dynamic capsule consumed only by the Response method lowerings, and
|
|
@@ -1888,10 +2395,9 @@ function mapTypeInner(type, ctx) {
|
|
|
1888
2395
|
// interfaces; @types/node's undici-types declares Response as a class).
|
|
1889
2396
|
{
|
|
1890
2397
|
const alias = widened.getAliasSymbol();
|
|
1891
|
-
if (alias
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2398
|
+
if (alias !== undefined &&
|
|
2399
|
+
ts.symbolName(alias) === "ReadableStreamReadResult" &&
|
|
2400
|
+
alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1895
2401
|
const elemTs = widened.getAliasTypeArguments()?.[0];
|
|
1896
2402
|
const elem = elemTs && elemTs.flags & ts.TypeFlags.Any ? DYN : elemTs ? mapType(elemTs, ctx) : null;
|
|
1897
2403
|
if (!elem)
|
|
@@ -1900,56 +2406,70 @@ function mapTypeInner(type, ctx) {
|
|
|
1900
2406
|
}
|
|
1901
2407
|
}
|
|
1902
2408
|
if (psym &&
|
|
1903
|
-
(psym
|
|
1904
|
-
psym
|
|
1905
|
-
|
|
1906
|
-
.declarationsOf(psym)
|
|
1907
|
-
.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2409
|
+
(ts.symbolName(psym) === "ReadableStreamReadValueResult" ||
|
|
2410
|
+
ts.symbolName(psym) === "ReadableStreamReadDoneResult") &&
|
|
2411
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1908
2412
|
const elemTs = checker.getTypeArguments(widened)[0];
|
|
1909
2413
|
const elem = elemTs && elemTs.flags & ts.TypeFlags.Any ? DYN : elemTs ? mapType(elemTs, ctx) : null;
|
|
1910
2414
|
if (!elem)
|
|
1911
2415
|
return null;
|
|
1912
2416
|
return genResultRecord(elem, VOID, ctx.shapes, ctx.unions);
|
|
1913
2417
|
}
|
|
2418
|
+
// node:net's SocketAddress and BlockList: native handles (scr_net.c)
|
|
2419
|
+
// whose getters and methods dispatch through the handle.
|
|
2420
|
+
if (((psym !== undefined && ts.symbolName(psym) === "SocketAddress") ||
|
|
2421
|
+
(psym !== undefined && ts.symbolName(psym) === "BlockList")) &&
|
|
2422
|
+
psym.declarations.some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
2423
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2424
|
+
return DYN;
|
|
2425
|
+
}
|
|
2426
|
+
// WebCrypto: the crypto global and its subtle object are dynamic
|
|
2427
|
+
// objects, CryptoKey values are native handles (scr_webcrypto.c), and
|
|
2428
|
+
// the algorithm dictionaries the methods take and keys report are plain
|
|
2429
|
+
// checked-dynamic objects.
|
|
2430
|
+
if (psym &&
|
|
2431
|
+
WEBCRYPTO_DYN_TYPES.has(ts.symbolName(psym)) &&
|
|
2432
|
+
psym.declarations.some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
2433
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2434
|
+
return DYN;
|
|
2435
|
+
}
|
|
1914
2436
|
// node:crypto's KeyObject: secret keys are native handles (scr_lib.c)
|
|
1915
2437
|
// whose getters and methods dispatch through the handle. The JsonWebKey
|
|
1916
2438
|
// that export() returns is a plain checked-dynamic object.
|
|
1917
|
-
if ((psym
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
.
|
|
1921
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2439
|
+
if (((psym !== undefined && ts.symbolName(psym) === "KeyObject") ||
|
|
2440
|
+
(psym !== undefined && ts.symbolName(psym) === "JsonWebKey")) &&
|
|
2441
|
+
psym.declarations.some((d) => (ts.isClassDeclaration(d) || ts.isInterfaceDeclaration(d)) &&
|
|
2442
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1922
2443
|
return DYN;
|
|
1923
2444
|
}
|
|
1924
2445
|
if (psym &&
|
|
1925
|
-
FETCH_AMBIENT_TYPES.includes(psym
|
|
1926
|
-
!(psym
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
checker
|
|
1931
|
-
.declarationsOf(psym)
|
|
1932
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
1933
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2446
|
+
FETCH_AMBIENT_TYPES.includes(ts.symbolName(psym)) &&
|
|
2447
|
+
!(ts.symbolName(psym) === "ReadableStream" &&
|
|
2448
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && isDeclaredInAmbientNamespace(d, "NodeJS"))) &&
|
|
2449
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2450
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1934
2451
|
return DYN;
|
|
1935
2452
|
}
|
|
1936
2453
|
// The stdlib Console interface (the global console and node:console
|
|
1937
2454
|
// Console instances) is a native handle carried by the checked-dynamic
|
|
1938
2455
|
// representation and consumed by the console method lowerings. The
|
|
1939
|
-
// stdlib Disposable (events.addAbortListener's result)
|
|
1940
|
-
//
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
2456
|
+
// stdlib Disposable (events.addAbortListener's result) and
|
|
2457
|
+
// AsyncDisposable are checked objects carrying their Symbol.dispose or
|
|
2458
|
+
// Symbol.asyncDispose method. A DisposableStack is a native handle whose
|
|
2459
|
+
// methods are function values of its checked-dynamic view.
|
|
2460
|
+
if (((psym !== undefined && ts.symbolName(psym) === "Console") ||
|
|
2461
|
+
(psym !== undefined && ts.symbolName(psym) === "Disposable") ||
|
|
2462
|
+
(psym !== undefined && ts.symbolName(psym) === "AsyncDisposable") ||
|
|
2463
|
+
(psym !== undefined && ts.symbolName(psym) === "DisposableStack")) &&
|
|
2464
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1945
2465
|
return DYN;
|
|
1946
2466
|
}
|
|
1947
2467
|
// node:crypto Cipheriv/Decipheriv values (and @types/node's per-mode
|
|
1948
2468
|
// interfaces over them) are native handles carried by the checked-dynamic
|
|
1949
2469
|
// representation; lowerCipherMethodCall dispatches their methods.
|
|
1950
2470
|
if (psym !== undefined &&
|
|
1951
|
-
CIPHER_TYPE_NAMES.has(psym
|
|
1952
|
-
|
|
2471
|
+
CIPHER_TYPE_NAMES.has(ts.symbolName(psym)) &&
|
|
2472
|
+
psym.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
1953
2473
|
return DYN;
|
|
1954
2474
|
}
|
|
1955
2475
|
// ReadonlyMap/ReadonlySet are the SAME runtime values as Map/Set — the
|
|
@@ -2069,6 +2589,8 @@ function mapTypeInner(type, ctx) {
|
|
|
2069
2589
|
// SharedArrayBuffer, and the i32 semantics hold for every other use.
|
|
2070
2590
|
if (isStdlibInterface("Int32Array"))
|
|
2071
2591
|
return bytesOf("i32");
|
|
2592
|
+
if (isStdlibInterface("Float16Array"))
|
|
2593
|
+
return bytesOf("f16");
|
|
2072
2594
|
if (isStdlibInterface("Float32Array"))
|
|
2073
2595
|
return bytesOf("f32");
|
|
2074
2596
|
if (isStdlibInterface("Float64Array"))
|
|
@@ -2084,11 +2606,10 @@ function mapTypeInner(type, ctx) {
|
|
|
2084
2606
|
// (the u8 bytes kind). Declared `interface Buffer` by the shipped
|
|
2085
2607
|
// fallback and by @types/node (whose NonSharedBuffer alias resolves to
|
|
2086
2608
|
// the same symbol); provenance-checked like URL.
|
|
2087
|
-
if (psym
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
.
|
|
2091
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2609
|
+
if (psym !== undefined &&
|
|
2610
|
+
ts.symbolName(psym) === "Buffer" &&
|
|
2611
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2612
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2092
2613
|
return bytesOf("u8");
|
|
2093
2614
|
}
|
|
2094
2615
|
// URL: the WHATWG URL instance type — declared as a global `interface
|
|
@@ -2096,41 +2617,36 @@ function mapTypeInner(type, ctx) {
|
|
|
2096
2617
|
// URL` in @types/node's "url" module (`new URL(x)` types as the class's
|
|
2097
2618
|
// instance type). Provenance, not the name: a user's own URL maps as a
|
|
2098
2619
|
// record/class like any other.
|
|
2099
|
-
if (psym
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
.
|
|
2103
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2620
|
+
if (psym !== undefined &&
|
|
2621
|
+
ts.symbolName(psym) === "URL" &&
|
|
2622
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2623
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2104
2624
|
return { kind: "url" };
|
|
2105
2625
|
}
|
|
2106
2626
|
// URLSearchParams: the WHATWG live query view — declared as a global
|
|
2107
2627
|
// interface by the shipped fallback and by @types/node (plus `class
|
|
2108
2628
|
// URLSearchParams` in the "url" module). Provenance-checked like URL.
|
|
2109
|
-
if (psym
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
.
|
|
2113
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2629
|
+
if (psym !== undefined &&
|
|
2630
|
+
ts.symbolName(psym) === "URLSearchParams" &&
|
|
2631
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2632
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2114
2633
|
return { kind: "searchParams" };
|
|
2115
2634
|
}
|
|
2116
2635
|
// fs.Stats: @types/node's `class Stats` (module "fs") or the fallback
|
|
2117
2636
|
// declarations' interface. Provenance-checked like URL.
|
|
2118
|
-
if (psym
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
.
|
|
2122
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2637
|
+
if (psym !== undefined &&
|
|
2638
|
+
ts.symbolName(psym) === "Stats" &&
|
|
2639
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2640
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2123
2641
|
return { kind: "stats" };
|
|
2124
2642
|
}
|
|
2125
2643
|
// Capacity snapshots and options keep their live object representation
|
|
2126
2644
|
// across numeric/BigInt overloads, runtime options, and callbacks.
|
|
2127
|
-
if ((psym
|
|
2128
|
-
psym
|
|
2129
|
-
psym
|
|
2130
|
-
|
|
2131
|
-
.
|
|
2132
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2133
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2645
|
+
if (((psym !== undefined && ts.symbolName(psym) === "StatsFs") ||
|
|
2646
|
+
(psym !== undefined && ts.symbolName(psym) === "BigIntStatsFs") ||
|
|
2647
|
+
(psym !== undefined && ts.symbolName(psym) === "StatFsOptions")) &&
|
|
2648
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2649
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2134
2650
|
isDeclaredInAmbientModule(d, "fs")))
|
|
2135
2651
|
return DYN;
|
|
2136
2652
|
if (isWorkerHandleSymbol(psym, ctx))
|
|
@@ -2138,21 +2654,19 @@ function mapTypeInner(type, ctx) {
|
|
|
2138
2654
|
// fs/promises.FileHandle: an owned descriptor object. Module provenance
|
|
2139
2655
|
// distinguishes it from user interfaces with the same name; both the
|
|
2140
2656
|
// fallback and @types/node declare it in "fs/promises".
|
|
2141
|
-
if (psym
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
.
|
|
2145
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2657
|
+
if (psym !== undefined &&
|
|
2658
|
+
ts.symbolName(psym) === "FileHandle" &&
|
|
2659
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2660
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2146
2661
|
isDeclaredInAmbientModule(d, "fs/promises"))) {
|
|
2147
2662
|
return { kind: "fileHandle" };
|
|
2148
2663
|
}
|
|
2149
2664
|
// fs.Dir: an open directory stream, declared in "fs" by both the
|
|
2150
2665
|
// fallback and @types/node.
|
|
2151
|
-
if (psym
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
.
|
|
2155
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2666
|
+
if (psym !== undefined &&
|
|
2667
|
+
ts.symbolName(psym) === "Dir" &&
|
|
2668
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2669
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2156
2670
|
isDeclaredInAmbientModule(d, "fs"))) {
|
|
2157
2671
|
return { kind: "dir" };
|
|
2158
2672
|
}
|
|
@@ -2160,24 +2674,21 @@ function mapTypeInner(type, ctx) {
|
|
|
2160
2674
|
// Buffer/string split is re-checked at the stdout/stderr READ — status
|
|
2161
2675
|
// reads work either way) or the fallback declarations' plain interface.
|
|
2162
2676
|
// Provenance-checked like Stats.
|
|
2163
|
-
if (psym
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
.
|
|
2167
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2677
|
+
if (psym !== undefined &&
|
|
2678
|
+
ts.symbolName(psym) === "SpawnSyncReturns" &&
|
|
2679
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2680
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2168
2681
|
return { kind: "spawnRes" };
|
|
2169
2682
|
}
|
|
2170
2683
|
// child_process.ChildProcess and @types/node's stdio-refined return
|
|
2171
2684
|
// interfaces: all carry the same runtime child handle; the generic
|
|
2172
2685
|
// refinements only tell the checker which stdio properties are null.
|
|
2173
2686
|
if (psym !== undefined &&
|
|
2174
|
-
(psym
|
|
2175
|
-
psym
|
|
2176
|
-
psym
|
|
2177
|
-
|
|
2178
|
-
.
|
|
2179
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2180
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2687
|
+
(ts.symbolName(psym) === "ChildProcess" ||
|
|
2688
|
+
ts.symbolName(psym) === "ChildProcessWithoutNullStreams" ||
|
|
2689
|
+
ts.symbolName(psym) === "ChildProcessByStdio") &&
|
|
2690
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2691
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2181
2692
|
isDeclaredInAmbientModule(d, "child_process"))) {
|
|
2182
2693
|
return { kind: "child" };
|
|
2183
2694
|
}
|
|
@@ -2188,64 +2699,62 @@ function mapTypeInner(type, ctx) {
|
|
|
2188
2699
|
// declare these inside `declare module "net"` — a declaration outside
|
|
2189
2700
|
// that module (http's Server) stays unmapped and fences at its use
|
|
2190
2701
|
// site.
|
|
2191
|
-
if ((psym
|
|
2192
|
-
|
|
2193
|
-
|
|
2702
|
+
if (((psym !== undefined && ts.symbolName(psym) === "Server") ||
|
|
2703
|
+
(psym !== undefined && ts.symbolName(psym) === "Socket") ||
|
|
2704
|
+
(psym !== undefined && ts.symbolName(psym) === "TLSSocket")) &&
|
|
2705
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2706
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2194
2707
|
(isDeclaredInAmbientModule(d, "net") ||
|
|
2195
2708
|
// http.Server extends net.Server in @types/node — and tls.Server
|
|
2196
2709
|
// / https.Server extend it transitively: same lowered surface
|
|
2197
2710
|
// (listen/close/address/'error'), same handle kind. tls.TLSSocket
|
|
2198
2711
|
// extends net.Socket the same way: post-handshake it IS a net
|
|
2199
2712
|
// socket to every lowered member.
|
|
2200
|
-
(psym
|
|
2713
|
+
(ts.symbolName(psym) === "Server" &&
|
|
2201
2714
|
(isDeclaredInAmbientModule(d, "http") ||
|
|
2202
2715
|
isDeclaredInAmbientModule(d, "tls") ||
|
|
2203
2716
|
isDeclaredInAmbientModule(d, "https"))) ||
|
|
2204
|
-
(psym
|
|
2205
|
-
return psym
|
|
2717
|
+
(ts.symbolName(psym) === "TLSSocket" && isDeclaredInAmbientModule(d, "tls"))))) {
|
|
2718
|
+
return ts.symbolName(psym) === "Server" ? { kind: "netServer" } : { kind: "netSocket" };
|
|
2206
2719
|
}
|
|
2207
2720
|
// tls.SecureContext: the opaque parsed-cert/key handle SNI callbacks
|
|
2208
2721
|
// answer with (tls.createSecureContext({ cert, key }) mints it; the TLS
|
|
2209
2722
|
// server's handshake consumes it). Module-checked like net.Server —
|
|
2210
2723
|
// @types/node declares `interface SecureContext` inside `declare module
|
|
2211
2724
|
// "tls"`, and the shipped fallback mirrors it.
|
|
2212
|
-
if (psym
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
.
|
|
2216
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2725
|
+
if (psym !== undefined &&
|
|
2726
|
+
ts.symbolName(psym) === "SecureContext" &&
|
|
2727
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2728
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2217
2729
|
isDeclaredInAmbientModule(d, "tls"))) {
|
|
2218
2730
|
return { kind: "secureCtx" };
|
|
2219
2731
|
}
|
|
2220
2732
|
// Scrypt's runtime options retain property accessors and aliases. Use
|
|
2221
2733
|
// checked values so presence probes and repeated getter reads match Node.
|
|
2222
|
-
if (psym
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
.
|
|
2226
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2734
|
+
if (psym !== undefined &&
|
|
2735
|
+
ts.symbolName(psym) === "ScryptOptions" &&
|
|
2736
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2737
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2227
2738
|
isDeclaredInAmbientModule(d, "crypto")))
|
|
2228
2739
|
return DYN;
|
|
2229
2740
|
// crypto.Hash / crypto.Hmac: native incremental digest handles. Keep
|
|
2230
2741
|
// provenance module-qualified so user classes with these common names
|
|
2231
2742
|
// retain their ordinary structural/class representation.
|
|
2232
|
-
if ((psym
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
.
|
|
2236
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2743
|
+
if (((psym !== undefined && ts.symbolName(psym) === "Hash") ||
|
|
2744
|
+
(psym !== undefined && ts.symbolName(psym) === "Hmac")) &&
|
|
2745
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2746
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2237
2747
|
isDeclaredInAmbientModule(d, "crypto"))) {
|
|
2238
|
-
return psym
|
|
2748
|
+
return ts.symbolName(psym) === "Hash" ? CRYPTOHASH_T : CRYPTOHMAC_T;
|
|
2239
2749
|
}
|
|
2240
2750
|
// fs.FSWatcher: the fs.watch handle (scr_watch.c). Module-checked like
|
|
2241
2751
|
// net.Server — @types/node declares `interface FSWatcher extends
|
|
2242
2752
|
// EventEmitter` inside `declare module "fs"`, and the shipped fallback
|
|
2243
2753
|
// mirrors it.
|
|
2244
|
-
if (psym
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
.
|
|
2248
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2754
|
+
if (psym !== undefined &&
|
|
2755
|
+
ts.symbolName(psym) === "FSWatcher" &&
|
|
2756
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2757
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2249
2758
|
isDeclaredInAmbientModule(d, "fs"))) {
|
|
2250
2759
|
return { kind: "fsWatcher" };
|
|
2251
2760
|
}
|
|
@@ -2266,41 +2775,70 @@ function mapTypeInner(type, ctx) {
|
|
|
2266
2775
|
// global-namespace interface real code writes in its own signatures —
|
|
2267
2776
|
// prefixStream's `output` param). The representation is the raw fd
|
|
2268
2777
|
// scalar; the lowered surface is write(string).
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2778
|
+
// Under the program's general stream representation (generalNodeStreams)
|
|
2779
|
+
// NodeJS.WritableStream is the runtime Writable instead: the process
|
|
2780
|
+
// streams convert into it where they flow (process.stdioWritable).
|
|
2781
|
+
// Checked-dynamic stream slots: an intersection over a NodeJS stream
|
|
2782
|
+
// interface (`NodeJS.ReadableStream & { destroy?(): void }`) holds the
|
|
2783
|
+
// same values as the interface.
|
|
2784
|
+
if (ctx.dynNodeStreams === true &&
|
|
2785
|
+
(type.flags & ts.TypeFlags.Intersection) !== 0 &&
|
|
2786
|
+
ts.constituentTypes(type).some((part) => {
|
|
2787
|
+
const sym = part.getSymbol();
|
|
2788
|
+
return (((sym !== undefined && ts.symbolName(sym) === "ReadableStream") ||
|
|
2789
|
+
(sym !== undefined && ts.symbolName(sym) === "WritableStream")) &&
|
|
2790
|
+
sym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2791
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2792
|
+
isDeclaredInAmbientNamespace(d, "NodeJS")));
|
|
2793
|
+
})) {
|
|
2794
|
+
return DYN;
|
|
2795
|
+
}
|
|
2796
|
+
const nodeWritableInterface = psym !== undefined &&
|
|
2797
|
+
ts.symbolName(psym) === "WritableStream" &&
|
|
2798
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2799
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2800
|
+
isDeclaredInAmbientNamespace(d, "NodeJS"));
|
|
2801
|
+
if (nodeWritableInterface && ctx.generalNodeStreams === true) {
|
|
2802
|
+
return ctx.dynNodeStreams === true ? DYN : { kind: "object", className: "%Writable" };
|
|
2803
|
+
}
|
|
2804
|
+
if ((psym !== undefined &&
|
|
2805
|
+
ts.symbolName(psym) === "WriteStream" &&
|
|
2806
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2807
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2274
2808
|
(isDeclaredInAmbientModule(d, "tty") ||
|
|
2275
|
-
(isDeclaredInAmbientModule(d, "process") &&
|
|
2276
|
-
|
|
2277
|
-
(psym?.name === "WritableStream" &&
|
|
2278
|
-
checker
|
|
2279
|
-
.declarationsOf(psym)
|
|
2280
|
-
.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2281
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2282
|
-
isDeclaredInAmbientNamespace(d, "NodeJS")))) {
|
|
2809
|
+
(isDeclaredInAmbientModule(d, "process") && isDeclaredInAmbientNamespace(d, "NodeJS"))))) ||
|
|
2810
|
+
nodeWritableInterface) {
|
|
2283
2811
|
return PROCSTREAM_T;
|
|
2284
2812
|
}
|
|
2285
2813
|
// A piped child stdin writer. The fallback declarations give it the
|
|
2286
2814
|
// dedicated ChildStdin name; @types/node spells the same value as
|
|
2287
2815
|
// stream.Writable. As with stream.Readable below, unsupported producers
|
|
2288
2816
|
// of the broad @types class fence where they are constructed.
|
|
2289
|
-
if ((psym
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
ctx.isStdlibFile(
|
|
2817
|
+
if ((psym !== undefined &&
|
|
2818
|
+
ts.symbolName(psym) === "ChildStdin" &&
|
|
2819
|
+
ctx.generalNodeStreams !== true &&
|
|
2820
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2821
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2294
2822
|
isDeclaredInAmbientModule(d, "child_process"))) ||
|
|
2295
|
-
(psym
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
ctx.isStdlibFile(
|
|
2300
|
-
isNodeTypesPath(
|
|
2823
|
+
(psym !== undefined &&
|
|
2824
|
+
ts.symbolName(psym) === "Writable" &&
|
|
2825
|
+
ctx.generalNodeStreams !== true &&
|
|
2826
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2827
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2828
|
+
isNodeTypesPath(ts.getSourceFileOfNode(d).fileName) &&
|
|
2301
2829
|
isDeclaredInAmbientModule(d, "stream")))) {
|
|
2302
2830
|
return { kind: "childWriter" };
|
|
2303
2831
|
}
|
|
2832
|
+
// Under the general stream representation the fallback declarations'
|
|
2833
|
+
// ChildStdin is the runtime Writable too (child.stdioStream bridges it).
|
|
2834
|
+
if (ctx.generalNodeStreams === true &&
|
|
2835
|
+
psym !== undefined &&
|
|
2836
|
+
ts.symbolName(psym) === "ChildStdin" &&
|
|
2837
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2838
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2839
|
+
isDeclaredInAmbientModule(d, "child_process"))) {
|
|
2840
|
+
return { kind: "object", className: "%Writable" };
|
|
2841
|
+
}
|
|
2304
2842
|
// The static node:stream classes (the shipped fallback declarations —
|
|
2305
2843
|
// NOT @types/node, whose stream.Readable also types child stdio; under
|
|
2306
2844
|
// @types/node the childStream mapping below keeps priority and the
|
|
@@ -2308,93 +2846,102 @@ function mapTypeInner(type, ctx) {
|
|
|
2308
2846
|
// branch: the fallback's Readable must map to the runtime class, and
|
|
2309
2847
|
// under the fallback child.stdout is NodeJS.ReadableStream (its own
|
|
2310
2848
|
// branch below), so the two never collide.
|
|
2849
|
+
// @types/node's Duplex/Transform/PassThrough classes have no child-stdio
|
|
2850
|
+
// reading, so they map to the runtime classes too; its Readable and
|
|
2851
|
+
// Writable join them under the general representation.
|
|
2311
2852
|
for (const [irName, rec] of RUNTIME_STREAM_CLASSES) {
|
|
2312
|
-
if (psym
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
.
|
|
2316
|
-
|
|
2317
|
-
|
|
2853
|
+
if (psym !== undefined &&
|
|
2854
|
+
ts.symbolName(psym) === rec.lib &&
|
|
2855
|
+
psym.declarations.some((d) => ts.isClassDeclaration(d) &&
|
|
2856
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2857
|
+
(!isNodeTypesPath(ts.getSourceFileOfNode(d).fileName) ||
|
|
2858
|
+
ctx.generalNodeStreams === true ||
|
|
2859
|
+
(rec.lib !== "Readable" && rec.lib !== "Writable")) &&
|
|
2318
2860
|
isDeclaredInAmbientModule(d, "stream"))) {
|
|
2319
2861
|
return { kind: "object", className: irName };
|
|
2320
2862
|
}
|
|
2321
2863
|
}
|
|
2322
|
-
// node:zlib's stream classes (the shipped fallback declarations
|
|
2323
|
-
// instances are runtime Transform streams.
|
|
2864
|
+
// node:zlib's stream classes (the shipped fallback declarations and
|
|
2865
|
+
// @types/node's): their instances are runtime Transform streams.
|
|
2324
2866
|
if (psym !== undefined &&
|
|
2325
|
-
ZLIB_STREAM_MODES.has(psym
|
|
2326
|
-
|
|
2327
|
-
.
|
|
2328
|
-
.
|
|
2329
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2330
|
-
!isNodeTypesPath(d.getSourceFile().fileName) &&
|
|
2867
|
+
ZLIB_STREAM_MODES.has(ts.symbolName(psym)) &&
|
|
2868
|
+
psym.declarations.some((d) => (ts.isClassDeclaration(d) ||
|
|
2869
|
+
(ts.isInterfaceDeclaration(d) && isNodeTypesPath(ts.getSourceFileOfNode(d).fileName))) &&
|
|
2870
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2331
2871
|
isDeclaredInAmbientModule(d, "zlib"))) {
|
|
2332
2872
|
return { kind: "object", className: "%Transform" };
|
|
2333
2873
|
}
|
|
2334
|
-
// fs.ReadStream / fs.WriteStream (the shipped fallback declarations
|
|
2335
|
-
// their instances are runtime Readable / Writable
|
|
2336
|
-
// (scr_fs_stream.c).
|
|
2337
|
-
if ((psym
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
.
|
|
2341
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2342
|
-
!isNodeTypesPath(d.getSourceFile().fileName) &&
|
|
2874
|
+
// fs.ReadStream / fs.WriteStream (the shipped fallback declarations and
|
|
2875
|
+
// @types/node's): their instances are runtime Readable / Writable
|
|
2876
|
+
// streams (scr_fs_stream.c).
|
|
2877
|
+
if (((psym !== undefined && ts.symbolName(psym) === "ReadStream") ||
|
|
2878
|
+
(psym !== undefined && ts.symbolName(psym) === "WriteStream")) &&
|
|
2879
|
+
psym.declarations.some((d) => ts.isClassDeclaration(d) &&
|
|
2880
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2343
2881
|
isDeclaredInAmbientModule(d, "fs"))) {
|
|
2344
|
-
return {
|
|
2882
|
+
return {
|
|
2883
|
+
kind: "object",
|
|
2884
|
+
className: ts.symbolName(psym) === "ReadStream" ? "%Readable" : "%Writable",
|
|
2885
|
+
};
|
|
2345
2886
|
}
|
|
2346
|
-
if ((psym
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
.
|
|
2350
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2887
|
+
if ((psym !== undefined &&
|
|
2888
|
+
ts.symbolName(psym) === "Readable" &&
|
|
2889
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2890
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2351
2891
|
isDeclaredInAmbientModule(d, "stream"))) ||
|
|
2352
|
-
(psym
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
.
|
|
2356
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2892
|
+
(psym !== undefined &&
|
|
2893
|
+
ts.symbolName(psym) === "ReadableStream" &&
|
|
2894
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2895
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2357
2896
|
isDeclaredInAmbientNamespace(d, "NodeJS")))) {
|
|
2897
|
+
// The general representation: the runtime Readable, which child
|
|
2898
|
+
// stdio reads produce through the child stream bridge. With
|
|
2899
|
+
// checked-dynamic stream slots, NodeJS.ReadableStream holds any
|
|
2900
|
+
// stream value (dyn-streams.ts); stream.Readable keeps the class.
|
|
2901
|
+
if (ctx.generalNodeStreams === true) {
|
|
2902
|
+
if (ctx.dynNodeStreams === true && ts.symbolName(psym) === "ReadableStream")
|
|
2903
|
+
return DYN;
|
|
2904
|
+
return { kind: "object", className: "%Readable" };
|
|
2905
|
+
}
|
|
2358
2906
|
return { kind: "childStream" };
|
|
2359
2907
|
}
|
|
2360
2908
|
// dgram.Socket: the same ambiguous "Socket" name disambiguated by its
|
|
2361
2909
|
// enclosing ambient module — @types/node's `class Socket extends
|
|
2362
2910
|
// EventEmitter` and the fallback declarations' interface both live
|
|
2363
2911
|
// inside `declare module "dgram"`.
|
|
2364
|
-
if (psym
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
.
|
|
2368
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2912
|
+
if (psym !== undefined &&
|
|
2913
|
+
ts.symbolName(psym) === "Socket" &&
|
|
2914
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2915
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2369
2916
|
isDeclaredInAmbientModule(d, "dgram"))) {
|
|
2370
2917
|
return { kind: "dgramSocket" };
|
|
2371
2918
|
}
|
|
2372
2919
|
// node:test's TestContext — the test-body parameter (`test('x', (t) =>
|
|
2373
|
-
// ...)`)
|
|
2374
|
-
//
|
|
2375
|
-
//
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2920
|
+
// ...)`) — and SuiteContext, the describe-body and suite-hook parameter:
|
|
2921
|
+
// both are the runner's node for the test or suite. @types/node's
|
|
2922
|
+
// classes and the fallback declarations' interfaces all live inside
|
|
2923
|
+
// `declare module "node:test"` (isDeclaredInAmbientModule answers for
|
|
2924
|
+
// both spellings).
|
|
2925
|
+
if (((psym !== undefined && ts.symbolName(psym) === "TestContext") ||
|
|
2926
|
+
(psym !== undefined && ts.symbolName(psym) === "SuiteContext")) &&
|
|
2927
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2928
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2381
2929
|
isDeclaredInAmbientModule(d, "test"))) {
|
|
2382
2930
|
return { kind: "testCtx" };
|
|
2383
2931
|
}
|
|
2384
2932
|
// node:test's MockFunctionContext<F> and MockFunctionCall<F>: compiler
|
|
2385
2933
|
// records built from F (mock-shapes.ts). Mock<F> then maps as the hybrid
|
|
2386
2934
|
// { %call: F, mock } record through mapHybridCallableIntersection.
|
|
2387
|
-
if ((psym
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
.
|
|
2391
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2935
|
+
if (((psym !== undefined && ts.symbolName(psym) === "MockFunctionContext") ||
|
|
2936
|
+
(psym !== undefined && ts.symbolName(psym) === "MockFunctionCall")) &&
|
|
2937
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2938
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2392
2939
|
isDeclaredInAmbientModule(d, "test"))) {
|
|
2393
2940
|
const fnTs = checker.getTypeArguments(widened)[0];
|
|
2394
2941
|
const fn = fnTs ? mapType(fnTs, ctx) : null;
|
|
2395
2942
|
if (!fn || fn.kind !== "func")
|
|
2396
2943
|
return null;
|
|
2397
|
-
return psym
|
|
2944
|
+
return ts.symbolName(psym) === "MockFunctionContext"
|
|
2398
2945
|
? mockContextType(fn, ctx)
|
|
2399
2946
|
: mockCallRecordType(fn, ctx);
|
|
2400
2947
|
}
|
|
@@ -2403,10 +2950,9 @@ function mapTypeInner(type, ctx) {
|
|
|
2403
2950
|
// it to the runtime %Error hierarchy like the lib Error interfaces
|
|
2404
2951
|
// above; optional metadata uses the same checked property view.
|
|
2405
2952
|
// Provenance-checked like the rest.
|
|
2406
|
-
if (psym
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))) {
|
|
2953
|
+
if (psym !== undefined &&
|
|
2954
|
+
ts.symbolName(psym) === "ErrnoException" &&
|
|
2955
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2410
2956
|
return { kind: "object", className: "%Error" };
|
|
2411
2957
|
}
|
|
2412
2958
|
// http.Agent / https.Agent — the Agent VALUE is a checked-dynamic
|
|
@@ -2415,24 +2961,22 @@ function mapTypeInner(type, ctx) {
|
|
|
2415
2961
|
// binding, parameter, or field carrying an Agent stays usable instead
|
|
2416
2962
|
// of fencing at the declaration. Module-checked like the rest (https'
|
|
2417
2963
|
// Agent extends http's; both live in their ambient modules).
|
|
2418
|
-
if (psym
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
.
|
|
2422
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2964
|
+
if (psym !== undefined &&
|
|
2965
|
+
ts.symbolName(psym) === "Agent" &&
|
|
2966
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2967
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2423
2968
|
(isDeclaredInAmbientModule(d, "http") || isDeclaredInAmbientModule(d, "https")))) {
|
|
2424
2969
|
return { kind: "dyn" };
|
|
2425
2970
|
}
|
|
2426
2971
|
// http.IncomingMessage / http.ServerResponse — module-checked like
|
|
2427
2972
|
// net.Server (the names repeat nowhere today, but provenance stays the
|
|
2428
2973
|
// rule).
|
|
2429
|
-
if ((psym
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
.
|
|
2433
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2974
|
+
if (((psym !== undefined && ts.symbolName(psym) === "IncomingMessage") ||
|
|
2975
|
+
(psym !== undefined && ts.symbolName(psym) === "ServerResponse")) &&
|
|
2976
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2977
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2434
2978
|
isDeclaredInAmbientModule(d, "http"))) {
|
|
2435
|
-
return psym
|
|
2979
|
+
return ts.symbolName(psym) === "IncomingMessage" ? { kind: "httpReq" } : { kind: "httpRes" };
|
|
2436
2980
|
}
|
|
2437
2981
|
// http2's compatibility surface (the allowHTTP1 lowering): the secure
|
|
2438
2982
|
// server IS a net server (listen/close/address/emit ride the same
|
|
@@ -2442,17 +2986,15 @@ function mapTypeInner(type, ctx) {
|
|
|
2442
2986
|
// ServerResponse surface. h2-only members (stream, session) fence per
|
|
2443
2987
|
// member at their use sites (lower-server.ts). Module-checked like the
|
|
2444
2988
|
// rest.
|
|
2445
|
-
if ((psym
|
|
2446
|
-
psym
|
|
2447
|
-
psym
|
|
2448
|
-
|
|
2449
|
-
.
|
|
2450
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2451
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
2989
|
+
if (((psym !== undefined && ts.symbolName(psym) === "Http2SecureServer") ||
|
|
2990
|
+
(psym !== undefined && ts.symbolName(psym) === "Http2ServerRequest") ||
|
|
2991
|
+
(psym !== undefined && ts.symbolName(psym) === "Http2ServerResponse")) &&
|
|
2992
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2993
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2452
2994
|
isDeclaredInAmbientModule(d, "http2"))) {
|
|
2453
|
-
return psym
|
|
2995
|
+
return ts.symbolName(psym) === "Http2SecureServer"
|
|
2454
2996
|
? { kind: "netServer" }
|
|
2455
|
-
: psym
|
|
2997
|
+
: ts.symbolName(psym) === "Http2ServerRequest"
|
|
2456
2998
|
? { kind: "httpReq" }
|
|
2457
2999
|
: { kind: "httpRes" };
|
|
2458
3000
|
}
|
|
@@ -2460,30 +3002,27 @@ function mapTypeInner(type, ctx) {
|
|
|
2460
3002
|
// like the secure one; sessions and streams are first-class handle
|
|
2461
3003
|
// kinds (client and server flavors share a kind — the runtime handle
|
|
2462
3004
|
// carries the role). Module-checked like the rest.
|
|
2463
|
-
if ((psym
|
|
2464
|
-
psym
|
|
2465
|
-
psym
|
|
2466
|
-
psym
|
|
2467
|
-
psym
|
|
2468
|
-
psym
|
|
2469
|
-
|
|
2470
|
-
.
|
|
2471
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2472
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
3005
|
+
if (((psym !== undefined && ts.symbolName(psym) === "Http2Server") ||
|
|
3006
|
+
(psym !== undefined && ts.symbolName(psym) === "Http2Session") ||
|
|
3007
|
+
(psym !== undefined && ts.symbolName(psym) === "ClientHttp2Session") ||
|
|
3008
|
+
(psym !== undefined && ts.symbolName(psym) === "ServerHttp2Session") ||
|
|
3009
|
+
(psym !== undefined && ts.symbolName(psym) === "ClientHttp2Stream") ||
|
|
3010
|
+
(psym !== undefined && ts.symbolName(psym) === "ServerHttp2Stream")) &&
|
|
3011
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
3012
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2473
3013
|
isDeclaredInAmbientModule(d, "http2"))) {
|
|
2474
|
-
return psym
|
|
3014
|
+
return ts.symbolName(psym) === "Http2Server"
|
|
2475
3015
|
? { kind: "netServer" }
|
|
2476
|
-
: psym
|
|
3016
|
+
: ts.symbolName(psym) === "ClientHttp2Stream" || ts.symbolName(psym) === "ServerHttp2Stream"
|
|
2477
3017
|
? { kind: "http2Stream" }
|
|
2478
3018
|
: { kind: "http2Session" };
|
|
2479
3019
|
}
|
|
2480
3020
|
// http.ClientRequest (http.request/http.get results) — module-checked
|
|
2481
3021
|
// like IncomingMessage.
|
|
2482
|
-
if (psym
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
.
|
|
2486
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
3022
|
+
if (psym !== undefined &&
|
|
3023
|
+
ts.symbolName(psym) === "ClientRequest" &&
|
|
3024
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
3025
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2487
3026
|
isDeclaredInAmbientModule(d, "http"))) {
|
|
2488
3027
|
return { kind: "httpClientReq" };
|
|
2489
3028
|
}
|
|
@@ -2495,10 +3034,9 @@ function mapTypeInner(type, ctx) {
|
|
|
2495
3034
|
// record) and ProcessEnv-typed parameters mappable. The fallback
|
|
2496
3035
|
// declarations' anonymous env type takes the pureIndexShape path below
|
|
2497
3036
|
// and interns the SAME shape.
|
|
2498
|
-
if (psym
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))) {
|
|
3037
|
+
if (psym !== undefined &&
|
|
3038
|
+
ts.symbolName(psym) === "ProcessEnv" &&
|
|
3039
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2502
3040
|
const value = withUndefinedArm(STRING, ctx.unions);
|
|
2503
3041
|
if (!value)
|
|
2504
3042
|
return null;
|
|
@@ -2532,8 +3070,9 @@ function mapTypeInner(type, ctx) {
|
|
|
2532
3070
|
if (isStdlibInterface("MapIterator") || isStdlibInterface("SetIterator"))
|
|
2533
3071
|
return DYN;
|
|
2534
3072
|
// Array iterators (`list.values()` and friends) are generators over the
|
|
2535
|
-
// live array: each step reads the current length and element.
|
|
2536
|
-
|
|
3073
|
+
// live array: each step reads the current length and element. String
|
|
3074
|
+
// iterators (`s[Symbol.iterator]()`) are generators over the code points.
|
|
3075
|
+
if (isStdlibInterface("ArrayIterator") || isStdlibInterface("StringIterator")) {
|
|
2537
3076
|
const arg = checker.getTypeArguments(widened)[0];
|
|
2538
3077
|
const yieldT = arg ? mapType(arg, ctx) : null;
|
|
2539
3078
|
if (!yieldT || yieldT.kind === "void" || isUnitType(yieldT))
|
|
@@ -2568,7 +3107,10 @@ function mapTypeInner(type, ctx) {
|
|
|
2568
3107
|
isStdlibInterface("IterableIterator") ||
|
|
2569
3108
|
// An Iterator<T> annotation holds a single-pass iterator object: a
|
|
2570
3109
|
// generator, or a native iterator adapted into one.
|
|
2571
|
-
isStdlibInterface("Iterator")
|
|
3110
|
+
isStdlibInterface("Iterator") ||
|
|
3111
|
+
// IteratorObject<T> is what the iterator helpers return: a helper
|
|
3112
|
+
// generator over its source (containers/iterator-helpers.ts).
|
|
3113
|
+
isStdlibInterface("IteratorObject")) {
|
|
2572
3114
|
const args = checker.getTypeArguments(widened);
|
|
2573
3115
|
const channels = genChannels(args[0], args[1], args[2], ctx);
|
|
2574
3116
|
if (!channels)
|
|
@@ -2589,10 +3131,9 @@ function mapTypeInner(type, ctx) {
|
|
|
2589
3131
|
// g.next()` binds without an annotation and reads flow.
|
|
2590
3132
|
{
|
|
2591
3133
|
const alias = widened.getAliasSymbol();
|
|
2592
|
-
if (alias
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))) {
|
|
3134
|
+
if (alias !== undefined &&
|
|
3135
|
+
ts.symbolName(alias) === "IteratorResult" &&
|
|
3136
|
+
alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2596
3137
|
const targs = widened.getAliasTypeArguments() ?? [];
|
|
2597
3138
|
const channels = genChannels(targs[0], targs[1], undefined, ctx);
|
|
2598
3139
|
if (!channels)
|
|
@@ -2690,12 +3231,12 @@ function mapTypeInner(type, ctx) {
|
|
|
2690
3231
|
];
|
|
2691
3232
|
const fields = [];
|
|
2692
3233
|
for (const property of checker.getPropertiesOfType(widened)) {
|
|
2693
|
-
if (!known.includes(property
|
|
3234
|
+
if (!known.includes(ts.symbolName(property)))
|
|
2694
3235
|
return null;
|
|
2695
3236
|
const type = mapType(checker.getTypeOfSymbol(property), ctx);
|
|
2696
3237
|
if (!type)
|
|
2697
3238
|
return null;
|
|
2698
|
-
fields.push({ name: property
|
|
3239
|
+
fields.push({ name: ts.symbolName(property), type });
|
|
2699
3240
|
}
|
|
2700
3241
|
const order = fields.map((field) => field.name);
|
|
2701
3242
|
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
@@ -2703,23 +3244,21 @@ function mapTypeInner(type, ctx) {
|
|
|
2703
3244
|
}
|
|
2704
3245
|
// Filesystem options are data records. Keep their declared optional fields
|
|
2705
3246
|
// instead of allowing arbitrary standard-library interfaces into records.
|
|
2706
|
-
if ((psym
|
|
2707
|
-
psym
|
|
2708
|
-
psym
|
|
2709
|
-
psym
|
|
2710
|
-
|
|
2711
|
-
.
|
|
2712
|
-
.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2713
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
3247
|
+
if (((psym !== undefined && ts.symbolName(psym) === "FileReadOptions") ||
|
|
3248
|
+
(psym !== undefined && ts.symbolName(psym) === "ReadOptions") ||
|
|
3249
|
+
(psym !== undefined && ts.symbolName(psym) === "ReadOptionsWithBuffer") ||
|
|
3250
|
+
(psym !== undefined && ts.symbolName(psym) === "WriteOptions")) &&
|
|
3251
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
3252
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2714
3253
|
(isDeclaredInAmbientModule(d, "fs/promises") || isDeclaredInAmbientModule(d, "fs")))) {
|
|
2715
3254
|
const fields = [];
|
|
2716
3255
|
for (const property of checker.getPropertiesOfType(widened)) {
|
|
2717
|
-
if (!["buffer", "offset", "length", "position"].includes(property
|
|
3256
|
+
if (!["buffer", "offset", "length", "position"].includes(ts.symbolName(property)))
|
|
2718
3257
|
return null;
|
|
2719
3258
|
const type = mapType(checker.getTypeOfSymbol(property), ctx);
|
|
2720
3259
|
if (!type)
|
|
2721
3260
|
return null;
|
|
2722
|
-
fields.push({ name: property
|
|
3261
|
+
fields.push({ name: ts.symbolName(property), type });
|
|
2723
3262
|
}
|
|
2724
3263
|
const order = fields.map((field) => field.name);
|
|
2725
3264
|
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
@@ -2729,26 +3268,24 @@ function mapTypeInner(type, ctx) {
|
|
|
2729
3268
|
// null-prototype objects returned by FileHandle.read/write. The native
|
|
2730
3269
|
// record does not model the prototype (unobservable through the lowered
|
|
2731
3270
|
// surface); it preserves the caller buffer/string by reference.
|
|
2732
|
-
if ((psym
|
|
2733
|
-
psym
|
|
2734
|
-
psym
|
|
2735
|
-
psym
|
|
2736
|
-
psym
|
|
2737
|
-
psym
|
|
2738
|
-
|
|
2739
|
-
.
|
|
2740
|
-
.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
2741
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
3271
|
+
if (((psym !== undefined && ts.symbolName(psym) === "FileReadResult") ||
|
|
3272
|
+
(psym !== undefined && ts.symbolName(psym) === "FileWriteResult") ||
|
|
3273
|
+
(psym !== undefined && ts.symbolName(psym) === "FileReadvResult") ||
|
|
3274
|
+
(psym !== undefined && ts.symbolName(psym) === "FileWritevResult") ||
|
|
3275
|
+
(psym !== undefined && ts.symbolName(psym) === "ReadVResult") ||
|
|
3276
|
+
(psym !== undefined && ts.symbolName(psym) === "WriteVResult")) &&
|
|
3277
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) &&
|
|
3278
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2742
3279
|
(isDeclaredInAmbientModule(d, "fs/promises") ||
|
|
2743
|
-
((psym
|
|
3280
|
+
((ts.symbolName(psym) === "ReadVResult" || ts.symbolName(psym) === "WriteVResult") &&
|
|
2744
3281
|
isDeclaredInAmbientModule(d, "fs"))))) {
|
|
2745
3282
|
const args = checker.getTypeArguments(widened);
|
|
2746
3283
|
if (args.length !== 1)
|
|
2747
3284
|
return null;
|
|
2748
|
-
const vector = psym
|
|
2749
|
-
psym
|
|
2750
|
-
psym
|
|
2751
|
-
psym
|
|
3285
|
+
const vector = ts.symbolName(psym) === "FileReadvResult" ||
|
|
3286
|
+
ts.symbolName(psym) === "FileWritevResult" ||
|
|
3287
|
+
ts.symbolName(psym) === "ReadVResult" ||
|
|
3288
|
+
ts.symbolName(psym) === "WriteVResult";
|
|
2752
3289
|
const emptyVector = vector &&
|
|
2753
3290
|
checker.isArrayType(args[0]) &&
|
|
2754
3291
|
(checker.getTypeArguments(args[0])[0].flags & ts.TypeFlags.Never) !== 0;
|
|
@@ -2759,9 +3296,9 @@ function mapTypeInner(type, ctx) {
|
|
|
2759
3296
|
: !(payload.kind === "string" || (payload.kind === "bytes" && payload.elem === "u8")))) {
|
|
2760
3297
|
return null;
|
|
2761
3298
|
}
|
|
2762
|
-
const count = psym
|
|
2763
|
-
psym
|
|
2764
|
-
psym
|
|
3299
|
+
const count = ts.symbolName(psym) === "FileReadResult" ||
|
|
3300
|
+
ts.symbolName(psym) === "FileReadvResult" ||
|
|
3301
|
+
ts.symbolName(psym) === "ReadVResult"
|
|
2765
3302
|
? "bytesRead"
|
|
2766
3303
|
: "bytesWritten";
|
|
2767
3304
|
const payloadName = vector ? "buffers" : "buffer";
|
|
@@ -2787,11 +3324,10 @@ function mapTypeInner(type, ctx) {
|
|
|
2787
3324
|
// encoding:'buffer' readdir form has no lowering); the shipped fallback
|
|
2788
3325
|
// declares it concrete (an interface; @types/node uses a class — both
|
|
2789
3326
|
// provenance-checked, the Buffer/URL pattern).
|
|
2790
|
-
if (psym
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
.
|
|
2794
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
3327
|
+
if (psym !== undefined &&
|
|
3328
|
+
ts.symbolName(psym) === "Dirent" &&
|
|
3329
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
3330
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2795
3331
|
const args = checker.getTypeArguments(widened);
|
|
2796
3332
|
if (args.length > 1)
|
|
2797
3333
|
return null;
|
|
@@ -2829,15 +3365,13 @@ function mapTypeInner(type, ctx) {
|
|
|
2829
3365
|
shapeId: ctx.shapes.intern(["idle", "irq", "nice", "sys", "user"].map((name) => ({ name, type: F64 })), false, undefined, ["user", "nice", "sys", "idle", "irq"]),
|
|
2830
3366
|
});
|
|
2831
3367
|
if (psym &&
|
|
2832
|
-
|
|
2833
|
-
.declarationsOf(psym)
|
|
2834
|
-
.some((d) => ts.isTypeLiteralNode(d) &&
|
|
3368
|
+
psym.declarations.some((d) => ts.isTypeLiteralNode(d) &&
|
|
2835
3369
|
ts.isPropertySignature(d.parent) &&
|
|
2836
3370
|
ts.isIdentifier(d.parent.name) &&
|
|
2837
3371
|
d.parent.name.text === "times" &&
|
|
2838
3372
|
ts.isInterfaceDeclaration(d.parent.parent) &&
|
|
2839
3373
|
d.parent.parent.name.text === "CpuInfo" &&
|
|
2840
|
-
ctx.isStdlibFile(
|
|
3374
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d))))
|
|
2841
3375
|
return cpuTimes();
|
|
2842
3376
|
if (isStdlibInterface("CpuInfo")) {
|
|
2843
3377
|
const times = cpuTimes();
|
|
@@ -2851,7 +3385,7 @@ function mapTypeInner(type, ctx) {
|
|
|
2851
3385
|
};
|
|
2852
3386
|
}
|
|
2853
3387
|
if (isStdlibInterface("ParsedPath") || isStdlibInterface("FormatInputPathObject")) {
|
|
2854
|
-
const field = psym
|
|
3388
|
+
const field = ts.symbolName(psym) === "ParsedPath" ? STRING : withUndefinedArm(STRING, ctx.unions);
|
|
2855
3389
|
if (!field)
|
|
2856
3390
|
return null;
|
|
2857
3391
|
return {
|
|
@@ -2881,26 +3415,40 @@ function mapTypeInner(type, ctx) {
|
|
|
2881
3415
|
], false, undefined, ["uid", "gid", "username", "homedir", "shell"]),
|
|
2882
3416
|
};
|
|
2883
3417
|
}
|
|
2884
|
-
// The promisified exec/execFile result `{ stdout: string; stderr: string }
|
|
2885
|
-
//
|
|
2886
|
-
//
|
|
2887
|
-
//
|
|
2888
|
-
//
|
|
2889
|
-
//
|
|
3418
|
+
// The promisified exec/execFile result `{ stdout: string; stderr: string }`
|
|
3419
|
+
// and the promisified dns.lookupService result `{ hostname: string;
|
|
3420
|
+
// service: string }`: anonymous type literals (@types/node's
|
|
3421
|
+
// __promisify__ overloads in child_process and dns, the shipped
|
|
3422
|
+
// fallback's promisify overloads in util), so they map by provenance and
|
|
3423
|
+
// exact shape. The exec result is interned as the %execFileAsync/
|
|
3424
|
+
// %execAsync helpers build it; Node builds { stdout, stderr } and
|
|
3425
|
+
// { hostname, service }. The Buffer-typed literals do not match and stay
|
|
2890
3426
|
// unmapped.
|
|
2891
3427
|
if (psym &&
|
|
2892
|
-
|
|
2893
|
-
.
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
3428
|
+
psym.declarations.some((d) => ts.isTypeLiteralNode(d) &&
|
|
3429
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
3430
|
+
(isDeclaredInAmbientModule(d, "child_process") ||
|
|
3431
|
+
isDeclaredInAmbientModule(d, "util") ||
|
|
3432
|
+
isDeclaredInAmbientModule(d, "dns")))) {
|
|
2897
3433
|
const props = checker.getPropertiesOfType(widened);
|
|
2898
|
-
|
|
2899
|
-
props.every((p) => (p.
|
|
2900
|
-
(p.flags & ts.
|
|
2901
|
-
|
|
2902
|
-
|
|
3434
|
+
const names = props.length === 2 &&
|
|
3435
|
+
props.every((p) => (p.flags & ts.SymbolFlags.Optional) === 0 &&
|
|
3436
|
+
(checker.getTypeOfSymbol(p).flags & ts.TypeFlags.String) !== 0)
|
|
3437
|
+
? props
|
|
3438
|
+
.map((p) => ts.symbolName(p))
|
|
3439
|
+
.sort()
|
|
3440
|
+
.join(",")
|
|
3441
|
+
: "";
|
|
3442
|
+
if (names === "stderr,stdout")
|
|
2903
3443
|
return { kind: "record", shapeId: execResultShape(ctx.shapes) };
|
|
3444
|
+
if (names === "hostname,service") {
|
|
3445
|
+
return {
|
|
3446
|
+
kind: "record",
|
|
3447
|
+
shapeId: ctx.shapes.intern([
|
|
3448
|
+
{ name: "hostname", type: STRING },
|
|
3449
|
+
{ name: "service", type: STRING },
|
|
3450
|
+
], false, undefined, ["hostname", "service"]),
|
|
3451
|
+
};
|
|
2904
3452
|
}
|
|
2905
3453
|
}
|
|
2906
3454
|
// crypto.X509Certificate — the Dirent-style data record: THREE visible
|
|
@@ -2910,11 +3458,10 @@ function mapTypeInner(type, ctx) {
|
|
|
2910
3458
|
// `declare module "crypto"`, the shipped fallback mirrors it.
|
|
2911
3459
|
// JSON.stringify of one shows the three fields where Node's
|
|
2912
3460
|
// internal-slot object shows {} — the Dirent %dtype edge's cousin.
|
|
2913
|
-
if (psym
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
.
|
|
2917
|
-
ctx.isStdlibFile(d.getSourceFile()) &&
|
|
3461
|
+
if (psym !== undefined &&
|
|
3462
|
+
ts.symbolName(psym) === "X509Certificate" &&
|
|
3463
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
3464
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)) &&
|
|
2918
3465
|
isDeclaredInAmbientModule(d, "crypto"))) {
|
|
2919
3466
|
return {
|
|
2920
3467
|
kind: "record",
|
|
@@ -2933,15 +3480,40 @@ function mapTypeInner(type, ctx) {
|
|
|
2933
3480
|
// record (util.inspect names the class from entryType, like Node).
|
|
2934
3481
|
// @types/node declares the classes in perf_hooks and global interfaces
|
|
2935
3482
|
// over them; the shipped fallback declares the classes.
|
|
2936
|
-
if ((psym
|
|
2937
|
-
psym
|
|
2938
|
-
psym
|
|
2939
|
-
|
|
2940
|
-
.
|
|
2941
|
-
.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
2942
|
-
ctx.isStdlibFile(d.getSourceFile()))) {
|
|
3483
|
+
if (((psym !== undefined && ts.symbolName(psym) === "PerformanceEntry") ||
|
|
3484
|
+
(psym !== undefined && ts.symbolName(psym) === "PerformanceMark") ||
|
|
3485
|
+
(psym !== undefined && ts.symbolName(psym) === "PerformanceMeasure")) &&
|
|
3486
|
+
psym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
3487
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
2943
3488
|
return { kind: "record", shapeId: perfEntryShape(ctx.shapes, ctx.unions) };
|
|
2944
3489
|
}
|
|
3490
|
+
// readline's getCursorPos() record, in Node's key order ({ cols, rows }).
|
|
3491
|
+
// perf_hooks' EventLoopUtilization (performance.eventLoopUtilization's
|
|
3492
|
+
// result): a plain data record in Node's key order.
|
|
3493
|
+
if (isStdlibInterface("EventLoopUtilization")) {
|
|
3494
|
+
return {
|
|
3495
|
+
kind: "record",
|
|
3496
|
+
shapeId: ctx.shapes.intern([
|
|
3497
|
+
{ name: "active", type: F64 },
|
|
3498
|
+
{ name: "idle", type: F64 },
|
|
3499
|
+
{ name: "utilization", type: F64 },
|
|
3500
|
+
], false, undefined, ["idle", "active", "utilization"]),
|
|
3501
|
+
};
|
|
3502
|
+
}
|
|
3503
|
+
// monitorEventLoopDelay's IntervalHistogram: a numeric handle into the
|
|
3504
|
+
// runtime's histogram table, like a timer handle. Its members lower over
|
|
3505
|
+
// the handle (builtins/performance.ts).
|
|
3506
|
+
if (isStdlibInterface("IntervalHistogram"))
|
|
3507
|
+
return F64;
|
|
3508
|
+
if (isStdlibInterface("CursorPos")) {
|
|
3509
|
+
return {
|
|
3510
|
+
kind: "record",
|
|
3511
|
+
shapeId: ctx.shapes.intern([
|
|
3512
|
+
{ name: "cols", type: F64 },
|
|
3513
|
+
{ name: "rows", type: F64 },
|
|
3514
|
+
], false, undefined, ["cols", "rows"]),
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
2945
3517
|
// process.memoryUsage()'s record, in Node's key order.
|
|
2946
3518
|
if (isStdlibInterface("MemoryUsage")) {
|
|
2947
3519
|
const names = ["rss", "heapTotal", "heapUsed", "external", "arrayBuffers"];
|
|
@@ -2950,6 +3522,29 @@ function mapTypeInner(type, ctx) {
|
|
|
2950
3522
|
shapeId: ctx.shapes.intern([...names].sort().map((name) => ({ name, type: F64 })), false, undefined, names),
|
|
2951
3523
|
};
|
|
2952
3524
|
}
|
|
3525
|
+
// v8.getHeapStatistics()'s record, in Node's key order (builtins/v8.ts).
|
|
3526
|
+
if (isStdlibInterface("HeapInfo")) {
|
|
3527
|
+
const names = [
|
|
3528
|
+
"total_heap_size",
|
|
3529
|
+
"total_heap_size_executable",
|
|
3530
|
+
"total_physical_size",
|
|
3531
|
+
"total_available_size",
|
|
3532
|
+
"used_heap_size",
|
|
3533
|
+
"heap_size_limit",
|
|
3534
|
+
"malloced_memory",
|
|
3535
|
+
"peak_malloced_memory",
|
|
3536
|
+
"does_zap_garbage",
|
|
3537
|
+
"number_of_native_contexts",
|
|
3538
|
+
"number_of_detached_contexts",
|
|
3539
|
+
"total_global_handles_size",
|
|
3540
|
+
"used_global_handles_size",
|
|
3541
|
+
"external_memory",
|
|
3542
|
+
];
|
|
3543
|
+
return {
|
|
3544
|
+
kind: "record",
|
|
3545
|
+
shapeId: ctx.shapes.intern([...names].sort().map((name) => ({ name, type: F64 })), false, undefined, names),
|
|
3546
|
+
};
|
|
3547
|
+
}
|
|
2953
3548
|
// process.cpuUsage()/threadCpuUsage()'s {user, system} microsecond
|
|
2954
3549
|
// record and resourceUsage()'s getrusage record — stdlib data
|
|
2955
3550
|
// interfaces interned explicitly (the RemoteInfo pattern; declared
|
|
@@ -3008,7 +3603,7 @@ function mapTypeInner(type, ctx) {
|
|
|
3008
3603
|
// over a row answers exactly Node.
|
|
3009
3604
|
if (isStdlibInterface("NetworkInterfaceInfoIPv4") ||
|
|
3010
3605
|
isStdlibInterface("NetworkInterfaceInfoIPv6")) {
|
|
3011
|
-
const v6 = psym
|
|
3606
|
+
const v6 = ts.symbolName(psym) === "NetworkInterfaceInfoIPv6";
|
|
3012
3607
|
const cidrArms = [NULL_T, STRING].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
3013
3608
|
const cidr = { kind: "union", unionId: ctx.unions.intern(cidrArms) };
|
|
3014
3609
|
const scopeid = v6 ? F64 : withUndefinedArm(F64, ctx.unions);
|
|
@@ -3099,147 +3694,17 @@ function mapTypeInner(type, ctx) {
|
|
|
3099
3694
|
checker.getPropertiesOfType(widened).length > 0)
|
|
3100
3695
|
return DYN;
|
|
3101
3696
|
}
|
|
3697
|
+
// A union of such hybrids that all map to ONE record is that record:
|
|
3698
|
+
// node:test's Mock<F | Implementation> distributes to (F & { mock }) |
|
|
3699
|
+
// (Implementation & { mock }), and the two function types can map alike.
|
|
3700
|
+
if (widened.isUnionType()) {
|
|
3701
|
+
const hybrid = mapUniformHybridUnion(widened, ctx);
|
|
3702
|
+
if (hybrid)
|
|
3703
|
+
return hybrid;
|
|
3704
|
+
}
|
|
3102
3705
|
const callSigs = checker.getCallSignatures(widened);
|
|
3103
|
-
if (callSigs.length === 1)
|
|
3104
|
-
|
|
3105
|
-
if (sig.getTypeParameters().length)
|
|
3106
|
-
return null;
|
|
3107
|
-
// A SYNTHESIZED rest param (tsc's JS inference for a function body
|
|
3108
|
-
// reading `arguments` — `(...args: any[]) => any` whose args symbol
|
|
3109
|
-
// has no declaration): the dotDotDot check below can't see it, and a
|
|
3110
|
-
// fixed-arity func mapping would LIE about the value's calling
|
|
3111
|
-
// convention. Detected by the param-count mismatch against the
|
|
3112
|
-
// signature's own declaration, excluding an erased `this` parameter.
|
|
3113
|
-
{
|
|
3114
|
-
const sigDecl = checker.signatureDeclaration(sig);
|
|
3115
|
-
const declParams = sigDecl !== undefined && ts.isFunctionLike(sigDecl) ? sigDecl.parameters : undefined;
|
|
3116
|
-
if (declParams !== undefined &&
|
|
3117
|
-
runtimeParameterCount(declParams) !== sig.getParameters().length) {
|
|
3118
|
-
return null;
|
|
3119
|
-
}
|
|
3120
|
-
// tsgo never SYNTHESIZES that rest param into the inferred signature
|
|
3121
|
-
// (5.9.3 did — the count mismatch above was the whole detector
|
|
3122
|
-
// there), so the declaration's own body answers directly.
|
|
3123
|
-
if (sigDecl !== undefined && ts.isFunctionLike(sigDecl) && bodyReadsArguments(sigDecl)) {
|
|
3124
|
-
return null;
|
|
3125
|
-
}
|
|
3126
|
-
}
|
|
3127
|
-
const params = [];
|
|
3128
|
-
let typedRest = false;
|
|
3129
|
-
for (const p of sig.getParameters()) {
|
|
3130
|
-
const decl = checker.valueDeclarationOf(p);
|
|
3131
|
-
const rest = decl !== undefined && ts.isParameter(decl) && decl.dotDotDotToken !== undefined;
|
|
3132
|
-
// arity ABI selected by lambdaSignature. Treating an inferred any[]
|
|
3133
|
-
// declaration as a typed packed-array closure would bypass its boxed
|
|
3134
|
-
// spread/error semantics and change coverage classification.
|
|
3135
|
-
if (rest && decl !== undefined && isJsSourceFile(decl.getSourceFile()))
|
|
3136
|
-
return null;
|
|
3137
|
-
const optional = decl !== undefined &&
|
|
3138
|
-
ts.isParameter(decl) &&
|
|
3139
|
-
(decl.questionToken !== undefined || decl.initializer !== undefined);
|
|
3140
|
-
let pt = mapType(checker.getTypeOfSymbol(p), ctx);
|
|
3141
|
-
if (decl &&
|
|
3142
|
-
ts.isParameter(decl) &&
|
|
3143
|
-
ts.isSetAccessorDeclaration(decl.parent) &&
|
|
3144
|
-
isJsSourceFile(decl.getSourceFile()))
|
|
3145
|
-
pt = DYN;
|
|
3146
|
-
// An inferred JavaScript binding pattern consumes an iterable; it
|
|
3147
|
-
// does not require the caller's array to have exactly this length.
|
|
3148
|
-
const executor = decl && ts.isParameter(decl) ? decl.parent : null;
|
|
3149
|
-
const construction = executor?.parent;
|
|
3150
|
-
const constructorSymbol = construction && ts.isNewExpression(construction)
|
|
3151
|
-
? checker.getSymbolAtLocation(construction.expression)
|
|
3152
|
-
: undefined;
|
|
3153
|
-
const nativeExecutor = executor &&
|
|
3154
|
-
(ts.isArrowFunction(executor) || ts.isFunctionExpression(executor)) &&
|
|
3155
|
-
construction &&
|
|
3156
|
-
ts.isNewExpression(construction) &&
|
|
3157
|
-
construction.arguments?.[0] === executor &&
|
|
3158
|
-
ts.isIdentifier(construction.expression) &&
|
|
3159
|
-
construction.expression.text === "Promise" &&
|
|
3160
|
-
constructorSymbol &&
|
|
3161
|
-
checker
|
|
3162
|
-
.declarationsOf(constructorSymbol)
|
|
3163
|
-
.some((site) => ctx.isStdlibFile(site.getSourceFile()));
|
|
3164
|
-
if (!nativeExecutor &&
|
|
3165
|
-
decl &&
|
|
3166
|
-
ts.isParameter(decl) &&
|
|
3167
|
-
!decl.dotDotDotToken &&
|
|
3168
|
-
!ts.isSetAccessorDeclaration(decl.parent) &&
|
|
3169
|
-
isJsSourceFile(decl.getSourceFile()) &&
|
|
3170
|
-
!decl.type &&
|
|
3171
|
-
!/@(?:param|type)\b/.test(decl.getSourceFile().text.slice(decl.parent?.pos ?? decl.pos, decl.getStart())))
|
|
3172
|
-
pt = DYN;
|
|
3173
|
-
if (pt)
|
|
3174
|
-
pt = jsOpenObjectType(decl, pt, ctx.shapes, ctx.unions);
|
|
3175
|
-
// Belt and braces for non-strict type worlds: an optional param's
|
|
3176
|
-
// ABI slot is always the undefined-armed union (strictNullChecks
|
|
3177
|
-
// already spells it that way; arm it here if the world didn't).
|
|
3178
|
-
if (optional && pt && pt.kind !== "void" && pt.kind !== "dyn") {
|
|
3179
|
-
const armed = withUndefinedArm(pt, ctx.unions);
|
|
3180
|
-
if (!armed)
|
|
3181
|
-
return null;
|
|
3182
|
-
pt = armed;
|
|
3183
|
-
}
|
|
3184
|
-
if (!pt)
|
|
3185
|
-
return null;
|
|
3186
|
-
if (rest) {
|
|
3187
|
-
if (pt.kind !== "array")
|
|
3188
|
-
return null;
|
|
3189
|
-
typedRest = true;
|
|
3190
|
-
}
|
|
3191
|
-
// `(value: void) => void` (Promise<void>'s resolve) is callable with
|
|
3192
|
-
// no arguments — a void param is dropped, not a mapping failure.
|
|
3193
|
-
if (pt.kind === "void")
|
|
3194
|
-
continue;
|
|
3195
|
-
params.push(pt);
|
|
3196
|
-
}
|
|
3197
|
-
const retT = checker.getReturnTypeOfSignature(sig);
|
|
3198
|
-
// `() => never` (a throw-only lambda's inferred type) is assignable to
|
|
3199
|
-
// `() => void` and its calls never produce a value — map the return
|
|
3200
|
-
// like declaredReturnType does for declarations. JS null/undefined
|
|
3201
|
-
// returns can read mutable fields, so callable values use the same
|
|
3202
|
-
// checked-native return ABI as their implementations.
|
|
3203
|
-
const sigDecl = checker.signatureDeclaration(sig);
|
|
3204
|
-
const jsUnitReturn = sigDecl !== undefined &&
|
|
3205
|
-
isJsSourceFile(sigDecl.getSourceFile()) &&
|
|
3206
|
-
(retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0;
|
|
3207
|
-
let ret = jsUnitReturn || (retT.flags & ts.TypeFlags.Any) !== 0
|
|
3208
|
-
? DYN
|
|
3209
|
-
: retT.flags & ts.TypeFlags.Never
|
|
3210
|
-
? VOID
|
|
3211
|
-
: mapType(retT, ctx);
|
|
3212
|
-
if (sigDecl && ts.isGetAccessorDeclaration(sigDecl) && isJsSourceFile(sigDecl.getSourceFile()))
|
|
3213
|
-
ret = DYN;
|
|
3214
|
-
if (sigDecl && isJsSourceFile(sigDecl.getSourceFile()) && ret?.kind === "array")
|
|
3215
|
-
ret = DYN;
|
|
3216
|
-
if (sigDecl &&
|
|
3217
|
-
ts.isFunctionLike(sigDecl) &&
|
|
3218
|
-
isJsSourceFile(sigDecl.getSourceFile()) &&
|
|
3219
|
-
!sigDecl.type &&
|
|
3220
|
-
!/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) &&
|
|
3221
|
-
ret?.kind === "record")
|
|
3222
|
-
ret = DYN;
|
|
3223
|
-
if (sigDecl &&
|
|
3224
|
-
ts.isFunctionLike(sigDecl) &&
|
|
3225
|
-
isJsSourceFile(sigDecl.getSourceFile()) &&
|
|
3226
|
-
!sigDecl.type &&
|
|
3227
|
-
!/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) &&
|
|
3228
|
-
(ret?.kind === "date" ||
|
|
3229
|
-
(ret?.kind === "union" &&
|
|
3230
|
-
ctx.unions.get(ret.unionId)?.arms.some((arm) => arm.kind === "func"))))
|
|
3231
|
-
ret = DYN;
|
|
3232
|
-
if (ret &&
|
|
3233
|
-
sigDecl &&
|
|
3234
|
-
isJsSourceFile(sigDecl.getSourceFile()) &&
|
|
3235
|
-
functionCanReturnUndefined(sigDecl))
|
|
3236
|
-
ret = withUndefinedArm(ret, ctx.unions) ?? ret;
|
|
3237
|
-
if (!ret)
|
|
3238
|
-
return null;
|
|
3239
|
-
return typedRest
|
|
3240
|
-
? { kind: "func", params, ret, rest: true, restAbi: "typed" }
|
|
3241
|
-
: funcOf(params, ret);
|
|
3242
|
-
}
|
|
3706
|
+
if (callSigs.length === 1)
|
|
3707
|
+
return mapCallSignature(callSigs[0], ctx);
|
|
3243
3708
|
// Records: object types whose members are all data properties (shorthand
|
|
3244
3709
|
// methods in type position count — they're func-typed fields) with
|
|
3245
3710
|
// mappable types; no call/construct signatures, no index signatures, not
|
|
@@ -3276,10 +3741,8 @@ function mapTypeInner(type, ctx) {
|
|
|
3276
3741
|
if (flags & ts.TypeFlags.Object &&
|
|
3277
3742
|
callSigs.length === 0 &&
|
|
3278
3743
|
psym !== undefined &&
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
.declarationsOf(psym)
|
|
3282
|
-
.every((d) => ts.isInterfaceDeclaration(d) && !ctx.isStdlibFile(d.getSourceFile()))) {
|
|
3744
|
+
psym.declarations.length > 0 &&
|
|
3745
|
+
psym.declarations.every((d) => ts.isInterfaceDeclaration(d) && !ctx.isStdlibFile(ts.getSourceFileOfNode(d)))) {
|
|
3283
3746
|
const CHILD_SURFACE = new Set([
|
|
3284
3747
|
"pid",
|
|
3285
3748
|
"exitCode",
|
|
@@ -3312,37 +3775,49 @@ function mapTypeInner(type, ctx) {
|
|
|
3312
3775
|
const props = checker.getPropertiesOfType(widened);
|
|
3313
3776
|
let core = 0;
|
|
3314
3777
|
const childMemberType = (p) => {
|
|
3315
|
-
if (["kill", "on", "once", "off", "removeListener", "unref", "ref"].includes(p
|
|
3778
|
+
if (["kill", "on", "once", "off", "removeListener", "unref", "ref"].includes(ts.symbolName(p))) {
|
|
3316
3779
|
return checker.getCallSignatures(checker.getTypeOfSymbol(p)).length > 0;
|
|
3317
3780
|
}
|
|
3318
|
-
const expected = p
|
|
3781
|
+
const expected = ts.symbolName(p) === "stdout" || ts.symbolName(p) === "stderr"
|
|
3319
3782
|
? "childStream"
|
|
3320
|
-
: p
|
|
3783
|
+
: ts.symbolName(p) === "stdin"
|
|
3321
3784
|
? "childWriter"
|
|
3322
|
-
: p
|
|
3785
|
+
: ts.symbolName(p) === "killed"
|
|
3323
3786
|
? "bool"
|
|
3324
3787
|
: "f64";
|
|
3325
|
-
const unit = p
|
|
3788
|
+
const unit = ts.symbolName(p) === "pid"
|
|
3326
3789
|
? "undefinedT"
|
|
3327
|
-
: p
|
|
3328
|
-
p
|
|
3329
|
-
p
|
|
3330
|
-
p
|
|
3790
|
+
: ts.symbolName(p) === "exitCode" ||
|
|
3791
|
+
ts.symbolName(p) === "stdin" ||
|
|
3792
|
+
ts.symbolName(p) === "stdout" ||
|
|
3793
|
+
ts.symbolName(p) === "stderr"
|
|
3331
3794
|
? "nullT"
|
|
3332
3795
|
: null;
|
|
3333
3796
|
const mapped = mapType(checker.getTypeOfSymbol(p), ctx);
|
|
3334
3797
|
if (!mapped)
|
|
3335
3798
|
return false;
|
|
3336
3799
|
const arms = mapped.kind === "union" ? ctx.unions.get(mapped.unionId)?.arms : [mapped];
|
|
3800
|
+
// Under the general stream representation the stdio members are the
|
|
3801
|
+
// runtime stream classes.
|
|
3802
|
+
const isExpected = (arm) => arm.kind === expected ||
|
|
3803
|
+
(ctx.generalNodeStreams === true &&
|
|
3804
|
+
arm.kind === "object" &&
|
|
3805
|
+
((expected === "childStream" && arm.className === "%Readable") ||
|
|
3806
|
+
(expected === "childWriter" && arm.className === "%Writable"))) ||
|
|
3807
|
+
// Checked-dynamic stream slots: `NodeJS.ReadableStream | null`
|
|
3808
|
+
// collapses to dyn (the reads still produce the bridged stream).
|
|
3809
|
+
(ctx.dynNodeStreams === true &&
|
|
3810
|
+
arm.kind === "dyn" &&
|
|
3811
|
+
(expected === "childStream" || expected === "childWriter"));
|
|
3337
3812
|
return (arms !== undefined &&
|
|
3338
|
-
arms.some(
|
|
3339
|
-
arms.every((arm) => arm
|
|
3813
|
+
arms.some(isExpected) &&
|
|
3814
|
+
arms.every((arm) => isExpected(arm) || arm.kind === unit));
|
|
3340
3815
|
};
|
|
3341
3816
|
const childShaped = props.length > 0 &&
|
|
3342
3817
|
props.every((p) => {
|
|
3343
|
-
if (!CHILD_SURFACE.has(p
|
|
3818
|
+
if (!CHILD_SURFACE.has(ts.symbolName(p)) || !childMemberType(p))
|
|
3344
3819
|
return false;
|
|
3345
|
-
if (CHILD_CORE.has(p
|
|
3820
|
+
if (CHILD_CORE.has(ts.symbolName(p)))
|
|
3346
3821
|
core++;
|
|
3347
3822
|
return true;
|
|
3348
3823
|
});
|
|
@@ -3350,6 +3825,9 @@ function mapTypeInner(type, ctx) {
|
|
|
3350
3825
|
return CHILD_T;
|
|
3351
3826
|
}
|
|
3352
3827
|
if (flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) && callSigs.length === 0) {
|
|
3828
|
+
const viaMapped = mapBoundMappedType(widened, ctx);
|
|
3829
|
+
if (viaMapped)
|
|
3830
|
+
return viaMapped;
|
|
3353
3831
|
const viaAlias = mapGenericUtilityAlias(widened, ctx);
|
|
3354
3832
|
if (viaAlias)
|
|
3355
3833
|
return viaAlias;
|
|
@@ -3483,7 +3961,7 @@ function mapTypeInner(type, ctx) {
|
|
|
3483
3961
|
a.kind === "date" ||
|
|
3484
3962
|
a.kind === "dyn" ||
|
|
3485
3963
|
a.kind === "generator") ||
|
|
3486
|
-
!
|
|
3964
|
+
!maybePromiseUnionOk(parts, arms, ctx)) {
|
|
3487
3965
|
return null;
|
|
3488
3966
|
}
|
|
3489
3967
|
arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
@@ -3509,6 +3987,221 @@ function mapTypeInner(type, ctx) {
|
|
|
3509
3987
|
}
|
|
3510
3988
|
return null;
|
|
3511
3989
|
}
|
|
3990
|
+
/** One non-overloaded call signature's func type (mapTypeInner's
|
|
3991
|
+
* single-signature rule; erasedOverloadMemberType maps each overload of a
|
|
3992
|
+
* member through it). */
|
|
3993
|
+
function mapCallSignature(sig, ctx) {
|
|
3994
|
+
const { checker } = ctx;
|
|
3995
|
+
if (sig.getTypeParameters().length && ctx.erasingSignature !== sig)
|
|
3996
|
+
return null;
|
|
3997
|
+
// A SYNTHESIZED rest param (tsc's JS inference for a function body
|
|
3998
|
+
// reading `arguments` — `(...args: any[]) => any` whose args symbol
|
|
3999
|
+
// has no declaration): the dotDotDot check below can't see it, and a
|
|
4000
|
+
// fixed-arity func mapping would LIE about the value's calling
|
|
4001
|
+
// convention. Detected by the param-count mismatch against the
|
|
4002
|
+
// signature's own declaration, excluding an erased `this` parameter.
|
|
4003
|
+
{
|
|
4004
|
+
const sigDecl = sig.declaration;
|
|
4005
|
+
const declParams = sigDecl !== undefined && ts.isFunctionLike(sigDecl) ? sigDecl.parameters.nodes : undefined;
|
|
4006
|
+
if (declParams !== undefined &&
|
|
4007
|
+
runtimeParameterCount(declParams) !== sig.getParameters().length) {
|
|
4008
|
+
return null;
|
|
4009
|
+
}
|
|
4010
|
+
// tsgo never SYNTHESIZES that rest param into the inferred signature
|
|
4011
|
+
// (5.9.3 did — the count mismatch above was the whole detector
|
|
4012
|
+
// there), so the declaration's own body answers directly.
|
|
4013
|
+
if (sigDecl !== undefined && ts.isFunctionLike(sigDecl) && bodyReadsArguments(sigDecl)) {
|
|
4014
|
+
return null;
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
const params = [];
|
|
4018
|
+
let typedRest = false;
|
|
4019
|
+
let dynRest = false;
|
|
4020
|
+
for (const p of sig.getParameters()) {
|
|
4021
|
+
const decl = p.valueDeclaration;
|
|
4022
|
+
const rest = decl !== undefined && ts.isParameter(decl) && decl.dotDotDotToken !== undefined;
|
|
4023
|
+
// arity ABI selected by lambdaSignature. Treating an inferred any[]
|
|
4024
|
+
// declaration as a typed packed-array closure would bypass its boxed
|
|
4025
|
+
// spread/error semantics and change coverage classification.
|
|
4026
|
+
if (rest && decl !== undefined && isJsSourceFile(ts.getSourceFileOfNode(decl)))
|
|
4027
|
+
return null;
|
|
4028
|
+
// A fixed-tuple rest (`...args: [A, B]`, `...args: Parameters<F>` over
|
|
4029
|
+
// a bound F) flattens to its positional parameters. Pattern rests keep
|
|
4030
|
+
// their packed-record ABI and stay unmapped as values.
|
|
4031
|
+
if (rest && decl !== undefined && ts.isParameter(decl) && ts.isIdentifier(decl.name)) {
|
|
4032
|
+
const elems = restTupleParamTypes(checker.getTypeOfSymbol(p), ctx);
|
|
4033
|
+
if (elems) {
|
|
4034
|
+
params.push(...elems);
|
|
4035
|
+
continue;
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
const optional = decl !== undefined &&
|
|
4039
|
+
ts.isParameter(decl) &&
|
|
4040
|
+
(decl.questionToken !== undefined || decl.initializer !== undefined);
|
|
4041
|
+
let pt = mapType(checker.getTypeOfSymbol(p), ctx);
|
|
4042
|
+
// A parameter a TypeScript program types `any` takes whatever the
|
|
4043
|
+
// caller passes: the checked-dynamic slot, as an `any`-typed binding
|
|
4044
|
+
// already is (dynFallbackType). Declaration files keep their paths.
|
|
4045
|
+
// Only function declarations, spelled function types and lambda
|
|
4046
|
+
// parameters whose default is the only source of their type (`(n =
|
|
4047
|
+
// lookup() ?? 5) => ...` with an `any` lookup): other lambdas and
|
|
4048
|
+
// methods in object literals keep their existing checked-dynamic story.
|
|
4049
|
+
if (!pt &&
|
|
4050
|
+
!rest &&
|
|
4051
|
+
decl !== undefined &&
|
|
4052
|
+
ts.isParameter(decl) &&
|
|
4053
|
+
decl.parent !== undefined &&
|
|
4054
|
+
(ts.isFunctionDeclaration(decl.parent) ||
|
|
4055
|
+
ts.isFunctionTypeNode(decl.parent) ||
|
|
4056
|
+
((ts.isArrowFunction(decl.parent) || ts.isFunctionExpression(decl.parent)) &&
|
|
4057
|
+
decl.initializer !== undefined &&
|
|
4058
|
+
decl.type === undefined &&
|
|
4059
|
+
!isJsSourceFile(ts.getSourceFileOfNode(decl)))) &&
|
|
4060
|
+
!ts.getSourceFileOfNode(decl).isDeclarationFile &&
|
|
4061
|
+
(checker.getTypeOfSymbol(p).flags & ts.TypeFlags.Any) !== 0)
|
|
4062
|
+
pt = DYN;
|
|
4063
|
+
if (decl &&
|
|
4064
|
+
ts.isParameter(decl) &&
|
|
4065
|
+
ts.isSetAccessorDeclaration(decl.parent) &&
|
|
4066
|
+
isJsSourceFile(ts.getSourceFileOfNode(decl)))
|
|
4067
|
+
pt = DYN;
|
|
4068
|
+
// An inferred JavaScript binding pattern consumes an iterable; it
|
|
4069
|
+
// does not require the caller's array to have exactly this length.
|
|
4070
|
+
const executor = decl && ts.isParameter(decl) ? decl.parent : null;
|
|
4071
|
+
const construction = executor?.parent;
|
|
4072
|
+
const constructorSymbol = construction && ts.isNewExpression(construction)
|
|
4073
|
+
? checker.getSymbolAtLocation(construction.expression)
|
|
4074
|
+
: undefined;
|
|
4075
|
+
const nativeExecutor = executor &&
|
|
4076
|
+
(ts.isArrowFunction(executor) || ts.isFunctionExpression(executor)) &&
|
|
4077
|
+
construction &&
|
|
4078
|
+
ts.isNewExpression(construction) &&
|
|
4079
|
+
construction.arguments?.nodes[0] === executor &&
|
|
4080
|
+
ts.isIdentifier(construction.expression) &&
|
|
4081
|
+
construction.expression.text === "Promise" &&
|
|
4082
|
+
constructorSymbol &&
|
|
4083
|
+
constructorSymbol.declarations.some((site) => ctx.isStdlibFile(ts.getSourceFileOfNode(site)));
|
|
4084
|
+
if (!nativeExecutor &&
|
|
4085
|
+
decl &&
|
|
4086
|
+
ts.isParameter(decl) &&
|
|
4087
|
+
!decl.dotDotDotToken &&
|
|
4088
|
+
!ts.isSetAccessorDeclaration(decl.parent) &&
|
|
4089
|
+
isJsSourceFile(ts.getSourceFileOfNode(decl)) &&
|
|
4090
|
+
!decl.type &&
|
|
4091
|
+
!/@(?:param|type)\b/.test(ts
|
|
4092
|
+
.getSourceFileOfNode(decl)
|
|
4093
|
+
.text.slice(decl.parent?.pos ?? decl.pos, ts.tokenStartOfNode(decl))))
|
|
4094
|
+
pt = DYN;
|
|
4095
|
+
// A DEFAULTED program-source parameter of a function, arrow or function
|
|
4096
|
+
// expression that the checker types `any` — a default under an
|
|
4097
|
+
// `(...args: any[]) => any` wrapper slot (`wrap((limit = 5) => ...)`),
|
|
4098
|
+
// where the contextual `any` wins over the default's type: its binding
|
|
4099
|
+
// is already the checked-dynamic kind inside the body
|
|
4100
|
+
// (dynFallbackType), so the callable's ABI slot is the same dyn value.
|
|
4101
|
+
// Other `any` parameters keep their existing paths (an object literal
|
|
4102
|
+
// holding such a callback stays a checked-dynamic object).
|
|
4103
|
+
if (pt === null &&
|
|
4104
|
+
!rest &&
|
|
4105
|
+
decl !== undefined &&
|
|
4106
|
+
ts.isParameter(decl) &&
|
|
4107
|
+
decl.initializer !== undefined &&
|
|
4108
|
+
(ts.isArrowFunction(decl.parent) ||
|
|
4109
|
+
ts.isFunctionExpression(decl.parent) ||
|
|
4110
|
+
ts.isFunctionDeclaration(decl.parent)) &&
|
|
4111
|
+
!ts.getSourceFileOfNode(decl).isDeclarationFile &&
|
|
4112
|
+
(checker.getTypeOfSymbol(p).flags & ts.TypeFlags.Any) !== 0)
|
|
4113
|
+
pt = DYN;
|
|
4114
|
+
if (pt)
|
|
4115
|
+
pt = jsOpenObjectType(decl, pt, ctx.shapes, ctx.unions);
|
|
4116
|
+
// Belt and braces for non-strict type worlds: an optional param's
|
|
4117
|
+
// ABI slot is always the undefined-armed union (strictNullChecks
|
|
4118
|
+
// already spells it that way; arm it here if the world didn't).
|
|
4119
|
+
if (optional && pt && pt.kind !== "void" && pt.kind !== "dyn") {
|
|
4120
|
+
const armed = withUndefinedArm(pt, ctx.unions);
|
|
4121
|
+
if (!armed)
|
|
4122
|
+
return null;
|
|
4123
|
+
pt = armed;
|
|
4124
|
+
}
|
|
4125
|
+
// `...args: unknown[]` / `...args: any[]` declared in program source:
|
|
4126
|
+
// the checked-dynamic variadic ABI (no typed slot; the callee's hidden
|
|
4127
|
+
// trailing dyn array receives every surplus argument, as for JS rest
|
|
4128
|
+
// params). Declaration files keep their existing paths: library
|
|
4129
|
+
// callback slots such as String#replace's `(substring, ...args: any[])`
|
|
4130
|
+
// have intrinsic lowerings that inspect the unmapped type.
|
|
4131
|
+
// node:test's default mock function type, `(...args: any[]) =>
|
|
4132
|
+
// undefined` (the type parameter default of mock.fn), takes the same
|
|
4133
|
+
// ABI: mock.fn() without an original records whatever its callers pass.
|
|
4134
|
+
if (rest &&
|
|
4135
|
+
decl !== undefined &&
|
|
4136
|
+
(!ts.getSourceFileOfNode(decl).isDeclarationFile ||
|
|
4137
|
+
isNodeTestDefaultFunctionParam(decl, ctx)) &&
|
|
4138
|
+
(pt?.kind === "dyn" || (!pt && isAnyArrayType(checker.getTypeOfSymbol(p), checker)))) {
|
|
4139
|
+
dynRest = true;
|
|
4140
|
+
continue;
|
|
4141
|
+
}
|
|
4142
|
+
if (!pt)
|
|
4143
|
+
return null;
|
|
4144
|
+
if (rest) {
|
|
4145
|
+
if (pt.kind !== "array")
|
|
4146
|
+
return null;
|
|
4147
|
+
typedRest = true;
|
|
4148
|
+
}
|
|
4149
|
+
// `(value: void) => void` (Promise<void>'s resolve) is callable with
|
|
4150
|
+
// no arguments — a void param is dropped, not a mapping failure.
|
|
4151
|
+
if (pt.kind === "void")
|
|
4152
|
+
continue;
|
|
4153
|
+
params.push(pt);
|
|
4154
|
+
}
|
|
4155
|
+
const retT = checker.getReturnTypeOfSignature(sig);
|
|
4156
|
+
// `() => never` (a throw-only lambda's inferred type) is assignable to
|
|
4157
|
+
// `() => void` and its calls never produce a value — map the return
|
|
4158
|
+
// like declaredReturnType does for declarations. JS null/undefined
|
|
4159
|
+
// returns can read mutable fields, so callable values use the same
|
|
4160
|
+
// checked-native return ABI as their implementations.
|
|
4161
|
+
const sigDecl = sig.declaration;
|
|
4162
|
+
const jsUnitReturn = sigDecl !== undefined &&
|
|
4163
|
+
isJsSourceFile(ts.getSourceFileOfNode(sigDecl)) &&
|
|
4164
|
+
(retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0;
|
|
4165
|
+
let ret = jsUnitReturn || (retT.flags & ts.TypeFlags.Any) !== 0
|
|
4166
|
+
? DYN
|
|
4167
|
+
: retT.flags & ts.TypeFlags.Never
|
|
4168
|
+
? VOID
|
|
4169
|
+
: mapType(retT, ctx);
|
|
4170
|
+
if (sigDecl &&
|
|
4171
|
+
ts.isGetAccessorDeclaration(sigDecl) &&
|
|
4172
|
+
isJsSourceFile(ts.getSourceFileOfNode(sigDecl)))
|
|
4173
|
+
ret = DYN;
|
|
4174
|
+
if (sigDecl && isJsSourceFile(ts.getSourceFileOfNode(sigDecl)) && ret?.kind === "array")
|
|
4175
|
+
ret = DYN;
|
|
4176
|
+
if (sigDecl &&
|
|
4177
|
+
ts.isFunctionLike(sigDecl) &&
|
|
4178
|
+
isJsSourceFile(ts.getSourceFileOfNode(sigDecl)) &&
|
|
4179
|
+
!sigDecl.type &&
|
|
4180
|
+
!/@returns?\b/.test(ts.getSourceFileOfNode(sigDecl).text.slice(sigDecl.pos, ts.tokenStartOfNode(sigDecl))) &&
|
|
4181
|
+
ret?.kind === "record")
|
|
4182
|
+
ret = DYN;
|
|
4183
|
+
if (sigDecl &&
|
|
4184
|
+
ts.isFunctionLike(sigDecl) &&
|
|
4185
|
+
isJsSourceFile(ts.getSourceFileOfNode(sigDecl)) &&
|
|
4186
|
+
!sigDecl.type &&
|
|
4187
|
+
!/@returns?\b/.test(ts.getSourceFileOfNode(sigDecl).text.slice(sigDecl.pos, ts.tokenStartOfNode(sigDecl))) &&
|
|
4188
|
+
(ret?.kind === "date" ||
|
|
4189
|
+
(ret?.kind === "union" &&
|
|
4190
|
+
ctx.unions.get(ret.unionId)?.arms.some((arm) => arm.kind === "func"))))
|
|
4191
|
+
ret = DYN;
|
|
4192
|
+
if (ret &&
|
|
4193
|
+
sigDecl &&
|
|
4194
|
+
isJsSourceFile(ts.getSourceFileOfNode(sigDecl)) &&
|
|
4195
|
+
functionCanReturnUndefined(sigDecl))
|
|
4196
|
+
ret = withUndefinedArm(ret, ctx.unions) ?? ret;
|
|
4197
|
+
if (!ret)
|
|
4198
|
+
return null;
|
|
4199
|
+
return typedRest
|
|
4200
|
+
? { kind: "func", params, ret, rest: true, restAbi: "typed" }
|
|
4201
|
+
: dynRest
|
|
4202
|
+
? { kind: "func", params, ret, rest: true }
|
|
4203
|
+
: funcOf(params, ret);
|
|
4204
|
+
}
|
|
3512
4205
|
/** Retain a literal discriminator before widening erases its values. A
|
|
3513
4206
|
* structural match alone is insufficient: `{ kind: "loop", body: ... }`
|
|
3514
4207
|
* also fits a smaller `{ kind: "empty" }` record. Choosing that layout
|
|
@@ -3523,14 +4216,18 @@ function unionDiscriminant(parts, arms, ctx) {
|
|
|
3523
4216
|
if (arms.filter((arm) => arm.kind === "record").length < 2 || parts.length < 2)
|
|
3524
4217
|
return undefined;
|
|
3525
4218
|
const { checker } = ctx;
|
|
4219
|
+
// Tuple shapes keep positions only: their checker `length` literal has
|
|
4220
|
+
// no slot to compare (discriminantField refuses tuple shapes too).
|
|
4221
|
+
if (parts.some((part) => ctx.shapes.get(part.mapped.shapeId)?.tuple))
|
|
4222
|
+
return undefined;
|
|
3526
4223
|
for (const candidate of checker.getPropertiesOfType(parts[0].source)) {
|
|
3527
|
-
if (candidate.
|
|
4224
|
+
if (ts.symbolName(candidate).startsWith("__@"))
|
|
3528
4225
|
continue;
|
|
3529
4226
|
const byTag = new Map();
|
|
3530
4227
|
const owner = new Map();
|
|
3531
4228
|
let complete = true;
|
|
3532
4229
|
for (const part of parts) {
|
|
3533
|
-
const prop = checker.getPropertyOfType(part.source, candidate
|
|
4230
|
+
const prop = checker.getPropertyOfType(part.source, ts.symbolName(candidate));
|
|
3534
4231
|
if (!prop ||
|
|
3535
4232
|
prop.flags &
|
|
3536
4233
|
(ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor)) {
|
|
@@ -3561,7 +4258,7 @@ function unionDiscriminant(parts, arms, ctx) {
|
|
|
3561
4258
|
}
|
|
3562
4259
|
if (complete) {
|
|
3563
4260
|
return {
|
|
3564
|
-
field: candidate
|
|
4261
|
+
field: ts.symbolName(candidate),
|
|
3565
4262
|
cases: [...byTag]
|
|
3566
4263
|
.sort(([a], [b]) => a - b)
|
|
3567
4264
|
.map(([tag, values]) => ({
|
|
@@ -3594,9 +4291,9 @@ function mapClassView(type, ctx, seen = new Set()) {
|
|
|
3594
4291
|
}
|
|
3595
4292
|
else {
|
|
3596
4293
|
const symbol = type.getSymbol();
|
|
3597
|
-
const declarations = symbol ?
|
|
4294
|
+
const declarations = symbol ? symbol.declarations : [];
|
|
3598
4295
|
if (declarations.length === 0 ||
|
|
3599
|
-
!declarations.every((decl) => ts.isInterfaceDeclaration(decl) && !ctx.isStdlibFile(
|
|
4296
|
+
!declarations.every((decl) => ts.isInterfaceDeclaration(decl) && !ctx.isStdlibFile(ts.getSourceFileOfNode(decl))))
|
|
3600
4297
|
return undefined;
|
|
3601
4298
|
const target = type.isTypeReference() ? type.getTarget() : type;
|
|
3602
4299
|
if (target === undefined || !target.isClassOrInterface())
|
|
@@ -3629,10 +4326,10 @@ function mapClassView(type, ctx, seen = new Set()) {
|
|
|
3629
4326
|
let representation;
|
|
3630
4327
|
for (const base of bases) {
|
|
3631
4328
|
const symbol = base.getSymbol();
|
|
3632
|
-
const declaration = symbol ?
|
|
4329
|
+
const declaration = symbol ? symbol.valueDeclaration : undefined;
|
|
3633
4330
|
const classBase = declaration &&
|
|
3634
4331
|
(ts.isClassDeclaration(declaration) || ts.isClassExpression(declaration)) &&
|
|
3635
|
-
!
|
|
4332
|
+
!ts.getSourceFileOfNode(declaration).isDeclarationFile;
|
|
3636
4333
|
const mapped = classBase ? mapType(base, viewCtx) : mapClassView(base, viewCtx, seen);
|
|
3637
4334
|
if (mapped === null)
|
|
3638
4335
|
return null;
|
|
@@ -3650,13 +4347,13 @@ function mapClassView(type, ctx, seen = new Set()) {
|
|
|
3650
4347
|
checker.getIndexInfosOfType(type).length)
|
|
3651
4348
|
return null;
|
|
3652
4349
|
for (const property of checker.getPropertiesOfType(type)) {
|
|
3653
|
-
const original = checker.getPropertyOfType(baseType, property
|
|
4350
|
+
const original = checker.getPropertyOfType(baseType, ts.symbolName(property));
|
|
3654
4351
|
if (!original)
|
|
3655
4352
|
return null;
|
|
3656
4353
|
if (original === property)
|
|
3657
4354
|
continue;
|
|
3658
|
-
const originalDeclarations =
|
|
3659
|
-
const declarations =
|
|
4355
|
+
const originalDeclarations = original.declarations;
|
|
4356
|
+
const declarations = property.declarations;
|
|
3660
4357
|
// Instantiating an inherited member can create a new symbol without
|
|
3661
4358
|
// changing its declaration or ABI. Only refinements need validation.
|
|
3662
4359
|
if (declarations.length > 0 &&
|
|
@@ -3691,9 +4388,9 @@ function mapCollectionView(type, ctx, seen = new Set()) {
|
|
|
3691
4388
|
return null;
|
|
3692
4389
|
const { checker } = ctx;
|
|
3693
4390
|
const symbol = type.getSymbol();
|
|
3694
|
-
const declarations = symbol ?
|
|
4391
|
+
const declarations = symbol ? symbol.declarations : [];
|
|
3695
4392
|
if (declarations.length === 0 ||
|
|
3696
|
-
!declarations.every((decl) => ts.isInterfaceDeclaration(decl) && !ctx.isStdlibFile(
|
|
4393
|
+
!declarations.every((decl) => ts.isInterfaceDeclaration(decl) && !ctx.isStdlibFile(ts.getSourceFileOfNode(decl))))
|
|
3697
4394
|
return null;
|
|
3698
4395
|
const target = type.getTarget();
|
|
3699
4396
|
if (target === undefined ||
|
|
@@ -3734,21 +4431,17 @@ function mapCollectionView(type, ctx, seen = new Set()) {
|
|
|
3734
4431
|
const base = bases[0];
|
|
3735
4432
|
const baseSymbol = base.getSymbol();
|
|
3736
4433
|
const native = baseSymbol &&
|
|
3737
|
-
["Map", "ReadonlyMap", "Set", "ReadonlySet"].includes(baseSymbol
|
|
3738
|
-
|
|
3739
|
-
.declarationsOf(baseSymbol)
|
|
3740
|
-
.some((decl) => ts.isInterfaceDeclaration(decl) && ctx.isStdlibFile(decl.getSourceFile()));
|
|
4434
|
+
["Map", "ReadonlyMap", "Set", "ReadonlySet"].includes(ts.symbolName(baseSymbol)) &&
|
|
4435
|
+
baseSymbol.declarations.some((decl) => ts.isInterfaceDeclaration(decl) && ctx.isStdlibFile(ts.getSourceFileOfNode(decl)));
|
|
3741
4436
|
const mapped = native ? mapType(base, baseCtx) : mapCollectionView(base, baseCtx, seen);
|
|
3742
4437
|
if (mapped?.kind !== "map" && mapped?.kind !== "set")
|
|
3743
4438
|
return null;
|
|
3744
4439
|
const hasType = funcOf([mapped.kind === "map" ? mapped.key : mapped.elem], BOOL);
|
|
3745
4440
|
for (const property of checker.getPropertiesOfType(type)) {
|
|
3746
|
-
const own =
|
|
3747
|
-
.declarationsOf(property)
|
|
3748
|
-
.filter((decl) => !ctx.isStdlibFile(decl.getSourceFile()));
|
|
4441
|
+
const own = property.declarations.filter((decl) => !ctx.isStdlibFile(ts.getSourceFileOfNode(decl)));
|
|
3749
4442
|
if (own.length === 0)
|
|
3750
4443
|
continue;
|
|
3751
|
-
if (property
|
|
4444
|
+
if (ts.symbolName(property) !== "has" ||
|
|
3752
4445
|
property.flags & ts.SymbolFlags.Optional ||
|
|
3753
4446
|
!own.every((decl) => decl.kind === ts.SyntaxKind.MethodSignature))
|
|
3754
4447
|
return null;
|
|
@@ -3858,6 +4551,166 @@ function mapBoundIndexedAccess(type, ctx) {
|
|
|
3858
4551
|
return null;
|
|
3859
4552
|
return mapType(checker.getTypeOfSymbol(prop), ctx);
|
|
3860
4553
|
}
|
|
4554
|
+
/** The standard library's `Parameters<F>` / `ReturnType<F>` over a type
|
|
4555
|
+
* parameter the current instantiation binds to a callable checker type:
|
|
4556
|
+
* that type's one call signature. Concrete arguments never reach here (the
|
|
4557
|
+
* checker evaluates those conditionals itself); generic bodies keep them
|
|
4558
|
+
* symbolic because their `infer` sits in a call signature. */
|
|
4559
|
+
function boundSignatureAlias(type, ctx) {
|
|
4560
|
+
const { checker, resolveTypeParamTs } = ctx;
|
|
4561
|
+
if (!resolveTypeParamTs)
|
|
4562
|
+
return null;
|
|
4563
|
+
const alias = type.getAliasSymbol();
|
|
4564
|
+
const aliasName = alias === undefined ? undefined : ts.symbolName(alias);
|
|
4565
|
+
if (!alias || (aliasName !== "Parameters" && aliasName !== "ReturnType"))
|
|
4566
|
+
return null;
|
|
4567
|
+
const aliasArgs = type.getAliasTypeArguments();
|
|
4568
|
+
const arg = aliasArgs[0];
|
|
4569
|
+
if (aliasArgs.length !== 1 || !arg || !(arg.flags & ts.TypeFlags.TypeParameter))
|
|
4570
|
+
return null;
|
|
4571
|
+
const isLibAlias = alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)));
|
|
4572
|
+
if (!isLibAlias)
|
|
4573
|
+
return null;
|
|
4574
|
+
const bound = resolveTypeParamTs(arg);
|
|
4575
|
+
if (!bound || bound.flags & ts.TypeFlags.TypeParameter)
|
|
4576
|
+
return null;
|
|
4577
|
+
const sigs = checker.getCallSignatures(bound);
|
|
4578
|
+
const sig = sigs[0];
|
|
4579
|
+
if (sigs.length !== 1 || !sig || sig.getTypeParameters().length > 0)
|
|
4580
|
+
return null;
|
|
4581
|
+
return { name: aliasName, sig };
|
|
4582
|
+
}
|
|
4583
|
+
/** The positional parameters of a signature as a fixed tuple: a trailing
|
|
4584
|
+
* rest flattened when its own type is a fixed tuple. Null for a variadic
|
|
4585
|
+
* position, which has no fixed native arity. */
|
|
4586
|
+
function signatureParameters(sig, ctx) {
|
|
4587
|
+
const { checker } = ctx;
|
|
4588
|
+
const out = [];
|
|
4589
|
+
for (const p of sig.getParameters()) {
|
|
4590
|
+
const decl = p.valueDeclaration;
|
|
4591
|
+
const type = checker.getTypeOfSymbol(p);
|
|
4592
|
+
if (decl !== undefined && ts.isParameter(decl)) {
|
|
4593
|
+
if (decl.dotDotDotToken !== undefined) {
|
|
4594
|
+
const inner = restTupleElements(type, ctx);
|
|
4595
|
+
if (!inner)
|
|
4596
|
+
return null;
|
|
4597
|
+
out.push(...inner);
|
|
4598
|
+
continue;
|
|
4599
|
+
}
|
|
4600
|
+
out.push({
|
|
4601
|
+
type,
|
|
4602
|
+
optional: decl.questionToken !== undefined || decl.initializer !== undefined,
|
|
4603
|
+
});
|
|
4604
|
+
continue;
|
|
4605
|
+
}
|
|
4606
|
+
out.push({ type, optional: (p.flags & ts.SymbolFlags.Optional) !== 0 });
|
|
4607
|
+
}
|
|
4608
|
+
return out;
|
|
4609
|
+
}
|
|
4610
|
+
/** The required-only positional parameter types of a signature (the
|
|
4611
|
+
* value-level `Parameters<F>` tuple), null when a position is optional
|
|
4612
|
+
* or variadic: such a tuple's length varies per call. */
|
|
4613
|
+
function signatureParameterTypes(sig, ctx) {
|
|
4614
|
+
const elems = signatureParameters(sig, ctx);
|
|
4615
|
+
if (!elems || elems.some((e) => e.optional))
|
|
4616
|
+
return null;
|
|
4617
|
+
return elems.map((e) => e.type);
|
|
4618
|
+
}
|
|
4619
|
+
/** The element types of a REST parameter's type when it is a fixed tuple:
|
|
4620
|
+
* a tuple of required elements (`[number, string]`, the empty `[]`), a type
|
|
4621
|
+
* parameter bound to one, or `Parameters<F>` over a bound function type.
|
|
4622
|
+
* Such a rest parameter has a compile-time arity, so its native ABI is the
|
|
4623
|
+
* flattened positional list (exactly the equivalent fixed signature —
|
|
4624
|
+
* TypeScript treats `(...a: [A, B]) => R` and `(a: A, b: B) => R` alike). */
|
|
4625
|
+
export function restTupleElementTypes(type, ctx) {
|
|
4626
|
+
return restTupleElements(type, ctx)?.map((e) => e.type) ?? null;
|
|
4627
|
+
}
|
|
4628
|
+
/** restTupleElementTypes with each position's optionality: a rest tuple
|
|
4629
|
+
* may end in optional positions (`[A, B?]`, `Parameters<(a: A, b?: B) =>
|
|
4630
|
+
* R>`), which flatten to `T | undefined` slots exactly as the function
|
|
4631
|
+
* type's optional parameters do. */
|
|
4632
|
+
function restTupleElements(type, ctx) {
|
|
4633
|
+
const { checker } = ctx;
|
|
4634
|
+
if (type.flags & ts.TypeFlags.TypeParameter) {
|
|
4635
|
+
const bound = ctx.resolveTypeParamTs?.(type);
|
|
4636
|
+
return bound && bound !== type ? restTupleElements(bound, ctx) : null;
|
|
4637
|
+
}
|
|
4638
|
+
const viaAlias = boundSignatureAlias(type, ctx);
|
|
4639
|
+
if (viaAlias) {
|
|
4640
|
+
return viaAlias.name === "Parameters" ? signatureParameters(viaAlias.sig, ctx) : null;
|
|
4641
|
+
}
|
|
4642
|
+
if (!checker.isTupleType(type))
|
|
4643
|
+
return null;
|
|
4644
|
+
const ref = type;
|
|
4645
|
+
const tupleShape = ref.elementFlags !== undefined
|
|
4646
|
+
? ref
|
|
4647
|
+
: ref.getTarget();
|
|
4648
|
+
const args = checker.getTypeArguments(ref);
|
|
4649
|
+
if (args.length === 0)
|
|
4650
|
+
return [];
|
|
4651
|
+
const flags = tupleShape?.elementFlags;
|
|
4652
|
+
if (flags === undefined)
|
|
4653
|
+
return null;
|
|
4654
|
+
if (flags.some((f) => !(f & (ts.ElementFlags.Required | ts.ElementFlags.Optional))))
|
|
4655
|
+
return null;
|
|
4656
|
+
return args.map((t, i) => ({
|
|
4657
|
+
type: t,
|
|
4658
|
+
optional: (flags[i] & ts.ElementFlags.Optional) !== 0,
|
|
4659
|
+
}));
|
|
4660
|
+
}
|
|
4661
|
+
/** One tuple element's IR type under the tuple mapping's rules. */
|
|
4662
|
+
function mapTupleElement(t, ctx) {
|
|
4663
|
+
let et = (t.flags & ts.TypeFlags.Any) !== 0 ? DYN : mapType(t, ctx);
|
|
4664
|
+
if (et?.kind === "void" && isUnitOnlyTsType(t, ctx.resolveTypeParam))
|
|
4665
|
+
et = unitOnlyUnion(ctx.unions);
|
|
4666
|
+
return !et || et.kind === "void" ? null : et;
|
|
4667
|
+
}
|
|
4668
|
+
/** The mapped element types of a fixed-tuple rest parameter type
|
|
4669
|
+
* (restTupleElementTypes), null when it is not one or an element does not
|
|
4670
|
+
* map. */
|
|
4671
|
+
export function restTupleParamTypes(type, ctx) {
|
|
4672
|
+
const elems = restTupleElements(type, ctx);
|
|
4673
|
+
if (!elems)
|
|
4674
|
+
return null;
|
|
4675
|
+
const out = [];
|
|
4676
|
+
for (const e of elems) {
|
|
4677
|
+
let et = mapTupleElement(e.type, ctx);
|
|
4678
|
+
// An optional position's slot holds undefined when the caller omits
|
|
4679
|
+
// it, as an optional parameter's does (mapCallSignature).
|
|
4680
|
+
if (et && e.optional && et.kind !== "dyn")
|
|
4681
|
+
et = withUndefinedArm(et, ctx.unions);
|
|
4682
|
+
if (!et)
|
|
4683
|
+
return null;
|
|
4684
|
+
out.push(et);
|
|
4685
|
+
}
|
|
4686
|
+
return out;
|
|
4687
|
+
}
|
|
4688
|
+
/** `Parameters<F>` (the fixed tuple of F's parameters, interned exactly as
|
|
4689
|
+
* the spelled tuple maps) and `ReturnType<F>` (F's mapped result) over a
|
|
4690
|
+
* bound function-typed type parameter. */
|
|
4691
|
+
function mapBoundSignatureAlias(type, ctx) {
|
|
4692
|
+
const target = boundSignatureAlias(type, ctx);
|
|
4693
|
+
if (!target)
|
|
4694
|
+
return null;
|
|
4695
|
+
if (target.name === "ReturnType") {
|
|
4696
|
+
const ret = ctx.checker.getReturnTypeOfSignature(target.sig);
|
|
4697
|
+
return ret.flags & ts.TypeFlags.Any ? DYN : mapType(ret, ctx);
|
|
4698
|
+
}
|
|
4699
|
+
const elems = signatureParameterTypes(target.sig, ctx);
|
|
4700
|
+
if (!elems)
|
|
4701
|
+
return null;
|
|
4702
|
+
if (elems.length === 0)
|
|
4703
|
+
return arrayOf(unitOnlyUnion(ctx.unions));
|
|
4704
|
+
const fields = [];
|
|
4705
|
+
for (let i = 0; i < elems.length; i++) {
|
|
4706
|
+
const et = mapTupleElement(elems[i], ctx);
|
|
4707
|
+
if (!et)
|
|
4708
|
+
return null;
|
|
4709
|
+
fields.push({ name: String(i), type: et });
|
|
4710
|
+
}
|
|
4711
|
+
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
4712
|
+
return { kind: "record", shapeId: ctx.shapes.intern(fields, true) };
|
|
4713
|
+
}
|
|
3861
4714
|
/** `Partial<T>` / `Readonly<T>` where T is a STILL-GENERIC type parameter —
|
|
3862
4715
|
* the one mapped-type spelling a monomorphized body can contain that the
|
|
3863
4716
|
* checker cannot resolve for us (`keyof T` is unknown inside the body, so
|
|
@@ -3897,16 +4750,16 @@ export function underConstAssertion(n) {
|
|
|
3897
4750
|
* panic repair): a property symbol declared by a property assignment whose
|
|
3898
4751
|
* initializer is an EMPTY array literal inside a const assertion — its
|
|
3899
4752
|
* type is provably `readonly []`, whatever the panicked query answered. */
|
|
3900
|
-
function constAssertedEmptyArrayProp(p
|
|
3901
|
-
const d =
|
|
4753
|
+
function constAssertedEmptyArrayProp(p) {
|
|
4754
|
+
const d = p.valueDeclaration;
|
|
3902
4755
|
if (d === undefined || !ts.isPropertyAssignment(d))
|
|
3903
4756
|
return false;
|
|
3904
4757
|
const init = d.initializer;
|
|
3905
4758
|
// `a: [] as const` pins the field type by itself, wherever the literal sits.
|
|
3906
4759
|
if (ts.isAsExpression(init) && isConstAssertionTypeNode(init.type)) {
|
|
3907
|
-
return ts.isArrayLiteralExpression(init.expression) && init.expression.elements.length === 0;
|
|
4760
|
+
return (ts.isArrayLiteralExpression(init.expression) && init.expression.elements.nodes.length === 0);
|
|
3908
4761
|
}
|
|
3909
|
-
if (!ts.isArrayLiteralExpression(init) || init.elements.length > 0)
|
|
4762
|
+
if (!ts.isArrayLiteralExpression(init) || init.elements.nodes.length > 0)
|
|
3910
4763
|
return false;
|
|
3911
4764
|
return underConstAssertion(d);
|
|
3912
4765
|
}
|
|
@@ -3915,21 +4768,22 @@ function mapGenericAwaitedAlias(type, ctx) {
|
|
|
3915
4768
|
if (!resolveTypeParam)
|
|
3916
4769
|
return null;
|
|
3917
4770
|
const alias = type.getAliasSymbol();
|
|
3918
|
-
if (!alias || alias
|
|
4771
|
+
if (!alias || ts.symbolName(alias) !== "Awaited")
|
|
3919
4772
|
return null;
|
|
3920
4773
|
const aliasArgs = type.getAliasTypeArguments();
|
|
3921
4774
|
const arg = aliasArgs[0];
|
|
3922
4775
|
if (aliasArgs.length !== 1 || !arg)
|
|
3923
4776
|
return null;
|
|
3924
|
-
|
|
4777
|
+
// `Awaited<ReturnType<F>>` (an async wrapper's settled result) resolves
|
|
4778
|
+
// through F's bound signature like a bare type parameter.
|
|
4779
|
+
const viaSignature = arg.flags & ts.TypeFlags.TypeParameter ? null : boundSignatureAlias(arg, ctx);
|
|
4780
|
+
if (!(arg.flags & ts.TypeFlags.TypeParameter) && viaSignature?.name !== "ReturnType")
|
|
3925
4781
|
return null;
|
|
3926
4782
|
// Provenance: the STANDARD LIBRARY's alias, not a user's shadowing one.
|
|
3927
|
-
const isLibAlias = ctx.
|
|
3928
|
-
.declarationsOf(alias)
|
|
3929
|
-
.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()));
|
|
4783
|
+
const isLibAlias = alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)));
|
|
3930
4784
|
if (!isLibAlias)
|
|
3931
4785
|
return null;
|
|
3932
|
-
const bound = resolveTypeParam(arg);
|
|
4786
|
+
const bound = viaSignature ? mapBoundSignatureAlias(arg, ctx) : resolveTypeParam(arg);
|
|
3933
4787
|
if (!bound)
|
|
3934
4788
|
return null;
|
|
3935
4789
|
let r = bound;
|
|
@@ -3958,14 +4812,19 @@ function mapGenericIndexedAccess(type, ctx) {
|
|
|
3958
4812
|
if (obj === undefined || !(obj.flags & ts.TypeFlags.TypeParameter))
|
|
3959
4813
|
return null;
|
|
3960
4814
|
const bound = resolveTypeParam(obj);
|
|
4815
|
+
const idx = type.getIndexType();
|
|
4816
|
+
if (idx === undefined)
|
|
4817
|
+
return null;
|
|
4818
|
+
// `T[keyof T]` over a T bound to an unknown-valued record view
|
|
4819
|
+
// (`Record<string, unknown>` maps to the checked-dynamic value, see
|
|
4820
|
+
// mapRecordType): every member reads as unknown.
|
|
4821
|
+
if (bound?.kind === "dyn" && idx.isIndexType() && idx.getTarget() === obj)
|
|
4822
|
+
return DYN;
|
|
3961
4823
|
if (!bound || bound.kind !== "record")
|
|
3962
4824
|
return null;
|
|
3963
4825
|
const shape = shapes.get(bound.shapeId);
|
|
3964
4826
|
if (!shape || shape.tuple)
|
|
3965
4827
|
return null;
|
|
3966
|
-
const idx = type.getIndexType();
|
|
3967
|
-
if (idx === undefined)
|
|
3968
|
-
return null;
|
|
3969
4828
|
let covered = null;
|
|
3970
4829
|
if (idx.isStringLiteralType()) {
|
|
3971
4830
|
const f = shape.fields.find((x) => x.name === idx.value);
|
|
@@ -3984,14 +4843,414 @@ function mapGenericIndexedAccess(type, ctx) {
|
|
|
3984
4843
|
if (!covered || covered.length === 0)
|
|
3985
4844
|
return null;
|
|
3986
4845
|
const first = covered[0];
|
|
3987
|
-
|
|
4846
|
+
if (covered.every((t) => typeEquals(t, first)))
|
|
4847
|
+
return first;
|
|
4848
|
+
// Only the `keyof T` index itself covers every field at once; a key
|
|
4849
|
+
// parameter bound to string keeps its literal-key resolution below.
|
|
4850
|
+
if (!(idx.isIndexType() && idx.getTarget() === obj))
|
|
4851
|
+
return null;
|
|
4852
|
+
// Fields of different scalar types (`Object.entries` over a bound record
|
|
4853
|
+
// reads `T[keyof T]`): any one of them, the union of their types.
|
|
4854
|
+
const arms = [];
|
|
4855
|
+
for (const t of covered) {
|
|
4856
|
+
const parts = t.kind === "union" ? (ctx.unions.get(t.unionId)?.arms ?? null) : [t];
|
|
4857
|
+
if (!parts)
|
|
4858
|
+
return null;
|
|
4859
|
+
for (const part of parts) {
|
|
4860
|
+
if (part.kind !== "f64" &&
|
|
4861
|
+
part.kind !== "string" &&
|
|
4862
|
+
part.kind !== "bool" &&
|
|
4863
|
+
part.kind !== "undefinedT" &&
|
|
4864
|
+
part.kind !== "nullT")
|
|
4865
|
+
return null;
|
|
4866
|
+
if (!arms.some((a) => typeEquals(a, part)))
|
|
4867
|
+
arms.push(part);
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
if (arms.length === 1)
|
|
4871
|
+
return arms[0];
|
|
4872
|
+
arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
4873
|
+
return { kind: "union", unionId: ctx.unions.intern(arms) };
|
|
4874
|
+
}
|
|
4875
|
+
/** `keyof T extends never ? A : B` over a bound record T (the lib's
|
|
4876
|
+
* Object.entries element spelling): decided by whether the binding has any
|
|
4877
|
+
* key. */
|
|
4878
|
+
function mapBoundKeyofNeverConditional(type, ctx) {
|
|
4879
|
+
const { resolveTypeParam, shapes } = ctx;
|
|
4880
|
+
if (!resolveTypeParam || !type.isConditionalType())
|
|
4881
|
+
return null;
|
|
4882
|
+
const check = type.getCheckType();
|
|
4883
|
+
const ext = type.getExtendsType();
|
|
4884
|
+
if (!check || !ext || !(ext.flags & ts.TypeFlags.Never) || !check.isIndexType())
|
|
4885
|
+
return null;
|
|
4886
|
+
const target = check.getTarget();
|
|
4887
|
+
if (!target || !(target.flags & ts.TypeFlags.TypeParameter))
|
|
4888
|
+
return null;
|
|
4889
|
+
const bound = resolveTypeParam(target);
|
|
4890
|
+
// A T bound to the checked-dynamic value (`Record<string, unknown>`, an
|
|
4891
|
+
// unknown-valued record view) has no static key set to decide the
|
|
4892
|
+
// branch, but both branches of the lib's `keyof T extends never ?
|
|
4893
|
+
// unknown : T[keyof T]` read as unknown there: one answer either way.
|
|
4894
|
+
if (bound?.kind === "dyn") {
|
|
4895
|
+
const whenEmpty = type.getTrueType();
|
|
4896
|
+
const otherwise = type.getFalseType();
|
|
4897
|
+
const a = whenEmpty ? mapType(whenEmpty, ctx) : null;
|
|
4898
|
+
const b = otherwise ? mapType(otherwise, ctx) : null;
|
|
4899
|
+
return a && b && typeEquals(a, b) ? a : null;
|
|
4900
|
+
}
|
|
4901
|
+
if (bound?.kind !== "record")
|
|
4902
|
+
return null;
|
|
4903
|
+
const shape = shapes.get(bound.shapeId);
|
|
4904
|
+
if (!shape || shape.tuple)
|
|
4905
|
+
return null;
|
|
4906
|
+
const hasKeys = shape.fields.length > 0 || shape.indexValue !== undefined;
|
|
4907
|
+
const branch = hasKeys ? type.getFalseType() : type.getTrueType();
|
|
4908
|
+
return branch ? mapType(branch, ctx) : null;
|
|
4909
|
+
}
|
|
4910
|
+
/** A mapped type over a type parameter of the instance being lowered (`{
|
|
4911
|
+
* [K in keyof S]: S[K] }`, `{ [K in keyof S]: Infer<S[K]> }`): the checker
|
|
4912
|
+
* keeps it symbolic inside the generic body, but the instance binds `S`,
|
|
4913
|
+
* so each property of the bound type maps through the template evaluated
|
|
4914
|
+
* with `K` set to that property's key. Optionality follows the `?`
|
|
4915
|
+
* modifier, or the bound property's own for a homomorphic mapping. Null
|
|
4916
|
+
* when the shape is anything else or a template form does not evaluate. */
|
|
4917
|
+
function mapBoundMappedType(widened, ctx) {
|
|
4918
|
+
const { checker, resolveTypeParamTs, shapes, unions } = ctx;
|
|
4919
|
+
if (!resolveTypeParamTs || !isMappedShape(widened))
|
|
4920
|
+
return null;
|
|
4921
|
+
const symbol = widened.getSymbol();
|
|
4922
|
+
const node = symbol
|
|
4923
|
+
? symbol.declarations.find((d) => ts.isMappedTypeNode(d))
|
|
4924
|
+
: undefined;
|
|
4925
|
+
const constraint = node?.typeParameter.constraint;
|
|
4926
|
+
if (!node?.type ||
|
|
4927
|
+
!constraint ||
|
|
4928
|
+
!ts.isTypeOperatorNode(constraint) ||
|
|
4929
|
+
constraint.operator !== ts.SyntaxKind.KeyOfKeyword)
|
|
4930
|
+
return null;
|
|
4931
|
+
const source = checker.getTypeFromTypeNode(constraint.type);
|
|
4932
|
+
if (!(source.flags & ts.TypeFlags.TypeParameter))
|
|
4933
|
+
return null;
|
|
4934
|
+
const bound = resolveTypeParamTs(source);
|
|
4935
|
+
const key = checker.getSymbolAtLocation(node.typeParameter.name);
|
|
4936
|
+
if (!bound || !key)
|
|
4937
|
+
return null;
|
|
4938
|
+
const template = checker.getTypeFromTypeNode(node.type);
|
|
4939
|
+
const modifier = node.questionToken?.kind;
|
|
4940
|
+
const fields = [];
|
|
4941
|
+
const order = [];
|
|
4942
|
+
for (const property of checker.getPropertiesOfType(bound)) {
|
|
4943
|
+
const name = ts.symbolName(property);
|
|
4944
|
+
const evaluated = evalMappedTemplate(template, new Map([[key, name]]), new Map(), ctx);
|
|
4945
|
+
let type = evaluated ? mapType(evaluated, ctx) : null;
|
|
4946
|
+
if (!type)
|
|
4947
|
+
return null;
|
|
4948
|
+
const optional = modifier === ts.SyntaxKind.MinusToken
|
|
4949
|
+
? false
|
|
4950
|
+
: modifier !== undefined || (property.flags & ts.SymbolFlags.Optional) !== 0;
|
|
4951
|
+
if (optional) {
|
|
4952
|
+
const armed = withUndefinedArm(type, unions);
|
|
4953
|
+
if (!armed)
|
|
4954
|
+
return null;
|
|
4955
|
+
type = armed;
|
|
4956
|
+
}
|
|
4957
|
+
fields.push({ name, type });
|
|
4958
|
+
order.push(name);
|
|
4959
|
+
}
|
|
4960
|
+
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
4961
|
+
return { kind: "record", shapeId: shapes.intern(fields, false, undefined, order) };
|
|
4962
|
+
}
|
|
4963
|
+
/** The checker type a mapped type's template stands for at one key:
|
|
4964
|
+
* `keys` binds the mapped type parameter to a property name, `aliases`
|
|
4965
|
+
* binds type-alias and `infer` parameters met on the way. Handles type
|
|
4966
|
+
* parameters (through the instance's bindings), indexed accesses
|
|
4967
|
+
* (`S[K]`, `S[K]["_output"]`) and conditional types whose `extends` side
|
|
4968
|
+
* is a reference to the same generic type as the checked type
|
|
4969
|
+
* (`S extends Schema<infer T> ? T : never`); answers the type itself
|
|
4970
|
+
* when it mentions none of the bound parameters, null otherwise. */
|
|
4971
|
+
function evalMappedTemplate(type, keys, aliases, ctx) {
|
|
4972
|
+
const { checker, resolveTypeParamTs } = ctx;
|
|
4973
|
+
if (type.flags & ts.TypeFlags.TypeParameter) {
|
|
4974
|
+
const symbol = type.getSymbol();
|
|
4975
|
+
if (symbol && keys.has(symbol))
|
|
4976
|
+
return null;
|
|
4977
|
+
if (symbol && aliases.has(symbol))
|
|
4978
|
+
return aliases.get(symbol);
|
|
4979
|
+
return resolveTypeParamTs?.(type) ?? null;
|
|
4980
|
+
}
|
|
4981
|
+
if (type.isIndexedAccessType()) {
|
|
4982
|
+
const object = type.getObjectType();
|
|
4983
|
+
const index = type.getIndexType();
|
|
4984
|
+
if (!object || !index)
|
|
4985
|
+
return null;
|
|
4986
|
+
const receiver = evalMappedTemplate(object, keys, aliases, ctx);
|
|
4987
|
+
const indexSymbol = index.flags & ts.TypeFlags.TypeParameter ? index.getSymbol() : undefined;
|
|
4988
|
+
const name = indexSymbol && keys.has(indexSymbol)
|
|
4989
|
+
? keys.get(indexSymbol)
|
|
4990
|
+
: index.isStringLiteralType()
|
|
4991
|
+
? index.value
|
|
4992
|
+
: index.isNumberLiteralType()
|
|
4993
|
+
? String(index.value)
|
|
4994
|
+
: null;
|
|
4995
|
+
if (!receiver || name === null)
|
|
4996
|
+
return null;
|
|
4997
|
+
const property = checker.getPropertyOfType(receiver, name);
|
|
4998
|
+
return property ? checker.getTypeOfSymbol(property) : null;
|
|
4999
|
+
}
|
|
5000
|
+
if (type.isConditionalType()) {
|
|
5001
|
+
// A conditional reached through an alias (`Infer<S[K]>`) checks the
|
|
5002
|
+
// alias's own parameters: bind them to the evaluated arguments.
|
|
5003
|
+
let scope = aliases;
|
|
5004
|
+
const alias = type.getAliasSymbol();
|
|
5005
|
+
const aliasArgs = type.getAliasTypeArguments();
|
|
5006
|
+
const aliasDecl = alias
|
|
5007
|
+
? alias.declarations.find((d) => ts.isTypeAliasDeclaration(d))
|
|
5008
|
+
: undefined;
|
|
5009
|
+
if (aliasDecl?.typeParameters?.nodes &&
|
|
5010
|
+
aliasArgs.length === aliasDecl.typeParameters.nodes.length) {
|
|
5011
|
+
scope = new Map(aliases);
|
|
5012
|
+
for (let i = 0; i < aliasArgs.length; i++) {
|
|
5013
|
+
const param = checker.getSymbolAtLocation(aliasDecl.typeParameters.nodes[i].name);
|
|
5014
|
+
const arg = evalMappedTemplate(aliasArgs[i], keys, aliases, ctx);
|
|
5015
|
+
if (!param || !arg)
|
|
5016
|
+
return null;
|
|
5017
|
+
scope.set(param, arg);
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
const checkType = type.getCheckType();
|
|
5021
|
+
const extendsType = type.getExtendsType();
|
|
5022
|
+
if (!checkType || !extendsType)
|
|
5023
|
+
return null;
|
|
5024
|
+
const checked = evalMappedTemplate(checkType, keys, scope, ctx);
|
|
5025
|
+
if (!checked)
|
|
5026
|
+
return null;
|
|
5027
|
+
const inferred = matchInferReference(checked, extendsType, ctx);
|
|
5028
|
+
if (inferred === undefined)
|
|
5029
|
+
return null;
|
|
5030
|
+
const branch = inferred ? type.getTrueType() : type.getFalseType();
|
|
5031
|
+
const branchScope = inferred ? new Map([...scope, ...inferred]) : scope;
|
|
5032
|
+
return evalMappedTemplate(branch, keys, branchScope, ctx);
|
|
5033
|
+
}
|
|
5034
|
+
return mentionsMappedParams(type, keys, aliases) ? null : type;
|
|
5035
|
+
}
|
|
5036
|
+
/** `checked extends G<..., infer T, ...>`: the infer bindings when
|
|
5037
|
+
* `checked` is a reference to the same generic `G` (its arguments bind the
|
|
5038
|
+
* infer positions; other positions must be the same types), false when it
|
|
5039
|
+
* is a reference to another type or a primitive, undefined when the match
|
|
5040
|
+
* cannot be decided this way. */
|
|
5041
|
+
function matchInferReference(checked, extendsType, ctx) {
|
|
5042
|
+
const { checker } = ctx;
|
|
5043
|
+
const target = (t) => t.isTypeReference?.() ? t.getTarget?.() : undefined;
|
|
5044
|
+
const wantTarget = target(extendsType) ?? extendsType.getAliasSymbol();
|
|
5045
|
+
if (!wantTarget)
|
|
5046
|
+
return matchInferSignature(checked, extendsType, ctx);
|
|
5047
|
+
const gotTarget = target(checked) ?? checked.getAliasSymbol();
|
|
5048
|
+
if (!gotTarget)
|
|
5049
|
+
return checked.flags & ts.TypeFlags.Object
|
|
5050
|
+
? matchInferThenable(checked, extendsType, ctx)
|
|
5051
|
+
: false;
|
|
5052
|
+
if (gotTarget !== wantTarget)
|
|
5053
|
+
return matchInferThenable(checked, extendsType, ctx);
|
|
5054
|
+
const wantArgs = target(extendsType)
|
|
5055
|
+
? checker.getTypeArguments(extendsType)
|
|
5056
|
+
: extendsType.getAliasTypeArguments();
|
|
5057
|
+
const gotArgs = target(checked)
|
|
5058
|
+
? checker.getTypeArguments(checked)
|
|
5059
|
+
: checked.getAliasTypeArguments();
|
|
5060
|
+
if (wantArgs.length !== gotArgs.length)
|
|
5061
|
+
return undefined;
|
|
5062
|
+
const inferred = new Map();
|
|
5063
|
+
for (let i = 0; i < wantArgs.length; i++) {
|
|
5064
|
+
const want = wantArgs[i];
|
|
5065
|
+
const symbol = want.flags & ts.TypeFlags.TypeParameter ? want.getSymbol() : undefined;
|
|
5066
|
+
const isInfer = symbol
|
|
5067
|
+
? symbol.declarations.some((d) => d.parent !== undefined && ts.isInferTypeNode(d.parent))
|
|
5068
|
+
: false;
|
|
5069
|
+
if (isInfer && symbol)
|
|
5070
|
+
inferred.set(symbol, gotArgs[i]);
|
|
5071
|
+
else if (want !== gotArgs[i])
|
|
5072
|
+
return undefined;
|
|
5073
|
+
}
|
|
5074
|
+
return inferred;
|
|
5075
|
+
}
|
|
5076
|
+
/** The type parameter an `infer X` declares, when `t` is one. */
|
|
5077
|
+
function inferSymbolOf(t, _ctx) {
|
|
5078
|
+
if (!(t.flags & ts.TypeFlags.TypeParameter))
|
|
5079
|
+
return undefined;
|
|
5080
|
+
const symbol = t.getSymbol();
|
|
5081
|
+
return symbol &&
|
|
5082
|
+
symbol.declarations.some((d) => d.parent !== undefined && ts.isInferTypeNode(d.parent))
|
|
5083
|
+
? symbol
|
|
5084
|
+
: undefined;
|
|
5085
|
+
}
|
|
5086
|
+
/** `checked extends (...args: any) => infer R` — the shape of the standard
|
|
5087
|
+
* library's ReturnType, over a concrete function type: R binds to its
|
|
5088
|
+
* result. Pattern parameters must be `any` or `any[]`, and a pattern rest
|
|
5089
|
+
* `any` or `any[]`; anything else stays undecided. The match follows
|
|
5090
|
+
* TypeScript's assignability: a primitive never matches a function type,
|
|
5091
|
+
* a function that needs more arguments than a pattern without a rest
|
|
5092
|
+
* passes never matches, and a positional `any[]` parameter needs the
|
|
5093
|
+
* function's parameter there to accept an array. */
|
|
5094
|
+
function matchInferSignature(checked, extendsType, ctx) {
|
|
5095
|
+
const { checker } = ctx;
|
|
5096
|
+
const wantSigs = checker.getCallSignatures(extendsType);
|
|
5097
|
+
const want = wantSigs[0];
|
|
5098
|
+
if (wantSigs.length !== 1 || !want || want.getTypeParameters().length > 0)
|
|
5099
|
+
return undefined;
|
|
5100
|
+
const wantShape = signatureShape(want, ctx);
|
|
5101
|
+
if (wantShape === undefined)
|
|
5102
|
+
return undefined;
|
|
5103
|
+
const isAny = (t) => (t.flags & ts.TypeFlags.Any) !== 0;
|
|
5104
|
+
const isAnyArray = (t) => checker.isArrayType(t) && isAny(checker.getTypeArguments(t)[0]);
|
|
5105
|
+
if (!wantShape.params.every((p) => isAny(p.type) || isAnyArray(p.type)))
|
|
5106
|
+
return undefined;
|
|
5107
|
+
if (wantShape.rest !== null && !isAny(wantShape.rest))
|
|
5108
|
+
return undefined;
|
|
5109
|
+
if (!(checked.flags & ts.TypeFlags.Object))
|
|
5110
|
+
return false;
|
|
5111
|
+
const gotSigs = checker.getCallSignatures(checked);
|
|
5112
|
+
const got = gotSigs[0];
|
|
5113
|
+
if (gotSigs.length !== 1 || !got || got.getTypeParameters().length > 0)
|
|
5114
|
+
return undefined;
|
|
5115
|
+
const gotShape = signatureShape(got, ctx);
|
|
5116
|
+
if (gotShape !== undefined) {
|
|
5117
|
+
// `(a: any) => infer R` rejects `(a: string, b: string) => R` and
|
|
5118
|
+
// `(...args: [string, number]) => R`: they need more arguments.
|
|
5119
|
+
if (wantShape.rest === null && requiredArguments(gotShape) > wantShape.params.length)
|
|
5120
|
+
return false;
|
|
5121
|
+
for (let i = 0; i < wantShape.params.length; i++) {
|
|
5122
|
+
if (!isAnyArray(wantShape.params[i].type))
|
|
5123
|
+
continue;
|
|
5124
|
+
const param = gotShape.params[i]?.type ?? gotShape.rest;
|
|
5125
|
+
if (param === undefined || param === null)
|
|
5126
|
+
continue;
|
|
5127
|
+
const accepts = acceptsArray(param, ctx);
|
|
5128
|
+
if (accepts !== true)
|
|
5129
|
+
return accepts;
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
5132
|
+
else if (wantShape.params.some((p) => isAnyArray(p.type))) {
|
|
5133
|
+
return undefined;
|
|
5134
|
+
}
|
|
5135
|
+
const wantRet = checker.getReturnTypeOfSignature(want);
|
|
5136
|
+
const infer = inferSymbolOf(wantRet, ctx);
|
|
5137
|
+
if (infer)
|
|
5138
|
+
return new Map([[infer, checker.getReturnTypeOfSignature(got)]]);
|
|
5139
|
+
return wantRet.flags & ts.TypeFlags.Any ? new Map() : undefined;
|
|
5140
|
+
}
|
|
5141
|
+
/** A signature's parameters as a call sees them: the positional ones, with
|
|
5142
|
+
* a fixed-tuple rest (`...args: [A, B?]`) flattened into positions, and the
|
|
5143
|
+
* element type of an array rest (`any` for `...args: any`). Undefined when
|
|
5144
|
+
* a parameter has no declaration, or the rest is a variadic tuple or
|
|
5145
|
+
* another type. */
|
|
5146
|
+
function signatureShape(sig, ctx) {
|
|
5147
|
+
const { checker } = ctx;
|
|
5148
|
+
const params = [];
|
|
5149
|
+
for (const p of sig.getParameters()) {
|
|
5150
|
+
const decl = p.valueDeclaration;
|
|
5151
|
+
if (decl === undefined || !ts.isParameter(decl))
|
|
5152
|
+
return undefined;
|
|
5153
|
+
const type = checker.getTypeOfSymbol(p);
|
|
5154
|
+
if (decl.dotDotDotToken === undefined) {
|
|
5155
|
+
params.push({
|
|
5156
|
+
type,
|
|
5157
|
+
optional: decl.questionToken !== undefined || decl.initializer !== undefined,
|
|
5158
|
+
});
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
5161
|
+
if (type.flags & ts.TypeFlags.Any)
|
|
5162
|
+
return { params, rest: type };
|
|
5163
|
+
if (checker.isArrayType(type))
|
|
5164
|
+
return { params, rest: checker.getTypeArguments(type)[0] };
|
|
5165
|
+
const elems = restTupleElements(type, ctx);
|
|
5166
|
+
if (!elems)
|
|
5167
|
+
return undefined;
|
|
5168
|
+
for (const e of elems)
|
|
5169
|
+
params.push({ type: e.type, optional: e.optional });
|
|
5170
|
+
return { params, rest: null };
|
|
5171
|
+
}
|
|
5172
|
+
return { params, rest: null };
|
|
5173
|
+
}
|
|
5174
|
+
/** The fewest arguments a call must pass: up to the last required position. */
|
|
5175
|
+
function requiredArguments(shape) {
|
|
5176
|
+
let required = 0;
|
|
5177
|
+
shape.params.forEach((p, i) => {
|
|
5178
|
+
if (!p.optional)
|
|
5179
|
+
required = i + 1;
|
|
5180
|
+
});
|
|
5181
|
+
return required;
|
|
5182
|
+
}
|
|
5183
|
+
/** Whether a parameter of this type accepts an `any[]` argument: true for
|
|
5184
|
+
* `any`, `unknown` and array types, false for primitives, undefined
|
|
5185
|
+
* otherwise. */
|
|
5186
|
+
function acceptsArray(t, ctx) {
|
|
5187
|
+
if (t.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown))
|
|
5188
|
+
return true;
|
|
5189
|
+
if (ctx.checker.isArrayType(t))
|
|
5190
|
+
return true;
|
|
5191
|
+
const primitive = ts.TypeFlags.StringLike |
|
|
5192
|
+
ts.TypeFlags.NumberLike |
|
|
5193
|
+
ts.TypeFlags.BooleanLike |
|
|
5194
|
+
ts.TypeFlags.BigIntLike |
|
|
5195
|
+
ts.TypeFlags.ESSymbolLike |
|
|
5196
|
+
ts.TypeFlags.Undefined |
|
|
5197
|
+
ts.TypeFlags.Null |
|
|
5198
|
+
ts.TypeFlags.Void;
|
|
5199
|
+
return t.flags & primitive ? false : undefined;
|
|
5200
|
+
}
|
|
5201
|
+
/** `checked extends PromiseLike<infer U>` (or `Promise<infer U>`) over the
|
|
5202
|
+
* standard library's Promise: U binds to the settled type. An object with
|
|
5203
|
+
* no `then` member is no thenable. Everything else stays undecided. */
|
|
5204
|
+
function matchInferThenable(checked, extendsType, ctx) {
|
|
5205
|
+
const { checker } = ctx;
|
|
5206
|
+
const stdlibNamed = (t, names) => {
|
|
5207
|
+
const symbol = t.getSymbol();
|
|
5208
|
+
return (symbol !== undefined &&
|
|
5209
|
+
names.includes(ts.symbolName(symbol)) &&
|
|
5210
|
+
symbol.declarations.some((d) => ctx.isStdlibFile(ts.getSourceFileOfNode(d))));
|
|
5211
|
+
};
|
|
5212
|
+
if (!stdlibNamed(extendsType, ["PromiseLike", "Promise"]))
|
|
5213
|
+
return undefined;
|
|
5214
|
+
const wantArgs = checker.getTypeArguments(extendsType);
|
|
5215
|
+
const infer = wantArgs.length === 1 ? inferSymbolOf(wantArgs[0], ctx) : undefined;
|
|
5216
|
+
if (!infer)
|
|
5217
|
+
return undefined;
|
|
5218
|
+
if (stdlibNamed(checked, ["Promise", "PromiseLike"])) {
|
|
5219
|
+
const gotArgs = checker.getTypeArguments(checked);
|
|
5220
|
+
return gotArgs.length === 1 ? new Map([[infer, gotArgs[0]]]) : undefined;
|
|
5221
|
+
}
|
|
5222
|
+
return checker.getPropertyOfType(checked, "then") === undefined ? false : undefined;
|
|
5223
|
+
}
|
|
5224
|
+
/** The type mentions a mapped key or bound alias parameter (a template
|
|
5225
|
+
* shape evalMappedTemplate does not reduce). */
|
|
5226
|
+
function mentionsMappedParams(type, keys, aliases) {
|
|
5227
|
+
if (type.flags & ts.TypeFlags.TypeParameter) {
|
|
5228
|
+
const symbol = type.getSymbol();
|
|
5229
|
+
return symbol !== undefined && (keys.has(symbol) || aliases.has(symbol));
|
|
5230
|
+
}
|
|
5231
|
+
if (type.isUnionType() || type.isIntersectionType())
|
|
5232
|
+
return ts.constituentTypes(type).some((part) => mentionsMappedParams(part, keys, aliases));
|
|
5233
|
+
return false;
|
|
5234
|
+
}
|
|
5235
|
+
function readonlyClassType(type, ctx) {
|
|
5236
|
+
const alias = type.getAliasSymbol();
|
|
5237
|
+
if (alias === undefined || ts.symbolName(alias) !== "Readonly")
|
|
5238
|
+
return null;
|
|
5239
|
+
const args = type.getAliasTypeArguments();
|
|
5240
|
+
if (args.length !== 1 || !args[0])
|
|
5241
|
+
return null;
|
|
5242
|
+
const isLibAlias = alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)));
|
|
5243
|
+
if (!isLibAlias)
|
|
5244
|
+
return null;
|
|
5245
|
+
const mapped = mapType(args[0], ctx);
|
|
5246
|
+
return mapped !== null && isDynTypedRefType(mapped) ? mapped : null;
|
|
3988
5247
|
}
|
|
3989
5248
|
function mapGenericUtilityAlias(widened, ctx) {
|
|
3990
5249
|
const { resolveTypeParam, shapes, unions } = ctx;
|
|
3991
5250
|
if (!resolveTypeParam)
|
|
3992
5251
|
return null;
|
|
3993
5252
|
const alias = widened.getAliasSymbol();
|
|
3994
|
-
if (!alias || (alias
|
|
5253
|
+
if (!alias || (ts.symbolName(alias) !== "Partial" && ts.symbolName(alias) !== "Readonly"))
|
|
3995
5254
|
return null;
|
|
3996
5255
|
const aliasArgs = widened.getAliasTypeArguments();
|
|
3997
5256
|
const arg = aliasArgs[0];
|
|
@@ -4000,15 +5259,13 @@ function mapGenericUtilityAlias(widened, ctx) {
|
|
|
4000
5259
|
if (!(arg.flags & ts.TypeFlags.TypeParameter))
|
|
4001
5260
|
return null;
|
|
4002
5261
|
// Provenance: the STANDARD LIBRARY's alias, not a user's shadowing one.
|
|
4003
|
-
const isLibAlias = ctx.
|
|
4004
|
-
.declarationsOf(alias)
|
|
4005
|
-
.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()));
|
|
5262
|
+
const isLibAlias = alias.declarations.some((d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)));
|
|
4006
5263
|
if (!isLibAlias)
|
|
4007
5264
|
return null;
|
|
4008
5265
|
const bound = resolveTypeParam(arg);
|
|
4009
5266
|
if (!bound || bound.kind !== "record")
|
|
4010
5267
|
return null;
|
|
4011
|
-
if (alias
|
|
5268
|
+
if (ts.symbolName(alias) === "Readonly")
|
|
4012
5269
|
return bound;
|
|
4013
5270
|
const shape = shapes.get(bound.shapeId);
|
|
4014
5271
|
if (!shape)
|
|
@@ -4118,7 +5375,20 @@ export function isUnitOnlyTsType(t, resolveTypeParam) {
|
|
|
4118
5375
|
const UNIT = ts.TypeFlags.Undefined | ts.TypeFlags.Void | ts.TypeFlags.Null;
|
|
4119
5376
|
const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
|
|
4120
5377
|
return parts.every((p) => (p.flags & UNIT) !== 0 ||
|
|
4121
|
-
((p.flags & ts.TypeFlags.TypeParameter) !== 0 && resolveTypeParam?.(p)?.kind === "void")
|
|
5378
|
+
((p.flags & ts.TypeFlags.TypeParameter) !== 0 && resolveTypeParam?.(p)?.kind === "void") ||
|
|
5379
|
+
boundVoidReturnType(p, resolveTypeParam));
|
|
5380
|
+
}
|
|
5381
|
+
/** `ReturnType<F>` over a type parameter bound to a void-returning
|
|
5382
|
+
* function (a variadic wrapper's result slot): a unit-only value. */
|
|
5383
|
+
function boundVoidReturnType(p, resolveTypeParam) {
|
|
5384
|
+
if (!resolveTypeParam || ts.symbolNameOf(p.getAliasSymbol()) !== "ReturnType")
|
|
5385
|
+
return false;
|
|
5386
|
+
const args = p.getAliasTypeArguments();
|
|
5387
|
+
const arg = args[0];
|
|
5388
|
+
if (args.length !== 1 || !arg || !(arg.flags & ts.TypeFlags.TypeParameter))
|
|
5389
|
+
return false;
|
|
5390
|
+
const bound = resolveTypeParam(arg);
|
|
5391
|
+
return bound?.kind === "func" && bound.ret.kind === "void";
|
|
4122
5392
|
}
|
|
4123
5393
|
/** IR-level `t | undefined`, canonicalized and fenced exactly like the
|
|
4124
5394
|
* ts-union branch of mapType (typeKey-sorted arms, deduplicated;
|
|
@@ -4201,14 +5471,31 @@ function mapHybridCallableIntersection(widened, ctx) {
|
|
|
4201
5471
|
const pt = mapType(checker.getTypeOfSymbol(p), ctx);
|
|
4202
5472
|
if (!pt || pt.kind === "void")
|
|
4203
5473
|
return null;
|
|
4204
|
-
fields.push({ name: p
|
|
4205
|
-
declaredOrder.push(p
|
|
5474
|
+
fields.push({ name: ts.symbolName(p), type: pt });
|
|
5475
|
+
declaredOrder.push(ts.symbolName(p));
|
|
4206
5476
|
}
|
|
4207
5477
|
if (fields.length === 1)
|
|
4208
5478
|
return null; // no properties — it is just F
|
|
4209
5479
|
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
4210
5480
|
return { kind: "record", shapeId: shapes.intern(fields, false, undefined, declaredOrder) };
|
|
4211
5481
|
}
|
|
5482
|
+
/** The record every part of a union of function-with-properties
|
|
5483
|
+
* intersections maps to, or null when a part does not map to the same one. */
|
|
5484
|
+
function mapUniformHybridUnion(widened, ctx) {
|
|
5485
|
+
const parts = ts.constituentTypes(widened);
|
|
5486
|
+
if (!parts.every((p) => p.isIntersectionType()))
|
|
5487
|
+
return null;
|
|
5488
|
+
let first = null;
|
|
5489
|
+
for (const part of parts) {
|
|
5490
|
+
if (ctx.checker.getConstructSignatures(part).length > 0)
|
|
5491
|
+
return null;
|
|
5492
|
+
const mapped = mapHybridCallableIntersection(part, ctx);
|
|
5493
|
+
if (!mapped || (first && typeKey(mapped) !== typeKey(first)))
|
|
5494
|
+
return null;
|
|
5495
|
+
first ??= mapped;
|
|
5496
|
+
}
|
|
5497
|
+
return first;
|
|
5498
|
+
}
|
|
4212
5499
|
/** Optional standard error metadata refines an existing Error identity;
|
|
4213
5500
|
* it does not allocate a structural copy or extend its native layout. */
|
|
4214
5501
|
function mapErrorMetadataIntersection(type, ctx) {
|
|
@@ -4227,12 +5514,14 @@ function mapErrorMetadataIntersection(type, ctx) {
|
|
|
4227
5514
|
"TypeError",
|
|
4228
5515
|
"URIError",
|
|
4229
5516
|
"AggregateError",
|
|
4230
|
-
|
|
4231
|
-
|
|
5517
|
+
"SuppressedError",
|
|
5518
|
+
].includes(ts.symbolName(symbol)) &&
|
|
5519
|
+
symbol.declarations.some((decl) => ctx.isStdlibFile(ts.getSourceFileOfNode(decl))));
|
|
4232
5520
|
});
|
|
4233
5521
|
if (!hasError)
|
|
4234
5522
|
return null;
|
|
4235
5523
|
let error = null;
|
|
5524
|
+
const extra = [];
|
|
4236
5525
|
for (const part of parts) {
|
|
4237
5526
|
const mapped = mapType(part, ctx);
|
|
4238
5527
|
if (mapped?.kind === "object" && RUNTIME_ERROR_CLASSES.has(mapped.className)) {
|
|
@@ -4246,19 +5535,45 @@ function mapErrorMetadataIntersection(type, ctx) {
|
|
|
4246
5535
|
ctx.checker.getIndexInfosOfType(part).length)
|
|
4247
5536
|
return null;
|
|
4248
5537
|
for (const property of ctx.checker.getPropertiesOfType(part)) {
|
|
4249
|
-
const expected = property
|
|
5538
|
+
const expected = ts.symbolName(property) === "errno"
|
|
4250
5539
|
? "f64"
|
|
4251
|
-
: ["code", "syscall", "path", "dest"].includes(property
|
|
5540
|
+
: ["code", "syscall", "path", "dest"].includes(ts.symbolName(property))
|
|
4252
5541
|
? "string"
|
|
4253
5542
|
: null;
|
|
4254
|
-
if (!expected
|
|
4255
|
-
|
|
5543
|
+
if (!expected) {
|
|
5544
|
+
extra.push(property);
|
|
5545
|
+
continue;
|
|
5546
|
+
}
|
|
4256
5547
|
const field = mapType(ctx.checker.getTypeOfSymbol(property), ctx);
|
|
4257
5548
|
const arms = field?.kind === "union" ? ctx.unions.get(field.unionId)?.arms : field ? [field] : [];
|
|
4258
5549
|
if (!arms?.length || !arms.every((arm) => arm.kind === expected || arm.kind === "undefinedT"))
|
|
4259
5550
|
return null;
|
|
5551
|
+
// A required member must still admit the absent value the slot reads.
|
|
5552
|
+
if (!(property.flags & ts.SymbolFlags.Optional) &&
|
|
5553
|
+
!arms.some((arm) => arm.kind === "undefinedT"))
|
|
5554
|
+
return null;
|
|
4260
5555
|
}
|
|
4261
5556
|
}
|
|
5557
|
+
if (!error)
|
|
5558
|
+
return null;
|
|
5559
|
+
// Members beyond Error's own and the system-error metadata (`Error & {
|
|
5560
|
+
// status: number }`, Object.assign's result) are own properties of the
|
|
5561
|
+
// error's checked-dynamic node: each must map to a type a checked read
|
|
5562
|
+
// can produce. Error's own string members keep their slots.
|
|
5563
|
+
for (const property of extra) {
|
|
5564
|
+
const field = mapType(ctx.checker.getTypeOfSymbol(property), ctx);
|
|
5565
|
+
if (!field || field.kind === "void")
|
|
5566
|
+
return null;
|
|
5567
|
+
if (ts.symbolName(property) === "message" || ts.symbolName(property) === "name") {
|
|
5568
|
+
if (field.kind !== "string")
|
|
5569
|
+
return null;
|
|
5570
|
+
continue;
|
|
5571
|
+
}
|
|
5572
|
+
if (ts.symbolName(property) === "stack" || ts.symbolName(property) === "cause")
|
|
5573
|
+
return null;
|
|
5574
|
+
if (!canDynCheckTo(field, (id) => ctx.shapes.get(id), (id) => ctx.unions.get(id)))
|
|
5575
|
+
return null;
|
|
5576
|
+
}
|
|
4262
5577
|
return error;
|
|
4263
5578
|
}
|
|
4264
5579
|
/** A conventional primitive brand has one runtime-carrying primitive part
|
|
@@ -4365,13 +5680,13 @@ function immutableSourceType(type, ctx) {
|
|
|
4365
5680
|
return null;
|
|
4366
5681
|
const { checker } = ctx;
|
|
4367
5682
|
const symbol = type.getSymbol();
|
|
4368
|
-
const decl = symbol ?
|
|
4369
|
-
if (decl === undefined || !CONTRACT_TYPES_FILE.test(
|
|
5683
|
+
const decl = symbol ? symbol.declarations[0] : undefined;
|
|
5684
|
+
if (decl === undefined || !CONTRACT_TYPES_FILE.test(ts.getSourceFileOfNode(decl).fileName))
|
|
4370
5685
|
return null;
|
|
4371
5686
|
const props = checker.getPropertiesOfType(type);
|
|
4372
5687
|
const seen = new Set();
|
|
4373
5688
|
for (const prop of props) {
|
|
4374
|
-
const owner =
|
|
5689
|
+
const owner = prop.declarations[0]?.parent;
|
|
4375
5690
|
if (owner === undefined || seen.has(owner))
|
|
4376
5691
|
continue;
|
|
4377
5692
|
seen.add(owner);
|
|
@@ -4380,7 +5695,7 @@ function immutableSourceType(type, ctx) {
|
|
|
4380
5695
|
source = checker.getTypeFromTypeNode(owner);
|
|
4381
5696
|
else if ((ts.isClassDeclaration(owner) || ts.isInterfaceDeclaration(owner)) &&
|
|
4382
5697
|
owner.name !== undefined &&
|
|
4383
|
-
(owner.typeParameters?.length ?? 0) === 0) {
|
|
5698
|
+
(owner.typeParameters?.nodes.length ?? 0) === 0) {
|
|
4384
5699
|
const ownerSymbol = checker.getSymbolAtLocation(owner.name);
|
|
4385
5700
|
if (ownerSymbol)
|
|
4386
5701
|
source = checker.getDeclaredTypeOfSymbol(ownerSymbol);
|
|
@@ -4398,6 +5713,14 @@ function isMappedShape(t) {
|
|
|
4398
5713
|
return ((t.flags & ts.TypeFlags.Object) !== 0 &&
|
|
4399
5714
|
(t.objectFlags & ts.ObjectFlags.Mapped) !== 0);
|
|
4400
5715
|
}
|
|
5716
|
+
/** A declaration file an installed package ships (its own or an @types
|
|
5717
|
+
* twin), outside the standard library and @types/node: the type surface
|
|
5718
|
+
* of a package the program does not compile. Its pure type shapes —
|
|
5719
|
+
* interfaces, aliases, type literals — describe data a program can build
|
|
5720
|
+
* itself (`import type` from a types-only package such as type-fest). */
|
|
5721
|
+
function packageTypeFile(sf, ctx) {
|
|
5722
|
+
return (sf.isDeclarationFile && /[\\/]node_modules[\\/]/.test(sf.fileName) && !ctx.isStdlibFile(sf));
|
|
5723
|
+
}
|
|
4401
5724
|
/** The record path's provenance fence. Declared shapes (object literals,
|
|
4402
5725
|
* interfaces, type literals) must come from user code or an explicitly
|
|
4403
5726
|
* mapped external type surface, never an arbitrary .d.ts — the empty
|
|
@@ -4423,20 +5746,19 @@ function recordProvenanceOk(t, ctx) {
|
|
|
4423
5746
|
if (isMappedShape(t))
|
|
4424
5747
|
return true;
|
|
4425
5748
|
const tSym = t.getSymbol();
|
|
4426
|
-
const decls = tSym ?
|
|
5749
|
+
const decls = tSym ? tSym.declarations : undefined;
|
|
4427
5750
|
if (!decls || decls.length === 0) {
|
|
4428
5751
|
// Inferred destructuring parameters can have a synthesized anonymous
|
|
4429
5752
|
// shape with no declaration or member symbols to trace to a source.
|
|
4430
5753
|
return checker
|
|
4431
5754
|
.getPropertiesOfType(t)
|
|
4432
|
-
.every((property) =>
|
|
4433
|
-
.
|
|
4434
|
-
.
|
|
4435
|
-
ctx.isExternalTypeFile(decl.getSourceFile())));
|
|
5755
|
+
.every((property) => property.declarations.every((decl) => !ts.getSourceFileOfNode(decl).isDeclarationFile ||
|
|
5756
|
+
ctx.isExternalTypeFile(ts.getSourceFileOfNode(decl)) ||
|
|
5757
|
+
packageTypeFile(ts.getSourceFileOfNode(decl), ctx)));
|
|
4436
5758
|
}
|
|
4437
5759
|
return !decls.some((d) => {
|
|
4438
|
-
const sf =
|
|
4439
|
-
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf);
|
|
5760
|
+
const sf = ts.getSourceFileOfNode(d);
|
|
5761
|
+
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf) && !packageTypeFile(sf, ctx);
|
|
4440
5762
|
});
|
|
4441
5763
|
}
|
|
4442
5764
|
/** A GENERIC-callable member type (`m<T>(x: T): T` / `f: <T>(x: T) => T` in
|
|
@@ -4458,6 +5780,213 @@ export function isGenericCallableMemberType(t, checker) {
|
|
|
4458
5780
|
checker.getPropertiesOfType(t).length === 0 &&
|
|
4459
5781
|
checker.getIndexInfosOfType(t).length === 0);
|
|
4460
5782
|
}
|
|
5783
|
+
/** Result containers an erased async function or generator must keep:
|
|
5784
|
+
* their contents are erased instead (`Promise<T>` maps as
|
|
5785
|
+
* `Promise<unknown>`). */
|
|
5786
|
+
const ERASURE_KEPT_CONTAINERS = new Set(["Promise", "Generator", "AsyncGenerator"]);
|
|
5787
|
+
/** The type mentions a type parameter that the active erasure binds to
|
|
5788
|
+
* `unknown` (erasedGenericMemberType, erased bodies). */
|
|
5789
|
+
function mentionsErasedTypeParam(type, ctx, depth) {
|
|
5790
|
+
if (depth > 8)
|
|
5791
|
+
return false;
|
|
5792
|
+
const { checker } = ctx;
|
|
5793
|
+
if (type.flags & ts.TypeFlags.TypeParameter)
|
|
5794
|
+
return ctx.resolveTypeParam?.(type)?.kind === "dyn";
|
|
5795
|
+
if (type.flags &
|
|
5796
|
+
(ts.TypeFlags.IndexedAccess | ts.TypeFlags.Conditional | ts.TypeFlags.Substitution))
|
|
5797
|
+
return true;
|
|
5798
|
+
if (type.isUnionType() || type.isIntersectionType())
|
|
5799
|
+
return ts.constituentTypes(type).some((part) => mentionsErasedTypeParam(part, ctx, depth + 1));
|
|
5800
|
+
if ((type.flags & ts.TypeFlags.Object) === 0)
|
|
5801
|
+
return false;
|
|
5802
|
+
if (type.isTypeReference() &&
|
|
5803
|
+
checker
|
|
5804
|
+
.getTypeArguments(type)
|
|
5805
|
+
.some((arg) => mentionsErasedTypeParam(arg, ctx, depth + 1)))
|
|
5806
|
+
return true;
|
|
5807
|
+
for (const sig of checker.getCallSignatures(type)) {
|
|
5808
|
+
if (mentionsErasedTypeParam(checker.getReturnTypeOfSignature(sig), ctx, depth + 1))
|
|
5809
|
+
return true;
|
|
5810
|
+
for (const param of sig.getParameters())
|
|
5811
|
+
if (mentionsErasedTypeParam(checker.getTypeOfSymbol(param), ctx, depth + 1))
|
|
5812
|
+
return true;
|
|
5813
|
+
}
|
|
5814
|
+
const symbol = type.getSymbol();
|
|
5815
|
+
const anonymous = symbol !== undefined &&
|
|
5816
|
+
(symbol.flags & (ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.ObjectLiteral)) !== 0;
|
|
5817
|
+
if (anonymous)
|
|
5818
|
+
for (const property of checker.getPropertiesOfType(type))
|
|
5819
|
+
if (mentionsErasedTypeParam(checker.getTypeOfSymbol(property), ctx, depth + 1))
|
|
5820
|
+
return true;
|
|
5821
|
+
return false;
|
|
5822
|
+
}
|
|
5823
|
+
/** A generic callable member's runtime type: its one call signature with
|
|
5824
|
+
* every own type parameter bound to `unknown`, the erased instance a stored
|
|
5825
|
+
* or escaping definition carries (JavaScript erases type parameters the
|
|
5826
|
+
* same way). Undefined when the member has overloads or the erased
|
|
5827
|
+
* signature does not map: the member then stays out of the shape, and only
|
|
5828
|
+
* calls on a provable definition compile. */
|
|
5829
|
+
export function erasedGenericMemberType(t, ctx) {
|
|
5830
|
+
const sigs = ctx.checker.getCallSignatures(t);
|
|
5831
|
+
if (sigs.length !== 1)
|
|
5832
|
+
return undefined;
|
|
5833
|
+
const sig = sigs[0];
|
|
5834
|
+
const own = new Set(sig.getTypeParameters());
|
|
5835
|
+
const outer = ctx.resolveTypeParam;
|
|
5836
|
+
const erased = mapType(t, {
|
|
5837
|
+
...ctx,
|
|
5838
|
+
erasingSignature: sig,
|
|
5839
|
+
resolveTypeParam: (param) => (own.has(param) ? DYN : (outer?.(param) ?? null)),
|
|
5840
|
+
});
|
|
5841
|
+
return erased?.kind === "func" ? erased : undefined;
|
|
5842
|
+
}
|
|
5843
|
+
/** An OVERLOADED callable member type (`on(event: "a", h: (x: number) =>
|
|
5844
|
+
* void): () => void; on(event: "b", h: (x: string) => void): () => void`
|
|
5845
|
+
* in a program interface or type literal): two or more call signatures and
|
|
5846
|
+
* nothing else (no data properties, construct signatures, or index
|
|
5847
|
+
* signatures), every one declared in TypeScript program source. Such a
|
|
5848
|
+
* member keeps a record slot holding its erased runtime function
|
|
5849
|
+
* (erasedOverloadMemberType); calls convert per their resolved overload
|
|
5850
|
+
* (lowerRecordFieldCall). */
|
|
5851
|
+
export function isOverloadedCallableMemberType(t, checker) {
|
|
5852
|
+
const sigs = checker.getCallSignatures(t);
|
|
5853
|
+
if (sigs.length < 2)
|
|
5854
|
+
return false;
|
|
5855
|
+
if (checker.getConstructSignatures(t).length > 0 ||
|
|
5856
|
+
checker.getPropertiesOfType(t).length > 0 ||
|
|
5857
|
+
checker.getIndexInfosOfType(t).length > 0)
|
|
5858
|
+
return false;
|
|
5859
|
+
return sigs.every((sig) => {
|
|
5860
|
+
const decl = sig.declaration;
|
|
5861
|
+
if (decl === undefined)
|
|
5862
|
+
return false;
|
|
5863
|
+
if (!ts.isMethodSignatureDeclaration(decl) && !ts.isCallSignatureDeclaration(decl))
|
|
5864
|
+
return false;
|
|
5865
|
+
const file = ts.getSourceFileOfNode(decl);
|
|
5866
|
+
return !file.isDeclarationFile && !isJsSourceFile(file);
|
|
5867
|
+
});
|
|
5868
|
+
}
|
|
5869
|
+
/** Scalar arms an overload join may combine into one union. */
|
|
5870
|
+
const OVERLOAD_JOIN_SCALARS = new Set(["f64", "string", "bool", "undefinedT", "nullT"]);
|
|
5871
|
+
/** The join of one position's types across an overload set: equal types
|
|
5872
|
+
* stay; scalar mixes form their union; anything else is `unknown` when
|
|
5873
|
+
* every joined type crosses the checked-dynamic boundary in both directions
|
|
5874
|
+
* (the call site converts into the slot, the implementation converts out
|
|
5875
|
+
* of it). Differing callbacks (`(x: number) => void` beside `(x: string) =>
|
|
5876
|
+
* void`) therefore travel as checked function values, which any
|
|
5877
|
+
* implementation's own callback type adapts from. Null when no join
|
|
5878
|
+
* exists. */
|
|
5879
|
+
function joinOverloadTypes(types, ctx) {
|
|
5880
|
+
const first = types[0];
|
|
5881
|
+
if (types.every((t) => typeEquals(t, first)))
|
|
5882
|
+
return first;
|
|
5883
|
+
const getRecord = (id) => ctx.shapes.get(id);
|
|
5884
|
+
const getUnion = (id) => ctx.unions.get(id);
|
|
5885
|
+
const arms = new Map();
|
|
5886
|
+
let scalar = true;
|
|
5887
|
+
for (const t of types) {
|
|
5888
|
+
const parts = t.kind === "union" ? (ctx.unions.get(t.unionId)?.arms ?? []) : [t];
|
|
5889
|
+
if (parts.length === 0)
|
|
5890
|
+
scalar = false;
|
|
5891
|
+
for (const part of parts) {
|
|
5892
|
+
if (!OVERLOAD_JOIN_SCALARS.has(part.kind))
|
|
5893
|
+
scalar = false;
|
|
5894
|
+
arms.set(typeKey(part), part);
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5897
|
+
if (scalar && [...arms.values()].some((arm) => !isUnitType(arm))) {
|
|
5898
|
+
const sorted = [...arms.values()].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
5899
|
+
return { kind: "union", unionId: ctx.unions.intern(sorted) };
|
|
5900
|
+
}
|
|
5901
|
+
if (types.every((t) => t.kind === "dyn" ||
|
|
5902
|
+
(t.kind !== "void" &&
|
|
5903
|
+
canConvertToDyn(t, getRecord, getUnion) &&
|
|
5904
|
+
canDynCheckTo(t, getRecord, getUnion))))
|
|
5905
|
+
return DYN;
|
|
5906
|
+
return null;
|
|
5907
|
+
}
|
|
5908
|
+
/** An overloaded member's runtime type (isOverloadedCallableMemberType).
|
|
5909
|
+
* JavaScript stores ONE function under the member; overload signatures only
|
|
5910
|
+
* constrain call sites. The slot's type joins the overloads per parameter
|
|
5911
|
+
* position and result (joinOverloadTypes), and a position some overloads
|
|
5912
|
+
* omit is optional. Each overload's own type parameters erase to `unknown`
|
|
5913
|
+
* first. Calls pick their overload statically, convert arguments into the
|
|
5914
|
+
* slot's parameter types and the result back to the overload's; an
|
|
5915
|
+
* implementation converts into the slot like any function value. Undefined
|
|
5916
|
+
* when the set does not join (rest parameters, a void result beside a
|
|
5917
|
+
* value result, a component outside the checked-dynamic boundary): the
|
|
5918
|
+
* member keeps its fence. */
|
|
5919
|
+
export function erasedOverloadMemberType(t, ctx) {
|
|
5920
|
+
const funcs = [];
|
|
5921
|
+
for (const sig of ctx.checker.getCallSignatures(t)) {
|
|
5922
|
+
const own = new Set(sig.getTypeParameters());
|
|
5923
|
+
const outer = ctx.resolveTypeParam;
|
|
5924
|
+
const mapped = mapCallSignature(sig, own.size === 0
|
|
5925
|
+
? ctx
|
|
5926
|
+
: {
|
|
5927
|
+
...ctx,
|
|
5928
|
+
erasingSignature: sig,
|
|
5929
|
+
resolveTypeParam: (param) => (own.has(param) ? DYN : (outer?.(param) ?? null)),
|
|
5930
|
+
});
|
|
5931
|
+
if (mapped?.kind !== "func" || mapped.rest === true || mapped.argumentsAll === true)
|
|
5932
|
+
return undefined;
|
|
5933
|
+
funcs.push(mapped);
|
|
5934
|
+
}
|
|
5935
|
+
const arity = Math.max(...funcs.map((f) => f.params.length));
|
|
5936
|
+
const params = [];
|
|
5937
|
+
for (let i = 0; i < arity; i++) {
|
|
5938
|
+
const present = funcs.filter((f) => i < f.params.length).map((f) => f.params[i]);
|
|
5939
|
+
let param = joinOverloadTypes(present, ctx);
|
|
5940
|
+
if (param !== null && present.length < funcs.length && param.kind !== "dyn")
|
|
5941
|
+
param = withUndefinedArm(param, ctx.unions);
|
|
5942
|
+
if (param === null)
|
|
5943
|
+
return undefined;
|
|
5944
|
+
params.push(param);
|
|
5945
|
+
}
|
|
5946
|
+
const voids = funcs.filter((f) => f.ret.kind === "void").length;
|
|
5947
|
+
if (voids !== 0 && voids !== funcs.length)
|
|
5948
|
+
return undefined;
|
|
5949
|
+
const ret = voids === funcs.length
|
|
5950
|
+
? VOID
|
|
5951
|
+
: joinOverloadTypes(funcs.map((f) => f.ret), ctx);
|
|
5952
|
+
if (ret === null)
|
|
5953
|
+
return undefined;
|
|
5954
|
+
return funcOf(params, ret);
|
|
5955
|
+
}
|
|
5956
|
+
/** Why an overloaded member's set has no erased type
|
|
5957
|
+
* (erasedOverloadMemberType): the first overload, and within it the first
|
|
5958
|
+
* parameter or result, that does not map; otherwise the join itself. A
|
|
5959
|
+
* message tail after "its member 'name'". */
|
|
5960
|
+
function describeOverloadSetBlocker(t, ctx) {
|
|
5961
|
+
const { checker } = ctx;
|
|
5962
|
+
for (const sig of checker.getCallSignatures(t)) {
|
|
5963
|
+
const own = new Set(sig.getTypeParameters());
|
|
5964
|
+
const outer = ctx.resolveTypeParam;
|
|
5965
|
+
const sigCtx = own.size === 0
|
|
5966
|
+
? ctx
|
|
5967
|
+
: {
|
|
5968
|
+
...ctx,
|
|
5969
|
+
erasingSignature: sig,
|
|
5970
|
+
resolveTypeParam: (param) => (own.has(param) ? DYN : (outer?.(param) ?? null)),
|
|
5971
|
+
};
|
|
5972
|
+
const mapped = mapCallSignature(sig, sigCtx);
|
|
5973
|
+
if (mapped?.kind === "func" && mapped.rest !== true && mapped.argumentsAll !== true)
|
|
5974
|
+
continue;
|
|
5975
|
+
const decl = sig.declaration;
|
|
5976
|
+
const spelled = decl ? ts.getTextOfNode(decl).replace(/\s+/g, " ").replace(/;$/, "") : "";
|
|
5977
|
+
const which = spelled ? `overload '${spelled}'` : "one overload";
|
|
5978
|
+
if (mapped?.kind === "func")
|
|
5979
|
+
return `is an overload set, and its ${which} has a rest parameter (an overload set stores one fixed-arity function)`;
|
|
5980
|
+
for (const param of sig.getParameters()) {
|
|
5981
|
+
const paramTs = checker.getTypeOfSymbol(param);
|
|
5982
|
+
if (!mapType(paramTs, sigCtx))
|
|
5983
|
+
return `is an overload set, and its ${which} has parameter '${ts.symbolName(param)}' of type '${checker.typeToString(paramTs)}', which does not compile`;
|
|
5984
|
+
}
|
|
5985
|
+
const retTs = checker.getReturnTypeOfSignature(sig);
|
|
5986
|
+
return `is an overload set, and its ${which} returns '${checker.typeToString(retTs)}', which does not compile`;
|
|
5987
|
+
}
|
|
5988
|
+
return "is an overload set whose signatures do not join into one stored function (a void result beside a value result, or positions whose differing types do not cross the checked-dynamic boundary)";
|
|
5989
|
+
}
|
|
4461
5990
|
function mapRecordType(widened, ctx) {
|
|
4462
5991
|
const { shapes } = ctx;
|
|
4463
5992
|
// A type whose recursive shape already finalized answers its id straight
|
|
@@ -4496,10 +6025,9 @@ function mapRecordType(widened, ctx) {
|
|
|
4496
6025
|
// checker-type identity — fence recursive generic-open shapes.
|
|
4497
6026
|
if (contextResolutions !== sensitivityAtEntry)
|
|
4498
6027
|
return null;
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
};
|
|
6028
|
+
const recursive = shapes.finalizeRecursive(widened, inner.fields, inner.indexValue, inner.declaredOrder);
|
|
6029
|
+
adoptAccessorOrder(shapes.get(recursive), inner.accessorOrder);
|
|
6030
|
+
return { kind: "record", shapeId: recursive };
|
|
4503
6031
|
}
|
|
4504
6032
|
// A record with no typed payload contract is a view of an existing
|
|
4505
6033
|
// object, including across parameters and returns. Building a native
|
|
@@ -4510,18 +6038,294 @@ function mapRecordType(widened, ctx) {
|
|
|
4510
6038
|
inner.fields.every((field) => field.type.kind === "dyn") &&
|
|
4511
6039
|
(inner.indexValue === undefined || inner.indexValue.kind === "dyn"))
|
|
4512
6040
|
return DYN;
|
|
6041
|
+
const covered = coveredOptionalFieldsShape(widened, inner, ctx);
|
|
6042
|
+
if (covered !== null)
|
|
6043
|
+
return { kind: "record", shapeId: covered };
|
|
6044
|
+
const merged = dictSpreadLiteralShape(widened, inner, ctx);
|
|
6045
|
+
if (merged === "dyn")
|
|
6046
|
+
return DYN;
|
|
6047
|
+
if (merged !== null)
|
|
6048
|
+
return { kind: "record", shapeId: merged };
|
|
4513
6049
|
const refined = refinedConstituentShape(widened, inner, ctx);
|
|
4514
6050
|
if (refined !== null)
|
|
4515
6051
|
return { kind: "record", shapeId: refined };
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
};
|
|
6052
|
+
const shapeId = shapes.intern(inner.fields, false, inner.indexValue, inner.declaredOrder);
|
|
6053
|
+
adoptAccessorOrder(shapes.get(shapeId), inner.accessorOrder);
|
|
6054
|
+
return { kind: "record", shapeId };
|
|
4520
6055
|
}
|
|
4521
6056
|
finally {
|
|
4522
6057
|
shapes.inProgress.delete(widened);
|
|
4523
6058
|
}
|
|
4524
6059
|
}
|
|
6060
|
+
/** An index signature already describes every OPTIONAL declared member
|
|
6061
|
+
* whose type is its slot type: @types/node's `ProcessEnv extends
|
|
6062
|
+
* Dict<string> { TZ?: string }` and every spread of it, or a declared
|
|
6063
|
+
* environment `{ CI?: string } & Dictionary<string>`. At runtime such a
|
|
6064
|
+
* member is just another key, so the shape interns as the pure
|
|
6065
|
+
* index-signature record. Its slot admits undefined, as the optional
|
|
6066
|
+
* members do (`env.CI = undefined` keeps the key). A hybrid layout would
|
|
6067
|
+
* give each member a struct slot, which enumerates before the overflow
|
|
6068
|
+
* keys (Node keeps one insertion order) and makes `delete` and spread
|
|
6069
|
+
* answer differently for declared and undeclared keys. Required members,
|
|
6070
|
+
* and members typed otherwise than the slot (whose reads the slot type
|
|
6071
|
+
* could not give back), keep the hybrid shape. */
|
|
6072
|
+
function coveredOptionalFieldsShape(widened, parts, ctx) {
|
|
6073
|
+
const slot = parts.indexValue;
|
|
6074
|
+
if (!slot || parts.fields.length === 0)
|
|
6075
|
+
return null;
|
|
6076
|
+
const { checker, shapes, unions } = ctx;
|
|
6077
|
+
// The members' common type must be the slot plus undefined. Read it off
|
|
6078
|
+
// the members (already interned) rather than building it: a hybrid that
|
|
6079
|
+
// does not qualify must not intern anything new.
|
|
6080
|
+
const optionalSlot = parts.fields[0].type;
|
|
6081
|
+
if (!parts.fields.every((field) => typeEquals(field.type, optionalSlot)))
|
|
6082
|
+
return null;
|
|
6083
|
+
if (optionalSlot.kind !== "union" || unions.armTag(optionalSlot.unionId, UNDEFINED_T) < 0)
|
|
6084
|
+
return null;
|
|
6085
|
+
const memberArms = unions.get(optionalSlot.unionId)?.arms ?? [];
|
|
6086
|
+
const slotArms = slot.kind === "union" ? (unions.get(slot.unionId)?.arms ?? []) : isUnitType(slot) ? [] : [slot];
|
|
6087
|
+
const definedArms = memberArms.filter((arm) => arm.kind !== "undefinedT");
|
|
6088
|
+
const slotDefined = slotArms.filter((arm) => arm.kind !== "undefinedT");
|
|
6089
|
+
if (definedArms.length === 0 ||
|
|
6090
|
+
definedArms.length !== slotDefined.length ||
|
|
6091
|
+
!slotDefined.every((arm) => definedArms.some((other) => typeEquals(arm, other))))
|
|
6092
|
+
return null;
|
|
6093
|
+
if (!isSupportedIndexValue(optionalSlot))
|
|
6094
|
+
return null;
|
|
6095
|
+
const props = checker.getPropertiesOfType(widened);
|
|
6096
|
+
if (props.length !== parts.fields.length)
|
|
6097
|
+
return null;
|
|
6098
|
+
if (!props.every((p) => (p.flags & ts.SymbolFlags.Optional) !== 0))
|
|
6099
|
+
return null;
|
|
6100
|
+
return shapes.intern([], false, optionalSlot, []);
|
|
6101
|
+
}
|
|
6102
|
+
/** The type of an object literal that spreads an index-signature record
|
|
6103
|
+
* (`{ ...tags, bucket: b, status }`, the metric-tags idiom). The checker
|
|
6104
|
+
* drops the signature and types the literal by its explicit members only,
|
|
6105
|
+
* but at run time the object holds every key the spread copied, in one
|
|
6106
|
+
* insertion order. Such a literal maps to the pure index-signature record
|
|
6107
|
+
* whose slot joins the spread slots and the member types, so the merge,
|
|
6108
|
+
* every enumeration and keyed writes see the same keys Node does. A
|
|
6109
|
+
* member read still answers its member type: members written after the
|
|
6110
|
+
* spreads always win, and a member written before a spread must have that
|
|
6111
|
+
* spread's slot type, so an override cannot change its type. The join
|
|
6112
|
+
* covers scalar and unit types only; other literals keep their shape and
|
|
6113
|
+
* the spread fence. */
|
|
6114
|
+
function dictSpreadLiteralShape(widened, parts, ctx) {
|
|
6115
|
+
if (parts.indexValue)
|
|
6116
|
+
return null;
|
|
6117
|
+
const symbol = widened.getSymbol();
|
|
6118
|
+
if (!symbol || (symbol.flags & ts.SymbolFlags.ObjectLiteral) === 0)
|
|
6119
|
+
return null;
|
|
6120
|
+
const literal = symbol.declarations.find((d) => ts.isObjectLiteralExpression(d));
|
|
6121
|
+
if (!literal)
|
|
6122
|
+
return null;
|
|
6123
|
+
const { checker, shapes, unions } = ctx;
|
|
6124
|
+
const props = literal.properties.nodes;
|
|
6125
|
+
if (!props.some((p) => ts.isSpreadAssignment(p)))
|
|
6126
|
+
return null;
|
|
6127
|
+
// Decide on checker types alone before mapping anything: object literals
|
|
6128
|
+
// with ordinary spreads are everywhere, and mapping their sources here
|
|
6129
|
+
// would intern types out of their usual order.
|
|
6130
|
+
// A literal written into a typed index-signature slot already lowers into
|
|
6131
|
+
// it (the merge into the contextual record); its own type keeps its
|
|
6132
|
+
// mapping.
|
|
6133
|
+
const contextualRaw = checker.getContextualType(literal);
|
|
6134
|
+
const contextual = contextualRaw ? checker.getNonNullableType(contextualRaw) : undefined;
|
|
6135
|
+
// A literal written into a declared slot lowers into that slot (a typed
|
|
6136
|
+
// index-signature record merges into it, a declared record converts),
|
|
6137
|
+
// and its own type keeps its mapping. Only a literal with no declared
|
|
6138
|
+
// destination (an unannotated binding, a type parameter, `any` or
|
|
6139
|
+
// `unknown`, an unknown-valued record) is built by its own type.
|
|
6140
|
+
// A generic argument's context is the instantiated parameter: the
|
|
6141
|
+
// literal's own type when the type argument was inferred from it.
|
|
6142
|
+
const ownContext = contextual !== undefined &&
|
|
6143
|
+
(contextual === widened || contextual.getSymbol()?.declarations.includes(literal) === true);
|
|
6144
|
+
if (contextual &&
|
|
6145
|
+
!ownContext &&
|
|
6146
|
+
!(contextual.flags & (ts.TypeFlags.TypeParameter | ts.TypeFlags.Any | ts.TypeFlags.Unknown))) {
|
|
6147
|
+
const infos = checker.getIndexInfosOfType(contextual);
|
|
6148
|
+
const unknownValued = infos.length > 0 &&
|
|
6149
|
+
infos.every((info) => (info.type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0);
|
|
6150
|
+
if (!unknownValued)
|
|
6151
|
+
return null;
|
|
6152
|
+
}
|
|
6153
|
+
const kinds = props.map((p) => ts.isSpreadAssignment(p) ? spreadSourceKindTs(checker, p.expression) : "member");
|
|
6154
|
+
if (kinds.some((k) => k === null) || !kinds.includes("dict"))
|
|
6155
|
+
return null;
|
|
6156
|
+
const dictSlotOf = (e) => {
|
|
6157
|
+
const t = checker.getNonNullableType(checker.getTypeAtLocation(e));
|
|
6158
|
+
if (checker.getPropertiesOfType(t).length === 0) {
|
|
6159
|
+
const infos = checker.getIndexInfosOfType(t);
|
|
6160
|
+
if (infos.length !== 1 || !(infos[0].keyType.flags & ts.TypeFlags.String))
|
|
6161
|
+
return null;
|
|
6162
|
+
return mapType(infos[0].type, ctx);
|
|
6163
|
+
}
|
|
6164
|
+
// Another such literal's type (`{ ...tags, repo }` over a binding
|
|
6165
|
+
// initialized by `{ ...base, plan }`) is stored as the same kind of
|
|
6166
|
+
// pure index-signature record.
|
|
6167
|
+
if (t === widened)
|
|
6168
|
+
return null;
|
|
6169
|
+
const mapped = mapType(t, ctx);
|
|
6170
|
+
if (mapped?.kind === "dyn")
|
|
6171
|
+
return DYN;
|
|
6172
|
+
const shape = mapped?.kind === "record" ? shapes.get(mapped.shapeId) : undefined;
|
|
6173
|
+
return shape?.indexValue && shape.fields.length === 0 && !shape.tuple ? shape.indexValue : null;
|
|
6174
|
+
};
|
|
6175
|
+
const arms = new Map();
|
|
6176
|
+
const addArms = (t) => {
|
|
6177
|
+
const list = t.kind === "union" ? (unions.get(t.unionId)?.arms ?? []) : [t];
|
|
6178
|
+
for (const arm of list) {
|
|
6179
|
+
if (!OVERLOAD_JOIN_SCALARS.has(arm.kind))
|
|
6180
|
+
return false;
|
|
6181
|
+
arms.set(typeKey(arm), arm);
|
|
6182
|
+
}
|
|
6183
|
+
return true;
|
|
6184
|
+
};
|
|
6185
|
+
const before = [];
|
|
6186
|
+
// An unknown-valued spread (`Record<string, unknown>`, or another such
|
|
6187
|
+
// literal) makes the object the checked-dynamic value: it is built like
|
|
6188
|
+
// a JavaScript object literal (copy each spread's own keys in order), and
|
|
6189
|
+
// member reads check their declared types.
|
|
6190
|
+
let unknownValued = false;
|
|
6191
|
+
for (const [i, p] of props.entries()) {
|
|
6192
|
+
// A fixed-shape or conditional spread contributes its own members,
|
|
6193
|
+
// which the checker already types exactly (they are in `parts`).
|
|
6194
|
+
if (kinds[i] === "record") {
|
|
6195
|
+
// Its members may be overwritten by a later dict spread, like members
|
|
6196
|
+
// written before one.
|
|
6197
|
+
before.push(...spreadMemberNamesTs(checker, p.expression));
|
|
6198
|
+
continue;
|
|
6199
|
+
}
|
|
6200
|
+
if (ts.isSpreadAssignment(p)) {
|
|
6201
|
+
const slot = dictSlotOf(p.expression);
|
|
6202
|
+
if (slot?.kind === "dyn") {
|
|
6203
|
+
unknownValued = true;
|
|
6204
|
+
continue;
|
|
6205
|
+
}
|
|
6206
|
+
if (!slot)
|
|
6207
|
+
return null;
|
|
6208
|
+
if (!addArms(slot)) {
|
|
6209
|
+
// A slot outside the scalar join still has the checked-dynamic
|
|
6210
|
+
// representation when it converts to it.
|
|
6211
|
+
if (!canConvertToDyn(slot, (id) => shapes.get(id), (id) => unions.get(id)))
|
|
6212
|
+
return null;
|
|
6213
|
+
unknownValued = true;
|
|
6214
|
+
}
|
|
6215
|
+
// A member written before this spread may be overwritten by it: the
|
|
6216
|
+
// typed join keeps member types only where the slot is that type;
|
|
6217
|
+
// otherwise the checked-dynamic object (whose member reads check
|
|
6218
|
+
// their types) holds whatever the spread wrote.
|
|
6219
|
+
for (const name of before) {
|
|
6220
|
+
const field = parts.fields.find((f) => f.name === name);
|
|
6221
|
+
if (!field)
|
|
6222
|
+
return null;
|
|
6223
|
+
if (!typeEquals(field.type, slot))
|
|
6224
|
+
unknownValued = true;
|
|
6225
|
+
}
|
|
6226
|
+
continue;
|
|
6227
|
+
}
|
|
6228
|
+
if (!(ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)))
|
|
6229
|
+
return null;
|
|
6230
|
+
const name = p.name;
|
|
6231
|
+
if (!(ts.isIdentifier(name) || ts.isStringLiteral(name)))
|
|
6232
|
+
return null;
|
|
6233
|
+
before.push(name.text);
|
|
6234
|
+
}
|
|
6235
|
+
if (parts.fields.some((f) => f.name.startsWith("%")))
|
|
6236
|
+
return null;
|
|
6237
|
+
// Members outside the scalar join (an array of labels beside the tags)
|
|
6238
|
+
// make the object the checked-dynamic value too.
|
|
6239
|
+
if (!unknownValued && !parts.fields.every((f) => addArms(f.type)))
|
|
6240
|
+
unknownValued = true;
|
|
6241
|
+
if (unknownValued) {
|
|
6242
|
+
const getRecord = (id) => shapes.get(id);
|
|
6243
|
+
const getUnion = (id) => unions.get(id);
|
|
6244
|
+
return parts.fields.every((f) => f.type.kind === "dyn" || canConvertToDyn(f.type, getRecord, getUnion))
|
|
6245
|
+
? "dyn"
|
|
6246
|
+
: null;
|
|
6247
|
+
}
|
|
6248
|
+
for (const field of parts.fields)
|
|
6249
|
+
if (!addArms(field.type))
|
|
6250
|
+
return null;
|
|
6251
|
+
if (![...arms.values()].some((arm) => !isUnitType(arm)))
|
|
6252
|
+
return null;
|
|
6253
|
+
const sorted = [...arms.values()].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
6254
|
+
const slot = sorted.length === 1 ? sorted[0] : { kind: "union", unionId: unions.intern(sorted) };
|
|
6255
|
+
return shapes.intern([], false, slot, []);
|
|
6256
|
+
}
|
|
6257
|
+
/** How a spread source contributes to dictSpreadLiteralShape, judged on
|
|
6258
|
+
* checker types only: "dict" for a pure string index signature or another
|
|
6259
|
+
* literal that spreads one, "record" for a fixed object shape or a
|
|
6260
|
+
* conditional spread (`...(c && { k: v })`), null otherwise. */
|
|
6261
|
+
function spreadSourceKindTs(checker, e) {
|
|
6262
|
+
if (dictSpreadSourceTs(checker, e, 0))
|
|
6263
|
+
return "dict";
|
|
6264
|
+
let inner = e;
|
|
6265
|
+
while (ts.isParenthesizedExpression(inner))
|
|
6266
|
+
inner = inner.expression;
|
|
6267
|
+
if ((ts.isBinaryExpression(inner) &&
|
|
6268
|
+
inner.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) ||
|
|
6269
|
+
ts.isConditionalExpression(inner))
|
|
6270
|
+
return "record";
|
|
6271
|
+
const t = checker.getNonNullableType(checker.getTypeAtLocation(e));
|
|
6272
|
+
if ((t.flags & ts.TypeFlags.Object) === 0 || t.isUnionType())
|
|
6273
|
+
return null;
|
|
6274
|
+
if (checker.getIndexInfosOfType(t).length > 0)
|
|
6275
|
+
return null;
|
|
6276
|
+
if (checker.getCallSignatures(t).length > 0 || checker.getConstructSignatures(t).length > 0)
|
|
6277
|
+
return null;
|
|
6278
|
+
const symbol = t.getSymbol();
|
|
6279
|
+
if (symbol && (symbol.flags & ts.SymbolFlags.Class) !== 0)
|
|
6280
|
+
return null;
|
|
6281
|
+
return "record";
|
|
6282
|
+
}
|
|
6283
|
+
/** The member names a fixed-shape or conditional spread contributes. */
|
|
6284
|
+
function spreadMemberNamesTs(checker, e) {
|
|
6285
|
+
let inner = e;
|
|
6286
|
+
while (ts.isParenthesizedExpression(inner))
|
|
6287
|
+
inner = inner.expression;
|
|
6288
|
+
const literals = [];
|
|
6289
|
+
if (ts.isBinaryExpression(inner))
|
|
6290
|
+
literals.push(inner.right);
|
|
6291
|
+
else if (ts.isConditionalExpression(inner))
|
|
6292
|
+
literals.push(inner.whenTrue, inner.whenFalse);
|
|
6293
|
+
else
|
|
6294
|
+
literals.push(inner);
|
|
6295
|
+
const names = [];
|
|
6296
|
+
for (const l of literals) {
|
|
6297
|
+
const t = checker.getNonNullableType(checker.getTypeAtLocation(l));
|
|
6298
|
+
for (const property of checker.getPropertiesOfType(t))
|
|
6299
|
+
names.push(ts.symbolName(property));
|
|
6300
|
+
}
|
|
6301
|
+
return names;
|
|
6302
|
+
}
|
|
6303
|
+
/** A spread source the checker types as a pure string index signature,
|
|
6304
|
+
* or as another object literal that spreads one (dictSpreadLiteralShape),
|
|
6305
|
+
* judged on checker types only. */
|
|
6306
|
+
function dictSpreadSourceTs(checker, e, depth) {
|
|
6307
|
+
const t = checker.getNonNullableType(checker.getTypeAtLocation(e));
|
|
6308
|
+
if (checker.getPropertiesOfType(t).length === 0) {
|
|
6309
|
+
const infos = checker.getIndexInfosOfType(t);
|
|
6310
|
+
return infos.length === 1 && (infos[0].keyType.flags & ts.TypeFlags.String) !== 0;
|
|
6311
|
+
}
|
|
6312
|
+
if (depth > 4)
|
|
6313
|
+
return false;
|
|
6314
|
+
const symbol = t.getSymbol();
|
|
6315
|
+
if (!symbol || (symbol.flags & ts.SymbolFlags.ObjectLiteral) === 0)
|
|
6316
|
+
return false;
|
|
6317
|
+
const literal = symbol.declarations.find((d) => ts.isObjectLiteralExpression(d));
|
|
6318
|
+
if (!literal)
|
|
6319
|
+
return false;
|
|
6320
|
+
const spreads = literal.properties.nodes.filter((p) => ts.isSpreadAssignment(p));
|
|
6321
|
+
return (spreads.length > 0 &&
|
|
6322
|
+
spreads.every((p) => dictSpreadSourceTs(checker, p.expression, depth + 1)));
|
|
6323
|
+
}
|
|
6324
|
+
/** The first-seen accessor key order of a shape with accessor slots. */
|
|
6325
|
+
function adoptAccessorOrder(shape, order) {
|
|
6326
|
+
if (shape !== undefined && order !== undefined && shape.accessorOrder === undefined)
|
|
6327
|
+
shape.accessorOrder = order;
|
|
6328
|
+
}
|
|
4525
6329
|
/** A refinement intersection (`Expr & { kind: "mul" }`, which the checker
|
|
4526
6330
|
* reduces to `Mul & { kind: "mul" }`) keeps the shape of the constituent it
|
|
4527
6331
|
* refines when the refinement changes no field's representation. Recursive
|
|
@@ -4535,12 +6339,12 @@ function refinedConstituentShape(widened, parts, ctx) {
|
|
|
4535
6339
|
if (!widened.isIntersectionType())
|
|
4536
6340
|
return null;
|
|
4537
6341
|
const { checker, shapes } = ctx;
|
|
4538
|
-
const names = checker.getPropertiesOfType(widened).map((prop) => prop
|
|
6342
|
+
const names = checker.getPropertiesOfType(widened).map((prop) => ts.symbolName(prop));
|
|
4539
6343
|
let found = null;
|
|
4540
6344
|
for (const part of ts.constituentTypes(widened)) {
|
|
4541
6345
|
if ((part.flags & ts.TypeFlags.Object) === 0 || shapes.inProgress.has(part))
|
|
4542
6346
|
continue;
|
|
4543
|
-
const own = new Set(checker.getPropertiesOfType(part).map((prop) => prop
|
|
6347
|
+
const own = new Set(checker.getPropertiesOfType(part).map((prop) => ts.symbolName(prop)));
|
|
4544
6348
|
if (own.size !== names.length || !names.every((name) => own.has(name)))
|
|
4545
6349
|
continue;
|
|
4546
6350
|
const mapped = mapType(part, ctx);
|
|
@@ -4560,6 +6364,29 @@ function refinedConstituentShape(widened, parts, ctx) {
|
|
|
4560
6364
|
}
|
|
4561
6365
|
return found;
|
|
4562
6366
|
}
|
|
6367
|
+
/** The optional `undefined` members widening adds to an object literal's
|
|
6368
|
+
* type for properties only its sibling literals declare (`[{ a: 1 }, { b: 2
|
|
6369
|
+
* }]` gives the first `b?: undefined`). They are never own keys of the
|
|
6370
|
+
* literal's value, so they go after the declared members, by name. Where
|
|
6371
|
+
* the checker lists them is not observable: TypeScript 7.0.2 orders them
|
|
6372
|
+
* by the literal its checker widened first, TypeScript 7.1 by the sibling
|
|
6373
|
+
* that declares them. */
|
|
6374
|
+
function wideningAddedProperties(type, props, ctx) {
|
|
6375
|
+
const added = new Set();
|
|
6376
|
+
const literal = type.getSymbol()?.declarations.find(ts.isObjectLiteralExpression);
|
|
6377
|
+
if (literal === undefined || literal.properties.nodes.some(ts.isSpreadAssignment))
|
|
6378
|
+
return added;
|
|
6379
|
+
for (const prop of props) {
|
|
6380
|
+
if ((prop.flags & ts.SymbolFlags.Optional) === 0 || prop.declarations.length === 0)
|
|
6381
|
+
continue;
|
|
6382
|
+
if (prop.declarations.some((d) => d.parent === literal))
|
|
6383
|
+
continue;
|
|
6384
|
+
if ((ctx.checker.getTypeOfSymbol(prop).flags & ts.TypeFlags.Undefined) === 0)
|
|
6385
|
+
continue;
|
|
6386
|
+
added.add(ts.symbolName(prop));
|
|
6387
|
+
}
|
|
6388
|
+
return added;
|
|
6389
|
+
}
|
|
4563
6390
|
function mapRecordTypeInner(widened, ctx) {
|
|
4564
6391
|
const { checker, shapes } = ctx;
|
|
4565
6392
|
if (checker.getConstructSignatures(widened).length > 0)
|
|
@@ -4612,7 +6439,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4612
6439
|
for (const info of indexInfos) {
|
|
4613
6440
|
if (!stringKey(info.keyType) && !(info.keyType.flags & ts.TypeFlags.Number))
|
|
4614
6441
|
return null;
|
|
4615
|
-
const iv = mapType(info.
|
|
6442
|
+
const iv = mapType(info.type, ctx);
|
|
4616
6443
|
// JSONValue>` (a package's own JSON alias) and `Record<string, any>`
|
|
4617
6444
|
if (!iv || !isSupportedIndexValue(iv))
|
|
4618
6445
|
return null;
|
|
@@ -4688,7 +6515,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4688
6515
|
// stance), records of other shapes at theirs — the declaration itself is
|
|
4689
6516
|
// representable.
|
|
4690
6517
|
const anonSym = widened.getSymbol();
|
|
4691
|
-
const anonymousEmpty = (anonSym === undefined ||
|
|
6518
|
+
const anonymousEmpty = (anonSym === undefined || anonSym.declarations.length === 0) &&
|
|
4692
6519
|
!widened.isIntersectionType() &&
|
|
4693
6520
|
indexValue === undefined &&
|
|
4694
6521
|
checker.getPropertiesOfType(widened).length === 0;
|
|
@@ -4703,7 +6530,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4703
6530
|
return DYN;
|
|
4704
6531
|
// Symbol-keyed records use the checked object's descriptor table. A
|
|
4705
6532
|
// checker-internal __@ name is not a string field in a native struct.
|
|
4706
|
-
if (props.some((property) => property.
|
|
6533
|
+
if (props.some((property) => ts.symbolName(property).startsWith("__@")))
|
|
4707
6534
|
return DYN;
|
|
4708
6535
|
// A computed shape with NO members is not a real empty record: inside a
|
|
4709
6536
|
// generic body `Partial<T>` resolves to no members at all (keyof T is
|
|
@@ -4730,8 +6557,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4730
6557
|
indexValue === undefined &&
|
|
4731
6558
|
checker.getCallSignatures(widened).length === 0 &&
|
|
4732
6559
|
checker.getConstructSignatures(widened).length === 0 &&
|
|
4733
|
-
!(anonSym !== undefined &&
|
|
4734
|
-
checker.declarationsOf(anonSym).some((d) => ts.isObjectLiteralExpression(d)))) {
|
|
6560
|
+
!(anonSym !== undefined && anonSym.declarations.some((d) => ts.isObjectLiteralExpression(d)))) {
|
|
4735
6561
|
return DYN;
|
|
4736
6562
|
}
|
|
4737
6563
|
const fields = [];
|
|
@@ -4752,7 +6578,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4752
6578
|
// their existing paths (the CJS export-table narrowing and the
|
|
4753
6579
|
// checked-dynamic fallback), and .d.ts declarations stay out with
|
|
4754
6580
|
// the rest of the lib's type worlds.
|
|
4755
|
-
const decls =
|
|
6581
|
+
const decls = p.declarations;
|
|
4756
6582
|
const getDecl = decls.find((d) => ts.isGetAccessorDeclaration(d));
|
|
4757
6583
|
const setDecl = decls.find((d) => ts.isSetAccessorDeclaration(d));
|
|
4758
6584
|
const accessorOwned = decls.length > 0 &&
|
|
@@ -4761,13 +6587,13 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4761
6587
|
(ts.isObjectLiteralExpression(d.parent) ||
|
|
4762
6588
|
ts.isInterfaceDeclaration(d.parent) ||
|
|
4763
6589
|
d.parent.kind === ts.SyntaxKind.TypeLiteral) &&
|
|
4764
|
-
!
|
|
4765
|
-
!isJsSourceFile(
|
|
6590
|
+
!ts.getSourceFileOfNode(d).isDeclarationFile &&
|
|
6591
|
+
!isJsSourceFile(ts.getSourceFileOfNode(d)));
|
|
4766
6592
|
if (!accessorOwned || (!getDecl && !setDecl))
|
|
4767
6593
|
return null;
|
|
4768
6594
|
// Symbol-keyed accessors have no foldable literal name to fill at
|
|
4769
6595
|
// the literal — no slot to make.
|
|
4770
|
-
if (p.
|
|
6596
|
+
if (ts.symbolName(p).startsWith("__@"))
|
|
4771
6597
|
return null;
|
|
4772
6598
|
// An index-signature shape stores accessor NAMES nowhere the keyed
|
|
4773
6599
|
// read/walk machinery can answer (the overflow would miss where
|
|
@@ -4782,7 +6608,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4782
6608
|
}
|
|
4783
6609
|
let writeT = null;
|
|
4784
6610
|
if (setDecl) {
|
|
4785
|
-
const param = setDecl.parameters[0];
|
|
6611
|
+
const param = setDecl.parameters.nodes[0];
|
|
4786
6612
|
if (!param)
|
|
4787
6613
|
return null;
|
|
4788
6614
|
writeT = mapType(checker.getTypeAtLocation(param), ctx);
|
|
@@ -4795,9 +6621,9 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4795
6621
|
return null;
|
|
4796
6622
|
}
|
|
4797
6623
|
if (readT !== null || getDecl)
|
|
4798
|
-
fields.push({ name: `%get:${p
|
|
6624
|
+
fields.push({ name: `%get:${ts.symbolName(p)}`, type: funcOf([], readT ?? VOID) });
|
|
4799
6625
|
if (writeT !== null)
|
|
4800
|
-
fields.push({ name: `%set:${p
|
|
6626
|
+
fields.push({ name: `%set:${ts.symbolName(p)}`, type: funcOf([writeT], VOID) });
|
|
4801
6627
|
continue;
|
|
4802
6628
|
}
|
|
4803
6629
|
// Computed shapes carry provenance per MEMBER: a utility type over a
|
|
@@ -4805,9 +6631,9 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4805
6631
|
// a data shape. Synthesized members (a literal-key Record's) have no
|
|
4806
6632
|
// declarations and pass.
|
|
4807
6633
|
if (computed &&
|
|
4808
|
-
|
|
4809
|
-
const sf =
|
|
4810
|
-
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf);
|
|
6634
|
+
p.declarations.some((d) => {
|
|
6635
|
+
const sf = ts.getSourceFileOfNode(d);
|
|
6636
|
+
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf) && !packageTypeFile(sf, ctx);
|
|
4811
6637
|
})) {
|
|
4812
6638
|
return null;
|
|
4813
6639
|
}
|
|
@@ -4816,9 +6642,16 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4816
6642
|
// can hold them — see isGenericCallableMemberType): the shape keeps
|
|
4817
6643
|
// its data fields, and calls of the member monomorphize per call
|
|
4818
6644
|
// site against the defining object literal's declaration.
|
|
4819
|
-
|
|
6645
|
+
// OVERLOADED members hold their erased runtime function (see
|
|
6646
|
+
// erasedOverloadMemberType); a set that does not join fails the
|
|
6647
|
+
// shape as before.
|
|
6648
|
+
let pt = isGenericCallableMemberType(fieldTs, checker)
|
|
6649
|
+
? erasedGenericMemberType(fieldTs, ctx)
|
|
6650
|
+
: isOverloadedCallableMemberType(fieldTs, checker)
|
|
6651
|
+
? (erasedOverloadMemberType(fieldTs, ctx) ?? null)
|
|
6652
|
+
: mapType(fieldTs, ctx);
|
|
6653
|
+
if (pt === undefined)
|
|
4820
6654
|
continue;
|
|
4821
|
-
let pt = mapType(fieldTs, ctx);
|
|
4822
6655
|
// tsgo PANICS computing `readonly []` through the symbol-type query
|
|
4823
6656
|
// (the TupleType conversion — the facade's panic fence answers
|
|
4824
6657
|
// `any`), which would absorb the whole shape into the dynamic tier.
|
|
@@ -4828,7 +6661,7 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4828
6661
|
// unit-element array; see the `[] as const` rule there).
|
|
4829
6662
|
if (pt === null &&
|
|
4830
6663
|
(fieldTs.flags & ts.TypeFlags.Any) !== 0 &&
|
|
4831
|
-
constAssertedEmptyArrayProp(p
|
|
6664
|
+
constAssertedEmptyArrayProp(p)) {
|
|
4832
6665
|
pt = arrayOf(unitOnlyUnion(ctx.unions));
|
|
4833
6666
|
}
|
|
4834
6667
|
if (pt === null && (fieldTs.flags & ts.TypeFlags.Any) !== 0)
|
|
@@ -4849,10 +6682,10 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4849
6682
|
// A DATA property spelled like a reserved accessor slot (`{ "%get:x":
|
|
4850
6683
|
// v }` — a string-literal key): mapping it would collide with the
|
|
4851
6684
|
// accessor dispatch, so the shape stays unmapped.
|
|
4852
|
-
if (accessorSlotProp(p
|
|
6685
|
+
if (accessorSlotProp(ts.symbolName(p)) !== null)
|
|
4853
6686
|
return null;
|
|
4854
6687
|
// an options record with `signal?: AbortSignal` must not turn its
|
|
4855
|
-
fields.push({ name: p
|
|
6688
|
+
fields.push({ name: ts.symbolName(p), type: pt });
|
|
4856
6689
|
}
|
|
4857
6690
|
// getPropertiesOfType yields DECLARATION order (interface/alias/literal
|
|
4858
6691
|
// source order) — captured before the canonical sort so Object.keys/
|
|
@@ -4863,9 +6696,23 @@ function mapRecordTypeInner(widened, ctx) {
|
|
|
4863
6696
|
// indices, from folded numeric computed keys and quoted numeric keys)
|
|
4864
6697
|
// enumerate FIRST ascending, then string keys in insertion order
|
|
4865
6698
|
// (OrdinaryOwnPropertyKeys) — Object.keys/JSON/inspect all read it.
|
|
4866
|
-
const
|
|
6699
|
+
const widenedAbsent = wideningAddedProperties(widened, props, ctx);
|
|
6700
|
+
const declaredOrder = esOwnKeyOrder(fields
|
|
6701
|
+
.filter((f) => accessorSlotProp(f.name) === null && !widenedAbsent.has(f.name))
|
|
6702
|
+
.map((f) => f.name)
|
|
6703
|
+
.concat([...widenedAbsent].sort()));
|
|
6704
|
+
// With accessors: every own key in that order, an accessor property
|
|
6705
|
+
// named once for its get/set pair (the checked-dynamic copy lists it).
|
|
6706
|
+
const accessorOrder = fields.some((f) => accessorSlotProp(f.name) !== null)
|
|
6707
|
+
? esOwnKeyOrder([...new Set(fields.map((f) => accessorSlotProp(f.name)?.prop ?? f.name))])
|
|
6708
|
+
: undefined;
|
|
4867
6709
|
fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
4868
|
-
return {
|
|
6710
|
+
return {
|
|
6711
|
+
fields,
|
|
6712
|
+
...(indexValue ? { indexValue } : {}),
|
|
6713
|
+
declaredOrder,
|
|
6714
|
+
...(accessorOrder ? { accessorOrder } : {}),
|
|
6715
|
+
};
|
|
4869
6716
|
}
|
|
4870
6717
|
}
|
|
4871
6718
|
/* ── Component-fence classification (SC2009) ───────────────────────────────
|
|
@@ -4915,9 +6762,63 @@ function dynSubsumableUnionArm(arm, ctx) {
|
|
|
4915
6762
|
return false;
|
|
4916
6763
|
}
|
|
4917
6764
|
}
|
|
6765
|
+
/** A parameter of a function type that is the default of a type parameter
|
|
6766
|
+
* declared in node:test's standard-library declarations (MockTracker.fn's
|
|
6767
|
+
* `F extends Function = (...args: any[]) => undefined`). */
|
|
6768
|
+
function isNodeTestDefaultFunctionParam(decl, ctx) {
|
|
6769
|
+
const fnType = decl.parent;
|
|
6770
|
+
return (ts.isParameter(decl) &&
|
|
6771
|
+
fnType !== undefined &&
|
|
6772
|
+
ts.isFunctionTypeNode(fnType) &&
|
|
6773
|
+
fnType.parent !== undefined &&
|
|
6774
|
+
ts.isTypeParameterDeclaration(fnType.parent) &&
|
|
6775
|
+
fnType.parent.defaultType === fnType &&
|
|
6776
|
+
ctx.isStdlibFile(ts.getSourceFileOfNode(decl)) &&
|
|
6777
|
+
isDeclaredInAmbientModule(decl, "test"));
|
|
6778
|
+
}
|
|
6779
|
+
/** `any[]` (or `readonly any[]`): an array type whose element is `any`. */
|
|
6780
|
+
export function isAnyArrayType(t, checker) {
|
|
6781
|
+
if (!checker.isArrayType(t))
|
|
6782
|
+
return false;
|
|
6783
|
+
const elem = checker.getTypeArguments(t)[0];
|
|
6784
|
+
return elem !== undefined && (elem.flags & ts.TypeFlags.Any) !== 0;
|
|
6785
|
+
}
|
|
6786
|
+
/** The maybe-promise union rule (mapTypeInner's union rule; IR
|
|
6787
|
+
* maybePromiseUnionArmsOk): at most one promise arm, and when it has data
|
|
6788
|
+
* siblings none of them may be thenable — `await` and async `return`
|
|
6789
|
+
* dispatch on the union tag, so a data arm whose type declares `then`
|
|
6790
|
+
* would skip the thenable adoption JS performs. */
|
|
6791
|
+
function maybePromiseUnionOk(parts, arms, ctx) {
|
|
6792
|
+
if (unionContainerArmsOk(arms))
|
|
6793
|
+
return true;
|
|
6794
|
+
if (!maybePromiseUnionArmsOk(arms))
|
|
6795
|
+
return false;
|
|
6796
|
+
// A function beside a promise (`Promise<T> | (() => Promise<T>)`, the
|
|
6797
|
+
// assert.rejects argument) keeps its existing representation: callers
|
|
6798
|
+
// dispatch on callability, not on a then-able promise.
|
|
6799
|
+
if (arms.some((arm) => arm.kind === "func"))
|
|
6800
|
+
return false;
|
|
6801
|
+
return maybePromiseThenableArm(parts, ctx) === null;
|
|
6802
|
+
}
|
|
6803
|
+
/** The first non-promise constituent of a promise-armed union whose type
|
|
6804
|
+
* has a `then` member (a thenable data arm), or null. */
|
|
6805
|
+
function maybePromiseThenableArm(parts, ctx) {
|
|
6806
|
+
const { checker } = ctx;
|
|
6807
|
+
for (const part of parts) {
|
|
6808
|
+
if (part.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void | ts.TypeFlags.Null))
|
|
6809
|
+
continue;
|
|
6810
|
+
if (mapType(part, ctx)?.kind === "promise")
|
|
6811
|
+
continue;
|
|
6812
|
+
// Primitive arms answer through their wrapper prototypes, none of
|
|
6813
|
+
// which has `then`; object arms answer through their own members.
|
|
6814
|
+
if (checker.getPropertyOfType(part, "then"))
|
|
6815
|
+
return part;
|
|
6816
|
+
}
|
|
6817
|
+
return null;
|
|
6818
|
+
}
|
|
4918
6819
|
/** Arm kinds with no home in a compiled union (mapTypeInner's union rule):
|
|
4919
6820
|
* no runtime narrowing test exists against sibling data arms. */
|
|
4920
|
-
function armHasUnionHome(arm
|
|
6821
|
+
function armHasUnionHome(arm) {
|
|
4921
6822
|
switch (arm.kind) {
|
|
4922
6823
|
case "void":
|
|
4923
6824
|
case "union":
|
|
@@ -4926,9 +6827,6 @@ function armHasUnionHome(arm, siblingCount) {
|
|
|
4926
6827
|
case "generator":
|
|
4927
6828
|
case "dyn":
|
|
4928
6829
|
return false;
|
|
4929
|
-
// Promise data siblings still lack a supported narrowing contract.
|
|
4930
|
-
case "promise":
|
|
4931
|
-
return siblingCount === 0;
|
|
4932
6830
|
default:
|
|
4933
6831
|
return true;
|
|
4934
6832
|
}
|
|
@@ -4946,11 +6844,9 @@ export function describeComponentBlocker(widened, ctx) {
|
|
|
4946
6844
|
// `interface Map` is a record shape and keeps the record stories).
|
|
4947
6845
|
const psym = widened.getSymbol();
|
|
4948
6846
|
const container = psym !== undefined &&
|
|
4949
|
-
Object.prototype.hasOwnProperty.call(STDLIB_CONTAINERS, psym
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()))
|
|
4953
|
-
? psym.name
|
|
6847
|
+
Object.prototype.hasOwnProperty.call(STDLIB_CONTAINERS, ts.symbolName(psym)) &&
|
|
6848
|
+
psym.declarations.some((d) => ts.isInterfaceDeclaration(d) && ctx.isStdlibFile(ts.getSourceFileOfNode(d)))
|
|
6849
|
+
? ts.symbolName(psym)
|
|
4954
6850
|
: undefined;
|
|
4955
6851
|
if (container !== undefined) {
|
|
4956
6852
|
const spec = STDLIB_CONTAINERS[container];
|
|
@@ -5035,10 +6931,24 @@ export function describeComponentBlocker(widened, ctx) {
|
|
|
5035
6931
|
if (!mapped) {
|
|
5036
6932
|
return `the union shape is supported, but its arm '${text(part)}' does not compile`;
|
|
5037
6933
|
}
|
|
5038
|
-
if (!armHasUnionHome(mapped
|
|
6934
|
+
if (!armHasUnionHome(mapped)) {
|
|
5039
6935
|
return `the union shape is supported, but '${text(part)}' arms have no home in a compiled union yet (no runtime narrowing test exists against sibling arms)`;
|
|
5040
6936
|
}
|
|
5041
6937
|
}
|
|
6938
|
+
const promiseArms = mappedArms.filter(({ mapped }) => mapped?.kind === "promise");
|
|
6939
|
+
if (promiseArms.length > 1) {
|
|
6940
|
+
return `the union shape is supported, but it has several promise arms ('${text(promiseArms[0].p)}' and '${text(promiseArms[1].p)}'), and a compiled union holds at most one (the union tag is the 'instanceof Promise' test)`;
|
|
6941
|
+
}
|
|
6942
|
+
if (promiseArms.length === 1 && dataArms.length > 1) {
|
|
6943
|
+
const callable = mappedArms.find(({ mapped }) => mapped?.kind === "func");
|
|
6944
|
+
if (callable) {
|
|
6945
|
+
return `the union shape is supported, but its function arm '${text(callable.p)}' sits beside a promise arm, and a maybe-promise union holds only data arms beside its promise`;
|
|
6946
|
+
}
|
|
6947
|
+
const thenable = maybePromiseThenableArm(parts, ctx);
|
|
6948
|
+
if (thenable) {
|
|
6949
|
+
return `the union shape is supported, but its arm '${text(thenable)}' declares 'then' beside a promise arm, so 'await' would have to adopt it as a thenable (a maybe-promise union's data arms must not be thenable)`;
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
5042
6952
|
return null;
|
|
5043
6953
|
}
|
|
5044
6954
|
// Single-signature, non-generic function types: a parameter type or the
|
|
@@ -5051,17 +6961,17 @@ export function describeComponentBlocker(widened, ctx) {
|
|
|
5051
6961
|
const sig = callSigs[0];
|
|
5052
6962
|
if (sig.getTypeParameters().length > 0)
|
|
5053
6963
|
return null;
|
|
5054
|
-
const sigDecl =
|
|
6964
|
+
const sigDecl = sig.declaration;
|
|
5055
6965
|
if (sigDecl !== undefined &&
|
|
5056
6966
|
ts.isFunctionLike(sigDecl) &&
|
|
5057
|
-
(runtimeParameterCount(sigDecl.parameters) !== sig.getParameters().length ||
|
|
6967
|
+
(runtimeParameterCount(sigDecl.parameters.nodes) !== sig.getParameters().length ||
|
|
5058
6968
|
bodyReadsArguments(sigDecl))) {
|
|
5059
6969
|
return `the function shape is supported, but its signature is variadic ('arguments'-reading), and a compiled signature is fixed-arity`;
|
|
5060
6970
|
}
|
|
5061
6971
|
for (const p of sig.getParameters()) {
|
|
5062
6972
|
const pTs = checker.getTypeOfSymbol(p);
|
|
5063
6973
|
if (!mapType(pTs, ctx)) {
|
|
5064
|
-
return `the function shape is supported, but its parameter '${p
|
|
6974
|
+
return `the function shape is supported, but its parameter '${ts.symbolName(p)}' has type '${text(pTs)}', which does not compile`;
|
|
5065
6975
|
}
|
|
5066
6976
|
}
|
|
5067
6977
|
const retTs = checker.getReturnTypeOfSignature(sig);
|
|
@@ -5098,26 +7008,33 @@ export function describeRecordMemberBlocker(widened, ctx) {
|
|
|
5098
7008
|
// rules (mapRecordTypeInner) — no single-member claim is honest there.
|
|
5099
7009
|
if ((p.flags & (ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor)) !== 0)
|
|
5100
7010
|
continue;
|
|
5101
|
-
if (p.
|
|
7011
|
+
if (ts.symbolName(p).startsWith("__@"))
|
|
5102
7012
|
continue;
|
|
5103
7013
|
// Computed shapes over LIBRARY members (`Readonly<Date>`): the record
|
|
5104
7014
|
// fence there is per-member PROVENANCE (mapRecordTypeInner's rule), not
|
|
5105
7015
|
// any one member's type — that story stays with the residual fence.
|
|
5106
7016
|
if (computed &&
|
|
5107
|
-
|
|
5108
|
-
const sf =
|
|
5109
|
-
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf);
|
|
7017
|
+
p.declarations.some((d) => {
|
|
7018
|
+
const sf = ts.getSourceFileOfNode(d);
|
|
7019
|
+
return sf.isDeclarationFile && !ctx.isExternalTypeFile(sf) && !packageTypeFile(sf, ctx);
|
|
5110
7020
|
})) {
|
|
5111
7021
|
return null;
|
|
5112
7022
|
}
|
|
5113
7023
|
const fieldTs = checker.getTypeOfSymbol(p);
|
|
5114
|
-
if (
|
|
7024
|
+
if (isOverloadedCallableMemberType(fieldTs, checker)) {
|
|
7025
|
+
if (erasedOverloadMemberType(fieldTs, ctx) !== undefined)
|
|
7026
|
+
continue;
|
|
7027
|
+
return `the record shape is supported, but its member '${ts.symbolName(p)}' ${describeOverloadSetBlocker(fieldTs, ctx)}`;
|
|
7028
|
+
}
|
|
7029
|
+
let pt = isGenericCallableMemberType(fieldTs, checker)
|
|
7030
|
+
? erasedGenericMemberType(fieldTs, ctx)
|
|
7031
|
+
: mapType(fieldTs, ctx);
|
|
7032
|
+
if (pt === undefined)
|
|
5115
7033
|
continue;
|
|
5116
|
-
let pt = mapType(fieldTs, ctx);
|
|
5117
7034
|
if (pt?.kind === "void" && isUnitOnlyTsType(fieldTs, ctx.resolveTypeParam))
|
|
5118
7035
|
pt = unitOnlyUnion(ctx.unions);
|
|
5119
7036
|
if (!pt || pt.kind === "void") {
|
|
5120
|
-
return `the record shape is supported, but its member '${p
|
|
7037
|
+
return `the record shape is supported, but its member '${ts.symbolName(p)}' has type '${checker.typeToString(fieldTs)}', which does not compile`;
|
|
5121
7038
|
}
|
|
5122
7039
|
}
|
|
5123
7040
|
return null;
|