@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,1290 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { censusRefusal } from './census-refusal.js';
|
|
3
|
+
import { disjointUnionTypeOf, isGlobalObjectConstructor, literalMemberNameOf, widestOf } from './derived-expression-type.js';
|
|
4
|
+
import { emptyParameterBindingCensus } from './parameter-bindings.js';
|
|
5
|
+
import { definitelyReturns } from './return-paths.js';
|
|
6
|
+
import { createBagAbsenceResolver } from './bag-absence.js';
|
|
7
|
+
import { forEachReachableStatement } from './reachability.js';
|
|
8
|
+
import { isObjectLiteralPrototypeSetter } from './assignment-patterns.js';
|
|
9
|
+
/** An identity fixpoint that claimed nothing, for callers that state no program. */
|
|
10
|
+
const emptyObjectBagIdentity = {
|
|
11
|
+
roots: new Set(),
|
|
12
|
+
bagOf: new Map(),
|
|
13
|
+
returnsBag: new Map(),
|
|
14
|
+
conflicted: new Set(),
|
|
15
|
+
ungrounded: new Set()
|
|
16
|
+
};
|
|
17
|
+
/** A census that binds nothing, for callers that state no program. */
|
|
18
|
+
export const emptyObjectBagCensus = {
|
|
19
|
+
identity: emptyObjectBagIdentity,
|
|
20
|
+
shapeAt: () => null,
|
|
21
|
+
shapeForOwner: () => null,
|
|
22
|
+
shapeForType: () => null,
|
|
23
|
+
callResultShapeAt: () => null,
|
|
24
|
+
returnShapeOf: () => null,
|
|
25
|
+
slotTypeAt: () => null,
|
|
26
|
+
slotTypeOf: (type) => type,
|
|
27
|
+
boundCount: 0,
|
|
28
|
+
refusals: [],
|
|
29
|
+
refusalOf: () => null,
|
|
30
|
+
debugReport: () => ''
|
|
31
|
+
};
|
|
32
|
+
const isUnusableEvidence = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0;
|
|
33
|
+
const emptyEvidence = () => ({
|
|
34
|
+
namedWrites: new Map(),
|
|
35
|
+
namedReads: new Set(),
|
|
36
|
+
indexWrites: [],
|
|
37
|
+
namedDeletes: new Set(),
|
|
38
|
+
indexDelete: false,
|
|
39
|
+
indexRead: false,
|
|
40
|
+
opaqueUse: null
|
|
41
|
+
});
|
|
42
|
+
export const censusObjectBagBindings = (checker, files, reachable, parameters = emptyParameterBindingCensus,
|
|
43
|
+
/**
|
|
44
|
+
* The whole-program value-flow index -- see `flow/model.ts`. This census's
|
|
45
|
+
* own identity resolution (`ownerDeclOfExpr`) reads a plain identifier's
|
|
46
|
+
* target from it rather than re-deriving `checker.getSymbolAtLocation`
|
|
47
|
+
* itself, the same edge-source swap `field-bindings.ts`/
|
|
48
|
+
* `collection-bindings.ts` already made. It is NOT a full swap of this
|
|
49
|
+
* census's write discovery -- see this module's own doc comment, "What the
|
|
50
|
+
* shared index cannot express", for why the rest (a property access on a
|
|
51
|
+
* receiver the index cannot name, a call-expression alias root) stays this
|
|
52
|
+
* census's own.
|
|
53
|
+
*/
|
|
54
|
+
flow) => {
|
|
55
|
+
const declNodeOf = (symbol) => symbol?.getDeclarations()?.[0] ?? null;
|
|
56
|
+
/**
|
|
57
|
+
* The symbol a `receiver.name` access resolves to, asked of the composed
|
|
58
|
+
* census when the checker cannot answer.
|
|
59
|
+
*
|
|
60
|
+
* `checker.getSymbolAtLocation` on a property name returns nothing when the
|
|
61
|
+
* RECEIVER is `any` -- there is no type to look the member up in. That is
|
|
62
|
+
* precisely the state this whole campaign is unwinding, so relying on the
|
|
63
|
+
* checker alone makes the census blind exactly where the bags are: in
|
|
64
|
+
* three's renderer, `properties.get( renderTarget )` resolves inside
|
|
65
|
+
* `WebGLTextures.js` (whose `properties` parameter the parameter census has
|
|
66
|
+
* bound) and NOT inside `WebGLRenderer.js` (whose `properties` local the
|
|
67
|
+
* checker still calls `any`), so the same bag's reads were attributed and
|
|
68
|
+
* its writes were not -- and the bag then refused for a member that is
|
|
69
|
+
* written four lines from where it is read.
|
|
70
|
+
*
|
|
71
|
+
* The fallback is the same `known ?? resolve` rule `observedType` below
|
|
72
|
+
* applies, one level up: ask the census for the receiver's type, then look
|
|
73
|
+
* the member up in it.
|
|
74
|
+
*/
|
|
75
|
+
const memberSymbolOf = (access) => {
|
|
76
|
+
const direct = checker.getSymbolAtLocation(access.name);
|
|
77
|
+
if (direct)
|
|
78
|
+
return direct;
|
|
79
|
+
const own = checker.getTypeAtLocation(access.expression);
|
|
80
|
+
const receiver = isUnusableEvidence(own) ? parameters.typeAt(access.expression) : own;
|
|
81
|
+
return receiver?.getProperty(access.name.text);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* An EXPANDO member slot's identity: `x.k` where nothing in the program
|
|
85
|
+
* declares `k`.
|
|
86
|
+
*
|
|
87
|
+
* Three's `InterleavedBuffer.clone( data )` takes `@param {Object} [data]`
|
|
88
|
+
* and fills `data.arrayBuffers = {}` two lines before writing keys into it.
|
|
89
|
+
* `{Object}` resolves to the REAL `lib.es5` `Object` interface, which passes
|
|
90
|
+
* every vacuity test and declares no `arrayBuffers` -- so `memberSymbolOf`
|
|
91
|
+
* answers undefined, `ownerDeclOfExpr` answers null, and the bag census
|
|
92
|
+
* never sees a slot that is manifestly a bag. That one slot is the receiver
|
|
93
|
+
* of the keyed write blocking BOTH the `isFogExp2` class-family absence
|
|
94
|
+
* proof and the numeric-absence proof for the WebGL context: ~2042 of
|
|
95
|
+
* the three.js app's carriers, and the program's ONE `typedPropertyBoxes` row
|
|
96
|
+
* (`receiverCarrier: dynamic`, `valueCarrier: record` -- the value was
|
|
97
|
+
* always typed, only the receiver was not).
|
|
98
|
+
*
|
|
99
|
+
* Identity is the member NAME, program-wide, because that is the only
|
|
100
|
+
* over-approximation available: a receiver with no symbol for `k` has no
|
|
101
|
+
* declaration to key on, and `flow/class-family-member-read.ts` already
|
|
102
|
+
* settled on name-keying for exactly this population. Merging unrelated
|
|
103
|
+
* objects that share a name can only make a bag's member set LARGER than
|
|
104
|
+
* the truth, never smaller, and two genuinely different bags landing on one
|
|
105
|
+
* name are refused wholesale by the existing `refused` path rather than
|
|
106
|
+
* merged into a wrong answer.
|
|
107
|
+
*
|
|
108
|
+
* ⚠ The load-bearing guard is `declaredAnywhere`. If ANY access spelling
|
|
109
|
+
* this name resolves to a real symbol, the name is not expando at all and
|
|
110
|
+
* no slot is minted -- because that occurrence would take the ordinary
|
|
111
|
+
* declaration identity while these took the synthetic one, and the same
|
|
112
|
+
* object reached through both spellings would be two bags, each looking
|
|
113
|
+
* closed while the other wrote keys into it. That is a silently SMALLER
|
|
114
|
+
* member set, which is a wrong answer rather than a refusal. A name is
|
|
115
|
+
* therefore either wholly expando or not a bag root at all.
|
|
116
|
+
*/
|
|
117
|
+
const expandoSlots = new Map();
|
|
118
|
+
let expandoScanned = false;
|
|
119
|
+
/**
|
|
120
|
+
* ⚠ Cost, not style: this scan runs over EVERY property access in the
|
|
121
|
+
* program -- ~50k of them once three.js is in the graph -- so it may ask
|
|
122
|
+
* only the cheapest question per node. An earlier version called
|
|
123
|
+
* `memberSymbolOf`, whose fallback reaches `parameters.typeAt` and thus the
|
|
124
|
+
* whole composed parameter census, once per access; the three.js app then produced no
|
|
125
|
+
* output in 200 s. The checker's own `getSymbolAtLocation` is the cheap
|
|
126
|
+
* question and it is asked first for all of them; the expensive one is asked
|
|
127
|
+
* only of the handful of names that survive it.
|
|
128
|
+
*/
|
|
129
|
+
const scanExpandoNames = () => {
|
|
130
|
+
if (expandoScanned)
|
|
131
|
+
return;
|
|
132
|
+
expandoScanned = true;
|
|
133
|
+
const occurrences = new Map();
|
|
134
|
+
const declaredAnywhere = new Set();
|
|
135
|
+
const visit = (node) => {
|
|
136
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
137
|
+
const name = node.name.text;
|
|
138
|
+
if (checker.getSymbolAtLocation(node.name) !== undefined)
|
|
139
|
+
declaredAnywhere.add(name);
|
|
140
|
+
else {
|
|
141
|
+
const seen = occurrences.get(name);
|
|
142
|
+
if (seen)
|
|
143
|
+
seen.push(node);
|
|
144
|
+
else
|
|
145
|
+
occurrences.set(name, [node]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
ts.forEachChild(node, visit);
|
|
149
|
+
};
|
|
150
|
+
for (const file of files)
|
|
151
|
+
forEachReachableStatement(reachable, file, visit);
|
|
152
|
+
for (const [name, accesses] of occurrences) {
|
|
153
|
+
if (declaredAnywhere.has(name))
|
|
154
|
+
continue;
|
|
155
|
+
// Every occurrence must have a receiver the checker can type and which
|
|
156
|
+
// genuinely lacks the member. An `any`/`unknown` receiver is NOT
|
|
157
|
+
// evidence of absence -- it is the absence of evidence -- and admitting
|
|
158
|
+
// one would let a declared member elsewhere take the ordinary identity
|
|
159
|
+
// while this took the synthetic one, splitting one object into two bags.
|
|
160
|
+
const expando = accesses.every((access) => {
|
|
161
|
+
const receiver = checker.getTypeAtLocation(access.expression);
|
|
162
|
+
return !isUnusableEvidence(receiver) && receiver.getProperty(name) === undefined;
|
|
163
|
+
});
|
|
164
|
+
if (expando)
|
|
165
|
+
expandoSlots.set(name, accesses[0]);
|
|
166
|
+
}
|
|
167
|
+
if (process.env['GEA_EXPANDO_BAG_DEBUG'])
|
|
168
|
+
for (const [name, node] of expandoSlots)
|
|
169
|
+
console.error(`[EXPANDO-BAG] ${name} ${node.getSourceFile().fileName.split('/').slice(-1)[0]} occurrences=${occurrences.get(name)?.length}`);
|
|
170
|
+
};
|
|
171
|
+
/** The interned slot node for `x.k`, or null when `k` is declared somewhere. */
|
|
172
|
+
const expandoOwnerOf = (expression) => {
|
|
173
|
+
if (!ts.isPropertyAccessExpression(expression))
|
|
174
|
+
return null;
|
|
175
|
+
scanExpandoNames();
|
|
176
|
+
return expandoSlots.get(expression.name.text) ?? null;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* The declaration node backing a plain identifier or `x.prop` -- this
|
|
180
|
+
* census's one identity key.
|
|
181
|
+
*
|
|
182
|
+
* The identifier half is now the shared `flow.targetOf` -- the identical
|
|
183
|
+
* `checker.getSymbolAtLocation` + first-declaration computation this
|
|
184
|
+
* function used to make privately, sourced from the one walk every census
|
|
185
|
+
* now reads (see `flow/targets.ts`'s `flowTargetOf`). Measured
|
|
186
|
+
* byte-identical on the three.js app (see `NOTES.md`), which is the expected
|
|
187
|
+
* signature of a faithful edge-source swap, not a coincidence: an
|
|
188
|
+
* identifier's target is a pure symbol lookup with no receiver-type
|
|
189
|
+
* fallback to diverge over.
|
|
190
|
+
*
|
|
191
|
+
* The property-access half stays this census's own `memberSymbolOf`,
|
|
192
|
+
* deliberately not routed through `flow.targetOf`: that shared resolver has
|
|
193
|
+
* no receiver-type fallback (it answers `null` the instant
|
|
194
|
+
* `checker.getSymbolAtLocation` fails at both the access and its `.name`),
|
|
195
|
+
* while `memberSymbolOf`'s whole reason to exist is answering exactly that
|
|
196
|
+
* case from the composed parameter census -- `properties.get(renderTarget)`
|
|
197
|
+
* resolving where the checker alone cannot, because the receiver is `any`.
|
|
198
|
+
* Preferring the shared resolver's OWN whole-access fallback ahead of that
|
|
199
|
+
* one would silently pick a different (checker-only) answer over this
|
|
200
|
+
* census's richer one for no gain; deferring to `memberSymbolOf` unchanged
|
|
201
|
+
* keeps the fallback this file was written to have.
|
|
202
|
+
*/
|
|
203
|
+
const ownerDeclOfExpr = (expression) => {
|
|
204
|
+
if (ts.isIdentifier(expression))
|
|
205
|
+
return flow.targetOf(expression)?.declaration ?? null;
|
|
206
|
+
// The expando slot is consulted only AFTER both the checker and the
|
|
207
|
+
// composed census decline: a slot that has a declaration keeps it, so
|
|
208
|
+
// this adds an identity where there was none rather than replacing one.
|
|
209
|
+
if (ts.isPropertyAccessExpression(expression))
|
|
210
|
+
return declNodeOf(memberSymbolOf(expression)) ?? expandoOwnerOf(expression);
|
|
211
|
+
return null;
|
|
212
|
+
};
|
|
213
|
+
/** The checker's own answer, falling back to the composed parameter census -- the same `known ?? resolve` rule every census here applies. */
|
|
214
|
+
const observedType = (expression) => {
|
|
215
|
+
const own = checker.getTypeAtLocation(expression);
|
|
216
|
+
return isUnusableEvidence(own) ? parameters.typeAt(expression) : own;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Whether a type says anything this census would be overriding.
|
|
220
|
+
*
|
|
221
|
+
* `any`/`unknown`/`void`/`never` state nothing by construction. So does the
|
|
222
|
+
* EMPTY object type: `{}` in a contextual position, and `{}` observed as a
|
|
223
|
+
* written value, are the same non-statement -- zero members, zero index
|
|
224
|
+
* signatures, zero call signatures. Treating either as a stated answer is
|
|
225
|
+
* what silently excluded the exact shape this module exists for, because the
|
|
226
|
+
* contextual type of `map = {}`'s right-hand side is the left-hand side's
|
|
227
|
+
* own (`any`) type. And admitting one as evidence is how a bound bag ends up
|
|
228
|
+
* with a member whose carrier is an empty record -- a struct with no fields,
|
|
229
|
+
* which is not an improvement on a box, it is a different way to say
|
|
230
|
+
* nothing.
|
|
231
|
+
*
|
|
232
|
+
* `never[]` is the third spelling of the same non-statement: an empty array
|
|
233
|
+
* literal with no contextual type, which is TypeScript declining to guess
|
|
234
|
+
* rather than a fact about the program (`collection-bindings.ts`'s array
|
|
235
|
+
* census exists for exactly that reading).
|
|
236
|
+
*
|
|
237
|
+
* TRIED AND REVERTED: a bare JSDoc `@type {Object}` (or an un-dotted
|
|
238
|
+
* `@type {Object<K,V>}`, which TS's JSDoc parser does not treat as an
|
|
239
|
+
* index-signature shorthand) is a fourth spelling of the same
|
|
240
|
+
* non-statement, and `derived-expression-type.ts` already exports
|
|
241
|
+
* `annotationStatesNothing` for exactly this reading elsewhere in the
|
|
242
|
+
* compiler. OR-ing it into this check DOES widen candidacy exactly as
|
|
243
|
+
* expected -- three's `this.morphAttributes = {}` (`BufferGeometry`,
|
|
244
|
+
* annotated `@type {Object}`) and two `ShaderMaterial.js` uniform bags
|
|
245
|
+
* newly BIND -- but MEASURED on the three.js app this is a pure regression: boxed
|
|
246
|
+
* and ops stay byte-identical (725->773 `missing`, +48, 0 removed,
|
|
247
|
+
* confirmed via a before/after preflight-obligation-id diff) with zero
|
|
248
|
+
* compensating reduction anywhere. Root cause traced past this file: the
|
|
249
|
+
* newly-bound `morphAttributes` shape selects `record-with-index` (it has
|
|
250
|
+
* both named members AND a computed-key write,
|
|
251
|
+
* `geometry2.morphAttributes[ name ] = morphArray` in `.copy()`) where the
|
|
252
|
+
* SAME literal, unbound, was already resolving to a plain `record` via a
|
|
253
|
+
* different, existing authority -- and the C++ backend has no
|
|
254
|
+
* `value:allocation:object-literal:record-with-index` runtime helper for
|
|
255
|
+
* that combination (an array-typed member/index) yet, so the more precise
|
|
256
|
+
* answer this module now gives is correct but unimplementable downstream.
|
|
257
|
+
* That is a real, separate emitter gap (`targets/cpp/`), not something
|
|
258
|
+
* this file's identity tracking can fix, and out of this module's own
|
|
259
|
+
* scope -- landing the wider candidacy check without it trades a working
|
|
260
|
+
* plain-record path for a preflight failure, for zero app-visible
|
|
261
|
+
* gain. Left OUT. Whoever wires that runtime helper should revisit this.
|
|
262
|
+
*/
|
|
263
|
+
const statesNothing = (type) => {
|
|
264
|
+
if (isUnusableEvidence(type))
|
|
265
|
+
return true;
|
|
266
|
+
if (checker.isArrayType(type)) {
|
|
267
|
+
const [element] = checker.getTypeArguments(type);
|
|
268
|
+
return element !== undefined && (element.flags & ts.TypeFlags.Never) !== 0;
|
|
269
|
+
}
|
|
270
|
+
if ((type.flags & ts.TypeFlags.Object) === 0)
|
|
271
|
+
return false;
|
|
272
|
+
return (type.getProperties().length === 0 &&
|
|
273
|
+
checker.getIndexInfosOfType(type).length === 0 &&
|
|
274
|
+
type.getCallSignatures().length === 0 &&
|
|
275
|
+
type.getConstructSignatures().length === 0);
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* A declaration that states its own type states this census's answer too --
|
|
279
|
+
* there is nothing to add.
|
|
280
|
+
*
|
|
281
|
+
* Two spellings, and the second is the load-bearing one. An explicit type
|
|
282
|
+
* node is the obvious case. The other is the checker's own expando
|
|
283
|
+
* inference: in a JavaScript file `let output = {}` followed by
|
|
284
|
+
* `output.geometries = []` in the same scope is typed WITH those members by
|
|
285
|
+
* TypeScript itself, flow-sensitively, which is a better answer than this
|
|
286
|
+
* census can derive and is left alone for the same reason
|
|
287
|
+
* `collection-bindings.ts` leaves `settleEvolving`'s empty arrays alone. The
|
|
288
|
+
* literal itself is no help in telling the two apart -- `{}` is the empty
|
|
289
|
+
* object type at its own node either way -- so the question is asked of the
|
|
290
|
+
* declaration, which is where the inferred members actually land.
|
|
291
|
+
*/
|
|
292
|
+
const declaresOwnType = (declaration) => {
|
|
293
|
+
if (ts.isVariableDeclaration(declaration) || ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration)) {
|
|
294
|
+
if (declaration.type !== undefined)
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
const symbol = checker.getSymbolAtLocation(ts.isVariableDeclaration(declaration) || ts.isPropertyDeclaration(declaration) || ts.isPropertyAssignment(declaration)
|
|
298
|
+
? declaration.name
|
|
299
|
+
: declaration);
|
|
300
|
+
if (!symbol)
|
|
301
|
+
return false;
|
|
302
|
+
return !statesNothing(checker.getTypeOfSymbolAtLocation(symbol, declaration));
|
|
303
|
+
};
|
|
304
|
+
const declaresWrittenType = (owner) => ((ts.isVariableDeclaration(owner) || ts.isPropertyDeclaration(owner) || ts.isParameter(owner) || ts.isFunctionLike(owner)) &&
|
|
305
|
+
owner.type !== undefined) ||
|
|
306
|
+
ts.getJSDocType(owner) !== undefined ||
|
|
307
|
+
(ts.isFunctionLike(owner) && ts.getJSDocReturnType(owner) !== undefined) ||
|
|
308
|
+
(ts.isParameter(owner) && ts.getJSDocParameterTags(owner).some((tag) => tag.typeExpression !== undefined));
|
|
309
|
+
/**
|
|
310
|
+
* A `{}` the program has not already typed for itself, not cast, not spread
|
|
311
|
+
* into anything.
|
|
312
|
+
*
|
|
313
|
+
* Both halves of "already typed" are tested, and the second is the one that
|
|
314
|
+
* is easy to miss: in a JavaScript file the checker performs its OWN expando
|
|
315
|
+
* inference, synthesizing members onto `let output = {}` from the
|
|
316
|
+
* `output.geometries = []` assignments that follow it in the same scope. That
|
|
317
|
+
* answer is flow-sensitive within the function and is BETTER than anything
|
|
318
|
+
* this census could derive -- exactly the relationship
|
|
319
|
+
* `collection-bindings.ts` has with `settleEvolving` for an empty array
|
|
320
|
+
* literal, and it is left alone for the same reason. Overriding it does not
|
|
321
|
+
* merely duplicate work: it makes two authorities for one storage, and the
|
|
322
|
+
* conversions between them are unsatisfiable. MEASURED on the three.js app: admitting
|
|
323
|
+
* the expando-typed literals costs 52 unmet `native-record-ref(...) ->
|
|
324
|
+
* record(...)` obligations -- the checker's answer on one side of the arrow
|
|
325
|
+
* and this census's on the other -- for zero additional carriers.
|
|
326
|
+
*/
|
|
327
|
+
const isBareEmptyLiteral = (node) => {
|
|
328
|
+
if (!ts.isObjectLiteralExpression(node) || node.properties.length > 0)
|
|
329
|
+
return false;
|
|
330
|
+
const parent = node.parent;
|
|
331
|
+
if (ts.isAsExpression(parent) || ts.isSatisfiesExpression(parent) || ts.isTypeAssertionExpression(parent))
|
|
332
|
+
return false;
|
|
333
|
+
const contextual = checker.getContextualType(node);
|
|
334
|
+
if (contextual !== undefined && !statesNothing(contextual))
|
|
335
|
+
return false;
|
|
336
|
+
return statesNothing(checker.getTypeAtLocation(node));
|
|
337
|
+
};
|
|
338
|
+
// Seed an inferred record with its actual allocation writes. A populated
|
|
339
|
+
// literal is only published below when later writes add a missing member;
|
|
340
|
+
// otherwise its existing checker shape remains the authority.
|
|
341
|
+
const initialMembersOf = (node) => {
|
|
342
|
+
if (!ts.isObjectLiteralExpression(node) || node.properties.length === 0)
|
|
343
|
+
return null;
|
|
344
|
+
if (ts.isAsExpression(node.parent) || ts.isSatisfiesExpression(node.parent) || ts.isTypeAssertionExpression(node.parent))
|
|
345
|
+
return null;
|
|
346
|
+
if (checker.getContextualType(node) !== undefined)
|
|
347
|
+
return null;
|
|
348
|
+
const fields = new Map();
|
|
349
|
+
for (const property of node.properties) {
|
|
350
|
+
if (!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property))
|
|
351
|
+
return null;
|
|
352
|
+
if (!ts.isIdentifier(property.name) && !ts.isStringLiteral(property.name) && !ts.isNumericLiteral(property.name))
|
|
353
|
+
return null;
|
|
354
|
+
if (isObjectLiteralPrototypeSetter(property))
|
|
355
|
+
return null;
|
|
356
|
+
fields.set(property.name.text, ts.isShorthandPropertyAssignment(property) ? property.name : property.initializer);
|
|
357
|
+
}
|
|
358
|
+
return fields;
|
|
359
|
+
};
|
|
360
|
+
// Allocation ownership and replacement checks consume the same whole-cell
|
|
361
|
+
// inventory. A field initializer is an ordinary bind here, so it cannot be
|
|
362
|
+
// admitted as a root while its later replacements are invisible to the proof.
|
|
363
|
+
// Frame/return edges transport values but do not give an inline allocation a
|
|
364
|
+
// stable storage owner; their aliases are handled by the existing closure.
|
|
365
|
+
const storageWrites = flow.allWrites.filter((write) => write.slot === 'whole');
|
|
366
|
+
const ownerOfWrite = (write) => (write.naming && ts.isPropertyAccessExpression(write.naming) ? ownerDeclOfExpr(write.naming) : null) ?? write.target.declaration;
|
|
367
|
+
const allocationOwners = new Map();
|
|
368
|
+
for (const write of storageWrites) {
|
|
369
|
+
if (write.value === null ||
|
|
370
|
+
!['declaration-initializer', 'class-field-initializer', 'identifier-assignment', 'property-assignment', 'index-assignment'].includes(write.edge))
|
|
371
|
+
continue;
|
|
372
|
+
const owner = ownerOfWrite(write);
|
|
373
|
+
if (!owner)
|
|
374
|
+
continue;
|
|
375
|
+
const existing = allocationOwners.get(write.value);
|
|
376
|
+
allocationOwners.set(write.value, existing === undefined || existing === owner ? owner : null);
|
|
377
|
+
}
|
|
378
|
+
const literalOwnerOf = (node, populated = false) => {
|
|
379
|
+
const owner = allocationOwners.get(node);
|
|
380
|
+
return owner && !(populated ? declaresWrittenType : declaresOwnType)(owner) ? owner : null;
|
|
381
|
+
};
|
|
382
|
+
// Pass 1: every candidate `{}`, grouped by the declaration it fills.
|
|
383
|
+
const literalsByOwner = new Map();
|
|
384
|
+
const literalOwner = new Map();
|
|
385
|
+
const initialMembers = new Map();
|
|
386
|
+
const collectLiterals = (node) => {
|
|
387
|
+
const initial = initialMembersOf(node);
|
|
388
|
+
if (isBareEmptyLiteral(node) || (ts.isObjectLiteralExpression(node) && initial !== null)) {
|
|
389
|
+
const owner = literalOwnerOf(node, initial !== null);
|
|
390
|
+
if (owner) {
|
|
391
|
+
if (initial !== null)
|
|
392
|
+
initialMembers.set(node, initial);
|
|
393
|
+
literalOwner.set(node, owner);
|
|
394
|
+
const existing = literalsByOwner.get(owner);
|
|
395
|
+
if (existing)
|
|
396
|
+
existing.push(node);
|
|
397
|
+
else
|
|
398
|
+
literalsByOwner.set(owner, [node]);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
ts.forEachChild(node, collectLiterals);
|
|
402
|
+
};
|
|
403
|
+
for (const file of files)
|
|
404
|
+
forEachReachableStatement(reachable, file, collectLiterals);
|
|
405
|
+
// Pass 2: propagate bag identity outward along declaration-following edges,
|
|
406
|
+
// to a fixpoint. `bagOf` maps a declaration to the ROOT bag owner it holds;
|
|
407
|
+
// `returnsBag` maps a function declaration to the root bag it returns.
|
|
408
|
+
const bagOf = new Map();
|
|
409
|
+
for (const owner of literalsByOwner.keys())
|
|
410
|
+
bagOf.set(owner, owner);
|
|
411
|
+
const returnsBag = new Map();
|
|
412
|
+
/** Declarations that turned out to hold two different bags -- refused wholesale rather than merged. */
|
|
413
|
+
const conflicted = new Set();
|
|
414
|
+
/** Candidate roots whose owning cell also receives a value not proved to be that root. */
|
|
415
|
+
const ungrounded = new Set();
|
|
416
|
+
const claim = (declaration, root) => {
|
|
417
|
+
const existing = bagOf.get(declaration);
|
|
418
|
+
if (existing === root)
|
|
419
|
+
return false;
|
|
420
|
+
if (existing !== undefined) {
|
|
421
|
+
conflicted.add(existing);
|
|
422
|
+
conflicted.add(root);
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
bagOf.set(declaration, root);
|
|
426
|
+
return true;
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* Whether every write to a cell is PROVED to carry one bag root.
|
|
430
|
+
*
|
|
431
|
+
* This is deliberately an identity-only question. The old rule admitted a
|
|
432
|
+
* write when its current type was `any`/`unknown`/empty and revoked that
|
|
433
|
+
* admission once an outer census learned a concrete type. That made absence
|
|
434
|
+
* of evidence positive alias evidence, so the composed census was
|
|
435
|
+
* anti-monotone: Fastify's `let constraints = {}; constraints =
|
|
436
|
+
* opts.constraints` alternated forever between publishing the empty bag and
|
|
437
|
+
* withdrawing it as `opts.constraints` became known.
|
|
438
|
+
*
|
|
439
|
+
* A direct value-flow chain can only add a root to `bagOf`; it never loses
|
|
440
|
+
* one. A write not yet rooted is therefore pending, not permission. This is
|
|
441
|
+
* the must-alias lattice the public type census needs: one proven root may be
|
|
442
|
+
* published, two roots conflict, and an ungrounded write publishes nothing.
|
|
443
|
+
* Types still classify the VALUES stored in a proven bag's slots below, but
|
|
444
|
+
* they never decide whether two references are the same storage.
|
|
445
|
+
*/
|
|
446
|
+
const admissibleWrites = (declaration, root) => {
|
|
447
|
+
if (unknownWrites.has(declaration))
|
|
448
|
+
return false;
|
|
449
|
+
const writes = writesTo.get(declaration);
|
|
450
|
+
if (!writes)
|
|
451
|
+
return true;
|
|
452
|
+
return writes.every((value) => bagRootOf(value) === root);
|
|
453
|
+
};
|
|
454
|
+
/**
|
|
455
|
+
* The function a callee expression names, unwrapping one `k: fn`
|
|
456
|
+
* property-assignment alias -- OR, the same unwrap one syntax shape over,
|
|
457
|
+
* a `k: function( ... ) { ... }` property whose value IS the callable
|
|
458
|
+
* directly rather than a reference to one declared elsewhere. Three's
|
|
459
|
+
* `ColorManagement.define: function( colorSpaces ) {...}` is exactly this
|
|
460
|
+
* shape: nothing ever names `define` as an identifier, so the existing
|
|
461
|
+
* `ts.isIdentifier(declaration.initializer)` arm never fires, and every
|
|
462
|
+
* call `ColorManagement.define( x )` used to resolve no further than the
|
|
463
|
+
* `PropertyAssignment` itself -- not a `FunctionDeclaration`/
|
|
464
|
+
* `FunctionExpression`/`ArrowFunction`/`MethodDeclaration`, so neither the
|
|
465
|
+
* `returnsBag` edge nor the call-argument-to-parameter edge below ever
|
|
466
|
+
* saw it, and `define`'s own parameter never got claimed even though its
|
|
467
|
+
* ONLY reads are inside `define`'s own body. Reusing the initializer
|
|
468
|
+
* itself as the callee is not a new alias rule -- it is what
|
|
469
|
+
* `ownerDeclOfExpr` would have named directly had the call spelled the
|
|
470
|
+
* function out where it is written (`(function( colorSpaces ){...})( x )`)
|
|
471
|
+
* instead of through the one property that owns it.
|
|
472
|
+
*/
|
|
473
|
+
const calleeDeclarationOf = (callee) => {
|
|
474
|
+
const declaration = ownerDeclOfExpr(callee);
|
|
475
|
+
if (!declaration)
|
|
476
|
+
return null;
|
|
477
|
+
if (ts.isPropertyAssignment(declaration)) {
|
|
478
|
+
if (ts.isIdentifier(declaration.initializer))
|
|
479
|
+
return declNodeOf(checker.getSymbolAtLocation(declaration.initializer));
|
|
480
|
+
if (ts.isFunctionExpression(declaration.initializer) || ts.isArrowFunction(declaration.initializer))
|
|
481
|
+
return declaration.initializer;
|
|
482
|
+
}
|
|
483
|
+
return declaration;
|
|
484
|
+
};
|
|
485
|
+
/** The root bag this expression evaluates to, or `null`. */
|
|
486
|
+
const bagRootOf = (expression) => {
|
|
487
|
+
if (ts.isObjectLiteralExpression(expression)) {
|
|
488
|
+
const owner = literalOwner.get(expression);
|
|
489
|
+
return owner ? (bagOf.get(owner) ?? null) : null;
|
|
490
|
+
}
|
|
491
|
+
// `new F()` is the same question as `F()` here. JS's `[[Construct]]`
|
|
492
|
+
// returns the object a constructor-invoked function RETURNS, discarding
|
|
493
|
+
// the fresh `this` -- so a factory that ends `return theBag` evaluates to
|
|
494
|
+
// that bag under `new` just as it does under a call, and reading only
|
|
495
|
+
// `CallExpression` made this census answer two spellings of one fact
|
|
496
|
+
// differently.
|
|
497
|
+
//
|
|
498
|
+
// The one case `new` differs is a path that returns nothing: `[[Construct]]`
|
|
499
|
+
// then yields the fresh `this` rather than the bag. That is the same
|
|
500
|
+
// fall-through exposure the call arm already carries (a call returning
|
|
501
|
+
// `undefined` on one path), and `returnsBag` bounds both the same way --
|
|
502
|
+
// every `return` in the body must name the same bag, or nothing is claimed.
|
|
503
|
+
//
|
|
504
|
+
// A returned inline literal has no storage owner. A populated literal
|
|
505
|
+
// bound to a declaration can participate when later member writes extend
|
|
506
|
+
// it, under the same identity proof as an initially empty bag.
|
|
507
|
+
if (ts.isCallExpression(expression) || ts.isNewExpression(expression)) {
|
|
508
|
+
const callee = calleeDeclarationOf(expression.expression);
|
|
509
|
+
return callee ? (returnsBag.get(callee) ?? null) : null;
|
|
510
|
+
}
|
|
511
|
+
const declaration = ownerDeclOfExpr(expression);
|
|
512
|
+
return declaration ? (bagOf.get(declaration) ?? null) : null;
|
|
513
|
+
};
|
|
514
|
+
// The `return` expressions of every function body, and the declarations
|
|
515
|
+
// initialized/assigned from an expression -- both collected once, then
|
|
516
|
+
// replayed until nothing new is claimed.
|
|
517
|
+
const returnsOf = new Map();
|
|
518
|
+
const assignments = [];
|
|
519
|
+
/** Every write to one declaration, so a claim can be tested against ALL of them and not just the one that made it. */
|
|
520
|
+
const writesTo = new Map();
|
|
521
|
+
const unknownWrites = new Set();
|
|
522
|
+
const noteWrite = (target, value) => {
|
|
523
|
+
const existing = writesTo.get(target);
|
|
524
|
+
if (existing?.includes(value))
|
|
525
|
+
return;
|
|
526
|
+
assignments.push({ target, value });
|
|
527
|
+
if (existing)
|
|
528
|
+
existing.push(value);
|
|
529
|
+
else
|
|
530
|
+
writesTo.set(target, [value]);
|
|
531
|
+
};
|
|
532
|
+
for (const write of storageWrites) {
|
|
533
|
+
if (write.edge === 'return' || write.edge === 'yield')
|
|
534
|
+
continue;
|
|
535
|
+
const owner = ownerOfWrite(write);
|
|
536
|
+
if (!owner)
|
|
537
|
+
continue;
|
|
538
|
+
if (write.value === null)
|
|
539
|
+
unknownWrites.add(owner);
|
|
540
|
+
else
|
|
541
|
+
noteWrite(owner, write.value);
|
|
542
|
+
}
|
|
543
|
+
const collectEdges = (node) => {
|
|
544
|
+
if (ts.isReturnStatement(node)) {
|
|
545
|
+
const owner = ts.findAncestor(node, (candidate) => ts.isFunctionDeclaration(candidate) ||
|
|
546
|
+
ts.isFunctionExpression(candidate) ||
|
|
547
|
+
ts.isArrowFunction(candidate) ||
|
|
548
|
+
ts.isMethodDeclaration(candidate));
|
|
549
|
+
if (owner) {
|
|
550
|
+
const existing = returnsOf.get(owner);
|
|
551
|
+
if (existing)
|
|
552
|
+
existing.push(node.expression ?? null);
|
|
553
|
+
else
|
|
554
|
+
returnsOf.set(owner, [node.expression ?? null]);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
// A bag passed AS AN ARGUMENT is the same storage inside the callee: the
|
|
558
|
+
// callee's parameter is one more declaration holding it, claimed exactly
|
|
559
|
+
// the way a variable initialized from it is. Only an unannotated
|
|
560
|
+
// parameter of a callee resolved by declaration -- the same resolution a
|
|
561
|
+
// return already uses -- and only positionally: a rest parameter or a
|
|
562
|
+
// spread argument is no single slot and claims nothing.
|
|
563
|
+
// `new F( a, b )` binds F's parameters exactly as `F( a, b )` does -- the
|
|
564
|
+
// construct semantics differ only in what the EXPRESSION evaluates to, never
|
|
565
|
+
// in how arguments reach the frame. Excluding it had nothing to do with
|
|
566
|
+
// construction and everything to do with the node kind not being listed.
|
|
567
|
+
if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
|
|
568
|
+
const callee = calleeDeclarationOf(node.expression);
|
|
569
|
+
if (callee &&
|
|
570
|
+
(ts.isFunctionDeclaration(callee) ||
|
|
571
|
+
ts.isFunctionExpression(callee) ||
|
|
572
|
+
ts.isArrowFunction(callee) ||
|
|
573
|
+
ts.isMethodDeclaration(callee))) {
|
|
574
|
+
;
|
|
575
|
+
(node.arguments ?? []).forEach((argument, position) => {
|
|
576
|
+
if (ts.isSpreadElement(argument))
|
|
577
|
+
return;
|
|
578
|
+
const parameter = callee.parameters[position];
|
|
579
|
+
if (!parameter || parameter.dotDotDotToken || parameter.type || !ts.isIdentifier(parameter.name))
|
|
580
|
+
return;
|
|
581
|
+
noteWrite(parameter, argument);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
ts.forEachChild(node, collectEdges);
|
|
586
|
+
};
|
|
587
|
+
for (const file of files)
|
|
588
|
+
forEachReachableStatement(reachable, file, collectEdges);
|
|
589
|
+
// Finite ascending worklist: `bagOf` and `returnsBag` only gain entries, so
|
|
590
|
+
// this terminates after at most one successful claim per declaration/return
|
|
591
|
+
// cell. A numeric round cap would merely hide an incomplete identity graph.
|
|
592
|
+
while (true) {
|
|
593
|
+
let grew = false;
|
|
594
|
+
for (const { target, value } of assignments) {
|
|
595
|
+
const root = bagRootOf(value);
|
|
596
|
+
if (root && admissibleWrites(target, root) && claim(target, root))
|
|
597
|
+
grew = true;
|
|
598
|
+
}
|
|
599
|
+
for (const [owner, expressions] of returnsOf) {
|
|
600
|
+
if (!(ts.isFunctionDeclaration(owner) ||
|
|
601
|
+
ts.isFunctionExpression(owner) ||
|
|
602
|
+
ts.isArrowFunction(owner) ||
|
|
603
|
+
ts.isMethodDeclaration(owner)))
|
|
604
|
+
continue;
|
|
605
|
+
// A returned bag is not a promise/iterator or an optional result. Reuse
|
|
606
|
+
// the return census's exit proof and keep every bare return in the join.
|
|
607
|
+
if (!owner.body || !ts.isBlock(owner.body) || !definitelyReturns(owner.body.statements))
|
|
608
|
+
continue;
|
|
609
|
+
if ((ts.getCombinedModifierFlags(owner) & ts.ModifierFlags.Async) !== 0 || ('asteriskToken' in owner && owner.asteriskToken))
|
|
610
|
+
continue;
|
|
611
|
+
const roots = expressions.map((expression) => (expression ? bagRootOf(expression) : null));
|
|
612
|
+
const [first] = roots;
|
|
613
|
+
// Every `return` must be the same bag: a function returning a bag on one
|
|
614
|
+
// path and something else on another has no single storage to name.
|
|
615
|
+
if (!first || roots.some((root) => root !== first))
|
|
616
|
+
continue;
|
|
617
|
+
const existing = returnsBag.get(owner);
|
|
618
|
+
if (existing === first)
|
|
619
|
+
continue;
|
|
620
|
+
if (existing) {
|
|
621
|
+
conflicted.add(existing);
|
|
622
|
+
conflicted.add(first);
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
returnsBag.set(owner, first);
|
|
626
|
+
grew = true;
|
|
627
|
+
}
|
|
628
|
+
if (!grew)
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
// Root owners are cells too. Seeding their allocation site above is needed
|
|
632
|
+
// to ground alias cycles, but it is not permission to ignore a competing
|
|
633
|
+
// write to the owner itself. Validate them by the same must-alias rule before
|
|
634
|
+
// any shape is published.
|
|
635
|
+
for (const root of literalsByOwner.keys())
|
|
636
|
+
if (!admissibleWrites(root, root))
|
|
637
|
+
ungrounded.add(root);
|
|
638
|
+
// Pass 3: every property touch whose receiver resolves to a tracked bag.
|
|
639
|
+
const evidenceOf = new Map();
|
|
640
|
+
const evidenceFor = (root) => {
|
|
641
|
+
const existing = evidenceOf.get(root);
|
|
642
|
+
if (existing)
|
|
643
|
+
return existing;
|
|
644
|
+
const fresh = emptyEvidence();
|
|
645
|
+
evidenceOf.set(root, fresh);
|
|
646
|
+
return fresh;
|
|
647
|
+
};
|
|
648
|
+
const isWriteTarget = (access) => {
|
|
649
|
+
const parent = access.parent;
|
|
650
|
+
if (!ts.isBinaryExpression(parent) || parent.left !== access)
|
|
651
|
+
return null;
|
|
652
|
+
return parent.operatorToken.kind === ts.SyntaxKind.EqualsToken ? parent.right : null;
|
|
653
|
+
};
|
|
654
|
+
const isCompoundTarget = (access) => {
|
|
655
|
+
const parent = access.parent;
|
|
656
|
+
if (ts.isBinaryExpression(parent) && parent.left === access)
|
|
657
|
+
return parent.operatorToken.kind !== ts.SyntaxKind.EqualsToken;
|
|
658
|
+
if (ts.isPostfixUnaryExpression(parent))
|
|
659
|
+
return parent.operand === access;
|
|
660
|
+
return ts.isPrefixUnaryExpression(parent) && parent.operand === access;
|
|
661
|
+
};
|
|
662
|
+
/**
|
|
663
|
+
* `Object.assign( bag, source )` -- the one BULK write this census
|
|
664
|
+
* recognises, alongside the per-property `bag.x = v` / `bag[ k ] = v`
|
|
665
|
+
* writes `collectUses` already reads. Three's `ColorManagement.spaces` is
|
|
666
|
+
* the motivating case: every touch of it is `this.spaces[ colorSpace ]`
|
|
667
|
+
* (a computed read), and the ONLY write anywhere is
|
|
668
|
+
* `Object.assign( this.spaces, colorSpaces )` inside `define()` -- so
|
|
669
|
+
* without this, the bag's identity resolves (it is BOUND-able) but it
|
|
670
|
+
* refuses `bag:no-writes` for a write the program plainly makes, just not
|
|
671
|
+
* spelled as an assignment.
|
|
672
|
+
*
|
|
673
|
+
* The source is usually not the literal itself but a PARAMETER that
|
|
674
|
+
* merely forwards one -- three's actual call is
|
|
675
|
+
* `ColorManagement.define({ [ LinearSRGBColorSpace ]: {...}, ... })`,
|
|
676
|
+
* where `define`'s body reads `Object.assign( this.spaces, colorSpaces )`
|
|
677
|
+
* one frame removed from the literal. So this reads two shapes, in order:
|
|
678
|
+
* an INLINE literal's own syntax first, and otherwise the TYPE the
|
|
679
|
+
* checker (or, when that states nothing, the settled parameter census --
|
|
680
|
+
* `observedType`, the same `known ?? resolve` rule every reader in this
|
|
681
|
+
* module applies) gives the source expression, whose properties are
|
|
682
|
+
* exactly the ones the census's own composition already bound from the
|
|
683
|
+
* call site -- not a second guess, the SAME evidence the syntactic path
|
|
684
|
+
* would read, one indirection later. A property with a plain name is a
|
|
685
|
+
* named write, one with a computed name is index evidence -- literally
|
|
686
|
+
* the same partition `collectUses` already makes between a
|
|
687
|
+
* `PropertyAccessExpression` and an `ElementAccessExpression` write.
|
|
688
|
+
*
|
|
689
|
+
* A source whose shape cannot be read either way states no keys this
|
|
690
|
+
* census can attribute without guessing which ones moved, so it is
|
|
691
|
+
* `opaqueUse`, the same refusal a spread already gets -- proportional
|
|
692
|
+
* degradation stops at "one slot degrades to `any`" (see `joined`)
|
|
693
|
+
* because that answer needs a KNOWN key; a whole unknown key set has no
|
|
694
|
+
* slot to degrade.
|
|
695
|
+
*
|
|
696
|
+
* The callee is checked on its own TYPE's declaration IDENTITY --
|
|
697
|
+
* `isGlobalObjectConstructor` (`derived-expression-type.ts`), the shared
|
|
698
|
+
* authority that idiom now goes through, so a local binding that merely
|
|
699
|
+
* happens to be named `Object` is never mistaken for the global. This used
|
|
700
|
+
* to be a second, independently written copy of `flow/value-flow.ts`'s own
|
|
701
|
+
* `isGlobalObjectAssign` -- byte-for-byte identical logic asking the same
|
|
702
|
+
* question twice; both now call the one shared function.
|
|
703
|
+
*/
|
|
704
|
+
const isGlobalObjectAssignCall = (node) => {
|
|
705
|
+
const callee = node.expression;
|
|
706
|
+
if (!ts.isPropertyAccessExpression(callee) || callee.name.text !== 'assign')
|
|
707
|
+
return false;
|
|
708
|
+
if (!ts.isIdentifier(callee.expression))
|
|
709
|
+
return false;
|
|
710
|
+
return isGlobalObjectConstructor(checker, callee.expression, checker.getTypeAtLocation(callee.expression));
|
|
711
|
+
};
|
|
712
|
+
/** A merge source's own literal syntax, when it IS the literal. */
|
|
713
|
+
const mergedPropertiesFromLiteral = (source) => {
|
|
714
|
+
const named = new Map();
|
|
715
|
+
const index = [];
|
|
716
|
+
for (const property of source.properties) {
|
|
717
|
+
if (!ts.isPropertyAssignment(property))
|
|
718
|
+
return null;
|
|
719
|
+
if (ts.isComputedPropertyName(property.name)) {
|
|
720
|
+
index.push(property.initializer);
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
if (!ts.isIdentifier(property.name) && !ts.isStringLiteral(property.name) && !ts.isNumericLiteral(property.name))
|
|
724
|
+
return null;
|
|
725
|
+
named.set(property.name.text, property.initializer);
|
|
726
|
+
}
|
|
727
|
+
return { named, index };
|
|
728
|
+
};
|
|
729
|
+
/**
|
|
730
|
+
* The same shape read off a RESOLVED TYPE instead of syntax, for a merge
|
|
731
|
+
* source that is itself an alias (see this function's own doc) whose
|
|
732
|
+
* type genuinely lists named members. Only NAMED members are read this
|
|
733
|
+
* way: a property symbol's declaration is the `PropertyAssignment` the
|
|
734
|
+
* literal actually wrote, at whichever call site the parameter census
|
|
735
|
+
* resolved -- an index signature has no single declaration to cite one
|
|
736
|
+
* write expression from, so it is left for a `bag[ k ] = v` write or an
|
|
737
|
+
* inline/forwarded literal source (`mergedPropertiesOf`'s other arm) to
|
|
738
|
+
* state instead.
|
|
739
|
+
*/
|
|
740
|
+
const mergedPropertiesFromType = (source) => {
|
|
741
|
+
const type = observedType(source);
|
|
742
|
+
if (!type || statesNothing(type))
|
|
743
|
+
return null;
|
|
744
|
+
const named = new Map();
|
|
745
|
+
for (const property of type.getProperties()) {
|
|
746
|
+
const declaration = property.valueDeclaration ?? property.declarations?.[0];
|
|
747
|
+
if (!declaration || !ts.isPropertyAssignment(declaration) || ts.isComputedPropertyName(declaration.name))
|
|
748
|
+
return null;
|
|
749
|
+
named.set(property.name, declaration.initializer);
|
|
750
|
+
}
|
|
751
|
+
return { named, index: [] };
|
|
752
|
+
};
|
|
753
|
+
/**
|
|
754
|
+
* The merge source's shape, tried three ways in order: its own syntax
|
|
755
|
+
* when it IS the literal; failing that, the ONE literal expression this
|
|
756
|
+
* module's own write-set already recorded for it (`writesTo`, the same
|
|
757
|
+
* table the call-argument edge above fills for `define( colorSpaces )` --
|
|
758
|
+
* `colorSpaces` is not itself a bag, so `bagRootOf` never claims it, but
|
|
759
|
+
* it is still exactly one parameter written from exactly one place, and
|
|
760
|
+
* that place IS the literal -- reading it back out is not a second
|
|
761
|
+
* alias rule, it is the SAME edge `admissibleWrites` already reads for a
|
|
762
|
+
* bag value, asked of a non-bag one); and only then the resolved TYPE,
|
|
763
|
+
* for a source this module cannot trace to a single write at all.
|
|
764
|
+
*/
|
|
765
|
+
const mergedPropertiesOf = (source) => {
|
|
766
|
+
if (ts.isObjectLiteralExpression(source))
|
|
767
|
+
return mergedPropertiesFromLiteral(source);
|
|
768
|
+
const owner = ownerDeclOfExpr(source);
|
|
769
|
+
const writes = owner ? writesTo.get(owner) : undefined;
|
|
770
|
+
if (writes && writes.length === 1 && owner && !unknownWrites.has(owner)) {
|
|
771
|
+
const [only] = writes;
|
|
772
|
+
if (only && ts.isObjectLiteralExpression(only))
|
|
773
|
+
return mergedPropertiesFromLiteral(only);
|
|
774
|
+
}
|
|
775
|
+
return mergedPropertiesFromType(source);
|
|
776
|
+
};
|
|
777
|
+
const collectObjectAssign = (node) => {
|
|
778
|
+
const target = node.arguments[0];
|
|
779
|
+
if (target === undefined || node.arguments.length < 2 || !isGlobalObjectAssignCall(node))
|
|
780
|
+
return;
|
|
781
|
+
const root = bagRootOf(target);
|
|
782
|
+
if (!root)
|
|
783
|
+
return;
|
|
784
|
+
const evidence = evidenceFor(root);
|
|
785
|
+
for (const source of node.arguments.slice(1)) {
|
|
786
|
+
const merged = ts.isSpreadElement(source) ? null : mergedPropertiesOf(source);
|
|
787
|
+
if (!merged) {
|
|
788
|
+
evidence.opaqueUse = 'Object.assign';
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
for (const [key, value] of merged.named) {
|
|
792
|
+
const existing = evidence.namedWrites.get(key);
|
|
793
|
+
if (existing)
|
|
794
|
+
existing.push(value);
|
|
795
|
+
else
|
|
796
|
+
evidence.namedWrites.set(key, [value]);
|
|
797
|
+
}
|
|
798
|
+
evidence.indexWrites.push(...merged.index);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
const collectUses = (node) => {
|
|
802
|
+
if (ts.isCallExpression(node))
|
|
803
|
+
collectObjectAssign(node);
|
|
804
|
+
if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
|
|
805
|
+
const root = bagRootOf(node.expression);
|
|
806
|
+
if (root) {
|
|
807
|
+
const evidence = evidenceFor(root);
|
|
808
|
+
// A compound assignment (`bag.n += 1`, `bag.n ++`) is a READ, not a
|
|
809
|
+
// write this census can type: its value expression is the slot's own
|
|
810
|
+
// previous contents, which is what is being inferred. So it states
|
|
811
|
+
// that the member EXISTS and nothing about what it holds -- exactly
|
|
812
|
+
// what a plain read states. If some other site writes the member
|
|
813
|
+
// outright, that write types it; if none does, `member-never-written`
|
|
814
|
+
// refuses the bag, which is the same answer by the same rule rather
|
|
815
|
+
// than a second one.
|
|
816
|
+
const written = isCompoundTarget(node) ? null : isWriteTarget(node);
|
|
817
|
+
const key = ts.isPropertyAccessExpression(node) ? node.name.text : literalMemberNameOf(node);
|
|
818
|
+
if (key !== null) {
|
|
819
|
+
if (written) {
|
|
820
|
+
const existing = evidence.namedWrites.get(key);
|
|
821
|
+
if (existing)
|
|
822
|
+
existing.push(written);
|
|
823
|
+
else
|
|
824
|
+
evidence.namedWrites.set(key, [written]);
|
|
825
|
+
}
|
|
826
|
+
else
|
|
827
|
+
evidence.namedReads.add(key);
|
|
828
|
+
}
|
|
829
|
+
else if (written)
|
|
830
|
+
evidence.indexWrites.push(written);
|
|
831
|
+
else
|
|
832
|
+
evidence.indexRead = true;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (ts.isSpreadAssignment(node) || ts.isSpreadElement(node)) {
|
|
836
|
+
const root = bagRootOf(node.expression);
|
|
837
|
+
if (root)
|
|
838
|
+
evidenceFor(root).opaqueUse = 'spread';
|
|
839
|
+
}
|
|
840
|
+
if (ts.isDeleteExpression(node)) {
|
|
841
|
+
const target = node.expression;
|
|
842
|
+
// `delete bag[k]` is ordinary dictionary behaviour -- the `dictionary`
|
|
843
|
+
// carrier's own `std::map` erase (`emit-dynamic-properties.ts`) -- so it
|
|
844
|
+
// is index evidence, adding no type of its own. `delete bag.x` is a
|
|
845
|
+
// transition every member of a bag already admits: the members are all
|
|
846
|
+
// OPTIONAL (a bag starts empty), so "removed" is a state inside the
|
|
847
|
+
// member's stated domain, and the delete contributes no type either --
|
|
848
|
+
// only the fact that the member exists, recorded the way a read records
|
|
849
|
+
// it, so a member that is ONLY ever deleted still refuses as
|
|
850
|
+
// never-written. Whether the backend can lower the delete itself is the
|
|
851
|
+
// backend's own, separately-gated question; if it cannot, that one site
|
|
852
|
+
// fails closed by name instead of this census refusing the whole bag
|
|
853
|
+
// for a state its members already carry.
|
|
854
|
+
if (ts.isPropertyAccessExpression(target) || ts.isElementAccessExpression(target)) {
|
|
855
|
+
const root = bagRootOf(target.expression);
|
|
856
|
+
if (root) {
|
|
857
|
+
const evidence = evidenceFor(root);
|
|
858
|
+
const key = ts.isPropertyAccessExpression(target) ? target.name.text : literalMemberNameOf(target);
|
|
859
|
+
if (key === null) {
|
|
860
|
+
evidence.indexRead = true;
|
|
861
|
+
evidence.indexDelete = true;
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
evidence.namedReads.add(key);
|
|
865
|
+
evidence.namedDeletes.add(key);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
ts.forEachChild(node, collectUses);
|
|
871
|
+
};
|
|
872
|
+
for (const file of files)
|
|
873
|
+
forEachReachableStatement(reachable, file, collectUses);
|
|
874
|
+
/**
|
|
875
|
+
* The one type covering every value written to a slot.
|
|
876
|
+
*
|
|
877
|
+
* A write whose own type states nothing (`any`, an empty object, `never[]`)
|
|
878
|
+
* degrades THAT SLOT to the checker's own `any` -- the member field derives
|
|
879
|
+
* `dynamic`, exactly the carrier every touch of it has today -- rather than
|
|
880
|
+
* refusing the whole bag. This is not a guess: `any` is precisely what the
|
|
881
|
+
* program states for that value, restated at field granularity. What it
|
|
882
|
+
* buys is proportionality: one untyped write no longer forces every OTHER
|
|
883
|
+
* member, and every read of the bag itself, back into the box. Genuine
|
|
884
|
+
* DISAGREEMENT between typed writes still refuses -- `any` never absorbs a
|
|
885
|
+
* conflict this census can see, only a statement the program never made.
|
|
886
|
+
*/
|
|
887
|
+
const joined = (expressions) => {
|
|
888
|
+
const types = [];
|
|
889
|
+
for (const expression of expressions) {
|
|
890
|
+
const type = observedType(expression);
|
|
891
|
+
if (!type || statesNothing(type))
|
|
892
|
+
return 'states-nothing';
|
|
893
|
+
types.push(type);
|
|
894
|
+
}
|
|
895
|
+
// When no one write covers the others, the disagreement can still be the
|
|
896
|
+
// answer: three's renderer writes `materialProperties.lightProbeGrid` as a
|
|
897
|
+
// boolean at program acquisition and as a grid-or-null per object, and the
|
|
898
|
+
// slot holds exactly that union. Degrading it to `any` sent every read of
|
|
899
|
+
// it -- and the narrowing that follows -- to the box for a value whose
|
|
900
|
+
// every write was typed. The same second question the array census asks
|
|
901
|
+
// (`collection-bindings.ts`), answered by the same rule, so a set that
|
|
902
|
+
// census would refuse (a member subsuming another, too many arms) is
|
|
903
|
+
// refused here too.
|
|
904
|
+
const widest = widestOf(checker, types) ?? disjointUnionTypeOf(checker, types);
|
|
905
|
+
return widest ?? 'disagree';
|
|
906
|
+
};
|
|
907
|
+
/** See `ObjectBagCensus.slotTypeOf` -- the ONE widening, shared by both spellings of a slot. */
|
|
908
|
+
const widenSlot = (type) => (type.flags & ts.TypeFlags.Any) !== 0 ? type : checker.getNullableType(type, ts.TypeFlags.Undefined);
|
|
909
|
+
const bound = new Map();
|
|
910
|
+
const refusalReason = new Map();
|
|
911
|
+
// Why each slot that came out `any` did, keyed `<bag>.<member>`. A bound bag
|
|
912
|
+
// reporting `any=18` says nothing about whether there is work behind those
|
|
913
|
+
// slots: a slot degraded because its one write states nothing is a cascade,
|
|
914
|
+
// while one degraded because its writes DISAGREE or carry `null` is a
|
|
915
|
+
// decision this census made and could make differently. Measurement only --
|
|
916
|
+
// read by `debugReport`, which is itself behind an env var.
|
|
917
|
+
const memberReason = new Map();
|
|
918
|
+
const identityOf = (node) => {
|
|
919
|
+
const file = node.getSourceFile();
|
|
920
|
+
return `${file.fileName.split('/').slice(-1)[0]}:${file.getLineAndCharacterOfPosition(node.getStart()).line + 1}`;
|
|
921
|
+
};
|
|
922
|
+
// `censusRefusals` is the published list (`census-refusal.ts`); `refusalReason`
|
|
923
|
+
// stays as the internal by-root lookup `refusalOf`/`debugReport` already key
|
|
924
|
+
// on, so this one call sites both without a second, independently-drifting
|
|
925
|
+
// reason string. The owner is the root's own declaration -- `identityOf`,
|
|
926
|
+
// the same file:line this module already prints in `debugReport` -- because
|
|
927
|
+
// a whole-bag refusal is never about a slot, only about the storage itself.
|
|
928
|
+
const censusRefusals = [];
|
|
929
|
+
const refuseRoot = (root, censusRoot, reason) => {
|
|
930
|
+
refusalReason.set(root, reason);
|
|
931
|
+
censusRefusals.push(censusRefusal('bag', censusRoot, reason, identityOf(root)));
|
|
932
|
+
};
|
|
933
|
+
for (const root of literalsByOwner.keys()) {
|
|
934
|
+
if (conflicted.has(root)) {
|
|
935
|
+
refuseRoot(root, 'two-bags-one-cell', 'bag:two-bags-one-cell');
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
if (ungrounded.has(root)) {
|
|
939
|
+
refuseRoot(root, 'write-not-proven-alias', 'bag:write-not-proven-alias');
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
const evidence = evidenceOf.get(root);
|
|
943
|
+
const literals = literalsByOwner.get(root) ?? [];
|
|
944
|
+
const populated = literals.some((literal) => initialMembers.has(literal));
|
|
945
|
+
const initialKeys = new Set(literals.flatMap((literal) => [...(initialMembers.get(literal)?.keys() ?? [])]));
|
|
946
|
+
if (populated && (!evidence || ![...evidence.namedWrites.keys()].some((key) => !initialKeys.has(key))))
|
|
947
|
+
continue;
|
|
948
|
+
if (!evidence) {
|
|
949
|
+
refuseRoot(root, 'no-uses', 'bag:no-uses');
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
if (evidence.opaqueUse) {
|
|
953
|
+
// `opaqueUse` only ever holds one of two literal causes (`collectUses`,
|
|
954
|
+
// `collectObjectAssign`), so each is its own stable root rather than one
|
|
955
|
+
// root fed by an interpolated, in-principle-unbounded string.
|
|
956
|
+
refuseRoot(root, evidence.opaqueUse === 'spread' ? 'opaque-spread' : 'opaque-object-assign', `bag:${evidence.opaqueUse}`);
|
|
957
|
+
continue;
|
|
958
|
+
}
|
|
959
|
+
// Allocation fields and later assignments fill the same slots. Keep
|
|
960
|
+
// insertion order from the literal and include every initial value in
|
|
961
|
+
// the join, so augmentation cannot erase a field or narrow its writes.
|
|
962
|
+
const writes = new Map();
|
|
963
|
+
for (const literal of literals)
|
|
964
|
+
for (const [key, value] of initialMembers.get(literal) ?? []) {
|
|
965
|
+
const values = writes.get(key) ?? [];
|
|
966
|
+
values.push(value);
|
|
967
|
+
writes.set(key, values);
|
|
968
|
+
}
|
|
969
|
+
for (const [key, values] of evidence.namedWrites)
|
|
970
|
+
writes.set(key, [...(writes.get(key) ?? []), ...values]);
|
|
971
|
+
const required = new Set([...initialKeys].filter((key) => !evidence.indexDelete && !evidence.namedDeletes.has(key) && literals.every((literal) => initialMembers.get(literal)?.has(key))));
|
|
972
|
+
if (evidence.namedWrites.size === 0 && evidence.indexWrites.length === 0) {
|
|
973
|
+
refuseRoot(root, 'no-writes', 'bag:no-writes');
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
// A member READ but never visibly written is `any`, by the same
|
|
977
|
+
// degradation rule an untyped write follows (see `joined`): either no
|
|
978
|
+
// write exists anywhere and every read really is `undefined` (inside
|
|
979
|
+
// `any`), or a write flows through a receiver chain no census here can
|
|
980
|
+
// resolve -- and `any` is what the checker answers for that read today,
|
|
981
|
+
// restated at field granularity instead of refusing every OTHER member
|
|
982
|
+
// over it. The bag itself still needs at least one visible write to bind
|
|
983
|
+
// at all (above), so a value this census never saw touched stays refused.
|
|
984
|
+
const readOnly = [...evidence.namedReads].filter((key) => !writes.has(key));
|
|
985
|
+
const indexReadOnly = evidence.indexRead && evidence.indexWrites.length === 0;
|
|
986
|
+
// A member whose writes disagree degrades to `any` by the same
|
|
987
|
+
// proportionality rule an untyped write follows in `joined`:
|
|
988
|
+
// that ONE slot keeps exactly the carrier every touch of it has today,
|
|
989
|
+
// instead of its conflict refusing every other member and every read of
|
|
990
|
+
// the receiver itself. Nothing is guessed -- a conflicted slot is never
|
|
991
|
+
// given either side's type, only the absence of a statement.
|
|
992
|
+
const members = new Map();
|
|
993
|
+
for (const [key, values] of writes) {
|
|
994
|
+
const type = joined(values);
|
|
995
|
+
if (typeof type === 'string')
|
|
996
|
+
memberReason.set(`${identityOf(root)}.${key}`, type);
|
|
997
|
+
members.set(key, typeof type === 'string' ? checker.getAnyType() : type);
|
|
998
|
+
}
|
|
999
|
+
// A read of a literal key does not create a second fixed storage slot
|
|
1000
|
+
// when the bag already has indexed writes. That read belongs to the
|
|
1001
|
+
// index carrier, including its absence, just like bag[runtimeKey].
|
|
1002
|
+
for (const key of populated || evidence.indexWrites.length > 0 ? [] : readOnly) {
|
|
1003
|
+
memberReason.set(`${identityOf(root)}.${key}`, 'read-only');
|
|
1004
|
+
members.set(key, checker.getAnyType());
|
|
1005
|
+
}
|
|
1006
|
+
// A populated record already has a field protocol for runtime-key reads.
|
|
1007
|
+
// Such a read neither allocates a new property nor proves an index write.
|
|
1008
|
+
let index = indexReadOnly && !populated ? checker.getAnyType() : null;
|
|
1009
|
+
if (evidence.indexWrites.length > 0) {
|
|
1010
|
+
const type = joined(evidence.indexWrites);
|
|
1011
|
+
index = typeof type === 'string' ? checker.getAnyType() : type;
|
|
1012
|
+
}
|
|
1013
|
+
bound.set(root, { members, index, required });
|
|
1014
|
+
}
|
|
1015
|
+
// Type queries keep the allocation's checker identity even when there is
|
|
1016
|
+
// no value-flow edge to ask. Publishing only expression reads gives
|
|
1017
|
+
// `ReturnType<typeof factory>` the old literal fields while the factory
|
|
1018
|
+
// returns the augmented storage. This index publishes that same census
|
|
1019
|
+
// answer; unrelated structural annotations never match by field spelling.
|
|
1020
|
+
const shapesByType = new Map();
|
|
1021
|
+
for (const [root, shape] of bound) {
|
|
1022
|
+
for (const literal of literalsByOwner.get(root) ?? []) {
|
|
1023
|
+
if (!initialMembers.has(literal))
|
|
1024
|
+
continue;
|
|
1025
|
+
for (const node of [literal, root]) {
|
|
1026
|
+
const own = checker.getTypeAtLocation(node);
|
|
1027
|
+
for (const type of [own, checker.getWidenedType(own)]) {
|
|
1028
|
+
if ((type.flags & ts.TypeFlags.Object) === 0)
|
|
1029
|
+
continue;
|
|
1030
|
+
const existing = shapesByType.get(type);
|
|
1031
|
+
shapesByType.set(type, existing === undefined || existing === shape ? shape : null);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
const absencesAt = createBagAbsenceResolver(checker, ownerDeclOfExpr, calleeDeclarationOf, writesTo, returnsOf);
|
|
1037
|
+
const valueShape = (root, node) => {
|
|
1038
|
+
let bag = root ? bound.get(root) : undefined;
|
|
1039
|
+
const owner = ts.isExpression(node) ? ownerDeclOfExpr(node) : node;
|
|
1040
|
+
// A stated view keeps its own type. When that type names the allocation
|
|
1041
|
+
// itself (including through a type query), its fields are the census's
|
|
1042
|
+
// fields too; otherwise no alias proof overrides the annotation.
|
|
1043
|
+
if (bag === undefined || (owner && declaresWrittenType(owner)))
|
|
1044
|
+
bag = shapesByType.get(checker.getTypeAtLocation(node)) ?? undefined;
|
|
1045
|
+
return bag ? { ...bag, absences: absencesAt(node) } : null;
|
|
1046
|
+
};
|
|
1047
|
+
return {
|
|
1048
|
+
identity: { roots: new Set(literalsByOwner.keys()), bagOf, returnsBag, conflicted, ungrounded },
|
|
1049
|
+
shapeForType: (type) => shapesByType.get(type) ?? null,
|
|
1050
|
+
shapeAt: (expression) => {
|
|
1051
|
+
// Deliberately NOT answered at a CALL, even though `bagRootOf` resolves
|
|
1052
|
+
// one internally so the bag's identity can propagate through a `return`.
|
|
1053
|
+
// A call's result has TWO authorities -- this node's type and the
|
|
1054
|
+
// callee's own resolved signature -- and `producers/invocations.ts`
|
|
1055
|
+
// states both from the same census on purpose. Answering here would move
|
|
1056
|
+
// only one of them, so the invocation producer would find the two
|
|
1057
|
+
// disagreeing and withhold, taking its consumers with it: MEASURED at
|
|
1058
|
+
// withheld 8 -> 20 and 22 operations silently gone on the three.js app, for a
|
|
1059
|
+
// gain of 19 carriers. The variable a call's result is bound to is
|
|
1060
|
+
// claimed by the propagation above and answers normally, which is where
|
|
1061
|
+
// the bag's uses actually are.
|
|
1062
|
+
if (ts.isCallExpression(expression) || ts.isNewExpression(expression))
|
|
1063
|
+
return null;
|
|
1064
|
+
const root = bagRootOf(expression);
|
|
1065
|
+
return valueShape(root, expression);
|
|
1066
|
+
},
|
|
1067
|
+
callResultShapeAt: (expression) => {
|
|
1068
|
+
const root = bagRootOf(expression);
|
|
1069
|
+
return valueShape(root, expression);
|
|
1070
|
+
},
|
|
1071
|
+
returnShapeOf: (declaration) => {
|
|
1072
|
+
const root = returnsBag.get(declaration);
|
|
1073
|
+
return valueShape(root, declaration);
|
|
1074
|
+
},
|
|
1075
|
+
// The `ts.Type` twin of `bagMemberTypeAt` below, deliberately written to
|
|
1076
|
+
// the same three steps in the same order -- named member, then index,
|
|
1077
|
+
// then nothing -- so the two cannot answer one slot two ways. The
|
|
1078
|
+
// widening is `getNullableType`, which is `bagSlotTypeOf`'s flat union
|
|
1079
|
+
// spelled in the checker's own terms: a slot holding `T | null` comes
|
|
1080
|
+
// back `T | null | undefined`, three distinguishable values, never a
|
|
1081
|
+
// carrier tagged twice.
|
|
1082
|
+
slotTypeAt: (expression) => {
|
|
1083
|
+
const named = ts.isPropertyAccessExpression(expression);
|
|
1084
|
+
if (!named && !ts.isElementAccessExpression(expression))
|
|
1085
|
+
return null;
|
|
1086
|
+
const root = bagRootOf(expression.expression);
|
|
1087
|
+
const bag = valueShape(root, expression.expression);
|
|
1088
|
+
if (!bag)
|
|
1089
|
+
return null;
|
|
1090
|
+
const key = named ? expression.name.text : literalMemberNameOf(expression);
|
|
1091
|
+
const slot = (key === null ? undefined : bag.members.get(key)) ?? bag.index;
|
|
1092
|
+
if (!slot || (slot.flags & ts.TypeFlags.Any) !== 0)
|
|
1093
|
+
return null;
|
|
1094
|
+
return key !== null && bag.required?.has(key) ? slot : widenSlot(slot);
|
|
1095
|
+
},
|
|
1096
|
+
slotTypeOf: widenSlot,
|
|
1097
|
+
shapeForOwner: (declaration) => {
|
|
1098
|
+
const root = bagOf.get(declaration);
|
|
1099
|
+
return valueShape(root, declaration);
|
|
1100
|
+
},
|
|
1101
|
+
boundCount: bound.size,
|
|
1102
|
+
refusals: censusRefusals,
|
|
1103
|
+
refusalOf: (expression) => {
|
|
1104
|
+
const root = bagRootOf(expression);
|
|
1105
|
+
return root ? (refusalReason.get(root) ?? null) : null;
|
|
1106
|
+
},
|
|
1107
|
+
debugReport: () => {
|
|
1108
|
+
const where = (node) => {
|
|
1109
|
+
const file = node.getSourceFile();
|
|
1110
|
+
return `${file.fileName.split('/').slice(-1)[0]}:${file.getLineAndCharacterOfPosition(node.getStart()).line + 1}`;
|
|
1111
|
+
};
|
|
1112
|
+
const lines = [];
|
|
1113
|
+
for (const [root, shape] of bound) {
|
|
1114
|
+
// EVERY member, with its carrier -- never a silent `slice`. The
|
|
1115
|
+
// previous form printed the first 14 keys with no ellipsis, so a bag
|
|
1116
|
+
// holding 46 members reported 14 and read exactly like a census that
|
|
1117
|
+
// had dropped 32 of them. An investigation spent a build cycle per
|
|
1118
|
+
// hypothesis chasing writes the census had already attributed
|
|
1119
|
+
// correctly; `docs/DEFECT-PATTERNS.md` section 9 is about this and the
|
|
1120
|
+
// instrument still did it. The interesting question a bound bag raises
|
|
1121
|
+
// is which SLOTS are `any`, so the types are what this prints.
|
|
1122
|
+
const slots = [...shape.members].map(([key, type]) => {
|
|
1123
|
+
const reason = memberReason.get(`${identityOf(root)}.${key}`);
|
|
1124
|
+
return `${key}:${checker.typeToString(type)}${reason ? `[${reason}]` : ''}`;
|
|
1125
|
+
});
|
|
1126
|
+
const anySlots = [...shape.members.values()].filter((type) => (type.flags & ts.TypeFlags.Any) !== 0).length;
|
|
1127
|
+
lines.push(`[BAG] BOUND ${where(root)} members=${shape.members.size} any=${anySlots} index=${shape.index ? checker.typeToString(shape.index) : '-'}`);
|
|
1128
|
+
lines.push(`[BAG] ${slots.join(' ')}`);
|
|
1129
|
+
}
|
|
1130
|
+
for (const [root, reason] of refusalReason) {
|
|
1131
|
+
lines.push(`[BAG] REFUSED ${reason} ${where(root)}`);
|
|
1132
|
+
const evidence = evidenceOf.get(root);
|
|
1133
|
+
if (!evidence)
|
|
1134
|
+
continue;
|
|
1135
|
+
for (const [key, values] of evidence.namedWrites) {
|
|
1136
|
+
const type = joined(values);
|
|
1137
|
+
lines.push(`[BAG] ${key} <- ${typeof type === 'string' ? type : checker.typeToString(type)} (${values.length} writes)`);
|
|
1138
|
+
}
|
|
1139
|
+
for (const key of evidence.namedReads)
|
|
1140
|
+
if (!evidence.namedWrites.has(key))
|
|
1141
|
+
lines.push(`[BAG] ${key} <- READ-ONLY`);
|
|
1142
|
+
for (const value of evidence.indexWrites.slice(0, 6)) {
|
|
1143
|
+
const type = joined([value]);
|
|
1144
|
+
lines.push(`[BAG] [k] <- ${typeof type === 'string' ? type : checker.typeToString(type)}`);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return lines.join('\n') + '\n';
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
};
|
|
1151
|
+
/**
|
|
1152
|
+
* The `undefined`-widened spelling of ONE bag slot -- the single authority for
|
|
1153
|
+
* how this census states a member's type, used both by the whole-bag shape
|
|
1154
|
+
* below and by a member READ off that bag.
|
|
1155
|
+
*
|
|
1156
|
+
* An `any` slot (an untyped write, restated at field granularity -- see
|
|
1157
|
+
* `joined`) already holds every value including `undefined`; widening it would
|
|
1158
|
+
* union `any` with `undefined`, a spelling nobody wrote, for nothing.
|
|
1159
|
+
*/
|
|
1160
|
+
const bagSlotTypeOf = (typeOf, bags) => (type) => typeOf(bags.slotTypeOf(type));
|
|
1161
|
+
/**
|
|
1162
|
+
* A MEMBER READ off a known bag, typed by the bag rather than by the checker.
|
|
1163
|
+
*
|
|
1164
|
+
* `shapeAt` answers for the bag's OWNER aliases -- a bare identifier, or a
|
|
1165
|
+
* `this.field` access standing IN for the whole storage -- because that is the
|
|
1166
|
+
* identity `bagRootOf` keys on. It has no case for `bag.name` or `bag[ key ]`,
|
|
1167
|
+
* where the receiver names the bag and the NODE names one slot of it, so those
|
|
1168
|
+
* fell through the whole `typeAt` chain in `structural.ts` to the raw checker,
|
|
1169
|
+
* which for a `{}`-typed receiver answers `any`. The result was the two
|
|
1170
|
+
* authorities this compiler keeps rediscovering, one operation apart: the
|
|
1171
|
+
* struct field (or the index sidecar) is laid out NATIVELY from this same
|
|
1172
|
+
* census, while the GET reading it is planned `dynamic`, so the emitter
|
|
1173
|
+
* declares the receiving temp `gea::Value` and assigns a
|
|
1174
|
+
* `gea::Optional<std::string>` into it. The emitted expression text was
|
|
1175
|
+
* already right; only the representation selected for the read was wrong.
|
|
1176
|
+
*
|
|
1177
|
+
* The answer is the bag's own slot rule (`bagSlotTypeOf`), not a second
|
|
1178
|
+
* reading of it -- a named key resolves in `members`, and anything else the
|
|
1179
|
+
* bag admits resolves in the string-keyed `index` half, exactly as the
|
|
1180
|
+
* interned shape below spells them. A key the bag declares neither way answers
|
|
1181
|
+
* nothing and the existing fallback chain runs unchanged: this states what the
|
|
1182
|
+
* census already knows, it never guesses past it.
|
|
1183
|
+
*
|
|
1184
|
+
* A literal-keyed element access is a named read written with brackets --
|
|
1185
|
+
* `literalMemberNameOf` is the compiler's one authority for that reading and
|
|
1186
|
+
* is reused rather than restated here.
|
|
1187
|
+
*/
|
|
1188
|
+
const bagMemberTypeAt = (bags, typeOf, slotTypeOf, node) => {
|
|
1189
|
+
const named = ts.isPropertyAccessExpression(node);
|
|
1190
|
+
if (!named && !ts.isElementAccessExpression(node))
|
|
1191
|
+
return null;
|
|
1192
|
+
const bag = bags.shapeAt(node.expression);
|
|
1193
|
+
if (!bag)
|
|
1194
|
+
return null;
|
|
1195
|
+
const key = named ? node.name.text : literalMemberNameOf(node);
|
|
1196
|
+
const member = key === null ? undefined : bag.members.get(key);
|
|
1197
|
+
if (member)
|
|
1198
|
+
return key !== null && bag.required?.has(key) ? typeOf(member) : slotTypeOf(member);
|
|
1199
|
+
return bag.index ? slotTypeOf(bag.index) : null;
|
|
1200
|
+
};
|
|
1201
|
+
/**
|
|
1202
|
+
* The bag's inferred members, interned as an object shape -- the one place
|
|
1203
|
+
* this census's answer enters the type system.
|
|
1204
|
+
*
|
|
1205
|
+
* It lives beside the census rather than in `structural.ts` because it is the
|
|
1206
|
+
* bag's OWN shape rule, not a mapper rule: the optionality below is a fact
|
|
1207
|
+
* about how this storage is filled, and a second copy of it in the mapper
|
|
1208
|
+
* would be a second authority over the same question.
|
|
1209
|
+
*
|
|
1210
|
+
* Every later-added member is OPTIONAL, and its type includes `undefined`.
|
|
1211
|
+
* Allocation fields present in every seed retain their required status unless
|
|
1212
|
+
* a tracked deletion can remove them. A read of a later member that runs before
|
|
1213
|
+
* its write really does observe `undefined` -- `if ( bag.init === undefined )`
|
|
1214
|
+
* is the guard the shape exists to keep compiling. Making those later fields
|
|
1215
|
+
* required would erase a real absent state. A slot whose own type already carries
|
|
1216
|
+
* `null` is widened the same way and stays representable, because
|
|
1217
|
+
* `bagSlotTypeOf` builds the union FLAT -- see its own comment for the
|
|
1218
|
+
* measurement that settled that.
|
|
1219
|
+
*/
|
|
1220
|
+
export const bagShapeTypeAt = (table, typeOf, bags, node) => {
|
|
1221
|
+
// A binding's own published value is asked with the DECLARATION node, which
|
|
1222
|
+
// is never an expression, so the cell missed every answer below while every
|
|
1223
|
+
// READ of that binding -- asked with an identifier -- hit them. One storage,
|
|
1224
|
+
// two structural types, and the emitter then refuses (or worse, does not):
|
|
1225
|
+
// `const found = bag[ key ]` placed its cell as `undefined` while the read
|
|
1226
|
+
// filling it is `optional<string>`. The declaration states no type of its
|
|
1227
|
+
// own here, so its value IS its initializer's -- asking that one expression
|
|
1228
|
+
// is not a new rule, it is the same rule reaching the node that stands for
|
|
1229
|
+
// the same value.
|
|
1230
|
+
const assignment = ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken ? node : null;
|
|
1231
|
+
const asked = ts.isExpression(node) ? node : ts.isVariableDeclaration(node) ? node.initializer : undefined;
|
|
1232
|
+
const optional = bagSlotTypeOf(typeOf, bags);
|
|
1233
|
+
// A cell whose bag arrives by assignment rather than by its initializer --
|
|
1234
|
+
// see `shapeForOwner`. Asked only after the initializer, so a declaration
|
|
1235
|
+
// that DOES state its bag through one keeps answering exactly as before.
|
|
1236
|
+
// A JavaScript class field has no `PropertyDeclaration`: the checker gives
|
|
1237
|
+
// the field symbol the `this.field = {}` assignment itself as its sole
|
|
1238
|
+
// declaration. That assignment is therefore the storage declaration, not
|
|
1239
|
+
// merely an expression that happens to produce the bag. Treating it as the
|
|
1240
|
+
// latter leaves the class layout at `{}` while reads infer an index sidecar,
|
|
1241
|
+
// and a recursive `new Child()` write then re-enters through two different
|
|
1242
|
+
// carriers. `shapeForOwner` is identity-keyed and returns nothing for an
|
|
1243
|
+
// ordinary assignment to an existing variable, so this admits only the
|
|
1244
|
+
// checker-proven JS-field form rather than guessing from assignment syntax.
|
|
1245
|
+
const owned = ts.isVariableDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isParameter(node) || assignment !== null
|
|
1246
|
+
? bags.shapeForOwner(node)
|
|
1247
|
+
: null;
|
|
1248
|
+
if (asked === undefined)
|
|
1249
|
+
return owned ? internBagShape(table, typeOf, optional, owned) : null;
|
|
1250
|
+
// `callResultShapeAt` is asked here, and only here, because this is the one
|
|
1251
|
+
// path whose caller declares the matching divergence
|
|
1252
|
+
// (`producers/invocations.ts`'s `bagResultOverride`). See that accessor's own
|
|
1253
|
+
// header for why `shapeAt` withholds it.
|
|
1254
|
+
const bag = bags.shapeAt(asked) ?? (ts.isCallExpression(asked) || ts.isNewExpression(asked) ? bags.callResultShapeAt(asked) : null) ?? owned;
|
|
1255
|
+
if (!bag)
|
|
1256
|
+
return bagMemberTypeAt(bags, typeOf, optional, asked);
|
|
1257
|
+
return internBagShape(table, typeOf, optional, bag);
|
|
1258
|
+
};
|
|
1259
|
+
/** One bag shape as a structural record -- shared by both arms of `bagShapeTypeAt` so the two cannot state different layouts for one bag. */
|
|
1260
|
+
const internBagShape = (table, typeOf, optional, bag) => {
|
|
1261
|
+
const present = table.intern(bagStructuralShape(typeOf, optional, bag));
|
|
1262
|
+
return bag.absences?.length
|
|
1263
|
+
? table.intern({
|
|
1264
|
+
kind: 'union',
|
|
1265
|
+
members: [present, ...bag.absences.map((primitive) => table.intern({ kind: 'primitive', primitive }))]
|
|
1266
|
+
})
|
|
1267
|
+
: present;
|
|
1268
|
+
};
|
|
1269
|
+
const bagStructuralShape = (typeOf, optional, bag) => ({
|
|
1270
|
+
kind: 'object',
|
|
1271
|
+
membersDropped: false,
|
|
1272
|
+
members: [...bag.members].map(([key, type]) => ({
|
|
1273
|
+
key: { kind: 'string', value: key },
|
|
1274
|
+
type: bag.required?.has(key) ? typeOf(type) : optional(type),
|
|
1275
|
+
optional: !bag.required?.has(key),
|
|
1276
|
+
readonly: false,
|
|
1277
|
+
accessor: null
|
|
1278
|
+
})),
|
|
1279
|
+
index: bag.index ? [{ key: 'string', value: optional(bag.index), readonly: false }] : []
|
|
1280
|
+
});
|
|
1281
|
+
/** Type and value readers share one member/optionality publication, including recursive walks. */
|
|
1282
|
+
export const bagShapeOfType = (typeOf, bags, type) => {
|
|
1283
|
+
const bag = bags.shapeForType(type);
|
|
1284
|
+
return bag ? bagStructuralShape(typeOf, bagSlotTypeOf(typeOf, bags), bag) : null;
|
|
1285
|
+
};
|
|
1286
|
+
/** A callable and its call sites publish the identical inferred bag layout. */
|
|
1287
|
+
export const bagReturnTypeOf = (table, typeOf, bags, declaration) => {
|
|
1288
|
+
const bag = bags.returnShapeOf(declaration);
|
|
1289
|
+
return bag ? internBagShape(table, typeOf, bagSlotTypeOf(typeOf, bags), bag) : null;
|
|
1290
|
+
};
|