@geastack/compiler 1.0.15
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/LICENSE +202 -0
- package/README.md +149 -0
- package/dist/cli-analyze.d.ts +1 -0
- package/dist/cli-analyze.js +61 -0
- package/dist/cli-coverage.d.ts +1 -0
- package/dist/cli-coverage.js +329 -0
- package/dist/cli-emit.d.ts +10 -0
- package/dist/cli-emit.js +398 -0
- package/dist/cli-module-graph.d.ts +18 -0
- package/dist/cli-module-graph.js +123 -0
- package/dist/cli-package-source.d.ts +5 -0
- package/dist/cli-package-source.js +116 -0
- package/dist/cli-project.d.ts +2 -0
- package/dist/cli-project.js +60 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +199 -0
- package/dist/compiler.d.ts +228 -0
- package/dist/compiler.js +1029 -0
- package/dist/conversion/algebra.d.ts +218 -0
- package/dist/conversion/algebra.js +155 -0
- package/dist/conversion/build.d.ts +67 -0
- package/dist/conversion/build.js +1378 -0
- package/dist/conversion/derive.d.ts +37 -0
- package/dist/conversion/derive.js +260 -0
- package/dist/conversion/graph-validation.d.ts +8 -0
- package/dist/conversion/graph-validation.js +97 -0
- package/dist/conversion/native-callable-adapter.d.ts +13 -0
- package/dist/conversion/native-callable-adapter.js +53 -0
- package/dist/conversion/native-class-reference.d.ts +12 -0
- package/dist/conversion/native-class-reference.js +39 -0
- package/dist/conversion/native-payload-transport.d.ts +25 -0
- package/dist/conversion/native-payload-transport.js +33 -0
- package/dist/conversion/native-selection.d.ts +49 -0
- package/dist/conversion/native-selection.js +135 -0
- package/dist/conversion/native-sum.d.ts +42 -0
- package/dist/conversion/native-sum.js +115 -0
- package/dist/conversion/nodes.d.ts +55 -0
- package/dist/conversion/nodes.js +91 -0
- package/dist/conversion/operand-view.d.ts +14 -0
- package/dist/conversion/operand-view.js +20 -0
- package/dist/conversion/record-view.d.ts +157 -0
- package/dist/conversion/record-view.js +273 -0
- package/dist/conversion/registry.d.ts +217 -0
- package/dist/conversion/registry.js +1 -0
- package/dist/diagnostics/model.d.ts +76 -0
- package/dist/diagnostics/model.js +60 -0
- package/dist/diagnostics/sweep.d.ts +31 -0
- package/dist/diagnostics/sweep.js +112 -0
- package/dist/identity/ids.d.ts +179 -0
- package/dist/identity/ids.js +212 -0
- package/dist/ir/absent-class-arm.d.ts +48 -0
- package/dist/ir/absent-class-arm.js +157 -0
- package/dist/ir/borrow-effects.d.ts +23 -0
- package/dist/ir/borrow-effects.js +151 -0
- package/dist/ir/borrowed-call-arguments.d.ts +40 -0
- package/dist/ir/borrowed-call-arguments.js +117 -0
- package/dist/ir/build.d.ts +168 -0
- package/dist/ir/build.js +459 -0
- package/dist/ir/call-dispatch.d.ts +38 -0
- package/dist/ir/call-dispatch.js +502 -0
- package/dist/ir/call-entry.d.ts +142 -0
- package/dist/ir/call-entry.js +386 -0
- package/dist/ir/callable-class-flow.d.ts +27 -0
- package/dist/ir/callable-class-flow.js +1386 -0
- package/dist/ir/callable-field-slots.d.ts +22 -0
- package/dist/ir/callable-field-slots.js +166 -0
- package/dist/ir/callable-identity-demand.d.ts +52 -0
- package/dist/ir/callable-identity-demand.js +460 -0
- package/dist/ir/callable-member-candidates.d.ts +9 -0
- package/dist/ir/callable-member-candidates.js +39 -0
- package/dist/ir/callable-records.d.ts +21 -0
- package/dist/ir/callable-records.js +411 -0
- package/dist/ir/captures.d.ts +26 -0
- package/dist/ir/captures.js +335 -0
- package/dist/ir/certificate.d.ts +45 -0
- package/dist/ir/certificate.js +47 -0
- package/dist/ir/certify/carrier-keys.d.ts +73 -0
- package/dist/ir/certify/carrier-keys.js +221 -0
- package/dist/ir/certify/function-source.d.ts +4 -0
- package/dist/ir/certify/function-source.js +28 -0
- package/dist/ir/certify/has-property-key.d.ts +88 -0
- package/dist/ir/certify/has-property-key.js +116 -0
- package/dist/ir/certify/instanceof-key.d.ts +24 -0
- package/dist/ir/certify/instanceof-key.js +35 -0
- package/dist/ir/certify/property-access-keys.d.ts +172 -0
- package/dist/ir/certify/property-access-keys.js +291 -0
- package/dist/ir/certify/property-access.d.ts +3 -0
- package/dist/ir/certify/property-access.js +597 -0
- package/dist/ir/certify/runtime-helper.d.ts +3 -0
- package/dist/ir/certify/runtime-helper.js +326 -0
- package/dist/ir/certify/typeof-operand.d.ts +14 -0
- package/dist/ir/certify/typeof-operand.js +16 -0
- package/dist/ir/certify.d.ts +123 -0
- package/dist/ir/certify.js +481 -0
- package/dist/ir/class-evaluation.d.ts +26 -0
- package/dist/ir/class-evaluation.js +50 -0
- package/dist/ir/class-static-fields.d.ts +60 -0
- package/dist/ir/class-static-fields.js +108 -0
- package/dist/ir/construct-entry.d.ts +26 -0
- package/dist/ir/construct-entry.js +117 -0
- package/dist/ir/dead-values.d.ts +90 -0
- package/dist/ir/dead-values.js +184 -0
- package/dist/ir/deferral.d.ts +99 -0
- package/dist/ir/deferral.js +409 -0
- package/dist/ir/dense-loops.d.ts +230 -0
- package/dist/ir/dense-loops.js +697 -0
- package/dist/ir/dominance.d.ts +82 -0
- package/dist/ir/dominance.js +268 -0
- package/dist/ir/emission-representations.d.ts +71 -0
- package/dist/ir/emission-representations.js +350 -0
- package/dist/ir/facts.d.ts +218 -0
- package/dist/ir/facts.js +181 -0
- package/dist/ir/fixed-data-definition.d.ts +19 -0
- package/dist/ir/fixed-data-definition.js +49 -0
- package/dist/ir/generator-split.d.ts +38 -0
- package/dist/ir/generator-split.js +329 -0
- package/dist/ir/hoist.d.ts +55 -0
- package/dist/ir/hoist.js +375 -0
- package/dist/ir/instantiation.d.ts +61 -0
- package/dist/ir/instantiation.js +137 -0
- package/dist/ir/integer-storage.d.ts +170 -0
- package/dist/ir/integer-storage.js +822 -0
- package/dist/ir/integers.d.ts +161 -0
- package/dist/ir/integers.js +539 -0
- package/dist/ir/integrity-restrictions.d.ts +50 -0
- package/dist/ir/integrity-restrictions.js +118 -0
- package/dist/ir/local-iterators.d.ts +4 -0
- package/dist/ir/local-iterators.js +27 -0
- package/dist/ir/lower-allocation.d.ts +4 -0
- package/dist/ir/lower-allocation.js +325 -0
- package/dist/ir/lower-completion.d.ts +15 -0
- package/dist/ir/lower-completion.js +25 -0
- package/dist/ir/lower-destructuring.d.ts +5 -0
- package/dist/ir/lower-destructuring.js +693 -0
- package/dist/ir/lower-element.d.ts +29 -0
- package/dist/ir/lower-element.js +111 -0
- package/dist/ir/lower-exceptions.d.ts +47 -0
- package/dist/ir/lower-exceptions.js +92 -0
- package/dist/ir/lower-flow.d.ts +137 -0
- package/dist/ir/lower-flow.js +600 -0
- package/dist/ir/lower-graph.d.ts +218 -0
- package/dist/ir/lower-graph.js +687 -0
- package/dist/ir/lower-invocation.d.ts +4 -0
- package/dist/ir/lower-invocation.js +514 -0
- package/dist/ir/lower-narrow.d.ts +53 -0
- package/dist/ir/lower-narrow.js +320 -0
- package/dist/ir/lower-operands.d.ts +272 -0
- package/dist/ir/lower-operands.js +461 -0
- package/dist/ir/lower-property.d.ts +21 -0
- package/dist/ir/lower-property.js +132 -0
- package/dist/ir/lower-protocol.d.ts +11 -0
- package/dist/ir/lower-protocol.js +118 -0
- package/dist/ir/lower-short-circuit.d.ts +41 -0
- package/dist/ir/lower-short-circuit.js +63 -0
- package/dist/ir/lower.d.ts +82 -0
- package/dist/ir/lower.js +1346 -0
- package/dist/ir/model.d.ts +1474 -0
- package/dist/ir/model.js +6 -0
- package/dist/ir/native-absent-property.d.ts +3 -0
- package/dist/ir/native-absent-property.js +13 -0
- package/dist/ir/native-array-transport.d.ts +7 -0
- package/dist/ir/native-array-transport.js +46 -0
- package/dist/ir/native-callable-bind.d.ts +9 -0
- package/dist/ir/native-callable-bind.js +30 -0
- package/dist/ir/native-carrier-predicate.d.ts +34 -0
- package/dist/ir/native-carrier-predicate.js +49 -0
- package/dist/ir/native-class-accessor.d.ts +18 -0
- package/dist/ir/native-class-accessor.js +52 -0
- package/dist/ir/native-class-construction.d.ts +16 -0
- package/dist/ir/native-class-construction.js +71 -0
- package/dist/ir/native-class-initialization.d.ts +15 -0
- package/dist/ir/native-class-initialization.js +56 -0
- package/dist/ir/native-class-origins.d.ts +13 -0
- package/dist/ir/native-class-origins.js +237 -0
- package/dist/ir/native-dictionary-transport.d.ts +6 -0
- package/dist/ir/native-dictionary-transport.js +37 -0
- package/dist/ir/native-enumeration.d.ts +14 -0
- package/dist/ir/native-enumeration.js +26 -0
- package/dist/ir/native-equality.d.ts +10 -0
- package/dist/ir/native-equality.js +18 -0
- package/dist/ir/native-field-owner.d.ts +37 -0
- package/dist/ir/native-field-owner.js +183 -0
- package/dist/ir/native-fixed-layout.d.ts +41 -0
- package/dist/ir/native-fixed-layout.js +232 -0
- package/dist/ir/native-host-construction.d.ts +53 -0
- package/dist/ir/native-host-construction.js +62 -0
- package/dist/ir/native-key-query.d.ts +4 -0
- package/dist/ir/native-key-query.js +38 -0
- package/dist/ir/native-merge-transport.d.ts +25 -0
- package/dist/ir/native-merge-transport.js +71 -0
- package/dist/ir/native-record-index-transport.d.ts +11 -0
- package/dist/ir/native-record-index-transport.js +34 -0
- package/dist/ir/native-record-index.d.ts +12 -0
- package/dist/ir/native-record-index.js +27 -0
- package/dist/ir/native-reflect-field.d.ts +5 -0
- package/dist/ir/native-reflect-field.js +33 -0
- package/dist/ir/native-sequence-transport.d.ts +7 -0
- package/dist/ir/native-sequence-transport.js +53 -0
- package/dist/ir/numeric-intrinsics.d.ts +13 -0
- package/dist/ir/numeric-intrinsics.js +57 -0
- package/dist/ir/object-value-conversions.d.ts +20 -0
- package/dist/ir/object-value-conversions.js +50 -0
- package/dist/ir/physical-class-reflection.d.ts +9 -0
- package/dist/ir/physical-class-reflection.js +57 -0
- package/dist/ir/presence-proof.d.ts +42 -0
- package/dist/ir/presence-proof.js +490 -0
- package/dist/ir/program-facts.d.ts +106 -0
- package/dist/ir/program-facts.js +319 -0
- package/dist/ir/proven-branches.d.ts +16 -0
- package/dist/ir/proven-branches.js +219 -0
- package/dist/ir/queries.d.ts +41 -0
- package/dist/ir/queries.js +213 -0
- package/dist/ir/reflection-demand.d.ts +64 -0
- package/dist/ir/reflection-demand.js +1394 -0
- package/dist/ir/refusal.d.ts +43 -0
- package/dist/ir/refusal.js +28 -0
- package/dist/ir/shake.d.ts +37 -0
- package/dist/ir/shake.js +1078 -0
- package/dist/ir/static-callables.d.ts +11 -0
- package/dist/ir/static-callables.js +163 -0
- package/dist/ir/string-layout-reuse.d.ts +13 -0
- package/dist/ir/string-layout-reuse.js +39 -0
- package/dist/ir/string-length-reuse.d.ts +8 -0
- package/dist/ir/string-length-reuse.js +47 -0
- package/dist/ir/transfer.d.ts +78 -0
- package/dist/ir/transfer.js +270 -0
- package/dist/ir/type-query-results.d.ts +25 -0
- package/dist/ir/type-query-results.js +96 -0
- package/dist/ir/typed-property-access.d.ts +100 -0
- package/dist/ir/typed-property-access.js +161 -0
- package/dist/ir/verify.d.ts +19 -0
- package/dist/ir/verify.js +355 -0
- package/dist/plugins/apple/constructors.d.ts +112 -0
- package/dist/plugins/apple/constructors.js +217 -0
- package/dist/plugins/apple/host.d.ts +181 -0
- package/dist/plugins/apple/host.js +262 -0
- package/dist/plugins/apple/jsx.d.ts +2 -0
- package/dist/plugins/apple/jsx.js +293 -0
- package/dist/plugins/apple/members.d.ts +16 -0
- package/dist/plugins/apple/members.js +190 -0
- package/dist/plugins/apple/plugin.d.ts +2 -0
- package/dist/plugins/apple/plugin.js +156 -0
- package/dist/plugins/gea/component-classes.d.ts +25 -0
- package/dist/plugins/gea/component-classes.js +162 -0
- package/dist/plugins/gea/component-inline.d.ts +13 -0
- package/dist/plugins/gea/component-inline.js +532 -0
- package/dist/plugins/gea/constructors.d.ts +23 -0
- package/dist/plugins/gea/constructors.js +100 -0
- package/dist/plugins/gea/contract.d.ts +150 -0
- package/dist/plugins/gea/contract.js +195 -0
- package/dist/plugins/gea/element-ref.d.ts +31 -0
- package/dist/plugins/gea/element-ref.js +45 -0
- package/dist/plugins/gea/host.d.ts +520 -0
- package/dist/plugins/gea/host.js +762 -0
- package/dist/plugins/gea/lower.d.ts +6 -0
- package/dist/plugins/gea/lower.js +195 -0
- package/dist/plugins/gea/members.d.ts +22 -0
- package/dist/plugins/gea/members.js +221 -0
- package/dist/plugins/gea/plugin.d.ts +22 -0
- package/dist/plugins/gea/plugin.js +307 -0
- package/dist/plugins/gea/prelude.d.ts +78 -0
- package/dist/plugins/gea/prelude.js +153 -0
- package/dist/plugins/gea/producer.d.ts +5 -0
- package/dist/plugins/gea/producer.js +52 -0
- package/dist/plugins/gea/reactive-slots.d.ts +49 -0
- package/dist/plugins/gea/reactive-slots.js +578 -0
- package/dist/plugins/gea/render-bridge.d.ts +6 -0
- package/dist/plugins/gea/render-bridge.js +281 -0
- package/dist/plugins/gea/slots.d.ts +15 -0
- package/dist/plugins/gea/slots.js +36 -0
- package/dist/plugins/gea/template-analysis.d.ts +151 -0
- package/dist/plugins/gea/template-analysis.js +346 -0
- package/dist/plugins/gea/user-agent-styles.d.ts +9 -0
- package/dist/plugins/gea/user-agent-styles.js +94 -0
- package/dist/plugins/installed.d.ts +19 -0
- package/dist/plugins/installed.js +21 -0
- package/dist/plugins/load.d.ts +7 -0
- package/dist/plugins/load.js +207 -0
- package/dist/plugins/model.d.ts +735 -0
- package/dist/plugins/model.js +47 -0
- package/dist/plugins/webgl/host.d.ts +77 -0
- package/dist/plugins/webgl/host.js +162 -0
- package/dist/plugins/webgl/plugin.d.ts +40 -0
- package/dist/plugins/webgl/plugin.js +99 -0
- package/dist/preflight/obligations.d.ts +206 -0
- package/dist/preflight/obligations.js +36 -0
- package/dist/preflight/report.d.ts +20 -0
- package/dist/preflight/report.js +61 -0
- package/dist/preflight/run.d.ts +39 -0
- package/dist/preflight/run.js +403 -0
- package/dist/project-preparation.d.ts +33 -0
- package/dist/project-preparation.js +314 -0
- package/dist/projection/abi.d.ts +82 -0
- package/dist/projection/abi.js +349 -0
- package/dist/projection/apply-arguments.d.ts +12 -0
- package/dist/projection/apply-arguments.js +20 -0
- package/dist/projection/bindings.d.ts +250 -0
- package/dist/projection/bindings.js +340 -0
- package/dist/projection/callee.d.ts +196 -0
- package/dist/projection/callee.js +444 -0
- package/dist/projection/class-property-presence.d.ts +28 -0
- package/dist/projection/class-property-presence.js +58 -0
- package/dist/projection/class-prototype.d.ts +5 -0
- package/dist/projection/class-prototype.js +23 -0
- package/dist/projection/class-storage.d.ts +26 -0
- package/dist/projection/class-storage.js +236 -0
- package/dist/projection/classes.d.ts +283 -0
- package/dist/projection/classes.js +944 -0
- package/dist/projection/coercions.d.ts +20 -0
- package/dist/projection/coercions.js +33 -0
- package/dist/projection/dispatch.d.ts +167 -0
- package/dist/projection/dispatch.js +379 -0
- package/dist/projection/fields.d.ts +123 -0
- package/dist/projection/fields.js +383 -0
- package/dist/projection/instance-test.d.ts +78 -0
- package/dist/projection/instance-test.js +156 -0
- package/dist/projection/slots.d.ts +146 -0
- package/dist/projection/slots.js +663 -0
- package/dist/projection/synthesized-abi.d.ts +61 -0
- package/dist/projection/synthesized-abi.js +94 -0
- package/dist/representation/array-index.d.ts +14 -0
- package/dist/representation/array-index.js +17 -0
- package/dist/representation/callable-object.d.ts +3 -0
- package/dist/representation/callable-object.js +6 -0
- package/dist/representation/collections.d.ts +84 -0
- package/dist/representation/collections.js +139 -0
- package/dist/representation/derive.d.ts +159 -0
- package/dist/representation/derive.js +2546 -0
- package/dist/representation/difference.d.ts +30 -0
- package/dist/representation/difference.js +240 -0
- package/dist/representation/field-descriptor-policy.d.ts +19 -0
- package/dist/representation/field-descriptor-policy.js +39 -0
- package/dist/representation/function-constructor.d.ts +13 -0
- package/dist/representation/function-constructor.js +9 -0
- package/dist/representation/host-abi.d.ts +32 -0
- package/dist/representation/host-abi.js +97 -0
- package/dist/representation/host-templates.d.ts +67 -0
- package/dist/representation/host-templates.js +94 -0
- package/dist/representation/intersection.d.ts +84 -0
- package/dist/representation/intersection.js +149 -0
- package/dist/representation/literal-destination.d.ts +43 -0
- package/dist/representation/literal-destination.js +133 -0
- package/dist/representation/merge.d.ts +18 -0
- package/dist/representation/merge.js +83 -0
- package/dist/representation/model.d.ts +1160 -0
- package/dist/representation/model.js +1019 -0
- package/dist/representation/numeric-index.d.ts +13 -0
- package/dist/representation/numeric-index.js +29 -0
- package/dist/representation/object-shape.d.ts +109 -0
- package/dist/representation/object-shape.js +123 -0
- package/dist/representation/optional.d.ts +12 -0
- package/dist/representation/optional.js +87 -0
- package/dist/representation/plan.d.ts +60 -0
- package/dist/representation/plan.js +78 -0
- package/dist/representation/policies.d.ts +589 -0
- package/dist/representation/policies.js +107 -0
- package/dist/representation/primitive-domain.d.ts +1 -0
- package/dist/representation/primitive-domain.js +1 -0
- package/dist/representation/primitives.d.ts +44 -0
- package/dist/representation/primitives.js +78 -0
- package/dist/representation/publish.d.ts +49 -0
- package/dist/representation/publish.js +648 -0
- package/dist/representation/record-fields.d.ts +96 -0
- package/dist/representation/record-fields.js +116 -0
- package/dist/representation/template-object.d.ts +11 -0
- package/dist/representation/template-object.js +26 -0
- package/dist/representation/union.d.ts +30 -0
- package/dist/representation/union.js +324 -0
- package/dist/representation/value-records.d.ts +3 -0
- package/dist/representation/value-records.js +307 -0
- package/dist/representation/verify.d.ts +17 -0
- package/dist/representation/verify.js +221 -0
- package/dist/semantics/alias-this-field-declaration-transform.d.ts +4 -0
- package/dist/semantics/alias-this-field-declaration-transform.js +207 -0
- package/dist/semantics/ambient-type-realization-transform.d.ts +62 -0
- package/dist/semantics/ambient-type-realization-transform.js +168 -0
- package/dist/semantics/ambient.d.ts +24 -0
- package/dist/semantics/ambient.js +119 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.d.ts +4 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.js +341 -0
- package/dist/semantics/callable-origins.d.ts +46 -0
- package/dist/semantics/callable-origins.js +354 -0
- package/dist/semantics/class-alias.d.ts +7 -0
- package/dist/semantics/class-alias.js +37 -0
- package/dist/semantics/class-heritage.d.ts +34 -0
- package/dist/semantics/class-heritage.js +104 -0
- package/dist/semantics/commonjs-wrapper.d.ts +69 -0
- package/dist/semantics/commonjs-wrapper.js +231 -0
- package/dist/semantics/constructor-slot-subclasses.d.ts +28 -0
- package/dist/semantics/constructor-slot-subclasses.js +112 -0
- package/dist/semantics/declaration-overlay-transform.d.ts +35 -0
- package/dist/semantics/declaration-overlay-transform.js +2157 -0
- package/dist/semantics/define-property-source-transform.d.ts +4 -0
- package/dist/semantics/define-property-source-transform.js +437 -0
- package/dist/semantics/diagnostic-source-preparation.d.ts +24 -0
- package/dist/semantics/diagnostic-source-preparation.js +82 -0
- package/dist/semantics/documentation-ranges.d.ts +22 -0
- package/dist/semantics/documentation-ranges.js +36 -0
- package/dist/semantics/dynamic-fallback.d.ts +86 -0
- package/dist/semantics/dynamic-fallback.js +249 -0
- package/dist/semantics/frontend-timing.d.ts +6 -0
- package/dist/semantics/frontend-timing.js +35 -0
- package/dist/semantics/frontend.d.ts +504 -0
- package/dist/semantics/frontend.js +1157 -0
- package/dist/semantics/host-declaration-provenance.d.ts +11 -0
- package/dist/semantics/host-declaration-provenance.js +18 -0
- package/dist/semantics/host-methods.d.ts +24 -0
- package/dist/semantics/host-methods.js +74 -0
- package/dist/semantics/host-protocols.d.ts +429 -0
- package/dist/semantics/host-protocols.js +1501 -0
- package/dist/semantics/inherited-accessor.d.ts +7 -0
- package/dist/semantics/inherited-accessor.js +48 -0
- package/dist/semantics/interface-families.d.ts +70 -0
- package/dist/semantics/interface-families.js +180 -0
- package/dist/semantics/interface-implementors.d.ts +53 -0
- package/dist/semantics/interface-implementors.js +87 -0
- package/dist/semantics/jsdoc-namepath-transform.d.ts +4 -0
- package/dist/semantics/jsdoc-namepath-transform.js +85 -0
- package/dist/semantics/model/coverage.d.ts +68 -0
- package/dist/semantics/model/coverage.js +73 -0
- package/dist/semantics/model/edges.d.ts +103 -0
- package/dist/semantics/model/edges.js +20 -0
- package/dist/semantics/model/graph.d.ts +55 -0
- package/dist/semantics/model/graph.js +129 -0
- package/dist/semantics/model/operands.d.ts +159 -0
- package/dist/semantics/model/operands.js +26 -0
- package/dist/semantics/model/operations.d.ts +496 -0
- package/dist/semantics/model/operations.js +2 -0
- package/dist/semantics/model/primitive-domain.d.ts +26 -0
- package/dist/semantics/model/primitive-domain.js +38 -0
- package/dist/semantics/model/selected-signature.d.ts +261 -0
- package/dist/semantics/model/selected-signature.js +55 -0
- package/dist/semantics/model/structural-type-table.d.ts +93 -0
- package/dist/semantics/model/structural-type-table.js +237 -0
- package/dist/semantics/model/structural-types.d.ts +367 -0
- package/dist/semantics/model/structural-types.js +200 -0
- package/dist/semantics/module-resolution.d.ts +23 -0
- package/dist/semantics/module-resolution.js +227 -0
- package/dist/semantics/new-callee-class-tag-source-transform.d.ts +4 -0
- package/dist/semantics/new-callee-class-tag-source-transform.js +64 -0
- package/dist/semantics/node-project.d.ts +13 -0
- package/dist/semantics/node-project.js +107 -0
- package/dist/semantics/node-source-hooks.d.ts +1 -0
- package/dist/semantics/node-source-hooks.js +63 -0
- package/dist/semantics/normalize/absent-globals.d.ts +143 -0
- package/dist/semantics/normalize/absent-globals.js +191 -0
- package/dist/semantics/normalize/arguments-objects.d.ts +43 -0
- package/dist/semantics/normalize/arguments-objects.js +60 -0
- package/dist/semantics/normalize/asserted-arm-absence.d.ts +28 -0
- package/dist/semantics/normalize/asserted-arm-absence.js +61 -0
- package/dist/semantics/normalize/assignment-patterns.d.ts +70 -0
- package/dist/semantics/normalize/assignment-patterns.js +147 -0
- package/dist/semantics/normalize/bag-absence.d.ts +8 -0
- package/dist/semantics/normalize/bag-absence.js +42 -0
- package/dist/semantics/normalize/binding-fixpoint.d.ts +36 -0
- package/dist/semantics/normalize/binding-fixpoint.js +140 -0
- package/dist/semantics/normalize/callback-parameter-contracts.d.ts +16 -0
- package/dist/semantics/normalize/callback-parameter-contracts.js +91 -0
- package/dist/semantics/normalize/cells/agreement.d.ts +46 -0
- package/dist/semantics/normalize/cells/agreement.js +34 -0
- package/dist/semantics/normalize/cells/candidates.d.ts +17 -0
- package/dist/semantics/normalize/cells/candidates.js +35 -0
- package/dist/semantics/normalize/cells/facts.d.ts +19 -0
- package/dist/semantics/normalize/cells/facts.js +90 -0
- package/dist/semantics/normalize/cells/index.d.ts +10 -0
- package/dist/semantics/normalize/cells/index.js +6 -0
- package/dist/semantics/normalize/cells/model.d.ts +98 -0
- package/dist/semantics/normalize/cells/model.js +2 -0
- package/dist/semantics/normalize/cells/policies/bag.d.ts +44 -0
- package/dist/semantics/normalize/cells/policies/bag.js +114 -0
- package/dist/semantics/normalize/cells/policies/collection.d.ts +42 -0
- package/dist/semantics/normalize/cells/policies/collection.js +218 -0
- package/dist/semantics/normalize/cells/policies/field.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/field.js +40 -0
- package/dist/semantics/normalize/cells/policies/index.d.ts +49 -0
- package/dist/semantics/normalize/cells/policies/index.js +58 -0
- package/dist/semantics/normalize/cells/policies/local.d.ts +18 -0
- package/dist/semantics/normalize/cells/policies/local.js +37 -0
- package/dist/semantics/normalize/cells/policies/parameter.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/parameter.js +39 -0
- package/dist/semantics/normalize/cells/policies/return.d.ts +26 -0
- package/dist/semantics/normalize/cells/policies/return.js +45 -0
- package/dist/semantics/normalize/cells/policies/shared.d.ts +33 -0
- package/dist/semantics/normalize/cells/policies/shared.js +45 -0
- package/dist/semantics/normalize/cells/policy.d.ts +72 -0
- package/dist/semantics/normalize/cells/policy.js +18 -0
- package/dist/semantics/normalize/cells/registry.d.ts +14 -0
- package/dist/semantics/normalize/cells/registry.js +17 -0
- package/dist/semantics/normalize/census-refusal.d.ts +62 -0
- package/dist/semantics/normalize/census-refusal.js +27 -0
- package/dist/semantics/normalize/census.d.ts +109 -0
- package/dist/semantics/normalize/census.js +667 -0
- package/dist/semantics/normalize/collection-bindings.d.ts +278 -0
- package/dist/semantics/normalize/collection-bindings.js +677 -0
- package/dist/semantics/normalize/commonjs-module-record.d.ts +21 -0
- package/dist/semantics/normalize/commonjs-module-record.js +289 -0
- package/dist/semantics/normalize/commonjs-require.d.ts +13 -0
- package/dist/semantics/normalize/commonjs-require.js +1527 -0
- package/dist/semantics/normalize/contribution.d.ts +63 -0
- package/dist/semantics/normalize/contribution.js +172 -0
- package/dist/semantics/normalize/dead-typeof-guards.d.ts +64 -0
- package/dist/semantics/normalize/dead-typeof-guards.js +152 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.d.ts +57 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.js +109 -0
- package/dist/semantics/normalize/derived-expression-type.d.ts +1070 -0
- package/dist/semantics/normalize/derived-expression-type.js +3463 -0
- package/dist/semantics/normalize/evaluation-order.d.ts +16 -0
- package/dist/semantics/normalize/evaluation-order.js +37 -0
- package/dist/semantics/normalize/field-bindings.d.ts +167 -0
- package/dist/semantics/normalize/field-bindings.js +1125 -0
- package/dist/semantics/normalize/flow/array-element-continuation.d.ts +27 -0
- package/dist/semantics/normalize/flow/array-element-continuation.js +1452 -0
- package/dist/semantics/normalize/flow/callable-array-origins.d.ts +42 -0
- package/dist/semantics/normalize/flow/callable-array-origins.js +318 -0
- package/dist/semantics/normalize/flow/callable-completions.d.ts +45 -0
- package/dist/semantics/normalize/flow/callable-completions.js +82 -0
- package/dist/semantics/normalize/flow/callable-reach.d.ts +237 -0
- package/dist/semantics/normalize/flow/callable-reach.js +7174 -0
- package/dist/semantics/normalize/flow/class-family-member-read.d.ts +16 -0
- package/dist/semantics/normalize/flow/class-family-member-read.js +992 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.d.ts +21 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.js +192 -0
- package/dist/semantics/normalize/flow/component-solver.d.ts +199 -0
- package/dist/semantics/normalize/flow/component-solver.js +587 -0
- package/dist/semantics/normalize/flow/computed-key-set.d.ts +84 -0
- package/dist/semantics/normalize/flow/computed-key-set.js +660 -0
- package/dist/semantics/normalize/flow/export-importers.d.ts +24 -0
- package/dist/semantics/normalize/flow/export-importers.js +269 -0
- package/dist/semantics/normalize/flow/host-text-sink.d.ts +25 -0
- package/dist/semantics/normalize/flow/host-text-sink.js +87 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.d.ts +84 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.js +180 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.d.ts +35 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.js +140 -0
- package/dist/semantics/normalize/flow/invocation-facts.d.ts +98 -0
- package/dist/semantics/normalize/flow/invocation-facts.js +257 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.d.ts +122 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.js +835 -0
- package/dist/semantics/normalize/flow/model.d.ts +357 -0
- package/dist/semantics/normalize/flow/model.js +177 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.d.ts +24 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.js +252 -0
- package/dist/semantics/normalize/flow/node-path-token.d.ts +3 -0
- package/dist/semantics/normalize/flow/node-path-token.js +53 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.d.ts +11 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.js +42 -0
- package/dist/semantics/normalize/flow/origin-authority.d.ts +56 -0
- package/dist/semantics/normalize/flow/origin-authority.js +2 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.d.ts +35 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.js +191 -0
- package/dist/semantics/normalize/flow/parameter-values.d.ts +27 -0
- package/dist/semantics/normalize/flow/parameter-values.js +251 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.d.ts +66 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.js +162 -0
- package/dist/semantics/normalize/flow/record-alias-closure.d.ts +27 -0
- package/dist/semantics/normalize/flow/record-alias-closure.js +298 -0
- package/dist/semantics/normalize/flow/seeded-origins.d.ts +43 -0
- package/dist/semantics/normalize/flow/seeded-origins.js +54 -0
- package/dist/semantics/normalize/flow/source-class-data.d.ts +132 -0
- package/dist/semantics/normalize/flow/source-class-data.js +838 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.d.ts +13 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.js +37 -0
- package/dist/semantics/normalize/flow/source-class-static-data.d.ts +16 -0
- package/dist/semantics/normalize/flow/source-class-static-data.js +47 -0
- package/dist/semantics/normalize/flow/source-construction-frames.d.ts +12 -0
- package/dist/semantics/normalize/flow/source-construction-frames.js +118 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.d.ts +34 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.js +78 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.d.ts +37 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.js +95 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.d.ts +23 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.js +81 -0
- package/dist/semantics/normalize/flow/source-record-data.d.ts +29 -0
- package/dist/semantics/normalize/flow/source-record-data.js +626 -0
- package/dist/semantics/normalize/flow/source-value-session.d.ts +77 -0
- package/dist/semantics/normalize/flow/source-value-session.js +3089 -0
- package/dist/semantics/normalize/flow/targets.d.ts +118 -0
- package/dist/semantics/normalize/flow/targets.js +405 -0
- package/dist/semantics/normalize/flow/value-flow.d.ts +36 -0
- package/dist/semantics/normalize/flow/value-flow.js +823 -0
- package/dist/semantics/normalize/flow/value-provenance.d.ts +31 -0
- package/dist/semantics/normalize/flow/value-provenance.js +112 -0
- package/dist/semantics/normalize/gating.d.ts +51 -0
- package/dist/semantics/normalize/gating.js +560 -0
- package/dist/semantics/normalize/generic-function-choice.d.ts +31 -0
- package/dist/semantics/normalize/generic-function-choice.js +115 -0
- package/dist/semantics/normalize/global-host-mutations.d.ts +51 -0
- package/dist/semantics/normalize/global-host-mutations.js +5989 -0
- package/dist/semantics/normalize/host-effect-contracts.d.ts +77 -0
- package/dist/semantics/normalize/host-effect-contracts.js +143 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.d.ts +38 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.js +26 -0
- package/dist/semantics/normalize/host-mutation-key-reader.d.ts +66 -0
- package/dist/semantics/normalize/host-mutation-key-reader.js +192 -0
- package/dist/semantics/normalize/host-mutation-keys.d.ts +114 -0
- package/dist/semantics/normalize/host-mutation-keys.js +183 -0
- package/dist/semantics/normalize/identities.d.ts +172 -0
- package/dist/semantics/normalize/identities.js +426 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.d.ts +97 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.js +197 -0
- package/dist/semantics/normalize/implicit-arguments.d.ts +11 -0
- package/dist/semantics/normalize/implicit-arguments.js +39 -0
- package/dist/semantics/normalize/instantiation.d.ts +73 -0
- package/dist/semantics/normalize/instantiation.js +399 -0
- package/dist/semantics/normalize/intrinsic-property-call.d.ts +18 -0
- package/dist/semantics/normalize/intrinsic-property-call.js +69 -0
- package/dist/semantics/normalize/intrinsic-prototype.d.ts +41 -0
- package/dist/semantics/normalize/intrinsic-prototype.js +87 -0
- package/dist/semantics/normalize/intrinsic-static-member.d.ts +14 -0
- package/dist/semantics/normalize/intrinsic-static-member.js +23 -0
- package/dist/semantics/normalize/jsdoc-type-names.d.ts +32 -0
- package/dist/semantics/normalize/jsdoc-type-names.js +512 -0
- package/dist/semantics/normalize/keyof.d.ts +32 -0
- package/dist/semantics/normalize/keyof.js +110 -0
- package/dist/semantics/normalize/local-bindings.d.ts +176 -0
- package/dist/semantics/normalize/local-bindings.js +1826 -0
- package/dist/semantics/normalize/logical-result-type.d.ts +16 -0
- package/dist/semantics/normalize/logical-result-type.js +102 -0
- package/dist/semantics/normalize/namespace-paths.d.ts +57 -0
- package/dist/semantics/normalize/namespace-paths.js +108 -0
- package/dist/semantics/normalize/normalize.d.ts +57 -0
- package/dist/semantics/normalize/normalize.js +68 -0
- package/dist/semantics/normalize/object-bag-bindings.d.ts +305 -0
- package/dist/semantics/normalize/object-bag-bindings.js +1290 -0
- package/dist/semantics/normalize/omitted-stated-parameter.d.ts +53 -0
- package/dist/semantics/normalize/omitted-stated-parameter.js +59 -0
- package/dist/semantics/normalize/open-type-form.d.ts +10 -0
- package/dist/semantics/normalize/open-type-form.js +32 -0
- package/dist/semantics/normalize/parameter-bindings.d.ts +361 -0
- package/dist/semantics/normalize/parameter-bindings.js +3339 -0
- package/dist/semantics/normalize/parameter-slot.d.ts +264 -0
- package/dist/semantics/normalize/parameter-slot.js +491 -0
- package/dist/semantics/normalize/physical-overload-result.d.ts +77 -0
- package/dist/semantics/normalize/physical-overload-result.js +99 -0
- package/dist/semantics/normalize/primitive-property-absence.d.ts +12 -0
- package/dist/semantics/normalize/primitive-property-absence.js +60 -0
- package/dist/semantics/normalize/producer-context.d.ts +376 -0
- package/dist/semantics/normalize/producer-context.js +1 -0
- package/dist/semantics/normalize/producers/allocations.d.ts +3 -0
- package/dist/semantics/normalize/producers/allocations.js +863 -0
- package/dist/semantics/normalize/producers/binding-kind.d.ts +37 -0
- package/dist/semantics/normalize/producers/binding-kind.js +36 -0
- package/dist/semantics/normalize/producers/bindings.d.ts +85 -0
- package/dist/semantics/normalize/producers/bindings.js +710 -0
- package/dist/semantics/normalize/producers/boundary.d.ts +34 -0
- package/dist/semantics/normalize/producers/boundary.js +123 -0
- package/dist/semantics/normalize/producers/class-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/class-lifecycle.js +902 -0
- package/dist/semantics/normalize/producers/computations.d.ts +3 -0
- package/dist/semantics/normalize/producers/computations.js +613 -0
- package/dist/semantics/normalize/producers/control-loops.d.ts +30 -0
- package/dist/semantics/normalize/producers/control-loops.js +91 -0
- package/dist/semantics/normalize/producers/control.d.ts +30 -0
- package/dist/semantics/normalize/producers/control.js +923 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.js +390 -0
- package/dist/semantics/normalize/producers/destructuring.d.ts +45 -0
- package/dist/semantics/normalize/producers/destructuring.js +1180 -0
- package/dist/semantics/normalize/producers/dynamic-language.d.ts +3 -0
- package/dist/semantics/normalize/producers/dynamic-language.js +70 -0
- package/dist/semantics/normalize/producers/erasure.d.ts +51 -0
- package/dist/semantics/normalize/producers/erasure.js +90 -0
- package/dist/semantics/normalize/producers/installed.d.ts +3 -0
- package/dist/semantics/normalize/producers/installed.js +55 -0
- package/dist/semantics/normalize/producers/invocations.d.ts +35 -0
- package/dist/semantics/normalize/producers/invocations.js +1796 -0
- package/dist/semantics/normalize/producers/iteration-yield.d.ts +59 -0
- package/dist/semantics/normalize/producers/iteration-yield.js +235 -0
- package/dist/semantics/normalize/producers/jsx.d.ts +3 -0
- package/dist/semantics/normalize/producers/jsx.js +360 -0
- package/dist/semantics/normalize/producers/mint.d.ts +39 -0
- package/dist/semantics/normalize/producers/mint.js +44 -0
- package/dist/semantics/normalize/producers/nullish.d.ts +16 -0
- package/dist/semantics/normalize/producers/nullish.js +27 -0
- package/dist/semantics/normalize/producers/object-assignment.d.ts +8 -0
- package/dist/semantics/normalize/producers/object-assignment.js +204 -0
- package/dist/semantics/normalize/producers/object-tag.d.ts +9 -0
- package/dist/semantics/normalize/producers/object-tag.js +119 -0
- package/dist/semantics/normalize/producers/optional-chain.d.ts +44 -0
- package/dist/semantics/normalize/producers/optional-chain.js +75 -0
- package/dist/semantics/normalize/producers/properties.d.ts +21 -0
- package/dist/semantics/normalize/producers/properties.js +1053 -0
- package/dist/semantics/normalize/producers/protocol.d.ts +67 -0
- package/dist/semantics/normalize/producers/protocol.js +695 -0
- package/dist/semantics/normalize/producers/references.d.ts +53 -0
- package/dist/semantics/normalize/producers/references.js +1027 -0
- package/dist/semantics/normalize/producers/shared.d.ts +561 -0
- package/dist/semantics/normalize/producers/shared.js +1683 -0
- package/dist/semantics/normalize/producers/spread-arguments.d.ts +72 -0
- package/dist/semantics/normalize/producers/spread-arguments.js +375 -0
- package/dist/semantics/normalize/producers/tagged-template.d.ts +5 -0
- package/dist/semantics/normalize/producers/tagged-template.js +307 -0
- package/dist/semantics/normalize/producers/tuple-spread.d.ts +189 -0
- package/dist/semantics/normalize/producers/tuple-spread.js +279 -0
- package/dist/semantics/normalize/property-key-domain.d.ts +36 -0
- package/dist/semantics/normalize/property-key-domain.js +150 -0
- package/dist/semantics/normalize/reachability.d.ts +189 -0
- package/dist/semantics/normalize/reachability.js +1057 -0
- package/dist/semantics/normalize/reassigned-bindings.d.ts +13 -0
- package/dist/semantics/normalize/reassigned-bindings.js +41 -0
- package/dist/semantics/normalize/record-storage-families.d.ts +11 -0
- package/dist/semantics/normalize/record-storage-families.js +109 -0
- package/dist/semantics/normalize/return-bindings.d.ts +260 -0
- package/dist/semantics/normalize/return-bindings.js +1311 -0
- package/dist/semantics/normalize/return-paths.d.ts +2 -0
- package/dist/semantics/normalize/return-paths.js +28 -0
- package/dist/semantics/normalize/script-global-redefinition.d.ts +44 -0
- package/dist/semantics/normalize/script-global-redefinition.js +75 -0
- package/dist/semantics/normalize/specialization.d.ts +201 -0
- package/dist/semantics/normalize/specialization.js +1824 -0
- package/dist/semantics/normalize/structural-array-element.d.ts +176 -0
- package/dist/semantics/normalize/structural-array-element.js +700 -0
- package/dist/semantics/normalize/structural-array-read.d.ts +13 -0
- package/dist/semantics/normalize/structural-array-read.js +124 -0
- package/dist/semantics/normalize/structural-callable.d.ts +12 -0
- package/dist/semantics/normalize/structural-callable.js +82 -0
- package/dist/semantics/normalize/structural-creation-order.d.ts +32 -0
- package/dist/semantics/normalize/structural-creation-order.js +111 -0
- package/dist/semantics/normalize/structural-declarations.d.ts +395 -0
- package/dist/semantics/normalize/structural-declarations.js +968 -0
- package/dist/semantics/normalize/structural-declared-body.d.ts +25 -0
- package/dist/semantics/normalize/structural-declared-body.js +147 -0
- package/dist/semantics/normalize/structural-generics.d.ts +56 -0
- package/dist/semantics/normalize/structural-generics.js +120 -0
- package/dist/semantics/normalize/structural-indexed-access.d.ts +11 -0
- package/dist/semantics/normalize/structural-indexed-access.js +126 -0
- package/dist/semantics/normalize/structural-instantiated-member.d.ts +64 -0
- package/dist/semantics/normalize/structural-instantiated-member.js +407 -0
- package/dist/semantics/normalize/structural-joins.d.ts +44 -0
- package/dist/semantics/normalize/structural-joins.js +143 -0
- package/dist/semantics/normalize/structural-layout-relevance.d.ts +29 -0
- package/dist/semantics/normalize/structural-layout-relevance.js +391 -0
- package/dist/semantics/normalize/structural-layout-type.d.ts +11 -0
- package/dist/semantics/normalize/structural-layout-type.js +1468 -0
- package/dist/semantics/normalize/structural-leaves.d.ts +49 -0
- package/dist/semantics/normalize/structural-leaves.js +125 -0
- package/dist/semantics/normalize/structural-local-union.d.ts +13 -0
- package/dist/semantics/normalize/structural-local-union.js +133 -0
- package/dist/semantics/normalize/structural-members.d.ts +26 -0
- package/dist/semantics/normalize/structural-members.js +84 -0
- package/dist/semantics/normalize/structural-mutable-method.d.ts +15 -0
- package/dist/semantics/normalize/structural-mutable-method.js +109 -0
- package/dist/semantics/normalize/structural-parts.d.ts +131 -0
- package/dist/semantics/normalize/structural-parts.js +737 -0
- package/dist/semantics/normalize/structural-receiver.d.ts +66 -0
- package/dist/semantics/normalize/structural-receiver.js +551 -0
- package/dist/semantics/normalize/structural-rules.d.ts +112 -0
- package/dist/semantics/normalize/structural-rules.js +93 -0
- package/dist/semantics/normalize/structural-self-reference.d.ts +150 -0
- package/dist/semantics/normalize/structural-self-reference.js +494 -0
- package/dist/semantics/normalize/structural.d.ts +202 -0
- package/dist/semantics/normalize/structural.js +4218 -0
- package/dist/semantics/normalize/unreduced-type-form.d.ts +41 -0
- package/dist/semantics/normalize/unreduced-type-form.js +53 -0
- package/dist/semantics/normalize/unresolvable-names.d.ts +56 -0
- package/dist/semantics/normalize/unresolvable-names.js +140 -0
- package/dist/semantics/package-sources.d.ts +16 -0
- package/dist/semantics/package-sources.js +365 -0
- package/dist/semantics/program.d.ts +151 -0
- package/dist/semantics/program.js +667 -0
- package/dist/semantics/prototype-install-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-install-source-transform.js +341 -0
- package/dist/semantics/prototype-object-class-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-object-class-source-transform.js +525 -0
- package/dist/semantics/prototype-reparenting.d.ts +50 -0
- package/dist/semantics/prototype-reparenting.js +317 -0
- package/dist/semantics/stable-checker.d.ts +10 -0
- package/dist/semantics/stable-checker.js +148 -0
- package/dist/semantics/subclass-member-overlay-transform.d.ts +35 -0
- package/dist/semantics/subclass-member-overlay-transform.js +1418 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.d.ts +4 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.js +66 -0
- package/dist/semantics/this-constructor-source-transform.d.ts +4 -0
- package/dist/semantics/this-constructor-source-transform.js +122 -0
- package/dist/semantics/uninstantiable-classes.d.ts +22 -0
- package/dist/semantics/uninstantiable-classes.js +75 -0
- package/dist/targets/cpp/balanced-units.d.ts +3 -0
- package/dist/targets/cpp/balanced-units.js +58 -0
- package/dist/targets/cpp/borrowed-call-entry.d.ts +30 -0
- package/dist/targets/cpp/borrowed-call-entry.js +68 -0
- package/dist/targets/cpp/captures.d.ts +68 -0
- package/dist/targets/cpp/captures.js +269 -0
- package/dist/targets/cpp/class-layout.d.ts +313 -0
- package/dist/targets/cpp/class-layout.js +483 -0
- package/dist/targets/cpp/class-properties/computed-method-value.d.ts +25 -0
- package/dist/targets/cpp/class-properties/computed-method-value.js +22 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.d.ts +216 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.js +917 -0
- package/dist/targets/cpp/class-properties/native-prototype.d.ts +11 -0
- package/dist/targets/cpp/class-properties/native-prototype.js +101 -0
- package/dist/targets/cpp/class-ref-transport.d.ts +12 -0
- package/dist/targets/cpp/class-ref-transport.js +32 -0
- package/dist/targets/cpp/conversions.d.ts +3 -0
- package/dist/targets/cpp/conversions.js +2027 -0
- package/dist/targets/cpp/deferral-safety.d.ts +82 -0
- package/dist/targets/cpp/deferral-safety.js +86 -0
- package/dist/targets/cpp/direct-call-receivers.d.ts +37 -0
- package/dist/targets/cpp/direct-call-receivers.js +79 -0
- package/dist/targets/cpp/document.d.ts +74 -0
- package/dist/targets/cpp/document.js +106 -0
- package/dist/targets/cpp/emit-allocation.d.ts +60 -0
- package/dist/targets/cpp/emit-allocation.js +573 -0
- package/dist/targets/cpp/emit-arrays.d.ts +119 -0
- package/dist/targets/cpp/emit-arrays.js +1047 -0
- package/dist/targets/cpp/emit-binding-reference.d.ts +17 -0
- package/dist/targets/cpp/emit-binding-reference.js +120 -0
- package/dist/targets/cpp/emit-bindings.d.ts +158 -0
- package/dist/targets/cpp/emit-bindings.js +769 -0
- package/dist/targets/cpp/emit-buffers.d.ts +156 -0
- package/dist/targets/cpp/emit-buffers.js +573 -0
- package/dist/targets/cpp/emit-callable.d.ts +230 -0
- package/dist/targets/cpp/emit-callable.js +2154 -0
- package/dist/targets/cpp/emit-carrier-members.d.ts +406 -0
- package/dist/targets/cpp/emit-carrier-members.js +1224 -0
- package/dist/targets/cpp/emit-coercion.d.ts +26 -0
- package/dist/targets/cpp/emit-coercion.js +39 -0
- package/dist/targets/cpp/emit-context.d.ts +1882 -0
- package/dist/targets/cpp/emit-context.js +904 -0
- package/dist/targets/cpp/emit-dynamic-properties.d.ts +174 -0
- package/dist/targets/cpp/emit-dynamic-properties.js +1249 -0
- package/dist/targets/cpp/emit-equality.d.ts +39 -0
- package/dist/targets/cpp/emit-equality.js +472 -0
- package/dist/targets/cpp/emit-exceptions.d.ts +104 -0
- package/dist/targets/cpp/emit-exceptions.js +513 -0
- package/dist/targets/cpp/emit-field-owner.d.ts +4 -0
- package/dist/targets/cpp/emit-field-owner.js +27 -0
- package/dist/targets/cpp/emit-in.d.ts +31 -0
- package/dist/targets/cpp/emit-in.js +426 -0
- package/dist/targets/cpp/emit-instanceof.d.ts +19 -0
- package/dist/targets/cpp/emit-instanceof.js +601 -0
- package/dist/targets/cpp/emit-integers.d.ts +68 -0
- package/dist/targets/cpp/emit-integers.js +184 -0
- package/dist/targets/cpp/emit-iterator.d.ts +100 -0
- package/dist/targets/cpp/emit-iterator.js +1137 -0
- package/dist/targets/cpp/emit-json.d.ts +73 -0
- package/dist/targets/cpp/emit-json.js +823 -0
- package/dist/targets/cpp/emit-jsx.d.ts +74 -0
- package/dist/targets/cpp/emit-jsx.js +806 -0
- package/dist/targets/cpp/emit-mixed-binary.d.ts +51 -0
- package/dist/targets/cpp/emit-mixed-binary.js +60 -0
- package/dist/targets/cpp/emit-namespaces.d.ts +101 -0
- package/dist/targets/cpp/emit-namespaces.js +133 -0
- package/dist/targets/cpp/emit-narrowing.d.ts +738 -0
- package/dist/targets/cpp/emit-narrowing.js +3967 -0
- package/dist/targets/cpp/emit-native-equality.d.ts +3 -0
- package/dist/targets/cpp/emit-native-equality.js +14 -0
- package/dist/targets/cpp/emit-native-selection.d.ts +5 -0
- package/dist/targets/cpp/emit-native-selection.js +37 -0
- package/dist/targets/cpp/emit-object-tag.d.ts +4 -0
- package/dist/targets/cpp/emit-object-tag.js +108 -0
- package/dist/targets/cpp/emit-owned-record.d.ts +2 -0
- package/dist/targets/cpp/emit-owned-record.js +15 -0
- package/dist/targets/cpp/emit-presence.d.ts +78 -0
- package/dist/targets/cpp/emit-presence.js +376 -0
- package/dist/targets/cpp/emit-properties.d.ts +105 -0
- package/dist/targets/cpp/emit-properties.js +1640 -0
- package/dist/targets/cpp/emit-record-view.d.ts +20 -0
- package/dist/targets/cpp/emit-record-view.js +354 -0
- package/dist/targets/cpp/emit-return.d.ts +5 -0
- package/dist/targets/cpp/emit-return.js +237 -0
- package/dist/targets/cpp/emit-sum-widening.d.ts +10 -0
- package/dist/targets/cpp/emit-sum-widening.js +69 -0
- package/dist/targets/cpp/emit-tonumber.d.ts +38 -0
- package/dist/targets/cpp/emit-tonumber.js +177 -0
- package/dist/targets/cpp/emit-tostring.d.ts +92 -0
- package/dist/targets/cpp/emit-tostring.js +556 -0
- package/dist/targets/cpp/emit-typeof.d.ts +49 -0
- package/dist/targets/cpp/emit-typeof.js +317 -0
- package/dist/targets/cpp/emit-union-properties.d.ts +181 -0
- package/dist/targets/cpp/emit-union-properties.js +1281 -0
- package/dist/targets/cpp/emit.d.ts +45 -0
- package/dist/targets/cpp/emit.js +2225 -0
- package/dist/targets/cpp/error-types.d.ts +4 -0
- package/dist/targets/cpp/error-types.js +11 -0
- package/dist/targets/cpp/function-source-reads.d.ts +72 -0
- package/dist/targets/cpp/function-source-reads.js +148 -0
- package/dist/targets/cpp/host/atomics.d.ts +25 -0
- package/dist/targets/cpp/host/atomics.js +63 -0
- package/dist/targets/cpp/host/core-globals.d.ts +108 -0
- package/dist/targets/cpp/host/core-globals.js +158 -0
- package/dist/targets/cpp/host/dynamic-argument-members.d.ts +42 -0
- package/dist/targets/cpp/host/dynamic-argument-members.js +61 -0
- package/dist/targets/cpp/host/emit-host-arity.d.ts +139 -0
- package/dist/targets/cpp/host/emit-host-arity.js +232 -0
- package/dist/targets/cpp/host/emit-host-invoke.d.ts +91 -0
- package/dist/targets/cpp/host/emit-host-invoke.js +1105 -0
- package/dist/targets/cpp/host/emit-host-object.d.ts +55 -0
- package/dist/targets/cpp/host/emit-host-object.js +2206 -0
- package/dist/targets/cpp/host/emit-host-properties.d.ts +69 -0
- package/dist/targets/cpp/host/emit-host-properties.js +533 -0
- package/dist/targets/cpp/host/emit-host-reflect.d.ts +4 -0
- package/dist/targets/cpp/host/emit-host-reflect.js +180 -0
- package/dist/targets/cpp/host/emit-host-value.d.ts +120 -0
- package/dist/targets/cpp/host/emit-host-value.js +392 -0
- package/dist/targets/cpp/host/host-members.d.ts +505 -0
- package/dist/targets/cpp/host/host-members.js +819 -0
- package/dist/targets/cpp/host/host-method-aliases.d.ts +30 -0
- package/dist/targets/cpp/host/host-method-aliases.js +76 -0
- package/dist/targets/cpp/host/native-protocols.d.ts +47 -0
- package/dist/targets/cpp/host/native-protocols.js +183 -0
- package/dist/targets/cpp/host/object-protocol.d.ts +351 -0
- package/dist/targets/cpp/host/object-protocol.js +671 -0
- package/dist/targets/cpp/host-namespace-reads.d.ts +83 -0
- package/dist/targets/cpp/host-namespace-reads.js +113 -0
- package/dist/targets/cpp/manifest/capabilities.d.ts +39 -0
- package/dist/targets/cpp/manifest/capabilities.js +1484 -0
- package/dist/targets/cpp/manifest.d.ts +23 -0
- package/dist/targets/cpp/manifest.js +113 -0
- package/dist/targets/cpp/native-error-base.d.ts +38 -0
- package/dist/targets/cpp/native-error-base.js +74 -0
- package/dist/targets/cpp/native-narrowing-transport.d.ts +12 -0
- package/dist/targets/cpp/native-narrowing-transport.js +151 -0
- package/dist/targets/cpp/native-selection-helpers.d.ts +11 -0
- package/dist/targets/cpp/native-selection-helpers.js +46 -0
- package/dist/targets/cpp/native-symbol-keys.d.ts +8 -0
- package/dist/targets/cpp/native-symbol-keys.js +34 -0
- package/dist/targets/cpp/ownership.d.ts +43 -0
- package/dist/targets/cpp/ownership.js +38 -0
- package/dist/targets/cpp/owning-conversion-input.d.ts +14 -0
- package/dist/targets/cpp/owning-conversion-input.js +12 -0
- package/dist/targets/cpp/property-read-claims.d.ts +62 -0
- package/dist/targets/cpp/property-read-claims.js +23 -0
- package/dist/targets/cpp/property-store-claims.d.ts +62 -0
- package/dist/targets/cpp/property-store-claims.js +26 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.d.ts +111 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.js +602 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.d.ts +133 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.js +515 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.d.ts +13 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.js +54 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.d.ts +34 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.js +1003 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.d.ts +47 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.js +250 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.d.ts +46 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.js +143 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.d.ts +335 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.js +853 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.d.ts +42 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.js +252 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.d.ts +25 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.js +182 -0
- package/dist/targets/cpp/reactive-dependencies.d.ts +140 -0
- package/dist/targets/cpp/reactive-dependencies.js +432 -0
- package/dist/targets/cpp/reactive-origins.d.ts +44 -0
- package/dist/targets/cpp/reactive-origins.js +82 -0
- package/dist/targets/cpp/records.d.ts +277 -0
- package/dist/targets/cpp/records.js +2427 -0
- package/dist/targets/cpp/recursive-containers.d.ts +43 -0
- package/dist/targets/cpp/recursive-containers.js +144 -0
- package/dist/targets/cpp/regexp-types.d.ts +56 -0
- package/dist/targets/cpp/regexp-types.js +59 -0
- package/dist/targets/cpp/substrate.d.ts +125 -0
- package/dist/targets/cpp/substrate.js +12 -0
- package/dist/targets/cpp/translation-unit.d.ts +219 -0
- package/dist/targets/cpp/translation-unit.js +2063 -0
- package/dist/targets/cpp/types.d.ts +280 -0
- package/dist/targets/cpp/types.js +1135 -0
- package/dist/targets/cpp/virtual-methods.d.ts +95 -0
- package/dist/targets/cpp/virtual-methods.js +264 -0
- package/package.json +95 -0
- package/src/targets/cpp/runtime/gea_dynamic_proxy.h +824 -0
- package/src/targets/cpp/runtime/gea_eval.h +1376 -0
- package/src/targets/cpp/runtime/gea_native_class_prototype.h +44 -0
- package/src/targets/cpp/runtime/gea_runtime.h +29222 -0
- package/src/targets/cpp/runtime/gea_runtime_builtins.cpp +55 -0
|
@@ -0,0 +1,1826 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { annotationStatesNothing, exactEmptyObjectLiteralType, derivedExpressionType, disjointUnionMembersOf, indexedTypeOf, explicitThisCallReturnType, overloadInvariantReturnTypeAt, joinOfWrites as sharedJoinOfWrites, jsDocTypeStatesNothing, literalMemberNameOf, memberTypeOf, normalizedArrayConditionalType, objectAssignTargetType, isEmptyObjectType, synthesizedUnionArmsAt, unwrapExplicitThisCall, withoutUndefinedMember, widestOf } from './derived-expression-type.js';
|
|
3
|
+
import { emptyParameterBindingCensus } from './parameter-bindings.js';
|
|
4
|
+
import { emptyCollectionBindingCensus } from './collection-bindings.js';
|
|
5
|
+
import { emptyObjectBagCensus } from './object-bag-bindings.js';
|
|
6
|
+
import { iteratorYieldTypesOf } from './producers/iteration-yield.js';
|
|
7
|
+
import { arrayAssignmentPatternSourceExpression, arrayAssignmentTargetOf, objectAssignmentElementOfTarget, objectAssignmentSource } from './assignment-patterns.js';
|
|
8
|
+
import { classFamilyMemberReadTypeOf } from './flow/class-family-member-read.js';
|
|
9
|
+
import { forEachReachableStatement } from './reachability.js';
|
|
10
|
+
import { emptyCommonJsModuleRecordCensus } from './commonjs-module-record.js';
|
|
11
|
+
import { censusRefusal } from './census-refusal.js';
|
|
12
|
+
import { assertedReceiverArmMayLackMember } from './asserted-arm-absence.js';
|
|
13
|
+
import { contextTypedLiteralThisOf } from './structural-receiver.js';
|
|
14
|
+
/** A census that binds nothing, for callers that state no program. */
|
|
15
|
+
export const emptyLocalBindingCensus = {
|
|
16
|
+
typeAt: () => null,
|
|
17
|
+
bindingTypeAt: () => null,
|
|
18
|
+
preferredTypeAt: () => null,
|
|
19
|
+
unionArmsAt: () => null,
|
|
20
|
+
boundCount: 0,
|
|
21
|
+
refusals: [],
|
|
22
|
+
refusalOf: () => null
|
|
23
|
+
};
|
|
24
|
+
const isAnyType = (type) => (type.flags & ts.TypeFlags.Any) !== 0;
|
|
25
|
+
/** Duplicated from `parameter-bindings.ts` (not exported there): `any`/`void`/`never` say nothing about storage. */
|
|
26
|
+
const isUnusableEvidence = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0;
|
|
27
|
+
/** Duplicated from `object-assignment.ts` (not exported there): a property name spelled as an identifier or a literal. */
|
|
28
|
+
const staticPropertyName = (name) => ts.isIdentifier(name) || ts.isStringLiteralLike(name) || ts.isNumericLiteral(name) ? name.text : null;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a declaration is ambient (`declare let x`, or anything nested
|
|
31
|
+
* inside a `declare module`) -- duplicated from `producers/bindings.ts`'s own
|
|
32
|
+
* `isAmbient` (not exported there, and that file is not this module's to
|
|
33
|
+
* read internals out of): a host owns that cell, so its type is a host-
|
|
34
|
+
* boundary capability question, never this module's to answer.
|
|
35
|
+
*/
|
|
36
|
+
const isAmbientDeclaration = (node) => {
|
|
37
|
+
if ((ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Ambient) !== 0)
|
|
38
|
+
return true;
|
|
39
|
+
for (let current = node.parent; current; current = current.parent) {
|
|
40
|
+
if (ts.isModuleDeclaration(current) && (ts.getCombinedModifierFlags(current) & ts.ModifierFlags.Ambient) !== 0)
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Whether this declaration is the exact shape this module types: unannotated,
|
|
47
|
+
* a plain identifier name, not ambient, and a cell TypeScript itself could not
|
|
48
|
+
* type.
|
|
49
|
+
*
|
|
50
|
+
* ## Why an initializer is not a disqualification
|
|
51
|
+
*
|
|
52
|
+
* `!declaration.initializer` was the original test, on the reasoning that a
|
|
53
|
+
* cell WITH an initializer is one TypeScript already typed. That reasoning is
|
|
54
|
+
* right about the ordinary case and wrong about the case this module exists
|
|
55
|
+
* for. `const image = resizeImage( texture.image, false, ... )` has an
|
|
56
|
+
* initializer, and the checker types the cell `any` -- because the initializer
|
|
57
|
+
* is a call into a function whose own return type it could not name. The cell
|
|
58
|
+
* is no better described than `let image;` would have been; it was simply
|
|
59
|
+
* excluded from the census on the strength of a syntactic property that does
|
|
60
|
+
* not answer the question being asked.
|
|
61
|
+
*
|
|
62
|
+
* So the test is the checker's ANSWER, not the syntax. An initialized cell is
|
|
63
|
+
* a candidate when `checker.getTypeAtLocation` on it is unusable evidence, or
|
|
64
|
+
* when it is mutable and a later assignment proves that answer cannot be its
|
|
65
|
+
* storage type. The second case matters in JavaScript: TypeScript may describe
|
|
66
|
+
* `let id = match[1]` as `string` at the declaration even when the same cell is
|
|
67
|
+
* later assigned a number. The flow index supplies the complete write set, so
|
|
68
|
+
* admitting that declaration is evidence-driven rather than a widening guess.
|
|
69
|
+
* Where every later write fits the checker's answer, the initialized cell
|
|
70
|
+
* remains outside this census -- which is the ordinary typed-program case.
|
|
71
|
+
*
|
|
72
|
+
* The initializer then joins the write set (`resolveDeclaration`) rather than
|
|
73
|
+
* being read on its own: it is one write among however many assignments
|
|
74
|
+
* follow, and reading it alone would describe a value the program does not
|
|
75
|
+
* have -- the same two-authorities-on-one-cell defect
|
|
76
|
+
* `parameter-bindings.ts`'s `writeSetTypeOf` header describes.
|
|
77
|
+
*
|
|
78
|
+
* "Unannotated" includes a JSDoc `@type` tag that resolves to nothing. The
|
|
79
|
+
* tag's presence was the old test, and it is the wrong one: the checker
|
|
80
|
+
* degrades a JSDoc node naming an unbindable type to `any`, so a cell the
|
|
81
|
+
* program DID describe is excluded from this census and then carries
|
|
82
|
+
* `dynamic(declared-any-never-narrowed)` -- recorded as declared dynamic when
|
|
83
|
+
* the program declared the opposite. `parameter-bindings.ts` has drawn this
|
|
84
|
+
* distinction since the call-site census landed; this is the same predicate,
|
|
85
|
+
* shared rather than copied.
|
|
86
|
+
*
|
|
87
|
+
* Measured on the three.js app: ZERO uninitialized locals carry a JSDoc type at all, so
|
|
88
|
+
* this changes nothing there today. It is landed for the symmetry, not for a
|
|
89
|
+
* number -- the three censuses answering one question three different ways is
|
|
90
|
+
* how the return-side gap survived, and leaving one of them holding the old
|
|
91
|
+
* test preserves the trap for whichever program hits it first.
|
|
92
|
+
*/
|
|
93
|
+
/**
|
|
94
|
+
* Whether a WRITTEN type annotation actually states something, rather than
|
|
95
|
+
* merely occupying the syntax position -- the same distinction
|
|
96
|
+
* `jsDocTypeStatesNothing` draws for a JSDoc tag, drawn slightly more
|
|
97
|
+
* conservatively here because this is a real TypeScript annotation rather
|
|
98
|
+
* than a degraded doc comment: the literal `any`/`unknown` keyword is left
|
|
99
|
+
* alone (`true`, genuinely stated) because a program that writes that down
|
|
100
|
+
* is declaring the cell dynamic on purpose -- CLAUDE.md's own carve-out for
|
|
101
|
+
* a value the program declares `any`/`unknown` and never narrows, and this
|
|
102
|
+
* module must not talk it out of that. Anything else that merely EVALUATES
|
|
103
|
+
* to `any`/`unknown` through the type system -- a utility type applied to a
|
|
104
|
+
* library's own erased generic, `ReturnType<H>` over hono's `H = Handler |
|
|
105
|
+
* MiddlewareHandler` being the concrete case -- states nothing a reader
|
|
106
|
+
* could act on, and is treated as if the position were bare.
|
|
107
|
+
*/
|
|
108
|
+
const annotationIsGenuinelyStated = (checker, typeNode) => {
|
|
109
|
+
if (typeNode.kind === ts.SyntaxKind.AnyKeyword || typeNode.kind === ts.SyntaxKind.UnknownKeyword)
|
|
110
|
+
return true;
|
|
111
|
+
const resolved = checker.getTypeFromTypeNode(typeNode);
|
|
112
|
+
return (resolved.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) === 0;
|
|
113
|
+
};
|
|
114
|
+
const isCandidate = (checker, declaration, flow) => {
|
|
115
|
+
if (declaration.type && annotationIsGenuinelyStated(checker, declaration.type))
|
|
116
|
+
return false;
|
|
117
|
+
if (!ts.isIdentifier(declaration.name))
|
|
118
|
+
return false;
|
|
119
|
+
const jsDocType = ts.getJSDocType(declaration);
|
|
120
|
+
if (jsDocType && !jsDocTypeStatesNothing(checker, jsDocType))
|
|
121
|
+
return false;
|
|
122
|
+
if (isAmbientDeclaration(declaration))
|
|
123
|
+
return false;
|
|
124
|
+
if (declaration.initializer) {
|
|
125
|
+
const declared = checker.getTypeAtLocation(declaration);
|
|
126
|
+
if (!isUnusableEvidence(declared)) {
|
|
127
|
+
const declarationList = declaration.parent;
|
|
128
|
+
if (!ts.isVariableDeclarationList(declarationList) || (declarationList.flags & ts.NodeFlags.Const) !== 0)
|
|
129
|
+
return false;
|
|
130
|
+
const symbol = checker.getSymbolAtLocation(declaration.name);
|
|
131
|
+
if (!symbol)
|
|
132
|
+
return false;
|
|
133
|
+
const hasDivergentAssignment = flow.writesToSymbol(symbol).some((write) => {
|
|
134
|
+
if (write.slot !== 'whole' || write.edge !== 'identifier-assignment' || write.value === null)
|
|
135
|
+
return false;
|
|
136
|
+
const assigned = checker.getTypeAtLocation(write.value);
|
|
137
|
+
return !isUnusableEvidence(assigned) && !checker.isTypeAssignableTo(assigned, declared);
|
|
138
|
+
});
|
|
139
|
+
if (!hasDivergentAssignment)
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Whether one LEAF of a binding pattern -- one member of `const {a,b} = o`,
|
|
147
|
+
* one element of `const [a,b] = t`, the loop variable of `for (const x of
|
|
148
|
+
* xs)` when it is itself a pattern -- is this module's to type: a plain
|
|
149
|
+
* identifier name (a nested pattern is not itself a leaf; ITS OWN elements
|
|
150
|
+
* are the leaves, reached by the same walk one level deeper), not a rest
|
|
151
|
+
* element (`{...rest}`/`[...rest]` names a NEW shape -- an object/array of
|
|
152
|
+
* the remaining keys -- not a projection of one member), not ambient, and a
|
|
153
|
+
* cell TypeScript itself could not already type. The identical "ask the
|
|
154
|
+
* checker's own answer, not the syntax" rule `isCandidate` applies to a
|
|
155
|
+
* `VariableDeclaration`'s own name, applied here to a pattern's leaf instead
|
|
156
|
+
* -- rows 14 (object destructuring), 15 (array destructuring), 16
|
|
157
|
+
* (destructuring defaults) and the destructured half of row 22 (for-of) are
|
|
158
|
+
* this ONE predicate plus `resolveBindingElement`'s one recursive resolver,
|
|
159
|
+
* not four separate arms.
|
|
160
|
+
*/
|
|
161
|
+
const isElementCandidate = (checker, element) => {
|
|
162
|
+
if (!ts.isIdentifier(element.name))
|
|
163
|
+
return false;
|
|
164
|
+
if (isAmbientDeclaration(element))
|
|
165
|
+
return false;
|
|
166
|
+
// An object rest over an open dictionary keeps the source's unknown key set,
|
|
167
|
+
// even when TypeScript reports the post-exclusion view as the usable-looking
|
|
168
|
+
// but physically empty `{}`. `resolveBindingElement` proves the index below.
|
|
169
|
+
if (element.dotDotDotToken && ts.isObjectBindingPattern(element.parent))
|
|
170
|
+
return true;
|
|
171
|
+
if (element.dotDotDotToken)
|
|
172
|
+
return false;
|
|
173
|
+
return isUnusableEvidence(checker.getTypeAtLocation(element.name));
|
|
174
|
+
};
|
|
175
|
+
const isReturnEvidenceOwner = (node) => ts.isFunctionDeclaration(node) ||
|
|
176
|
+
ts.isFunctionExpression(node) ||
|
|
177
|
+
ts.isArrowFunction(node) ||
|
|
178
|
+
ts.isMethodDeclaration(node) ||
|
|
179
|
+
ts.isGetAccessorDeclaration(node);
|
|
180
|
+
/** Every syntax kind that owns its OWN `return`s -- a walk collecting one function's returns must stop at the next one's boundary. Duplicated from `return-bindings.ts`'s `isScopeBoundary` for the same reason. */
|
|
181
|
+
const isReturnEvidenceScopeBoundary = (node) => isReturnEvidenceOwner(node) ||
|
|
182
|
+
ts.isConstructorDeclaration(node) ||
|
|
183
|
+
ts.isSetAccessorDeclaration(node) ||
|
|
184
|
+
ts.isClassDeclaration(node) ||
|
|
185
|
+
ts.isClassExpression(node) ||
|
|
186
|
+
ts.isClassStaticBlockDeclaration(node);
|
|
187
|
+
const hasAsyncOrGeneratorModifier = (owner) => {
|
|
188
|
+
const async = (ts.canHaveModifiers(owner) ? ts.getModifiers(owner) : undefined)?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) ??
|
|
189
|
+
false;
|
|
190
|
+
const generator = 'asteriskToken' in owner && owner.asteriskToken !== undefined;
|
|
191
|
+
return async || generator;
|
|
192
|
+
};
|
|
193
|
+
/** Whether `symbol` is read anywhere inside this expression, by exact symbol identity (never by spelling, so a shadowed same-named binding elsewhere never matches). */
|
|
194
|
+
const expressionReadsSymbol = (checker, expression, symbol) => {
|
|
195
|
+
let found = false;
|
|
196
|
+
const walk = (node) => {
|
|
197
|
+
if (found)
|
|
198
|
+
return;
|
|
199
|
+
if (ts.isIdentifier(node) && checker.getSymbolAtLocation(node) === symbol) {
|
|
200
|
+
found = true;
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
ts.forEachChild(node, walk);
|
|
204
|
+
};
|
|
205
|
+
walk(expression);
|
|
206
|
+
return found;
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* The type a cell holds, read BACKWARD from the enclosing function's own
|
|
210
|
+
* STATED return type -- the one case the write side (`resolveDeclaration`'s
|
|
211
|
+
* own `writes`/`widestOf` machinery) can never resolve: every write is
|
|
212
|
+
* itself a call whose callee the checker could not type, because the
|
|
213
|
+
* callee's own signature return is `any` for a reason internal to the
|
|
214
|
+
* library that declared it (an erased generic default) rather than for any
|
|
215
|
+
* fact about THIS program. hono's `hono-base.ts`:
|
|
216
|
+
*
|
|
217
|
+
* #dispatch(...): Response | Promise<Response> {
|
|
218
|
+
* let res: ReturnType<H>
|
|
219
|
+
* try { res = matchResult[0][0][0][0](c, next) } catch (err) { ... }
|
|
220
|
+
* return res instanceof Promise ? res.then(...) : (res ?? ...)
|
|
221
|
+
* }
|
|
222
|
+
*
|
|
223
|
+
* is the concrete case: `H = Handler | MiddlewareHandler` (`types.ts`)
|
|
224
|
+
* defaults its own trailing type parameter to the literal `any`, and
|
|
225
|
+
* TypeScript's own union-with-`any` rule collapses `any | Promise<R | void>`
|
|
226
|
+
* to plain `any` -- a TypeScript typing rule, not a physical fact about
|
|
227
|
+
* what the call returns. Nothing at the WRITE reaches past that; `#dispatch`
|
|
228
|
+
* itself, though, states in its own signature exactly what its `return`
|
|
229
|
+
* hands back, and `res` is the one value that statement is built from -- so
|
|
230
|
+
* the function's own annotation is real evidence for the cell that feeds
|
|
231
|
+
* it, symmetric to `return-bindings.ts`'s own direction (a STATED return
|
|
232
|
+
* infers an unstated variable, rather than unstated returns inferring a
|
|
233
|
+
* declaration `return-bindings.ts` itself refuses to touch a function that
|
|
234
|
+
* already states its own return type, for the identical reason this module
|
|
235
|
+
* must not invent one where a real annotation stands -- this is the
|
|
236
|
+
* complementary gap: the FUNCTION stated a type, and an internal CELL
|
|
237
|
+
* feeding its `return` did not).
|
|
238
|
+
*
|
|
239
|
+
* Gated tightly, because the checker performs no assignability check at an
|
|
240
|
+
* `any`-typed expression and a wrong answer here is worse than staying
|
|
241
|
+
* dynamic:
|
|
242
|
+
* - the enclosing function/method must be a plain, non-async,
|
|
243
|
+
* non-generator function with a body block and a REAL stated return
|
|
244
|
+
* annotation of its own (never itself `any`/`unknown`/`void`/`never`) --
|
|
245
|
+
* an async function's own `return` hands back the AWAITED value, not the
|
|
246
|
+
* `Promise<T>` its signature states, so this refuses async and generator
|
|
247
|
+
* functions outright, the same exclusion `return-bindings.ts` documents
|
|
248
|
+
* for the identical reason;
|
|
249
|
+
* - the cell's own symbol must be read, by exact symbol identity, inside a
|
|
250
|
+
* `return` statement's own expression belonging to that SAME function --
|
|
251
|
+
* never a nested closure's, which owns its own returns;
|
|
252
|
+
* - only ever a FALLBACK, tried from `resolveDeclaration` after every
|
|
253
|
+
* write has already failed to resolve through the ordinary route: a cell
|
|
254
|
+
* whose writes DO resolve, even to a value that disagrees with the
|
|
255
|
+
* return, keeps disagreeing rather than being silently overridden here.
|
|
256
|
+
*/
|
|
257
|
+
const declaredReturnEvidenceFor = (checker, declaration, symbol) => {
|
|
258
|
+
let owner = declaration.parent;
|
|
259
|
+
while (owner && !ts.isFunctionLike(owner))
|
|
260
|
+
owner = owner.parent;
|
|
261
|
+
if (!owner || !isReturnEvidenceOwner(owner))
|
|
262
|
+
return null;
|
|
263
|
+
if (hasAsyncOrGeneratorModifier(owner))
|
|
264
|
+
return null;
|
|
265
|
+
const body = owner.body;
|
|
266
|
+
if (!body || !ts.isBlock(body))
|
|
267
|
+
return null;
|
|
268
|
+
if (!owner.type)
|
|
269
|
+
return null;
|
|
270
|
+
const declaredReturn = checker.getTypeFromTypeNode(owner.type);
|
|
271
|
+
if (isUnusableEvidence(declaredReturn))
|
|
272
|
+
return null;
|
|
273
|
+
let found = false;
|
|
274
|
+
const walk = (node) => {
|
|
275
|
+
if (found)
|
|
276
|
+
return;
|
|
277
|
+
if (node !== body && isReturnEvidenceScopeBoundary(node))
|
|
278
|
+
return;
|
|
279
|
+
if (ts.isReturnStatement(node) && node.expression && expressionReadsSymbol(checker, node.expression, symbol)) {
|
|
280
|
+
found = true;
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
ts.forEachChild(node, walk);
|
|
284
|
+
};
|
|
285
|
+
walk(body);
|
|
286
|
+
return found ? declaredReturn : null;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Whole-program census of what every unannotated, uninitialized `let`/`var`
|
|
290
|
+
* cell holds, once every assignment to it agrees.
|
|
291
|
+
*
|
|
292
|
+
* `parameters` is the ALREADY-SETTLED, composed parameter+return census
|
|
293
|
+
* (`withReturnBindings(...)`, or `emptyParameterBindingCensus` when none is
|
|
294
|
+
* available) -- asked first at every identifier, exactly as `return-bindings.
|
|
295
|
+
* ts`'s own local resolver asks it first. This module never reopens that
|
|
296
|
+
* fixpoint; it only adds what neither authority could answer because the
|
|
297
|
+
* chain passed through a cell with no initializer.
|
|
298
|
+
*/
|
|
299
|
+
export const censusLocalBindings = (checker, files, reachable, parameters = emptyParameterBindingCensus,
|
|
300
|
+
/** The same-round array census -- see `return-bindings.ts`'s identical parameter for why, and `frontend.ts`'s `compose`. */
|
|
301
|
+
collections = emptyCollectionBindingCensus,
|
|
302
|
+
/**
|
|
303
|
+
* The whole-program value-flow index -- the ONE walk that states where every
|
|
304
|
+
* write is. This module's own private write-discovery walk
|
|
305
|
+
* (`assignmentsBySymbol`) reads its edges from it rather than re-deriving
|
|
306
|
+
* them; see `flow/model.ts`. An edge-SOURCE swap: the policy below (which
|
|
307
|
+
* writes are evidence, how they join) is unchanged.
|
|
308
|
+
*/
|
|
309
|
+
flow,
|
|
310
|
+
/**
|
|
311
|
+
* The same-round property-bag census. Consulted where a WRITE or an
|
|
312
|
+
* initializer reads one slot off a tracked bag -- `bag.name`, `bag[ k ]` --
|
|
313
|
+
* as `slotTypeAt`, the one question about a bag whose answer is a plain
|
|
314
|
+
* `ts.Type` and so the only one this module can consume. See that
|
|
315
|
+
* accessor's own header.
|
|
316
|
+
*/
|
|
317
|
+
bags = emptyObjectBagCensus,
|
|
318
|
+
/**
|
|
319
|
+
* The prior OUTER composed view. `parameters` above is the newly rebuilt
|
|
320
|
+
* parameter+return stage and intentionally contains only those domains; it
|
|
321
|
+
* cannot carry this local census's own synthesized arms back to itself.
|
|
322
|
+
* This input is used only as the previous element of the local arm lattice.
|
|
323
|
+
*/
|
|
324
|
+
prior = emptyParameterBindingCensus,
|
|
325
|
+
/** Exact, authenticated `module.exports = callable` proofs for this program's CommonJS modules. */
|
|
326
|
+
moduleRecords = emptyCommonJsModuleRecordCensus) => {
|
|
327
|
+
const identifierWritesOf = (symbol) => {
|
|
328
|
+
const writes = [];
|
|
329
|
+
for (const write of flow.writesToSymbol(symbol)) {
|
|
330
|
+
if (write.slot !== 'whole')
|
|
331
|
+
continue;
|
|
332
|
+
if (write.value !== null && (write.edge === 'declaration-initializer' || write.edge === 'identifier-assignment')) {
|
|
333
|
+
writes.push({ node: write.value });
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
// `[a] = [1, 2, 3]` / `({ a } = { a: 1 })` -- a destructuring ASSIGNMENT
|
|
337
|
+
// writes a bare, previously-untyped cell exactly the way `a = expr`
|
|
338
|
+
// does, but `recordAssignmentPattern` (`flow/value-flow.ts`) records it
|
|
339
|
+
// with `value: null`: a pattern's target is not itself the source of
|
|
340
|
+
// its own value the way an ordinary assignment's left side is. The
|
|
341
|
+
// default's own value (`destructuring-default`, `[x = 3] = ...`) IS a
|
|
342
|
+
// real expression already -- `inner.right` -- so it needs no recovery.
|
|
343
|
+
if (write.value !== null && write.edge === 'destructuring-default') {
|
|
344
|
+
writes.push({ node: write.value });
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (write.edge === 'destructuring' && write.value === null && write.naming) {
|
|
348
|
+
const evidence = destructuringAssignmentEvidenceExpressionAt(write.naming);
|
|
349
|
+
if (evidence) {
|
|
350
|
+
writes.push({ node: evidence });
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
// A for-of/for-in LOOP-HEAD pattern (`for ([a, b] of pairs)`) has no
|
|
354
|
+
// literal source `destructuringAssignmentEvidenceExpressionAt` could
|
|
355
|
+
// index into -- the value comes from the loop's own iteration, never
|
|
356
|
+
// from an expression the program wrote. `forOfPatternElementTypeAt`
|
|
357
|
+
// derives the per-position/per-key type directly from the loop's own
|
|
358
|
+
// iterable (or, for a for-in head, its key string).
|
|
359
|
+
const patternType = forOfPatternElementTypeAt(write.naming);
|
|
360
|
+
if (patternType)
|
|
361
|
+
writes.push({ node: write.naming, resolvedType: patternType });
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
// `var v; for (v of xs) ...` -- a bare identifier reused as a for-of/
|
|
365
|
+
// for-in loop's own head, declared OUTSIDE the loop. See
|
|
366
|
+
// `forOfBareIdentifierElementTypeAt`'s own header for why this is a
|
|
367
|
+
// separate case from both the destructuring-pattern head above and
|
|
368
|
+
// `forOfElementType`'s declared-in-loop binding.
|
|
369
|
+
if (write.edge === 'iteration-binding' && write.value === null && write.naming) {
|
|
370
|
+
const elementType = forOfBareIdentifierElementTypeAt(write.naming);
|
|
371
|
+
if (elementType)
|
|
372
|
+
writes.push({ node: write.naming, resolvedType: elementType });
|
|
373
|
+
}
|
|
374
|
+
// `catch (err) { ... }` -- the binding's value is the thrown exception,
|
|
375
|
+
// never an expression this program wrote, exactly as a for-of/for-in
|
|
376
|
+
// loop's own head is not. `Catch(C, thrownValue)` (ECMA-262 14.15.2)
|
|
377
|
+
// BINDS the caught value with no further coercion, and this compiler's
|
|
378
|
+
// own dynamic-boundary rule already names "a thrown JS error carrier"
|
|
379
|
+
// as one of the genuinely dynamic values a program is allowed to leave
|
|
380
|
+
// unnarrowed -- so the checker's own type at the binding (`unknown`
|
|
381
|
+
// under `useUnknownInCatchVariables`, or whatever explicit annotation
|
|
382
|
+
// the program wrote, e.g. `catch (err: SomeError)`) is the answer, not
|
|
383
|
+
// a refusal. Before this, a caught error that the handler only ever
|
|
384
|
+
// READ (never reassigned -- the overwhelmingly common shape) found no
|
|
385
|
+
// evidence at all and refused as
|
|
386
|
+
// `no-writes:existence-only:catch-binding`, in this program and in
|
|
387
|
+
// hono's own `#handleError`.
|
|
388
|
+
if (write.edge === 'catch-binding' && write.value === null && write.naming) {
|
|
389
|
+
writes.push({ node: write.naming, resolvedType: checker.getTypeAtLocation(write.naming) });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return writes;
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* The real sub-expression backing a destructuring-ASSIGNMENT write with no
|
|
396
|
+
* recorded value: the array-literal element at the same position, or the
|
|
397
|
+
* object-literal property with the same name -- asked of whichever literal
|
|
398
|
+
* the program actually wrote on the right, never invented. `known`/
|
|
399
|
+
* `resolveExpr` need a `ts.Expression` to ask the checker about, the same
|
|
400
|
+
* currency every other edge already supplies; this recovers one for the
|
|
401
|
+
* one shape the flow index could not attach a value to.
|
|
402
|
+
*
|
|
403
|
+
* Refuses a REST target (no single element states "the rest") and any
|
|
404
|
+
* source that is not itself a literal (there is no sound way to index INTO
|
|
405
|
+
* an arbitrary expression's type without `checker.createArrayType`, which
|
|
406
|
+
* is checker-internal -- `structural-array-element.ts`'s header documents
|
|
407
|
+
* the identical wall for `never[]`). Both stay exactly as boxed as they are
|
|
408
|
+
* today; a wrong answer would be worse than a boxed one.
|
|
409
|
+
*/
|
|
410
|
+
const destructuringAssignmentEvidenceExpressionAt = (target) => {
|
|
411
|
+
const arrayTarget = arrayAssignmentTargetOf(target);
|
|
412
|
+
if (arrayTarget) {
|
|
413
|
+
if (ts.isSpreadElement(arrayTarget.keyNode))
|
|
414
|
+
return null;
|
|
415
|
+
const source = arrayAssignmentPatternSourceExpression(arrayTarget.pattern);
|
|
416
|
+
if (!source || !ts.isArrayLiteralExpression(source))
|
|
417
|
+
return null;
|
|
418
|
+
const element = source.elements[arrayTarget.position];
|
|
419
|
+
return element && !ts.isSpreadElement(element) && !ts.isOmittedExpression(element) ? element : null;
|
|
420
|
+
}
|
|
421
|
+
const objectElement = objectAssignmentElementOfTarget(target);
|
|
422
|
+
if (!objectElement)
|
|
423
|
+
return null;
|
|
424
|
+
const pattern = objectElement.parent;
|
|
425
|
+
if (!ts.isObjectLiteralExpression(pattern))
|
|
426
|
+
return null;
|
|
427
|
+
const source = objectAssignmentSource(pattern);
|
|
428
|
+
if (!source || !ts.isObjectLiteralExpression(source))
|
|
429
|
+
return null;
|
|
430
|
+
const keyName = ts.isShorthandPropertyAssignment(objectElement) ? objectElement.name.text : staticPropertyName(objectElement.name);
|
|
431
|
+
if (keyName === null)
|
|
432
|
+
return null;
|
|
433
|
+
for (const property of source.properties) {
|
|
434
|
+
if (!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property))
|
|
435
|
+
continue;
|
|
436
|
+
if (staticPropertyName(property.name) !== keyName)
|
|
437
|
+
continue;
|
|
438
|
+
return ts.isPropertyAssignment(property) ? property.initializer : property.name;
|
|
439
|
+
}
|
|
440
|
+
return null;
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* Why a cell `identifierWritesOf` found no VALUED write for has no evidence.
|
|
444
|
+
*
|
|
445
|
+
* `no-writes` was a single bucket, and it is half of every refusal any
|
|
446
|
+
* census in this compiler reports (3201 of 6340 on the largest measured
|
|
447
|
+
* program). A bucket that size is a measurement failure before it is a
|
|
448
|
+
* compiler one: it held four unrelated situations, which want four
|
|
449
|
+
* different answers and only one of which is "nothing writes this cell".
|
|
450
|
+
*
|
|
451
|
+
* - `none`: the index knows no write to the cell at all, and it has no
|
|
452
|
+
* initializer. In JavaScript such a cell holds exactly `undefined`
|
|
453
|
+
* forever, so this is answerable -- but only if the whole program really
|
|
454
|
+
* is in view, which is why it is REPORTED rather than assumed here.
|
|
455
|
+
* - `initializer-unseen`: the declaration HAS an initializer that the index
|
|
456
|
+
* did not attribute to this symbol. That is an index defect, never a
|
|
457
|
+
* property of the program.
|
|
458
|
+
* - `existence-only:<edges>`: every write states only that the slot exists
|
|
459
|
+
* (`flow/model.ts` records `value: null` for these) -- a `catch` binding,
|
|
460
|
+
* a `for..of` binding this module's `forOfElementType` could not open, a
|
|
461
|
+
* destructured element, a compound assignment. Each is a real edge with a
|
|
462
|
+
* real value; the value simply is not the recorded expression, so naming
|
|
463
|
+
* the edge names what to teach next.
|
|
464
|
+
* - `member-only`: nothing writes the cell as a whole, only its members or
|
|
465
|
+
* elements. The cell is a bag or a container, and its shape is another
|
|
466
|
+
* census's answer (`object-bag-bindings.ts`, `collection-bindings.ts`) --
|
|
467
|
+
* this one having no answer is correct.
|
|
468
|
+
*/
|
|
469
|
+
const noEvidenceReason = (symbol, declaration) => {
|
|
470
|
+
const all = flow.writesToSymbol(symbol);
|
|
471
|
+
const whole = all.filter((write) => write.slot === 'whole');
|
|
472
|
+
if (whole.length === 0) {
|
|
473
|
+
if (declaration.initializer)
|
|
474
|
+
return 'no-writes:initializer-unseen';
|
|
475
|
+
return all.length === 0 ? 'no-writes:none' : 'no-writes:member-only';
|
|
476
|
+
}
|
|
477
|
+
const edges = [...new Set(whole.map((write) => write.edge))].sort().join('+');
|
|
478
|
+
return `no-writes:existence-only:${edges}`;
|
|
479
|
+
};
|
|
480
|
+
const bound = new Map();
|
|
481
|
+
/** The synthesized union arms for a cell whose writes disagree but disjointly -- see `resolveDeclaration`. */
|
|
482
|
+
const unionArms = new Map();
|
|
483
|
+
const refusalOf = new Map();
|
|
484
|
+
const resolvingDeclarations = new Set();
|
|
485
|
+
/** Whether resolution is in the relaxed retry phase, where a silent write is an absence rather than a veto. See `resolveDeclaration`. */
|
|
486
|
+
let lenientPhase = false;
|
|
487
|
+
/**
|
|
488
|
+
* The checker's own answer at this node, when it says something usable.
|
|
489
|
+
* `annotationStatesNothing` is part of the test for the reason
|
|
490
|
+
* `field-bindings.ts`'s own `known` documents at length: a vacuous type
|
|
491
|
+
* (`Object`, `{}`, bare `object`) is not just non-evidence -- fed to a
|
|
492
|
+
* `widestOf` join it DOMINATES, because every type is assignable to it, so
|
|
493
|
+
* one vacuous write out-votes every real one. The layout resolver already
|
|
494
|
+
* asks both halves of the question; a census asking only one is drift.
|
|
495
|
+
*/
|
|
496
|
+
const known = (node) => {
|
|
497
|
+
const exported = moduleRecords.exportExpressionAt(node) ?? moduleRecords.requiredExportExpressionAt(node);
|
|
498
|
+
const type = exported ? checker.getTypeAtLocation(exported) : (objectAssignTargetType(checker, node) ?? checker.getTypeAtLocation(node));
|
|
499
|
+
return isUnusableEvidence(type) || annotationStatesNothing(checker, node, type) ? null : type;
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* Materialize an already-proved synthesized union for INTERNAL resolution.
|
|
503
|
+
*
|
|
504
|
+
* The public census keeps synthesized unions in `unionArmsAt`, because the
|
|
505
|
+
* structural mapper consumes the arm list directly. Recursive census
|
|
506
|
+
* resolution still needs one `ts.Type` to ask ordinary checker questions
|
|
507
|
+
* such as “what is this union's common member?” and “what does that member
|
|
508
|
+
* return?”. Without this bridge, a union published in one outer round was
|
|
509
|
+
* unreadable in the next: the local census fell back to its pre-union
|
|
510
|
+
* answer, then rediscovered the union one round later, forever.
|
|
511
|
+
*
|
|
512
|
+
* This is the same guarded checker reach used by
|
|
513
|
+
* `disjointUnionTypeOf`/`parameter-slot.ts`. Failure remains a refusal; no
|
|
514
|
+
* alternate union implementation is invented here.
|
|
515
|
+
*/
|
|
516
|
+
/** A carrier that states a DYNAMIC boundary rather than a type -- see `branchArmsOf`. */
|
|
517
|
+
const DYNAMIC_FLAGS = ts.TypeFlags.Any | ts.TypeFlags.Unknown;
|
|
518
|
+
/**
|
|
519
|
+
* The two values a BRANCHING write can store -- `value || "u"`, `a ?? b`,
|
|
520
|
+
* `cond ? x : y`.
|
|
521
|
+
*
|
|
522
|
+
* `derivedExpressionType` answers such an expression with the ONE type both
|
|
523
|
+
* operands agree on, and `null` when they disagree: for a join that is the
|
|
524
|
+
* honest answer, but for a WRITE it reads as silence, and the relaxed phase
|
|
525
|
+
* drops a silent write rather than letting it disagree. A cell written
|
|
526
|
+
* `f || "u"` in one place and `"q"` in another was then placed as
|
|
527
|
+
* `std::string` -- and the branching write, whose value really can be the
|
|
528
|
+
* function, was stored through a fail-open unbox that aborted at runtime
|
|
529
|
+
* (test262's propertyHelper `isWritable`, whose `value || unlikelyValue` is
|
|
530
|
+
* a function at `verifyNotWritable`'s call sites).
|
|
531
|
+
*
|
|
532
|
+
* Both operands ARE the write set -- the same reading `derivedExpressionType`
|
|
533
|
+
* already gives a ternary's two arms in its own comment -- so they are
|
|
534
|
+
* contributed as arms here, and the ordinary arm lattice decides whether
|
|
535
|
+
* they become one type, a synthesized union, or a dynamic cell. `&&` is
|
|
536
|
+
* excluded: its value
|
|
537
|
+
* is the right operand or the LEFT's falsy state, which is a narrowing of
|
|
538
|
+
* the left rather than the left itself.
|
|
539
|
+
*/
|
|
540
|
+
const branchArmsOf = (node) => {
|
|
541
|
+
const branches = ts.isConditionalExpression(node)
|
|
542
|
+
? [node.whenTrue, node.whenFalse]
|
|
543
|
+
: ts.isBinaryExpression(node) &&
|
|
544
|
+
(node.operatorToken.kind === ts.SyntaxKind.BarBarToken || node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken)
|
|
545
|
+
? [node.left, node.right]
|
|
546
|
+
: null;
|
|
547
|
+
if (!branches)
|
|
548
|
+
return null;
|
|
549
|
+
// A DYNAMIC operand is evidence too, and the evidence is that the cell is
|
|
550
|
+
// dynamic: `value || "u"` where `value` is bound `any` by its call sites
|
|
551
|
+
// stores the box, and dropping that arm placed the cell from the other
|
|
552
|
+
// write alone -- the fail-open unbox this rule exists to stop. The arm
|
|
553
|
+
// lattice reads an `any` arm as the whole cell (`carriesNoEvidence`
|
|
554
|
+
// vetoes a union carrying one), which is the honest answer. Only an
|
|
555
|
+
// operand nobody could type at all is still silence.
|
|
556
|
+
const arms = branches.map((branch) => knownOrResolve(branch));
|
|
557
|
+
if (arms.every((arm) => arm !== null))
|
|
558
|
+
return arms;
|
|
559
|
+
// An operand NO authority can type, whose checker answer is `any`, is a
|
|
560
|
+
// genuinely dynamic boundary rather than silence -- the same reading
|
|
561
|
+
// `parameter-bindings.ts`'s `isSuppliedDynamic` gives a supplied `any`.
|
|
562
|
+
// The storage really does hold the box, so the expression's own `any` is
|
|
563
|
+
// contributed as the arm: the cell goes dynamic instead of being placed
|
|
564
|
+
// from the OTHER write and reading this one back through a fail-open
|
|
565
|
+
// unbox. (`verifyProp || name`, `value || unlikelyValue` -- test262's
|
|
566
|
+
// propertyHelper, whose parameters are bound by call sites that disagree
|
|
567
|
+
// in arity.)
|
|
568
|
+
const dynamicOperand = branches.some((branch) => (checker.getTypeAtLocation(branch).flags & DYNAMIC_FLAGS) !== 0);
|
|
569
|
+
if (!dynamicOperand)
|
|
570
|
+
return null;
|
|
571
|
+
const own = checker.getTypeAtLocation(node);
|
|
572
|
+
return (own.flags & DYNAMIC_FLAGS) !== 0 ? [own] : null;
|
|
573
|
+
};
|
|
574
|
+
const unionTypeOf = (arms) => {
|
|
575
|
+
if (!arms || arms.length === 0)
|
|
576
|
+
return null;
|
|
577
|
+
const constructing = checker;
|
|
578
|
+
return typeof constructing.getUnionType === 'function' ? constructing.getUnionType(arms) : null;
|
|
579
|
+
};
|
|
580
|
+
/** Whether the checker's raw answer at a write is a REAL fact refusing storage (`void`/`never`), as opposed to silence. */
|
|
581
|
+
const statesNoStorage = (node) => (checker.getTypeAtLocation(node).flags & (ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0;
|
|
582
|
+
/** Node-level memo/cycle-guard for the general resolver below -- a property-access chain can revisit the same sub-expression more than once. */
|
|
583
|
+
const nodeMemo = new Map();
|
|
584
|
+
const nodeResolving = new Set();
|
|
585
|
+
/**
|
|
586
|
+
* A silent write's own answer, once its cell resolved via
|
|
587
|
+
* `declaredReturnEvidenceFor` -- deliberately a SEPARATE map from
|
|
588
|
+
* `nodeMemo`, which the lenient retry below clears every round on purpose
|
|
589
|
+
* (stale `null`s from a smaller view must not survive to the next). A
|
|
590
|
+
* declaration bound in the strict phase is never revisited (`resolveDeclaration`
|
|
591
|
+
* returns `already` before it would run the backfill again), so an answer
|
|
592
|
+
* recorded only in `nodeMemo` is erased by the very next round's `clear()`
|
|
593
|
+
* and never restored -- measured directly: hono's `res = matchResult[0][0]
|
|
594
|
+
* [0][0](c, next)` backfilled correctly, then read back as the stale `null`
|
|
595
|
+
* `compute` had cached before the backfill, because a LATER declaration's
|
|
596
|
+
* lenient retry cleared `nodeMemo` in between the write and the query. This
|
|
597
|
+
* map is never cleared, so the write keeps the cell's answer regardless of
|
|
598
|
+
* how many other declarations retry around it.
|
|
599
|
+
*/
|
|
600
|
+
const writeAnswers = new Map();
|
|
601
|
+
// The closed-family fallback is the parameter census's own rule, asked the
|
|
602
|
+
// same way -- see `flow/class-family-member-read.ts`.
|
|
603
|
+
const propertyTypeOf = (receiver, name, at) => memberTypeOf(checker, receiver, name, at, flow) ?? classFamilyMemberReadTypeOf(checker, flow, receiver, name, parameters);
|
|
604
|
+
const declarationOf = (node) => {
|
|
605
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
606
|
+
const declarations = symbol?.declarations;
|
|
607
|
+
const declaration = declarations && declarations.length === 1 ? declarations[0] : undefined;
|
|
608
|
+
return declaration && ts.isVariableDeclaration(declaration) ? declaration : null;
|
|
609
|
+
};
|
|
610
|
+
/** Synthesized arms visible while resolving this census, upstream first. */
|
|
611
|
+
const unionArmsForResolution = (node) => {
|
|
612
|
+
const upstream = parameters.unionArmsAt(node) ?? prior.unionArmsAt(node);
|
|
613
|
+
if (upstream)
|
|
614
|
+
return upstream;
|
|
615
|
+
const declaration = ts.isVariableDeclaration(node) ? node : ts.isIdentifier(node) ? declarationOf(node) : null;
|
|
616
|
+
return declaration ? (unionArms.get(declaration) ?? null) : null;
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* Project one property through a synthesized union without manufacturing a
|
|
620
|
+
* union of callable views. A property is available only on every present
|
|
621
|
+
* constituent; its result is the same ordinary widest-type join used for
|
|
622
|
+
* writes everywhere else in this census.
|
|
623
|
+
*
|
|
624
|
+
* Asking `checker.getPropertyOfType` on the materialized whole union is not
|
|
625
|
+
* equivalent. For two subclasses inheriting one method, TypeScript can
|
|
626
|
+
* return a union of per-arm function views. That object has multiple call
|
|
627
|
+
* signatures, so the next round refuses a call that the previous round had
|
|
628
|
+
* resolved and the census oscillates. Arm-wise projection observes that
|
|
629
|
+
* both views are the same assignable convention and returns one stable
|
|
630
|
+
* method type. Nullish constituents are absence, matching
|
|
631
|
+
* `memberTypeOf`'s existing `getNonNullableType` rule.
|
|
632
|
+
*/
|
|
633
|
+
const unionMemberTypeOf = (arms, name, at) => {
|
|
634
|
+
const members = [];
|
|
635
|
+
for (const arm of arms.flatMap((type) => (type.isUnion() ? type.types : [type]))) {
|
|
636
|
+
if ((arm.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)
|
|
637
|
+
continue;
|
|
638
|
+
const member = memberTypeOf(checker, arm, name, at);
|
|
639
|
+
if (!member)
|
|
640
|
+
return null;
|
|
641
|
+
members.push(member);
|
|
642
|
+
}
|
|
643
|
+
return members.length > 0 ? widestOf(checker, members) : null;
|
|
644
|
+
};
|
|
645
|
+
/**
|
|
646
|
+
* The exact nodes sharing an inferred indexed read whose absence the program
|
|
647
|
+
* observes one statement later.
|
|
648
|
+
*
|
|
649
|
+
* With `noUncheckedIndexedAccess` off, TypeScript gives
|
|
650
|
+
*
|
|
651
|
+
* let item = items[index]
|
|
652
|
+
* if (item === undefined) item = makeItem()
|
|
653
|
+
*
|
|
654
|
+
* the bare element type at both the initializer and comparison. JavaScript
|
|
655
|
+
* still produces `undefined` for a hole or an out-of-range index. A
|
|
656
|
+
* dictionary has the same gap when a missing key is tested for truthiness:
|
|
657
|
+
* its unchecked index signature says `T`, while JavaScript returns
|
|
658
|
+
* `undefined`. The property producer already knows how to emit both optional
|
|
659
|
+
* reads; this map supplies the missing fact across the local binding.
|
|
660
|
+
*
|
|
661
|
+
* Only the declaration, initializer and direct comparison references are
|
|
662
|
+
* widened. Reads after the fallback assignment keep the checker's narrowed
|
|
663
|
+
* element type, as do indexed reads whose absence is not observed.
|
|
664
|
+
*/
|
|
665
|
+
const observedIndexedAbsence = new Map();
|
|
666
|
+
const directUndefinedComparison = (expression) => {
|
|
667
|
+
let inner = expression;
|
|
668
|
+
let parent = inner.parent;
|
|
669
|
+
while (parent && ts.isParenthesizedExpression(parent)) {
|
|
670
|
+
inner = parent;
|
|
671
|
+
parent = parent.parent;
|
|
672
|
+
}
|
|
673
|
+
if (!parent || !ts.isBinaryExpression(parent))
|
|
674
|
+
return false;
|
|
675
|
+
const operator = parent.operatorToken.kind;
|
|
676
|
+
if (operator !== ts.SyntaxKind.EqualsEqualsToken &&
|
|
677
|
+
operator !== ts.SyntaxKind.ExclamationEqualsToken &&
|
|
678
|
+
operator !== ts.SyntaxKind.EqualsEqualsEqualsToken &&
|
|
679
|
+
operator !== ts.SyntaxKind.ExclamationEqualsEqualsToken)
|
|
680
|
+
return false;
|
|
681
|
+
const other = parent.left === inner ? parent.right : parent.right === inner ? parent.left : null;
|
|
682
|
+
return other !== null && (checker.getTypeAtLocation(other).flags & ts.TypeFlags.Undefined) !== 0;
|
|
683
|
+
};
|
|
684
|
+
/** Whether this reference is consumed directly by ToBoolean. */
|
|
685
|
+
const directTruthinessTest = (expression) => {
|
|
686
|
+
let inner = expression;
|
|
687
|
+
let parent = inner.parent;
|
|
688
|
+
while (parent && ts.isParenthesizedExpression(parent)) {
|
|
689
|
+
inner = parent;
|
|
690
|
+
parent = parent.parent;
|
|
691
|
+
}
|
|
692
|
+
if (!parent)
|
|
693
|
+
return false;
|
|
694
|
+
if (ts.isIfStatement(parent) || ts.isWhileStatement(parent) || ts.isDoStatement(parent))
|
|
695
|
+
return parent.expression === inner;
|
|
696
|
+
if (ts.isForStatement(parent))
|
|
697
|
+
return parent.condition === inner;
|
|
698
|
+
if (ts.isConditionalExpression(parent))
|
|
699
|
+
return parent.condition === inner;
|
|
700
|
+
if (ts.isPrefixUnaryExpression(parent))
|
|
701
|
+
return parent.operator === ts.SyntaxKind.ExclamationToken;
|
|
702
|
+
if (!ts.isBinaryExpression(parent) || parent.left !== inner)
|
|
703
|
+
return false;
|
|
704
|
+
return (parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
|
|
705
|
+
parent.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
|
|
706
|
+
parent.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken);
|
|
707
|
+
};
|
|
708
|
+
const registerObservedIndexedAbsence = (declaration) => {
|
|
709
|
+
if (declaration.type || ts.getJSDocType(declaration) || !ts.isIdentifier(declaration.name) || !declaration.initializer)
|
|
710
|
+
return;
|
|
711
|
+
let initializer = declaration.initializer;
|
|
712
|
+
while (ts.isParenthesizedExpression(initializer))
|
|
713
|
+
initializer = initializer.expression;
|
|
714
|
+
if (!ts.isElementAccessExpression(initializer) && !ts.isPropertyAccessExpression(initializer))
|
|
715
|
+
return;
|
|
716
|
+
const key = ts.isElementAccessExpression(initializer) ? checker.getTypeAtLocation(initializer.argumentExpression) : null;
|
|
717
|
+
const receiver = checker.getTypeAtLocation(initializer.expression);
|
|
718
|
+
const constituents = receiver.isUnion() ? receiver.types : [receiver];
|
|
719
|
+
const arrayRead = key !== null &&
|
|
720
|
+
(key.flags & ts.TypeFlags.NumberLike) !== 0 &&
|
|
721
|
+
constituents.every((member) => checker.isArrayType(member) && !checker.isTupleType(member));
|
|
722
|
+
const indexKind = key !== null && (key.flags & ts.TypeFlags.NumberLike) !== 0 ? ts.IndexKind.Number : ts.IndexKind.String;
|
|
723
|
+
const dictionaryRead = constituents.every((member) => checker.getIndexTypeOfType(checker.getNonNullableType(member), indexKind) !== undefined &&
|
|
724
|
+
// A declared field has its own presence contract. Only a name resolved
|
|
725
|
+
// through the index signature shares a computed lookup's missing key.
|
|
726
|
+
(!ts.isPropertyAccessExpression(initializer) || checker.getPropertyOfType(member, initializer.name.text) === undefined));
|
|
727
|
+
// The same gap for a named read through an `as` whose value's real arms
|
|
728
|
+
// may lack the member (`asserted-arm-absence.ts`): the checker types the
|
|
729
|
+
// cell as the asserted arm's member, and JavaScript reads `undefined`.
|
|
730
|
+
const assertedRead = ts.isPropertyAccessExpression(initializer) &&
|
|
731
|
+
assertedReceiverArmMayLackMember(checker, initializer, (receiver) => checker.getTypeAtLocation(receiver));
|
|
732
|
+
if (!arrayRead && !dictionaryRead && !assertedRead)
|
|
733
|
+
return;
|
|
734
|
+
const value = checker.getTypeAtLocation(initializer);
|
|
735
|
+
if (isUnusableEvidence(value) || (value.flags & ts.TypeFlags.Unknown) !== 0)
|
|
736
|
+
return;
|
|
737
|
+
const symbol = checker.getSymbolAtLocation(declaration.name);
|
|
738
|
+
if (!symbol)
|
|
739
|
+
return;
|
|
740
|
+
const observing = flow
|
|
741
|
+
.referencesToSymbol(symbol)
|
|
742
|
+
.filter((reference) => directUndefinedComparison(reference) || directTruthinessTest(reference));
|
|
743
|
+
if (observing.length === 0)
|
|
744
|
+
return;
|
|
745
|
+
const optional = checker.getNullableType(value, ts.TypeFlags.Undefined);
|
|
746
|
+
observedIndexedAbsence.set(declaration, optional);
|
|
747
|
+
observedIndexedAbsence.set(declaration.name, optional);
|
|
748
|
+
observedIndexedAbsence.set(declaration.initializer, optional);
|
|
749
|
+
observedIndexedAbsence.set(initializer, optional);
|
|
750
|
+
for (const reference of observing)
|
|
751
|
+
observedIndexedAbsence.set(reference, optional);
|
|
752
|
+
};
|
|
753
|
+
/** The identical lookup as `declarationOf`, for an identifier whose sole declaration is a binding-pattern LEAF rather than a plain `VariableDeclaration`. */
|
|
754
|
+
const bindingElementDeclarationOf = (node) => {
|
|
755
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
756
|
+
const declarations = symbol?.declarations;
|
|
757
|
+
const declaration = declarations && declarations.length === 1 ? declarations[0] : undefined;
|
|
758
|
+
return declaration && ts.isBindingElement(declaration) ? declaration : null;
|
|
759
|
+
};
|
|
760
|
+
const attribute = (declaration, reason) => {
|
|
761
|
+
if (!refusalOf.has(declaration))
|
|
762
|
+
refusalOf.set(declaration, reason);
|
|
763
|
+
return null;
|
|
764
|
+
};
|
|
765
|
+
/**
|
|
766
|
+
* The join of this cell's write set. `derived-expression-type.ts`'s
|
|
767
|
+
* `joinOfWrites` is the one rule -- `widestOf` first and unchanged, then a
|
|
768
|
+
* nullish write read as ABSENCE and a differing-literal set widened to its
|
|
769
|
+
* primitive. It lives there rather than here because `field-bindings.ts`
|
|
770
|
+
* asks the identical question of a class field, and a field written `null`
|
|
771
|
+
* in the constructor and filled in later is exactly the shape this landed
|
|
772
|
+
* for; see that function's own comment.
|
|
773
|
+
*/
|
|
774
|
+
const joinOfWrites = (types) => sharedJoinOfWrites(checker, types);
|
|
775
|
+
/**
|
|
776
|
+
* `declaration`'s own resolved type -- the join of every write to its
|
|
777
|
+
* symbol -- or `null` when this module refuses it. Memoized in `bound`;
|
|
778
|
+
* cycle-guarded by `resolvingDeclarations` so a cell whose write reads
|
|
779
|
+
* itself (or another cell whose write reads this one) refuses instead of
|
|
780
|
+
* looping.
|
|
781
|
+
*/
|
|
782
|
+
const resolveDeclaration = (declaration) => {
|
|
783
|
+
const already = bound.get(declaration);
|
|
784
|
+
if (already)
|
|
785
|
+
return already;
|
|
786
|
+
const synthesized = unionTypeOf(unionArms.get(declaration) ?? null);
|
|
787
|
+
if (synthesized)
|
|
788
|
+
return synthesized;
|
|
789
|
+
if (!isCandidate(checker, declaration, flow))
|
|
790
|
+
return null;
|
|
791
|
+
if (refusalOf.has(declaration))
|
|
792
|
+
return null;
|
|
793
|
+
if (resolvingDeclarations.has(declaration))
|
|
794
|
+
return null;
|
|
795
|
+
resolvingDeclarations.add(declaration);
|
|
796
|
+
const symbol = checker.getSymbolAtLocation(declaration.name);
|
|
797
|
+
let result = null;
|
|
798
|
+
if (!symbol) {
|
|
799
|
+
attribute(declaration, 'no-symbol');
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
// The initializer is a WRITE, and the first one. It is joined with every
|
|
803
|
+
// later assignment rather than answering alone, so a cell that starts
|
|
804
|
+
// `null` and is filled in later carries what it actually holds -- and
|
|
805
|
+
// two writes that do not agree refuse the cell instead of picking one.
|
|
806
|
+
const writes = identifierWritesOf(symbol);
|
|
807
|
+
if (writes.length === 0) {
|
|
808
|
+
// No assignment anywhere -- the ordinary "nothing ever writes it"
|
|
809
|
+
// refusal, UNLESS this declaration is itself a `for (const x of xs)`
|
|
810
|
+
// or `for (const x in obj)` loop's own binding, in which case the
|
|
811
|
+
// loop head (never an assignment syntactically, but the value the
|
|
812
|
+
// cell holds every iteration) is the one remaining source (row 22).
|
|
813
|
+
// See `forOfElementType`/`forInElementType`.
|
|
814
|
+
const viaForOf = forOfElementType(declaration) ?? forInElementType(declaration);
|
|
815
|
+
if (viaForOf)
|
|
816
|
+
result = viaForOf;
|
|
817
|
+
else
|
|
818
|
+
attribute(declaration, noEvidenceReason(symbol, declaration));
|
|
819
|
+
}
|
|
820
|
+
else {
|
|
821
|
+
// A synthesized union from the prior composed round is a proved
|
|
822
|
+
// summary of THIS declaration's same write set, not a competing
|
|
823
|
+
// authority. Seed the new join with its flattened arms so newly
|
|
824
|
+
// resolved writes can widen it while temporarily silent recursive
|
|
825
|
+
// writes cannot erase it. Without this feedback edge, a self-updating
|
|
826
|
+
// cell alternated between its initial type and the union discovered
|
|
827
|
+
// from its method-call assignments (`find-my-way`'s `currentNode`).
|
|
828
|
+
// The transfer is now inflationary over the census's own arm lattice:
|
|
829
|
+
// syntax contributes new evidence; no round retracts proven evidence.
|
|
830
|
+
const priorArms = parameters.unionArmsAt(declaration) ?? prior.unionArmsAt(declaration);
|
|
831
|
+
const types = priorArms ? priorArms.flatMap((type) => (type.isUnion() ? type.types : [type])) : [];
|
|
832
|
+
let silent = 0;
|
|
833
|
+
let refused = null;
|
|
834
|
+
for (const write of writes) {
|
|
835
|
+
// A loop-head pattern write already carries its own resolved type
|
|
836
|
+
// (`identifierWritesOf`'s `resolvedType`) -- there is no backing
|
|
837
|
+
// expression for `known`/`resolveExpr` to re-type, since the value
|
|
838
|
+
// comes from the loop's own iteration rather than any expression
|
|
839
|
+
// the program wrote.
|
|
840
|
+
const declared = write.resolvedType ?? known(write.node);
|
|
841
|
+
// Settled synthesized source arms outrank a fresh derivation from
|
|
842
|
+
// narrower caller/write samples, just as upstream typeAt does.
|
|
843
|
+
const sourceArms = declared ? null : unionArmsForResolution(write.node);
|
|
844
|
+
const type = declared ?? (sourceArms ? null : resolveExpr(write.node));
|
|
845
|
+
const arms = sourceArms ?? (type ? null : branchArmsOf(write.node));
|
|
846
|
+
// A checker union and a census arm list describe the same possible
|
|
847
|
+
// writes. Join their constituents uniformly from the first round;
|
|
848
|
+
// flattening only carried arms can alternate the publication between
|
|
849
|
+
// typeAt and unionArmsAt on every outer inference round.
|
|
850
|
+
if (type)
|
|
851
|
+
types.push(...(type.isUnion() ? type.types : [type]));
|
|
852
|
+
// A synthesized return has no checker ts.Type, but its complete
|
|
853
|
+
// member list is still evidence for the cell receiving it. Dropping
|
|
854
|
+
// that channel makes a native call result flow into an any cell.
|
|
855
|
+
else if (arms)
|
|
856
|
+
types.push(...arms.flatMap((arm) => (arm.isUnion() ? arm.types : [arm])));
|
|
857
|
+
// A write typed `void`/`never` is a real fact stating the storage
|
|
858
|
+
// holds nothing a program can use -- a veto in both phases, exactly
|
|
859
|
+
// as `parameter-bindings.ts` keeps `call-passes-no-argument` firing
|
|
860
|
+
// in its own relaxed phase. Only a write nobody could type is
|
|
861
|
+
// SILENCE.
|
|
862
|
+
else if (statesNoStorage(write.node)) {
|
|
863
|
+
refused = 'write-states-no-storage';
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
866
|
+
else
|
|
867
|
+
silent += 1;
|
|
868
|
+
}
|
|
869
|
+
// EVIDENCE EXHAUSTED -- the same rule, the same order, as
|
|
870
|
+
// `parameter-bindings.ts`'s `skipSilentSites` phase and
|
|
871
|
+
// `field-bindings.ts`'s twin of this loop: a write that states
|
|
872
|
+
// nothing is not a write that disagrees. Strict phase first (a silent
|
|
873
|
+
// write refuses the cell); the relaxed retry, run only over cells the
|
|
874
|
+
// strict pass could not bind, joins the writes that DO speak.
|
|
875
|
+
// `writes-disagree` still fires over what remains, and a cell whose
|
|
876
|
+
// every write is silent still asks `declaredReturnEvidenceFor` and
|
|
877
|
+
// then refuses, exactly as before.
|
|
878
|
+
if (refused)
|
|
879
|
+
attribute(declaration, refused);
|
|
880
|
+
else if (silent > 0 && (!lenientPhase || types.length === 0)) {
|
|
881
|
+
// Some write failed the ordinary route -- try the one remaining
|
|
882
|
+
// authority before giving up: the enclosing function's own STATED
|
|
883
|
+
// return type, when this cell is what its `return` is built from
|
|
884
|
+
// (a program statement, which outranks a join over a write
|
|
885
|
+
// SUBSET, so it keeps answering ahead of the relaxed retry). See
|
|
886
|
+
// `declaredReturnEvidenceFor`'s header.
|
|
887
|
+
const viaReturn = declaredReturnEvidenceFor(checker, declaration, symbol);
|
|
888
|
+
if (viaReturn) {
|
|
889
|
+
result = viaReturn;
|
|
890
|
+
// Publish the same answer at each SILENT write, not just at the
|
|
891
|
+
// declaration. `bound` (below) is keyed by the declaration alone,
|
|
892
|
+
// so a query landing on the write expression itself -- a call
|
|
893
|
+
// producer asking a `CallExpression` for its OWN result type,
|
|
894
|
+
// rather than something asking what the cell it feeds holds --
|
|
895
|
+
// used to retry `compute` from scratch and hit the identical
|
|
896
|
+
// wall that made the write silent to begin with: the checker's
|
|
897
|
+
// resolved signature return is `any` for a reason internal to
|
|
898
|
+
// the callee's own declaration (an erased generic default),
|
|
899
|
+
// which does not become less `any` on a second look. That
|
|
900
|
+
// divergence is exactly this module's header case, hono's own
|
|
901
|
+
// `res = matchResult[0][0][0][0](c, next)` inside `#dispatch` --
|
|
902
|
+
// `res`'s cell got the right answer FROM this return-evidence
|
|
903
|
+
// fallback, but the call expression that fed it never did,
|
|
904
|
+
// because nothing here fed it back. A cell and the expression
|
|
905
|
+
// that writes it are one fact, and both readers of that fact
|
|
906
|
+
// must agree, the same "two authorities" shape this compiler
|
|
907
|
+
// refuses everywhere else. Every write that reached this branch
|
|
908
|
+
// as silent was already run through `resolveExpr` (the `type`
|
|
909
|
+
// computed above came from `known(write) ?? resolveExpr(write)`,
|
|
910
|
+
// and `known` cannot have supplied a non-null `type` for a
|
|
911
|
+
// silent write by construction), so `nodeMemo` already holds a
|
|
912
|
+
// settled `null` for it -- never `undefined` (unresolved) and
|
|
913
|
+
// never a cycle-guard bail (which leaves no entry). Recorded into
|
|
914
|
+
// `writeAnswers`, not `nodeMemo` -- see that map's own comment
|
|
915
|
+
// for why overwriting the settled `null` in place does not
|
|
916
|
+
// survive: measured directly, it does not.
|
|
917
|
+
for (const write of writes) {
|
|
918
|
+
if (nodeMemo.get(write.node) === null)
|
|
919
|
+
writeAnswers.set(write.node, viaReturn);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
// The single largest refusal reason on the three.js app (2087, 39% of all
|
|
924
|
+
// binding refusals) and a pure CASCADE: every one of these cells
|
|
925
|
+
// is refused because some write it holds is itself unresolved, so
|
|
926
|
+
// ranking the cells says nothing about where to work. This prints
|
|
927
|
+
// the unresolved WRITES instead, which is the set that has roots.
|
|
928
|
+
if (process.env['GEA_LOCAL_DEBUG']) {
|
|
929
|
+
for (const write of writes) {
|
|
930
|
+
if (nodeMemo.get(write.node) !== null)
|
|
931
|
+
continue;
|
|
932
|
+
const file = write.node.getSourceFile();
|
|
933
|
+
const line = file.getLineAndCharacterOfPosition(write.node.getStart()).line + 1;
|
|
934
|
+
const where = `${file.fileName.split('/').slice(-2).join('/')}:${line}`;
|
|
935
|
+
process.stderr.write(`[LOCAL] ${ts.SyntaxKind[write.node.kind]} ${where} ${write.node.getText().slice(0, 60).replace(/\s+/g, ' ')}\n`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
attribute(declaration, 'write-unresolved');
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
else if (silent > 0 && types.every((type) => (type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)) {
|
|
942
|
+
// AN ABSENCE IS NOT EVIDENCE.
|
|
943
|
+
//
|
|
944
|
+
// The relaxed phase above joins the writes that DO speak, and that
|
|
945
|
+
// is right whenever one of them states a type. It is not right when
|
|
946
|
+
// every surviving write is `null`/`undefined` and some other write
|
|
947
|
+
// was silent: `null` says what the cell holds when nothing else has
|
|
948
|
+
// been stored in it, never what it holds. `WebXRManager.js`'s
|
|
949
|
+
// `let session = null` is written from `setSession( value )` too,
|
|
950
|
+
// and binding the cell to bare `null` on the strength of the
|
|
951
|
+
// initializer alone made every `session.removeEventListener(...)` a
|
|
952
|
+
// property access on `null` -- 69 unmet obligations on the three.js app, and
|
|
953
|
+
// underneath them a store-side silent miscompile: the emitted cell
|
|
954
|
+
// would hold a null pointer that the real write has no
|
|
955
|
+
// representation to fill. 76 locals program-wide were bound this
|
|
956
|
+
// way. The same rule `parameter-bindings.ts` applies to a defaulted
|
|
957
|
+
// parameter (a default value is not a type) and `field-bindings.ts`
|
|
958
|
+
// to a field initialized `null`.
|
|
959
|
+
//
|
|
960
|
+
// Refusing leaves the cell exactly as dynamic as its unresolved
|
|
961
|
+
// write makes it -- honest, and the boxing this costs closes when
|
|
962
|
+
// that write's own type is recovered.
|
|
963
|
+
attribute(declaration, 'writes-state-only-absence');
|
|
964
|
+
}
|
|
965
|
+
else {
|
|
966
|
+
// Keep a carried synthesized union in its canonical arm channel.
|
|
967
|
+
// Feeding its arms through `joinOfWrites` can materialize one
|
|
968
|
+
// checker union and move the same fact into `typeAt`; the following
|
|
969
|
+
// round then has no carried arms, reconstructs them, and alternates
|
|
970
|
+
// forever between two representations of one answer. Flatten first
|
|
971
|
+
// so a previously nullable arm and a duplicate newly-resolved write
|
|
972
|
+
// compare as their actual constituents.
|
|
973
|
+
const carried = priorArms
|
|
974
|
+
? disjointUnionMembersOf(checker, types.flatMap((type) => (type.isUnion() ? type.types : [type])))
|
|
975
|
+
: null;
|
|
976
|
+
if (carried)
|
|
977
|
+
unionArms.set(declaration, carried);
|
|
978
|
+
else {
|
|
979
|
+
const widest = joinOfWrites(types);
|
|
980
|
+
if (widest) {
|
|
981
|
+
result = widest;
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
// The join found no single covering type. Before refusing, ask
|
|
985
|
+
// whether the disagreement is itself a sound answer -- see
|
|
986
|
+
// `disjointUnionMembersOf`'s own comment for what "sound" means.
|
|
987
|
+
const arms = disjointUnionMembersOf(checker, types);
|
|
988
|
+
if (arms)
|
|
989
|
+
unionArms.set(declaration, arms);
|
|
990
|
+
else
|
|
991
|
+
attribute(declaration, 'writes-disagree');
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
resolvingDeclarations.delete(declaration);
|
|
998
|
+
if (result)
|
|
999
|
+
bound.set(declaration, result);
|
|
1000
|
+
return result;
|
|
1001
|
+
};
|
|
1002
|
+
const unwrapParens = (node) => {
|
|
1003
|
+
let current = node;
|
|
1004
|
+
while (ts.isParenthesizedExpression(current))
|
|
1005
|
+
current = current.expression;
|
|
1006
|
+
return current;
|
|
1007
|
+
};
|
|
1008
|
+
/** `known(node) ?? resolveExpr(node)`, except at an `as`/`<T>` cast: the checker's own answer there is taken as-is and never read past. */
|
|
1009
|
+
const knownOrResolve = (node) => {
|
|
1010
|
+
const unwrapped = unwrapParens(node);
|
|
1011
|
+
if (ts.isAsExpression(unwrapped) || ts.isTypeAssertionExpression(unwrapped))
|
|
1012
|
+
return known(unwrapped);
|
|
1013
|
+
return known(node) ?? resolveExpr(node);
|
|
1014
|
+
};
|
|
1015
|
+
/**
|
|
1016
|
+
* ONE recursive notion of the storage a binding PATTERN reaches into,
|
|
1017
|
+
* covering rows 14 (object destructuring), 15 (array destructuring), 16
|
|
1018
|
+
* (destructuring defaults) and the destructured half of row 22 (for-of)
|
|
1019
|
+
* together, rather than as separate arms per pattern shape. A binding
|
|
1020
|
+
* pattern is a TREE of references (`bind(reference, value)`'s
|
|
1021
|
+
* `reference` half, ADDENDUM 3's own vocabulary): an object pattern's
|
|
1022
|
+
* MEMBERS and an array pattern's ELEMENTS are the language's only two leaf
|
|
1023
|
+
* shapes, so the branch inside `resolveBindingElement` below is the
|
|
1024
|
+
* recursion's BASE CASE run once, not a syntax special case per pattern
|
|
1025
|
+
* kind -- and it runs identically at any nesting depth, because a NESTED
|
|
1026
|
+
* pattern's own source is just the outer element's own resolved type
|
|
1027
|
+
* (`sourceTypeOfPattern`'s `ts.isBindingElement(parent)` arm), so depth is
|
|
1028
|
+
* free and no depth-specific code exists.
|
|
1029
|
+
*
|
|
1030
|
+
* `boundElements`/`elementRefusalOf`/`resolvingElements` mirror
|
|
1031
|
+
* `bound`/`refusalOf`/`resolvingDeclarations` above -- the identical
|
|
1032
|
+
* memo/refusal/cycle-guard shape, keyed by `ts.BindingElement` instead of
|
|
1033
|
+
* `ts.VariableDeclaration`, because a pattern leaf is a different node
|
|
1034
|
+
* kind from a plain declaration and cannot share the same map key.
|
|
1035
|
+
*/
|
|
1036
|
+
const boundElements = new Map();
|
|
1037
|
+
const elementRefusalOf = new Map();
|
|
1038
|
+
const resolvingElements = new Set();
|
|
1039
|
+
/**
|
|
1040
|
+
* The iterable expression of a `for (const <name> of <expr>)` loop, when
|
|
1041
|
+
* `declaration` is that loop's own binding -- shared by the plain-
|
|
1042
|
+
* identifier case (`forOfElementType`, row 22) and the destructured-
|
|
1043
|
+
* binding case (`patternSourceExpression`), so both ask the identical "is
|
|
1044
|
+
* this a for-of binding" question once rather than twice. `for await` is
|
|
1045
|
+
* refused outright: it iterates a DIFFERENT protocol (the async-iterable
|
|
1046
|
+
* PROMISE each step resolves), not the plain element this reads.
|
|
1047
|
+
*/
|
|
1048
|
+
const forOfIterableOf = (declaration) => {
|
|
1049
|
+
const list = declaration.parent;
|
|
1050
|
+
if (!ts.isVariableDeclarationList(list))
|
|
1051
|
+
return null;
|
|
1052
|
+
const stmt = list.parent;
|
|
1053
|
+
if (!ts.isForOfStatement(stmt) || stmt.initializer !== list || stmt.awaitModifier)
|
|
1054
|
+
return null;
|
|
1055
|
+
return stmt.expression;
|
|
1056
|
+
};
|
|
1057
|
+
/**
|
|
1058
|
+
* The element type a `for (const x of xs)` binding receives -- `xs`'s own
|
|
1059
|
+
* numeric index signature, the identical checker query `indexedTypeOf`
|
|
1060
|
+
* already runs for an ordinary `a[i]` read elsewhere in this module, with
|
|
1061
|
+
* the same array-census fallback (`collections.arrayElementForRead`) an
|
|
1062
|
+
* ordinary element READ already falls back to when the receiver's own
|
|
1063
|
+
* index signature is unusable (`never[]`, most often, from a push-only
|
|
1064
|
+
* cell). Not a special case: any indexable iterable answers here, nothing
|
|
1065
|
+
* keyed to a particular library or container name.
|
|
1066
|
+
*/
|
|
1067
|
+
const forOfElementType = (declaration) => {
|
|
1068
|
+
const expression = forOfIterableOf(declaration);
|
|
1069
|
+
if (!expression)
|
|
1070
|
+
return null;
|
|
1071
|
+
const iterable = knownOrResolve(expression);
|
|
1072
|
+
if (!iterable)
|
|
1073
|
+
return null;
|
|
1074
|
+
const nonNull = checker.getNonNullableType(iterable);
|
|
1075
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1076
|
+
if (indexed && !isUnusableEvidence(indexed))
|
|
1077
|
+
return indexed;
|
|
1078
|
+
return collections.arrayElementForRead(expression);
|
|
1079
|
+
};
|
|
1080
|
+
/**
|
|
1081
|
+
* The element type a `for (const key in obj)` binding receives.
|
|
1082
|
+
*
|
|
1083
|
+
* `ForIn/OfHeadEvaluation` (ECMA-262 13.7.5.6, the `enumerate` case)
|
|
1084
|
+
* enumerates OWN-plus-INHERITED enumerable keys and coerces every one to a
|
|
1085
|
+
* STRING before the loop body ever sees it -- never a symbol, never the
|
|
1086
|
+
* object's own element type -- so the answer is `string` unconditionally,
|
|
1087
|
+
* the same checker type `forOfBareIdentifierElementTypeAt` already returns
|
|
1088
|
+
* a few lines up for the bare-identifier-reused shape of this same loop
|
|
1089
|
+
* (`var k; for (k in obj) ...`). This is `forOfElementType`'s DECLARED-in-
|
|
1090
|
+
* loop counterpart for `for...in`: without it, `for (const key in obj) ...`
|
|
1091
|
+
* with a `key` the body only ever READS found no evidence at all and
|
|
1092
|
+
* refused as `no-writes:existence-only:iteration-binding` -- the loop's own
|
|
1093
|
+
* binding is exactly as real a value as a for-of element is, just one this
|
|
1094
|
+
* module never asked the language's own (fixed, unconditional) answer for.
|
|
1095
|
+
*/
|
|
1096
|
+
const forInElementType = (declaration) => {
|
|
1097
|
+
const list = declaration.parent;
|
|
1098
|
+
if (!ts.isVariableDeclarationList(list))
|
|
1099
|
+
return null;
|
|
1100
|
+
const stmt = list.parent;
|
|
1101
|
+
if (!ts.isForInStatement(stmt) || stmt.initializer !== list)
|
|
1102
|
+
return null;
|
|
1103
|
+
return checker.getStringType();
|
|
1104
|
+
};
|
|
1105
|
+
/**
|
|
1106
|
+
* The element type a for-of/for-in loop's own BARE-IDENTIFIER head receives,
|
|
1107
|
+
* when that identifier is declared OUTSIDE the loop and reused as a plain
|
|
1108
|
+
* assignment target -- `var v; for (v of xs) ...` -- rather than declared
|
|
1109
|
+
* by the loop itself. `flow/value-flow.ts`'s `visit` records this write via
|
|
1110
|
+
* `recordAssignmentTarget(initializer, 'iteration-binding', null, node)`,
|
|
1111
|
+
* whose `naming` is the loop head's own identifier EXPRESSION -- a
|
|
1112
|
+
* different node from `forOfElementType`'s `declaration`, and one whose
|
|
1113
|
+
* `.parent` IS the ForOfStatement/ForInStatement directly (unlike a
|
|
1114
|
+
* declared-in-loop binding, whose name is parented under its own
|
|
1115
|
+
* `VariableDeclaration`, and unlike a literal pattern head, walked instead
|
|
1116
|
+
* by `forOfPatternElementTypeAt`). `identifierWritesOf` had no case for a
|
|
1117
|
+
* bare `'iteration-binding'` write at all, so a cell filled ONLY this way
|
|
1118
|
+
* found no evidence and boxed even though `xs` itself is a native array --
|
|
1119
|
+
* `forOfElementType`'s own logic, asked at the WRITE's loop statement
|
|
1120
|
+
* instead of at a declaration's syntactic position, since a `var v`
|
|
1121
|
+
* declared elsewhere is never itself parented under the for-of/for-in.
|
|
1122
|
+
*/
|
|
1123
|
+
const forOfBareIdentifierElementTypeAt = (naming) => {
|
|
1124
|
+
const parent = naming.parent;
|
|
1125
|
+
if (ts.isForOfStatement(parent) && parent.initializer === naming) {
|
|
1126
|
+
if (parent.awaitModifier)
|
|
1127
|
+
return null;
|
|
1128
|
+
const iterable = knownOrResolve(parent.expression);
|
|
1129
|
+
if (!iterable)
|
|
1130
|
+
return null;
|
|
1131
|
+
const nonNull = checker.getNonNullableType(iterable);
|
|
1132
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1133
|
+
if (indexed && !isUnusableEvidence(indexed))
|
|
1134
|
+
return indexed;
|
|
1135
|
+
return collections.arrayElementForRead(parent.expression);
|
|
1136
|
+
}
|
|
1137
|
+
if (ts.isForInStatement(parent) && parent.initializer === naming)
|
|
1138
|
+
return checker.getStringType();
|
|
1139
|
+
return null;
|
|
1140
|
+
};
|
|
1141
|
+
/**
|
|
1142
|
+
* Walks a destructuring-ASSIGNMENT target up through any nested array/
|
|
1143
|
+
* object literal patterns to the pattern's own ROOT, recording the
|
|
1144
|
+
* (position|key) step at each level -- the census-side twin of
|
|
1145
|
+
* `producers/destructuring.ts`'s `arrayAssignmentBoundTypeOf` recursion,
|
|
1146
|
+
* needed here because a for-of/for-in LOOP-HEAD pattern's per-position
|
|
1147
|
+
* value has no literal source expression
|
|
1148
|
+
* `destructuringAssignmentEvidenceExpressionAt` can index into: it comes
|
|
1149
|
+
* from the loop's own iteration, never from an expression the program
|
|
1150
|
+
* wrote. Steps are ordered OUTERMOST first, the order they must be applied
|
|
1151
|
+
* in to the loop's own per-iteration type.
|
|
1152
|
+
*/
|
|
1153
|
+
const assignmentPatternStepsAt = (target) => {
|
|
1154
|
+
const steps = [];
|
|
1155
|
+
let current = target;
|
|
1156
|
+
for (;;) {
|
|
1157
|
+
const arrayTarget = arrayAssignmentTargetOf(current);
|
|
1158
|
+
if (arrayTarget) {
|
|
1159
|
+
steps.unshift({ kind: 'array', position: arrayTarget.position });
|
|
1160
|
+
current = arrayTarget.pattern;
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
const objectElement = objectAssignmentElementOfTarget(current);
|
|
1164
|
+
if (objectElement) {
|
|
1165
|
+
const pattern = objectElement.parent;
|
|
1166
|
+
if (!ts.isObjectLiteralExpression(pattern))
|
|
1167
|
+
return null;
|
|
1168
|
+
const keyName = ts.isShorthandPropertyAssignment(objectElement) ? objectElement.name.text : staticPropertyName(objectElement.name);
|
|
1169
|
+
if (keyName === null)
|
|
1170
|
+
return null;
|
|
1171
|
+
steps.unshift({ kind: 'object', key: keyName });
|
|
1172
|
+
current = pattern;
|
|
1173
|
+
continue;
|
|
1174
|
+
}
|
|
1175
|
+
break;
|
|
1176
|
+
}
|
|
1177
|
+
return steps.length > 0 ? { root: current, steps } : null;
|
|
1178
|
+
};
|
|
1179
|
+
/**
|
|
1180
|
+
* The per-position/per-key type an array/object LITERAL for-of/for-in
|
|
1181
|
+
* loop-head pattern's element receives every iteration -- the assignment
|
|
1182
|
+
* twin of `resolveBindingElement`'s indexed/tuple read, over the loop's
|
|
1183
|
+
* own per-iteration value (a for-of's iterable element, a for-in's key
|
|
1184
|
+
* STRING) rather than a `const`/`let` declaration's initializer: `var
|
|
1185
|
+
* pairs = [[1, 2]]; var a, b; for ([a, b] of pairs)` never writes `a`/`b`
|
|
1186
|
+
* from any right-hand side, only from the loop head itself.
|
|
1187
|
+
*/
|
|
1188
|
+
const forOfPatternElementTypeAt = (naming) => {
|
|
1189
|
+
const located = assignmentPatternStepsAt(naming);
|
|
1190
|
+
if (!located)
|
|
1191
|
+
return null;
|
|
1192
|
+
const parent = located.root.parent;
|
|
1193
|
+
let elementType;
|
|
1194
|
+
if (ts.isForOfStatement(parent) && parent.initializer === located.root) {
|
|
1195
|
+
const iterable = knownOrResolve(parent.expression);
|
|
1196
|
+
if (!iterable)
|
|
1197
|
+
return null;
|
|
1198
|
+
const nonNull = checker.getNonNullableType(iterable);
|
|
1199
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1200
|
+
elementType = indexed && !isUnusableEvidence(indexed) ? indexed : collections.arrayElementForRead(parent.expression);
|
|
1201
|
+
}
|
|
1202
|
+
else if (ts.isForInStatement(parent) && parent.initializer === located.root) {
|
|
1203
|
+
elementType = checker.getStringType();
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
return null;
|
|
1207
|
+
}
|
|
1208
|
+
if (!elementType)
|
|
1209
|
+
return null;
|
|
1210
|
+
for (const step of located.steps) {
|
|
1211
|
+
if (step.kind === 'object') {
|
|
1212
|
+
const propType = propertyTypeOf(elementType, step.key, naming);
|
|
1213
|
+
if (!propType)
|
|
1214
|
+
return null;
|
|
1215
|
+
elementType = propType;
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
const nonNull = checker.getNonNullableType(elementType);
|
|
1219
|
+
if (checker.isTupleType(nonNull)) {
|
|
1220
|
+
const stated = checker.getTypeArguments(nonNull)[step.position];
|
|
1221
|
+
elementType = stated === undefined ? checker.getUndefinedType() : checker.getBaseTypeOfLiteralType(stated);
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1225
|
+
if (!indexed || isUnusableEvidence(indexed))
|
|
1226
|
+
return null;
|
|
1227
|
+
elementType = indexed;
|
|
1228
|
+
}
|
|
1229
|
+
return elementType;
|
|
1230
|
+
};
|
|
1231
|
+
/** The actual SOURCE expression a top-level (non-nested) pattern reads from, when one syntactically exists -- used only for the array-census fallback below; the recursive nested case has no single expression of its own (its source IS another element's resolved type) and does not need one. */
|
|
1232
|
+
const patternSourceExpression = (pattern) => {
|
|
1233
|
+
const parent = pattern.parent;
|
|
1234
|
+
if (!ts.isVariableDeclaration(parent))
|
|
1235
|
+
return null;
|
|
1236
|
+
return parent.initializer ?? forOfIterableOf(parent);
|
|
1237
|
+
};
|
|
1238
|
+
/**
|
|
1239
|
+
* The value flowing INTO a whole binding pattern -- the source half of the
|
|
1240
|
+
* `bind(reference, value)` primitive, asked at the pattern's own root
|
|
1241
|
+
* rather than at one leaf. Three roots, each already a question this
|
|
1242
|
+
* module (or a sibling one) asks for an ordinary identifier, never a new
|
|
1243
|
+
* one invented for destructuring:
|
|
1244
|
+
* - `const {a} = expr` / `let [a] = expr` -- the declaration's own
|
|
1245
|
+
* initializer, read the same way any other initializer is
|
|
1246
|
+
* (`knownOrResolve`).
|
|
1247
|
+
* - `for (const {a} of xs)` -- `xs`'s own element type
|
|
1248
|
+
* (`forOfElementType`), the identical question a for-of loop over a
|
|
1249
|
+
* PLAIN identifier already answers.
|
|
1250
|
+
* - a NESTED pattern (`const {a: {b}} = expr`) -- the outer element's own
|
|
1251
|
+
* resolved type (`resolveBindingElement`), so nesting recurses for
|
|
1252
|
+
* free.
|
|
1253
|
+
* A parameter's own pattern (`function f({a}) {}`) is PAR's cell, not this
|
|
1254
|
+
* module's: neither branch below matches a `ParameterDeclaration` parent,
|
|
1255
|
+
* so it falls through to `null` -- refusing exactly as everywhere else
|
|
1256
|
+
* this module does not own a cell.
|
|
1257
|
+
*/
|
|
1258
|
+
const sourceTypeOfPattern = (pattern) => {
|
|
1259
|
+
const parent = pattern.parent;
|
|
1260
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
1261
|
+
// `= {}` is a holder, not a non-statement -- see `exactEmptyObjectLiteralType`.
|
|
1262
|
+
if (parent.initializer)
|
|
1263
|
+
return exactEmptyObjectLiteralType(checker, parent.initializer) ?? knownOrResolve(parent.initializer);
|
|
1264
|
+
return forOfElementType(parent);
|
|
1265
|
+
}
|
|
1266
|
+
if (ts.isBindingElement(parent))
|
|
1267
|
+
return resolveBindingElement(parent);
|
|
1268
|
+
// A parameter's own pattern reads the slot the PARAMETER census bound
|
|
1269
|
+
// from the call sites (`parameter-bindings.ts`'s `isUnannotated` admits
|
|
1270
|
+
// a destructured parameter); that census also answers the leaves itself,
|
|
1271
|
+
// so this arm only matters for a leaf it declined and this module can
|
|
1272
|
+
// still finish (a default joined onto a resolved element, say).
|
|
1273
|
+
if (ts.isParameter(parent))
|
|
1274
|
+
return parameters.typeAt(parent);
|
|
1275
|
+
return null;
|
|
1276
|
+
};
|
|
1277
|
+
/**
|
|
1278
|
+
* The source CELL type for object-rest layout. Unlike a named property read,
|
|
1279
|
+
* rest copies the runtime object's remaining key set, so a predicate's closed
|
|
1280
|
+
* control-flow view cannot erase an index signature owned by the cited cell.
|
|
1281
|
+
*/
|
|
1282
|
+
const storageSourceTypeOfPattern = (pattern) => {
|
|
1283
|
+
const parent = pattern.parent;
|
|
1284
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
1285
|
+
if (parent.initializer)
|
|
1286
|
+
return resolveExpr(parent.initializer) ?? knownOrResolve(parent.initializer);
|
|
1287
|
+
return forOfElementType(parent);
|
|
1288
|
+
}
|
|
1289
|
+
if (ts.isBindingElement(parent))
|
|
1290
|
+
return resolveBindingElement(parent);
|
|
1291
|
+
return null;
|
|
1292
|
+
};
|
|
1293
|
+
/**
|
|
1294
|
+
* `element`'s own resolved type -- the ONE recursive function answering
|
|
1295
|
+
* every binding-pattern leaf, object or array, nested or not, defaulted or
|
|
1296
|
+
* not. Object and array are the language's only two pattern shapes, so the
|
|
1297
|
+
* branch below is the recursion's BASE CASE, not a special-cased arm per
|
|
1298
|
+
* pattern kind; a default value is joined in exactly once, after the
|
|
1299
|
+
* branch, for whichever shape produced `ownType` -- also not a third case,
|
|
1300
|
+
* since every leaf (object or array) can carry one.
|
|
1301
|
+
*
|
|
1302
|
+
* A computed property name (`{[k]: v}`) names no FIXED member -- `key` is
|
|
1303
|
+
* then not an identifier and `ownType` stays `null`, refused the same way
|
|
1304
|
+
* an unresolved member read anywhere else in this module refuses.
|
|
1305
|
+
*
|
|
1306
|
+
* `ownType` (the source-derived projection) must resolve successfully
|
|
1307
|
+
* BEFORE a default is ever considered -- a default's type is never used as
|
|
1308
|
+
* sole evidence, because an untyped source could hold anything at
|
|
1309
|
+
* runtime, not only the default's type. `joinOfWrites` (not plain
|
|
1310
|
+
* `widestOf`) combines `ownType` with a default's type because it already
|
|
1311
|
+
* safely handles the "nullish is absence" idiom a defaulted destructure
|
|
1312
|
+
* commonly is (`const {a = 1} = o` reads exactly as `a` being `T |
|
|
1313
|
+
* undefined` with the `undefined` arm's own default value).
|
|
1314
|
+
*/
|
|
1315
|
+
const resolveBindingElement = (element) => {
|
|
1316
|
+
const already = boundElements.get(element);
|
|
1317
|
+
if (already)
|
|
1318
|
+
return already;
|
|
1319
|
+
if (elementRefusalOf.has(element))
|
|
1320
|
+
return null;
|
|
1321
|
+
if (resolvingElements.has(element))
|
|
1322
|
+
return null;
|
|
1323
|
+
resolvingElements.add(element);
|
|
1324
|
+
const pattern = element.parent;
|
|
1325
|
+
if (element.dotDotDotToken) {
|
|
1326
|
+
const sourceType = ts.isObjectBindingPattern(pattern) ? storageSourceTypeOfPattern(pattern) : null;
|
|
1327
|
+
const nonNull = sourceType ? checker.getNonNullableType(sourceType) : null;
|
|
1328
|
+
const stringIndex = nonNull ? checker.getIndexTypeOfType(nonNull, ts.IndexKind.String) : undefined;
|
|
1329
|
+
const result = sourceType && stringIndex && checker.getPropertiesOfType(nonNull).length === 0 ? sourceType : null;
|
|
1330
|
+
resolvingElements.delete(element);
|
|
1331
|
+
if (result)
|
|
1332
|
+
boundElements.set(element, result);
|
|
1333
|
+
else
|
|
1334
|
+
elementRefusalOf.set(element, sourceType ? 'rest-source-not-open-dictionary' : 'source-unresolved');
|
|
1335
|
+
return result;
|
|
1336
|
+
}
|
|
1337
|
+
const sourceType = sourceTypeOfPattern(pattern);
|
|
1338
|
+
let ownType = null;
|
|
1339
|
+
if (sourceType) {
|
|
1340
|
+
if (ts.isObjectBindingPattern(pattern)) {
|
|
1341
|
+
const key = element.propertyName ?? element.name;
|
|
1342
|
+
const keyText = ts.isIdentifier(key) || ts.isStringLiteral(key) || ts.isNumericLiteral(key) ? key.text : null;
|
|
1343
|
+
const nonNull = checker.getNonNullableType(sourceType);
|
|
1344
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1345
|
+
// A numeric key over a plain array reads the element WITH `undefined`
|
|
1346
|
+
// (`[...{ 3: y }] = [7, 8, 9]`); the parameter census's
|
|
1347
|
+
// `arrayIndexPatternReadOf` is the same rule for a formal's pattern.
|
|
1348
|
+
const arrayIndexRead = keyText !== null &&
|
|
1349
|
+
/^(0|[1-9][0-9]*)$/.test(keyText) &&
|
|
1350
|
+
indexed &&
|
|
1351
|
+
!isUnusableEvidence(indexed) &&
|
|
1352
|
+
!checker.isTupleType(nonNull) &&
|
|
1353
|
+
!checker.getIndexTypeOfType(nonNull, ts.IndexKind.String)
|
|
1354
|
+
? checker.getNullableType(indexed, ts.TypeFlags.Undefined)
|
|
1355
|
+
: null;
|
|
1356
|
+
// A key the holder's closed object type declares no member for reads
|
|
1357
|
+
// `undefined` (`const { fn = function () {} } = {}` binds the default);
|
|
1358
|
+
// the parameter census's `absentKeyPatternReadOf` is the same rule and
|
|
1359
|
+
// states why an index signature or a union keeps the member read.
|
|
1360
|
+
const absentRead = keyText !== null &&
|
|
1361
|
+
arrayIndexRead === null &&
|
|
1362
|
+
!isUnusableEvidence(nonNull) &&
|
|
1363
|
+
(nonNull.flags & ts.TypeFlags.Object) !== 0 &&
|
|
1364
|
+
!checker.getPropertyOfType(nonNull, keyText) &&
|
|
1365
|
+
!indexed &&
|
|
1366
|
+
!checker.getIndexTypeOfType(nonNull, ts.IndexKind.String)
|
|
1367
|
+
? checker.getUndefinedType()
|
|
1368
|
+
: null;
|
|
1369
|
+
ownType = arrayIndexRead ?? absentRead ?? (keyText !== null ? propertyTypeOf(sourceType, keyText, element) : null);
|
|
1370
|
+
}
|
|
1371
|
+
else {
|
|
1372
|
+
const nonNull = checker.getNonNullableType(sourceType);
|
|
1373
|
+
const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
|
|
1374
|
+
// A plain array's element is read WITH `undefined`: the pattern may run
|
|
1375
|
+
// past the array's length, and the language binds the name to
|
|
1376
|
+
// `undefined` there (ECMA-262 IteratorBindingInitialization) rather
|
|
1377
|
+
// than faulting. A tuple states its length, so its position answers
|
|
1378
|
+
// bare -- `checker.isTupleType` is that distinction.
|
|
1379
|
+
const withAbsence = (element) => checker.isTupleType(nonNull) ? element : checker.getNullableType(element, ts.TypeFlags.Undefined);
|
|
1380
|
+
if (indexed && !isUnusableEvidence(indexed)) {
|
|
1381
|
+
ownType = withAbsence(indexed);
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
const expr = patternSourceExpression(pattern);
|
|
1385
|
+
const censused = expr ? collections.arrayElementForRead(expr) : null;
|
|
1386
|
+
// A non-array iterable (`var [a, b] = g()` over a generator, a Set,
|
|
1387
|
+
// a Map) has no numeric index to read; what a position holds is
|
|
1388
|
+
// what the source YIELDS -- and always with `undefined`, since a
|
|
1389
|
+
// cursor can be exhausted before any position (the checker types
|
|
1390
|
+
// the binding bare, which read `0` for a missing second value).
|
|
1391
|
+
const yielded = censused ? null : iteratorYieldTypesOf(checker, nonNull, pattern);
|
|
1392
|
+
ownType = censused ? withAbsence(censused) : yielded?.length === 1 && yielded[0] ? withAbsence(yielded[0]) : null;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
let result = null;
|
|
1397
|
+
if (ownType) {
|
|
1398
|
+
if (element.initializer) {
|
|
1399
|
+
// The name holds the read with its absence replaced by the default;
|
|
1400
|
+
// `var [a, b = 5] = arr` binds `b` a number, not `number | undefined`.
|
|
1401
|
+
const defaultType = knownOrResolve(element.initializer);
|
|
1402
|
+
// A read that is NOTHING BUT the absence (an absent key over a closed
|
|
1403
|
+
// holder) binds the default alone: `withoutUndefinedMember` has no
|
|
1404
|
+
// member to keep there, and joining it would put the absence back.
|
|
1405
|
+
const absentOnly = !ownType.isUnion() && (ownType.flags & ts.TypeFlags.Undefined) !== 0;
|
|
1406
|
+
result = defaultType
|
|
1407
|
+
? absentOnly
|
|
1408
|
+
? defaultType
|
|
1409
|
+
: (joinOfWrites([withoutUndefinedMember(checker, ownType), defaultType]) ?? ownType)
|
|
1410
|
+
: ownType;
|
|
1411
|
+
}
|
|
1412
|
+
else {
|
|
1413
|
+
result = ownType;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
resolvingElements.delete(element);
|
|
1417
|
+
if (result)
|
|
1418
|
+
boundElements.set(element, result);
|
|
1419
|
+
else
|
|
1420
|
+
elementRefusalOf.set(element, sourceType ? 'element-unresolved' : 'source-unresolved');
|
|
1421
|
+
return result;
|
|
1422
|
+
};
|
|
1423
|
+
/**
|
|
1424
|
+
* The general walk, one node at a time: an identifier defers to the
|
|
1425
|
+
* upstream (parameter+return) census first, and only falls to this
|
|
1426
|
+
* module's own write-set resolution where that authority has nothing --
|
|
1427
|
+
* which is exactly the cell-with-no-initializer gap this module exists
|
|
1428
|
+
* for. Every other node kind recurses through the SAME upstream-first rule
|
|
1429
|
+
* at its own operands, so a chain like `state.buffers` resolves once
|
|
1430
|
+
* `state` does, regardless of which layer actually answered `state`.
|
|
1431
|
+
*/
|
|
1432
|
+
/**
|
|
1433
|
+
* What `this` holds at a keyword: the checker's answer, except inside a
|
|
1434
|
+
* function written as an object literal's property (`{ valueOf: function
|
|
1435
|
+
* () { thisValue = this } }`), where the checker answers `any` for a JS
|
|
1436
|
+
* file and the literal is the only object that function is ever entered
|
|
1437
|
+
* with -- the same reading `structural-receiver.ts` gives the function's
|
|
1438
|
+
* receiver. An arrow between the keyword and that function is walked
|
|
1439
|
+
* through, as the language does.
|
|
1440
|
+
*/
|
|
1441
|
+
const thisValueTypeOf = (keyword) => {
|
|
1442
|
+
let scope = keyword.parent;
|
|
1443
|
+
while (scope && (ts.isArrowFunction(scope) || !(ts.isFunctionLike(scope) || ts.isClassLike(scope) || ts.isSourceFile(scope)))) {
|
|
1444
|
+
scope = scope.parent;
|
|
1445
|
+
}
|
|
1446
|
+
if (scope && (ts.isFunctionExpression(scope) || ts.isMethodDeclaration(scope))) {
|
|
1447
|
+
const owner = ts.isPropertyAssignment(scope.parent) ? scope.parent.parent : scope.parent;
|
|
1448
|
+
if (ts.isObjectLiteralExpression(owner))
|
|
1449
|
+
return contextTypedLiteralThisOf(checker, owner, keyword) ?? checker.getTypeAtLocation(owner);
|
|
1450
|
+
}
|
|
1451
|
+
return checker.getTypeAtLocation(keyword);
|
|
1452
|
+
};
|
|
1453
|
+
const compute = (node) => {
|
|
1454
|
+
if (ts.isParenthesizedExpression(node) ||
|
|
1455
|
+
ts.isAsExpression(node) ||
|
|
1456
|
+
ts.isNonNullExpression(node) ||
|
|
1457
|
+
ts.isTypeAssertionExpression(node)) {
|
|
1458
|
+
return knownOrResolve(node.expression);
|
|
1459
|
+
}
|
|
1460
|
+
if (ts.isVariableDeclaration(node))
|
|
1461
|
+
return resolveDeclaration(node);
|
|
1462
|
+
// `thisValue = this` inside an object literal's method: the checker
|
|
1463
|
+
// types the keyword as the literal (a class's method as the instance),
|
|
1464
|
+
// and that is as much a write of a record as `t = o` is. A `this` the
|
|
1465
|
+
// checker cannot place -- a plain function's, `any` -- states nothing.
|
|
1466
|
+
if (node.kind === ts.SyntaxKind.ThisKeyword) {
|
|
1467
|
+
const type = thisValueTypeOf(node);
|
|
1468
|
+
return type === null || isUnusableEvidence(type) || (type.flags & ts.TypeFlags.Unknown) !== 0 ? null : type;
|
|
1469
|
+
}
|
|
1470
|
+
if (ts.isIdentifier(node)) {
|
|
1471
|
+
const upstream = parameters.typeAt(node);
|
|
1472
|
+
if (upstream)
|
|
1473
|
+
return upstream;
|
|
1474
|
+
const synthesized = unionTypeOf(parameters.unionArmsAt(node));
|
|
1475
|
+
if (synthesized)
|
|
1476
|
+
return synthesized;
|
|
1477
|
+
const declaration = declarationOf(node);
|
|
1478
|
+
if (declaration)
|
|
1479
|
+
return resolveDeclaration(declaration);
|
|
1480
|
+
const element = bindingElementDeclarationOf(node);
|
|
1481
|
+
return element ? resolveBindingElement(element) : null;
|
|
1482
|
+
}
|
|
1483
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
1484
|
+
const upstream = parameters.typeAt(node);
|
|
1485
|
+
if (upstream)
|
|
1486
|
+
return upstream;
|
|
1487
|
+
const unionMember = unionArmsForResolution(node.expression);
|
|
1488
|
+
if (unionMember) {
|
|
1489
|
+
const projected = unionMemberTypeOf(unionMember, node.name.text, node);
|
|
1490
|
+
if (projected)
|
|
1491
|
+
return projected;
|
|
1492
|
+
}
|
|
1493
|
+
const receiver = knownOrResolve(node.expression);
|
|
1494
|
+
// The bag census before the receiver's own type AND after it, because a
|
|
1495
|
+
// `{}` receiver IS resolvable -- the checker types it as the empty
|
|
1496
|
+
// object -- so `propertyTypeOf` answers `null` for every slot rather
|
|
1497
|
+
// than failing to find a receiver. See `slotTypeAt`.
|
|
1498
|
+
if (!receiver)
|
|
1499
|
+
return bags.slotTypeAt(node);
|
|
1500
|
+
return propertyTypeOf(receiver, node.name.text, node) ?? bags.slotTypeAt(node);
|
|
1501
|
+
}
|
|
1502
|
+
if (ts.isElementAccessExpression(node) && node.argumentExpression) {
|
|
1503
|
+
const upstream = parameters.typeAt(node);
|
|
1504
|
+
if (upstream)
|
|
1505
|
+
return upstream;
|
|
1506
|
+
const receiver = knownOrResolve(node.expression);
|
|
1507
|
+
if (!receiver)
|
|
1508
|
+
return collections.arrayElementForRead(node.expression) ?? bags.slotTypeAt(node);
|
|
1509
|
+
// A literal key is a named member spelled with brackets; any other key
|
|
1510
|
+
// is answered by the receiver's index signature, and by nothing else.
|
|
1511
|
+
const name = literalMemberNameOf(node);
|
|
1512
|
+
if (name !== null)
|
|
1513
|
+
return propertyTypeOf(receiver, name, node) ?? bags.slotTypeAt(node);
|
|
1514
|
+
const key = knownOrResolve(node.argumentExpression);
|
|
1515
|
+
if (!key)
|
|
1516
|
+
return bags.slotTypeAt(node);
|
|
1517
|
+
// See `return-bindings.ts`'s identical fallback: a resolved receiver
|
|
1518
|
+
// with no index signature of its own (`never[]`, most often) is still
|
|
1519
|
+
// answerable from the array census's own push/write evidence -- and a
|
|
1520
|
+
// `{}` bag's index half from this census's own write evidence.
|
|
1521
|
+
return (indexedTypeOf(checker, receiver, key, node, flow, parameters) ??
|
|
1522
|
+
collections.arrayElementForRead(node.expression) ??
|
|
1523
|
+
bags.slotTypeAt(node));
|
|
1524
|
+
}
|
|
1525
|
+
if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
|
|
1526
|
+
const upstream = parameters.typeAt(node);
|
|
1527
|
+
if (upstream)
|
|
1528
|
+
return upstream;
|
|
1529
|
+
const invariant = overloadInvariantReturnTypeAt(checker, node, knownOrResolve);
|
|
1530
|
+
if (invariant)
|
|
1531
|
+
return invariant;
|
|
1532
|
+
const callee = knownOrResolve(node.expression);
|
|
1533
|
+
if (!callee)
|
|
1534
|
+
return keyedCollectionRead(node);
|
|
1535
|
+
const constructed = ts.isNewExpression(node) ? callee.getConstructSignatures() : [];
|
|
1536
|
+
const signatures = constructed.length > 0 ? constructed : callee.getCallSignatures();
|
|
1537
|
+
if (signatures.length !== 1)
|
|
1538
|
+
return keyedCollectionRead(node);
|
|
1539
|
+
const signature = signatures[0];
|
|
1540
|
+
const unwrapped = ts.isCallExpression(node) ? unwrapExplicitThisCall(checker, node) : null;
|
|
1541
|
+
const returned = explicitThisCallReturnType(signature, unwrapped ? knownOrResolve(unwrapped.callee) : null);
|
|
1542
|
+
if ((returned.flags & (ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0)
|
|
1543
|
+
return null;
|
|
1544
|
+
// `any` is not the only way a callee can state nothing about what it
|
|
1545
|
+
// returns, and a structurally EMPTY object type is the other way --
|
|
1546
|
+
// which is the answer the checker gives for a factory that builds a bag
|
|
1547
|
+
// through a dynamic key. `fetchAttributeLocations` (WebGLProgram.js)
|
|
1548
|
+
// opens `const attributes = {}`, fills `attributes[ name ] = { type,
|
|
1549
|
+
// location, locationSize }` and returns it; the checker's inferred
|
|
1550
|
+
// return type is `{}`, and taking that at face value bound the cell to
|
|
1551
|
+
// a record with no fields. That is worse than refusing: this census is
|
|
1552
|
+
// the FIRST half of the composed view, so its `{}` shadowed the bag
|
|
1553
|
+
// census's own real answer for the same node, and every
|
|
1554
|
+
// `programAttributes[ name ]` behind it stayed dynamic -- 64 boxes on
|
|
1555
|
+
// one read in `WebGLBindingStates.js` alone. Refusing lets the bag
|
|
1556
|
+
// census answer, which is the deferral `keyedCollectionRead` below
|
|
1557
|
+
// already makes for a container.
|
|
1558
|
+
if (!isAnyType(returned) && !isEmptyObjectType(returned))
|
|
1559
|
+
return returned;
|
|
1560
|
+
return keyedCollectionRead(node);
|
|
1561
|
+
}
|
|
1562
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken)
|
|
1563
|
+
return knownOrResolve(node.right);
|
|
1564
|
+
if (ts.isConditionalExpression(node) || ts.isBinaryExpression(node) || ts.isTemplateExpression(node)) {
|
|
1565
|
+
return derivedExpressionType(checker, node, (operand) => knownOrResolve(operand));
|
|
1566
|
+
}
|
|
1567
|
+
return null;
|
|
1568
|
+
};
|
|
1569
|
+
/**
|
|
1570
|
+
* The value a `container.get( k )` yields, when the CONTAINER's own census
|
|
1571
|
+
* knows it and the checker does not.
|
|
1572
|
+
*
|
|
1573
|
+
* `new WeakMap()` written with no type arguments is `WeakMap<object, any>`,
|
|
1574
|
+
* so `get`'s declared return is `any` and the call states nothing -- while
|
|
1575
|
+
* `collection-bindings.ts` has already inferred V from the program's own
|
|
1576
|
+
* `set` calls. That census is the authority for what a container holds,
|
|
1577
|
+
* exactly as `arrayElementForRead` is for an array's elements two arms
|
|
1578
|
+
* below, and asking it is the same deferral rather than a new inference.
|
|
1579
|
+
*
|
|
1580
|
+
* `V | undefined`, never bare `V`: `Map`/`WeakMap` `get` answers `undefined`
|
|
1581
|
+
* for an absent key, and three's `WebGLProperties.get` tests exactly that
|
|
1582
|
+
* (`if ( map === undefined ) { map = {}; ... }`). Dropping the absence here
|
|
1583
|
+
* would hand the guard a cell that cannot hold the value it tests for.
|
|
1584
|
+
*
|
|
1585
|
+
* Without this, `let map = properties.get( object )` refused as
|
|
1586
|
+
* `write-unresolved`; that left `WebGLProperties.get`'s own return `any`,
|
|
1587
|
+
* and every `properties.get( material ).uniforms` in `WebGLRenderer.js` and
|
|
1588
|
+
* `WebGLMaterials.js` dynamic behind it.
|
|
1589
|
+
*/
|
|
1590
|
+
const keyedCollectionRead = (node) => {
|
|
1591
|
+
if (!ts.isCallExpression(node))
|
|
1592
|
+
return null;
|
|
1593
|
+
const target = node.expression;
|
|
1594
|
+
if (!ts.isPropertyAccessExpression(target) || target.name.text !== 'get')
|
|
1595
|
+
return null;
|
|
1596
|
+
const argumentTypes = collections.typeArgumentsForRead(target.expression);
|
|
1597
|
+
const value = argumentTypes?.value;
|
|
1598
|
+
if (!value || isUnusableEvidence(value))
|
|
1599
|
+
return null;
|
|
1600
|
+
return checker.getNullableType(value, ts.TypeFlags.Undefined);
|
|
1601
|
+
};
|
|
1602
|
+
const resolveExpr = (node) => {
|
|
1603
|
+
// `writeAnswers` first, ahead of the ordinary memo: a write recorded
|
|
1604
|
+
// there was already resolved -- via the cell it feeds, not via `compute`
|
|
1605
|
+
// on this node -- and `nodeMemo` may hold a now-stale `null` for the
|
|
1606
|
+
// same node left over from before that resolution, or wiped since by the
|
|
1607
|
+
// lenient retry's own `clear()`. Either way this is the newer, better
|
|
1608
|
+
// answer and must win.
|
|
1609
|
+
const backfilled = writeAnswers.get(node);
|
|
1610
|
+
if (backfilled)
|
|
1611
|
+
return backfilled;
|
|
1612
|
+
const cached = nodeMemo.get(node);
|
|
1613
|
+
if (cached !== undefined)
|
|
1614
|
+
return cached;
|
|
1615
|
+
if (nodeResolving.has(node))
|
|
1616
|
+
return null;
|
|
1617
|
+
nodeResolving.add(node);
|
|
1618
|
+
const answer = compute(node);
|
|
1619
|
+
nodeResolving.delete(node);
|
|
1620
|
+
nodeMemo.set(node, answer);
|
|
1621
|
+
return answer;
|
|
1622
|
+
};
|
|
1623
|
+
/** A refusal's `owner` for a `VariableDeclaration` candidate: the cell's own name and where the program wrote it. */
|
|
1624
|
+
const ownerOfDeclaration = (declaration) => {
|
|
1625
|
+
const file = declaration.getSourceFile();
|
|
1626
|
+
const line = file.getLineAndCharacterOfPosition(declaration.getStart()).line + 1;
|
|
1627
|
+
return `${declaration.name.getText()} (${file.fileName}:${line})`;
|
|
1628
|
+
};
|
|
1629
|
+
/** The identical rendering for a binding-pattern leaf, whose own name is `element.name` rather than a `VariableDeclaration`'s. */
|
|
1630
|
+
const ownerOfElement = (element) => {
|
|
1631
|
+
const file = element.getSourceFile();
|
|
1632
|
+
const line = file.getLineAndCharacterOfPosition(element.getStart()).line + 1;
|
|
1633
|
+
return `${element.name.getText()} (${file.fileName}:${line})`;
|
|
1634
|
+
};
|
|
1635
|
+
// Resolve every candidate up front, so `boundCount`/`refusals` reflect the
|
|
1636
|
+
// whole program rather than only the nodes some other pass happened to
|
|
1637
|
+
// query.
|
|
1638
|
+
const candidates = [];
|
|
1639
|
+
const elementCandidates = [];
|
|
1640
|
+
/**
|
|
1641
|
+
* ⛔ The single largest `no-writes` bucket -- 127 of 127 measured on
|
|
1642
|
+
* the three.js app, every one of them `no-writes:initializer-unseen` -- was never a
|
|
1643
|
+
* write-index defect. It was THIS walk disagreeing with `flow`'s own about
|
|
1644
|
+
* what counts as live code.
|
|
1645
|
+
*
|
|
1646
|
+
* `indexValueFlow` (`flow/value-flow.ts`) checks `reachable.memberIsPruned`
|
|
1647
|
+
* on every node it descends into, so a method nothing calls (three's
|
|
1648
|
+
* `Node.prototype.analyze`, `PMREMGenerator.prototype._sceneToCubeUV`, the
|
|
1649
|
+
* entire `nodes/` TSL class family the app's WebGL renderer never reaches)
|
|
1650
|
+
* contributes zero writes -- correctly: dead code has no evidence to give.
|
|
1651
|
+
* This walk used to check only `forEachReachableStatement`'s TOP-LEVEL
|
|
1652
|
+
* filter and then recurse with a bare `ts.forEachChild`, never re-asking
|
|
1653
|
+
* `memberIsPruned` for a nested member the way `value-flow.ts` does. A
|
|
1654
|
+
* pruned method's locals were still gathered as CANDIDATES here, so
|
|
1655
|
+
* `resolveDeclaration` asked `flow.writesToSymbol` a question the index had
|
|
1656
|
+
* every right to answer "nothing" to, and reported that silence as if it
|
|
1657
|
+
* were a defect in the index rather than the correct absence of evidence
|
|
1658
|
+
* for code that never runs.
|
|
1659
|
+
*
|
|
1660
|
+
* Measured: every one of the three.js app's 127 `no-writes:initializer-unseen`
|
|
1661
|
+
* refusals sits inside a member `reachable.memberIsPruned` marks pruned
|
|
1662
|
+
* (`Quaternion.prototype.setFromUnitVectors`,
|
|
1663
|
+
* `PMREMGenerator.prototype._sceneToCubeUV`/`_halfBlur`, the whole `Node`/
|
|
1664
|
+
* `ContextNode`/`LightsNode`/`NodeMaterial` TSL base classes, and others);
|
|
1665
|
+
* none were reachable declarations the index dropped. Matching `flow`'s own
|
|
1666
|
+
* boundary here removes the false refusal instead of teaching
|
|
1667
|
+
* `noEvidenceReason` to explain evidence that was never going to exist.
|
|
1668
|
+
*/
|
|
1669
|
+
const visit = (node) => {
|
|
1670
|
+
if (reachable.memberIsPruned(node))
|
|
1671
|
+
return;
|
|
1672
|
+
if (ts.isVariableDeclaration(node)) {
|
|
1673
|
+
registerObservedIndexedAbsence(node);
|
|
1674
|
+
if (isCandidate(checker, node, flow))
|
|
1675
|
+
candidates.push(node);
|
|
1676
|
+
}
|
|
1677
|
+
if (ts.isBindingElement(node) && isElementCandidate(checker, node))
|
|
1678
|
+
elementCandidates.push(node);
|
|
1679
|
+
ts.forEachChild(node, visit);
|
|
1680
|
+
};
|
|
1681
|
+
for (const file of files)
|
|
1682
|
+
forEachReachableStatement(reachable, file, visit);
|
|
1683
|
+
for (const candidate of candidates)
|
|
1684
|
+
resolveDeclaration(candidate);
|
|
1685
|
+
for (const element of elementCandidates)
|
|
1686
|
+
resolveBindingElement(element);
|
|
1687
|
+
// The relaxed phase, run only once the strict pass has settled -- so every
|
|
1688
|
+
// cell the strict rule can bind is bound from ALL its writes before any
|
|
1689
|
+
// cell is bound from a subset. Rounds repeat because a cell bound from
|
|
1690
|
+
// surviving evidence is itself evidence for another cell's writes; the
|
|
1691
|
+
// node memo is cleared each round because its cached nulls are answers to
|
|
1692
|
+
// the smaller view. Terminates because bindings are only ever added.
|
|
1693
|
+
lenientPhase = true;
|
|
1694
|
+
for (;;) {
|
|
1695
|
+
const retry = candidates.filter((candidate) => !bound.has(candidate) && refusalOf.get(candidate) === 'write-unresolved');
|
|
1696
|
+
if (retry.length === 0)
|
|
1697
|
+
break;
|
|
1698
|
+
for (const candidate of retry)
|
|
1699
|
+
refusalOf.delete(candidate);
|
|
1700
|
+
nodeMemo.clear();
|
|
1701
|
+
const before = bound.size;
|
|
1702
|
+
for (const candidate of retry)
|
|
1703
|
+
resolveDeclaration(candidate);
|
|
1704
|
+
if (bound.size === before)
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
// `root` is the same stable, hand-written reason string this census always
|
|
1708
|
+
// keyed its old count map by (`no-symbol`, `write-unresolved`, one of
|
|
1709
|
+
// `noEvidenceReason`'s `no-writes:...` family, ...) -- never node text or a
|
|
1710
|
+
// type spelling, so it is already the ROOT `census-refusal.ts` asks for.
|
|
1711
|
+
// `owner` is the new fact: the declaration's/leaf's own name and source
|
|
1712
|
+
// location, the one thing a count could never say.
|
|
1713
|
+
const refusals = [];
|
|
1714
|
+
for (const candidate of candidates) {
|
|
1715
|
+
if (bound.has(candidate) || unionArms.has(candidate))
|
|
1716
|
+
continue;
|
|
1717
|
+
const root = refusalOf.get(candidate) ?? 'unresolved';
|
|
1718
|
+
refusals.push(censusRefusal('local', root, root, ownerOfDeclaration(candidate)));
|
|
1719
|
+
}
|
|
1720
|
+
for (const element of elementCandidates) {
|
|
1721
|
+
if (boundElements.has(element))
|
|
1722
|
+
continue;
|
|
1723
|
+
const root = elementRefusalOf.get(element) ?? 'element-unresolved';
|
|
1724
|
+
refusals.push(censusRefusal('local', root, root, ownerOfElement(element)));
|
|
1725
|
+
}
|
|
1726
|
+
return {
|
|
1727
|
+
bindingTypeAt: (node) => {
|
|
1728
|
+
// A checker narrowing belongs to the read; it does not replace the
|
|
1729
|
+
// storage contract. Only an untyped read takes the cell's full answer.
|
|
1730
|
+
if (ts.isIdentifier(node) && !isAnyType(checker.getTypeAtLocation(node)))
|
|
1731
|
+
return null;
|
|
1732
|
+
const declaration = ts.isVariableDeclaration(node) ? node : ts.isIdentifier(node) ? declarationOf(node) : null;
|
|
1733
|
+
return declaration ? (bound.get(declaration) ?? null) : null;
|
|
1734
|
+
},
|
|
1735
|
+
typeAt: (node) => {
|
|
1736
|
+
if (ts.isVariableDeclaration(node))
|
|
1737
|
+
return bound.get(node) ?? null;
|
|
1738
|
+
if (ts.isBindingElement(node))
|
|
1739
|
+
return boundElements.get(node) ?? null;
|
|
1740
|
+
return resolveExpr(node);
|
|
1741
|
+
},
|
|
1742
|
+
preferredTypeAt: (node) => {
|
|
1743
|
+
const observedAbsence = observedIndexedAbsence.get(node);
|
|
1744
|
+
if (observedAbsence)
|
|
1745
|
+
return observedAbsence;
|
|
1746
|
+
const element = ts.isBindingElement(node) ? node : ts.isIdentifier(node) ? bindingElementDeclarationOf(node) : null;
|
|
1747
|
+
if (element?.dotDotDotToken && ts.isObjectBindingPattern(element.parent)) {
|
|
1748
|
+
const rest = boundElements.get(element);
|
|
1749
|
+
if (rest)
|
|
1750
|
+
return rest;
|
|
1751
|
+
}
|
|
1752
|
+
const declaration = ts.isVariableDeclaration(node) ? node : ts.isIdentifier(node) ? declarationOf(node) : null;
|
|
1753
|
+
if (!declaration?.initializer || !ts.isConditionalExpression(declaration.initializer))
|
|
1754
|
+
return null;
|
|
1755
|
+
const declarationList = declaration.parent;
|
|
1756
|
+
if (!ts.isVariableDeclarationList(declarationList) || (declarationList.flags & ts.NodeFlags.Const) === 0)
|
|
1757
|
+
return null;
|
|
1758
|
+
// A const cell has exactly its initializer's construction invariant; no
|
|
1759
|
+
// later assignment can invalidate this stronger view. The conditional
|
|
1760
|
+
// operation itself keeps the checker's wider union and the binding
|
|
1761
|
+
// conversion explicitly selects the proven array arm.
|
|
1762
|
+
return normalizedArrayConditionalType(checker, declaration.initializer, (operand) => checker.getTypeAtLocation(operand));
|
|
1763
|
+
},
|
|
1764
|
+
unionArmsAt: (node) => {
|
|
1765
|
+
// `instanceof` and `typeof` can narrow even a checker-any reference.
|
|
1766
|
+
// Keep that read's established type; the declaration still owns the
|
|
1767
|
+
// full storage union and the ordinary narrowing conversion connects it.
|
|
1768
|
+
if (ts.isIdentifier(node) && !isAnyType(checker.getTypeAtLocation(node)))
|
|
1769
|
+
return null;
|
|
1770
|
+
return synthesizedUnionArmsAt(checker, node, unionArms, ts.isVariableDeclaration);
|
|
1771
|
+
},
|
|
1772
|
+
boundCount: bound.size + unionArms.size + boundElements.size,
|
|
1773
|
+
refusals,
|
|
1774
|
+
refusalOf: (declaration) => refusalOf.get(declaration) ?? null
|
|
1775
|
+
};
|
|
1776
|
+
};
|
|
1777
|
+
/**
|
|
1778
|
+
* A `ParameterBindingCensus`-shaped view answering from BOTH: `parameters`'s
|
|
1779
|
+
* own answer first, this census's otherwise -- the seam meant for
|
|
1780
|
+
* `frontend.ts`, composed exactly as `return-bindings.ts`'s own
|
|
1781
|
+
* `withReturnBindings` is: swap
|
|
1782
|
+
*
|
|
1783
|
+
* const parameters = withReturnBindings(checker, files, censusParameterBindings(checker, files))
|
|
1784
|
+
*
|
|
1785
|
+
* for
|
|
1786
|
+
*
|
|
1787
|
+
* const parameters = withLocalBindings(checker, files, withReturnBindings(checker, files, censusParameterBindings(checker, files)))
|
|
1788
|
+
*
|
|
1789
|
+
* and the rest of the pipeline (`createStructuralMapper` and everything past
|
|
1790
|
+
* it) is unchanged.
|
|
1791
|
+
*/
|
|
1792
|
+
export const withLocalBindings = (checker, files, reachable, parameters, collections = emptyCollectionBindingCensus,
|
|
1793
|
+
/** The whole-program value-flow index -- see `censusLocalBindings`'s own parameter. */
|
|
1794
|
+
flow,
|
|
1795
|
+
/** The same-round property-bag census -- see `censusLocalBindings`'s own parameter. */
|
|
1796
|
+
bags = emptyObjectBagCensus,
|
|
1797
|
+
/** The prior outer view carrying this domain's own arm facts. */
|
|
1798
|
+
prior = emptyParameterBindingCensus, moduleRecords = emptyCommonJsModuleRecordCensus) => {
|
|
1799
|
+
const locals = censusLocalBindings(checker, files, reachable, parameters, collections, flow, bags, prior, moduleRecords);
|
|
1800
|
+
// `parameters.refusals` is already `ParameterBindingCensus`'s own
|
|
1801
|
+
// `readonly CensusRefusal[]` -- both lists are the SAME vocabulary
|
|
1802
|
+
// (`census-refusal.ts`), each entry self-namespaced by its own `key`
|
|
1803
|
+
// (`census:parameter:...`/`census:return:...` upstream,
|
|
1804
|
+
// `census:local:...` here), so composing is concatenation: nothing to
|
|
1805
|
+
// recount, nothing to prefix, and no refusal is dropped on the way through
|
|
1806
|
+
// this wrapper.
|
|
1807
|
+
const refusals = [...parameters.refusals, ...locals.refusals];
|
|
1808
|
+
return {
|
|
1809
|
+
...parameters,
|
|
1810
|
+
// The owning local census replaces a prior-round answer propagated by
|
|
1811
|
+
// parameter inference. Otherwise that stale answer shadows its own
|
|
1812
|
+
// corrected write-set join forever. Other expression answers preserve
|
|
1813
|
+
// the established upstream-first order.
|
|
1814
|
+
// A synthesized union remains owned by the arm channel. `censusLocalBindings`
|
|
1815
|
+
// materializes it only while resolving dependants; publishing that
|
|
1816
|
+
// internal bridge here as a second `typeAt` authority would make the
|
|
1817
|
+
// structural mapper choose between two spellings of the same carrier.
|
|
1818
|
+
typeAt: (node) => locals.preferredTypeAt(node) ??
|
|
1819
|
+
locals.bindingTypeAt(node) ??
|
|
1820
|
+
(locals.unionArmsAt(node) ? null : (parameters.typeAt(node) ?? (parameters.unionArmsAt(node) ? null : locals.typeAt(node)))),
|
|
1821
|
+
preferredTypeAt: (node) => locals.preferredTypeAt(node) ?? parameters.preferredTypeAt?.(node) ?? null,
|
|
1822
|
+
unionArmsAt: (node) => locals.unionArmsAt(node) ?? parameters.unionArmsAt(node),
|
|
1823
|
+
boundCount: parameters.boundCount + locals.boundCount,
|
|
1824
|
+
refusals
|
|
1825
|
+
};
|
|
1826
|
+
};
|