@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,1418 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { existsSync, readdirSync } from 'fs';
|
|
3
|
+
import { dirname, join, relative, resolve, sep } from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* A member read through a BASE-typed reference, where only SUBCLASSES of
|
|
6
|
+
* that base declare the member -- three.js's whole duck-typing idiom.
|
|
7
|
+
* `Material.js` never declares `isMeshStandardMaterial`; `MeshStandardMaterial.js`
|
|
8
|
+
* sets it in its own constructor. `Light.js` never declares `shadow`;
|
|
9
|
+
* `DirectionalLight.js`/`SpotLight.js`/`PointLight.js` each assign one of
|
|
10
|
+
* their own. To `checkJs`, `material.isMeshStandardMaterial` and
|
|
11
|
+
* `light.shadow` are therefore unknown members of a JS class and resolve to
|
|
12
|
+
* `any` -- every one of them a `dynamic` (`gea_cpp_value`) carrier downstream,
|
|
13
|
+
* though the value the source reads is never actually dynamic at all.
|
|
14
|
+
*
|
|
15
|
+
* ## The fact this states
|
|
16
|
+
*
|
|
17
|
+
* If `x: Base` and `Base` declares no member `m`, but some subclasses of
|
|
18
|
+
* `Base` in this package DO declare `m`, then at runtime `x.m` is either the
|
|
19
|
+
* value one of those subclasses assigns it, or `undefined` (when `x` is an
|
|
20
|
+
* instance of `Base` itself, or of a subclass that never touches `m`). Its
|
|
21
|
+
* type is therefore the UNION of `m`'s type across every subclass of `Base`
|
|
22
|
+
* that declares it, plus `undefined` unconditionally -- since nothing here
|
|
23
|
+
* proves `Base` itself, or an undiscovered subclass, is unreachable. That is
|
|
24
|
+
* an over-approximation of the runtime value. Unannotated primitive field
|
|
25
|
+
* initializers widen to their mutable storage domain, including boolean;
|
|
26
|
+
* an initializer alone cannot prove a field never changes.
|
|
27
|
+
*
|
|
28
|
+
* ## Why this is a SOURCE TRANSFORM, not a census rule
|
|
29
|
+
*
|
|
30
|
+
* `dynamic` has one production site (`representation/primitives.ts`'s
|
|
31
|
+
* `primitiveCarrier`) and every hit already arrives typed `any` -- there is
|
|
32
|
+
* no representation-layer lever for this (`.scratch/fleet/BRIEF.md`'s closed
|
|
33
|
+
* lever list). The fix has to make the CHECKER itself answer
|
|
34
|
+
* `material.isMeshStandardMaterial` with something other than `any`, before
|
|
35
|
+
* any of the four per-kind censuses (`parameter-bindings.ts` etc.) or their
|
|
36
|
+
* shared `derived-expression-type.ts#memberTypeOf` ever ask. So this rewrites
|
|
37
|
+
* `Material.js`'s own text, ahead of parsing, to state the fact above as an
|
|
38
|
+
* ordinary JSDoc-annotated field -- `checker.getPropertyOfType` then just
|
|
39
|
+
* finds it, unmodified, the same way it finds any other declared field.
|
|
40
|
+
*
|
|
41
|
+
* The generated declaration is type evidence, not an allocation claim. It is
|
|
42
|
+
* tagged `@geaSubclassMemberOverlay`; normalization carries that tag through
|
|
43
|
+
* class projection so layout consumers can omit the ancestor slot and route a
|
|
44
|
+
* typed polymorphic read or write to the concrete descendant field (or to a
|
|
45
|
+
* native sidecar for a receiver with no such descendant). Treating the tag as
|
|
46
|
+
* ordinary storage is the source of the large common-base objects this pass
|
|
47
|
+
* must avoid.
|
|
48
|
+
*
|
|
49
|
+
* ## Why the type text is read from the SOURCE, not the checker
|
|
50
|
+
*
|
|
51
|
+
* The first version of this module spelled each declarer's contribution as
|
|
52
|
+
* `InstanceType<typeof MeshStandardMaterial>['isMeshStandardMaterial']`,
|
|
53
|
+
* asking the checker to answer for a subclass what it already answers fine
|
|
54
|
+
* when that subclass is the receiver directly. That is UNSOUNDLY circular:
|
|
55
|
+
* computing `MeshStandardMaterial`'s instance type first requires resolving
|
|
56
|
+
* its base (`Material`)'s FULL type, which -- once `Material` carries this
|
|
57
|
+
* very overlay field -- includes the field whose type is being asked for.
|
|
58
|
+
* TypeScript resolves that cycle to `any`, which is not a refusal a `dynamic`
|
|
59
|
+
* carrier can see: it is indistinguishable from the ORIGINAL unresolved
|
|
60
|
+
* member, so every overlay field this module added came back `any` anyway,
|
|
61
|
+
* while ALSO adding a new declared-but-unread `any` field to `Base` itself.
|
|
62
|
+
* Measured on the three.js app: boxed carriers ROSE 17429 -> 22882 rather than
|
|
63
|
+
* falling. `InstanceType<typeof Y>[...]` is therefore never used here.
|
|
64
|
+
*
|
|
65
|
+
* Instead, each declaring subclass's own assignment is read for its type as
|
|
66
|
+
* TEXT, exactly the way `declaration-overlay-transform.ts` takes a `.d.ts`
|
|
67
|
+
* field's type as text rather than as a `ts.Type` (see that file's own "Why
|
|
68
|
+
* no second `ts.Program`" for the identical reasoning, one boundary over):
|
|
69
|
+
* a JSDoc `@type` tag on the assignment when the subclass wrote one --
|
|
70
|
+
* three.js almost always does (`DirectionalLight.js`: `@type
|
|
71
|
+
* {DirectionalLightShadow}` directly above `this.shadow = new
|
|
72
|
+
* DirectionalLightShadow();`) -- or, failing that, the literal shape of the
|
|
73
|
+
* assigned expression (`true`/`false`, `null`, a number/string literal, or
|
|
74
|
+
* `new SomeClass(...)`). Every identifier the captured text names is checked
|
|
75
|
+
* against this package's own class index (or a small ambient-keyword list)
|
|
76
|
+
* before it is used; an unresolvable one refuses that ONE candidate rather
|
|
77
|
+
* than guessing.
|
|
78
|
+
*
|
|
79
|
+
* ## Scope: primitive members, and reference-typed members from ONE lineage
|
|
80
|
+
*
|
|
81
|
+
* A primitive `is*`-flag candidate (every resolved text a boolean/number/
|
|
82
|
+
* string literal or keyword) is always sound to overlay: over-approximating
|
|
83
|
+
* a flag with `| undefined` never costs a subclass anything it did not
|
|
84
|
+
* already have, because a primitive value has no member of its own for a
|
|
85
|
+
* wider declared type to shadow.
|
|
86
|
+
*
|
|
87
|
+
* A reference-typed candidate (`Light.shadow: DirectionalLightShadow |
|
|
88
|
+
* PointLightShadow | ...`) is sound to STATE (see "The fact this states",
|
|
89
|
+
* above) but is only sound to ADD when it cannot also corrupt what its own
|
|
90
|
+
* declarers read: TypeScript gives a subclass's un-annotated `this.x = ...`
|
|
91
|
+
* the type its base now declares, not the narrower type that assignment's
|
|
92
|
+
* own shape implies. `shareCommonAncestor` is the structural test that keeps
|
|
93
|
+
* this sound -- every declaring class must be drawn from ONE inheritance
|
|
94
|
+
* lineage, so a caller reaching the member through any union arm still
|
|
95
|
+
* resolves the SAME inherited method. Two declaring classes with no common
|
|
96
|
+
* ancestor (three.js's own `Object3D.matrix: Matrix4` and
|
|
97
|
+
* `Texture.matrix: Matrix3`, both root classes that happen to reuse a field
|
|
98
|
+
* NAME across unrelated branches of a near-universal base) each contribute
|
|
99
|
+
* their own same-named method with a different signature, and the union
|
|
100
|
+
* this module would add corrupts the narrower classes that already had a
|
|
101
|
+
* precise answer -- measured on the three.js app before this check existed: viol
|
|
102
|
+
* 0->13, unres 0->3, every one of them a `.matrix.copy`/`.matrix.premultiply`
|
|
103
|
+
* call reached through the widened type, not through anything this module's
|
|
104
|
+
* own fields touch directly. `modulesReachableFrom` is the second, unrelated
|
|
105
|
+
* guard: an `@import` this module adds for a reference-typed candidate's
|
|
106
|
+
* value type must not close a cycle back to the file it is added to (see
|
|
107
|
+
* that function's own comment, mirroring `declaration-overlay-transform.ts`).
|
|
108
|
+
*
|
|
109
|
+
* ## What it refuses
|
|
110
|
+
*
|
|
111
|
+
* - A receiver whose declared type is not a plain `class` (an interface, a
|
|
112
|
+
* union, an anonymous object type): those never reach this transform in
|
|
113
|
+
* the first place, because it only ever adds fields to a real
|
|
114
|
+
* `class X extends Y {}` declaration found by its own syntactic scan.
|
|
115
|
+
* - Any assignment whose type this scan cannot read as text: no JSDoc
|
|
116
|
+
* `@type`, and a right-hand side that is not one of the recognized literal
|
|
117
|
+
* shapes. That declarer contributes nothing for that member rather than a
|
|
118
|
+
* guess; if EVERY declarer refuses, the member is left exactly as `any`.
|
|
119
|
+
* - A type text naming an identifier this scan cannot resolve to either an
|
|
120
|
+
* ambient keyword/global or a class in this package's own index: refused
|
|
121
|
+
* the same way, per declarer.
|
|
122
|
+
* - Class hierarchy shapes it cannot trust: a heritage clause that is not a
|
|
123
|
+
* bare `extends Identifier` (a mixin factory) refuses the whole base whose
|
|
124
|
+
* name it mentions; `Object.assign( X.prototype, ... )` / `X.prototype.name
|
|
125
|
+
* = ...` refuses `X` specifically as a declarer, without refusing an
|
|
126
|
+
* unrelated hierarchy elsewhere in the same package (three.js's own
|
|
127
|
+
* `KeyframeTrack.js` uses this idiom; it has nothing to do with `Material`
|
|
128
|
+
* or `Light`).
|
|
129
|
+
* - A candidate name already bound in `Base`'s own file (an existing import,
|
|
130
|
+
* local class, or variable of that name): reusing it risks a second
|
|
131
|
+
* identity for the class the overlay means, so that declarer is dropped
|
|
132
|
+
* from the union rather than risking a wrong reference. Mirrors
|
|
133
|
+
* `declaration-overlay-transform.ts`'s own `boundHere` guard.
|
|
134
|
+
* - A reference-typed candidate whose value type would need an `@import`
|
|
135
|
+
* that closes a cycle back to `Base`'s own file: refused per declarer
|
|
136
|
+
* (`modulesReachableFrom`), same granularity as the two checks above.
|
|
137
|
+
* - A reference-typed member whose declaring classes span more than one
|
|
138
|
+
* inheritance lineage (`shareCommonAncestor`): refused for the WHOLE
|
|
139
|
+
* member, not per declarer -- a partial union would still corrupt the
|
|
140
|
+
* declarers it kept.
|
|
141
|
+
* - A member name never read anywhere in the package except via `this.`: a
|
|
142
|
+
* purely internal bookkeeping field is real but is not the fact this
|
|
143
|
+
* overlay states, and declaring it on `Base` anyway is only a field (and a
|
|
144
|
+
* possible `dynamic` carrier of its own) nothing in the program needed.
|
|
145
|
+
* - A member name Base (or a prior transform) already declares, and
|
|
146
|
+
* getter/setter members: the checker already has an answer, or this has no
|
|
147
|
+
* business overlaying a callable.
|
|
148
|
+
*/
|
|
149
|
+
// `examples`/`test(s)` are skipped as a general convention, not a three.js
|
|
150
|
+
// special case: a library package's demos and test harnesses routinely carry
|
|
151
|
+
// vendored, minified, or mock code (`Object.assign(X.prototype, ...)` mixins,
|
|
152
|
+
// dynamic base classes) that is never part of the package's own shipped
|
|
153
|
+
// class hierarchy and is not reachable from an application's import graph
|
|
154
|
+
// through the package's real entry points.
|
|
155
|
+
const SKIP_DIRS = new Set([
|
|
156
|
+
'node_modules',
|
|
157
|
+
'.git',
|
|
158
|
+
'dist',
|
|
159
|
+
'build',
|
|
160
|
+
'examples',
|
|
161
|
+
'example',
|
|
162
|
+
'test',
|
|
163
|
+
'tests',
|
|
164
|
+
'__tests__'
|
|
165
|
+
]);
|
|
166
|
+
/**
|
|
167
|
+
* Type texts this module will actually emit a field for -- primitive
|
|
168
|
+
* literal/keyword shapes only (`true`, `false`, `boolean`, `number`,
|
|
169
|
+
* `string`), never a class reference. Reference-typed members
|
|
170
|
+
* (`Light.shadow: DirectionalLightShadow | PointLightShadow | ...`) resolve
|
|
171
|
+
* correctly through the checker in isolation, but importing their classes
|
|
172
|
+
* into `Base`'s file reaches into subsystems this scan's own hierarchy walk
|
|
173
|
+
* never intended (three.js's WebGPU Node-material graph, `AttributeNode` and
|
|
174
|
+
* unrelated siblings) and traded boxed carriers for
|
|
175
|
+
* `unresolved-reaches-materialization` violations elsewhere in the program --
|
|
176
|
+
* a real regression, not a win (measured on the three.js app: viol 3->16, unres 2->5).
|
|
177
|
+
* Primitive-only keeps every emitted field free of any `@import`, so this
|
|
178
|
+
* module can never widen what a file resolves beyond the field itself.
|
|
179
|
+
*/
|
|
180
|
+
/** Type-position names that resolve without an import: JS/TS built-ins and generic utility types. */
|
|
181
|
+
const AMBIENT_TOKENS = new Set([
|
|
182
|
+
'any',
|
|
183
|
+
'bigint',
|
|
184
|
+
'boolean',
|
|
185
|
+
'false',
|
|
186
|
+
'never',
|
|
187
|
+
'null',
|
|
188
|
+
'number',
|
|
189
|
+
'object',
|
|
190
|
+
'string',
|
|
191
|
+
'symbol',
|
|
192
|
+
'true',
|
|
193
|
+
'undefined',
|
|
194
|
+
'unknown',
|
|
195
|
+
'void',
|
|
196
|
+
'this',
|
|
197
|
+
'Array',
|
|
198
|
+
'ArrayBuffer',
|
|
199
|
+
'ArrayBufferLike',
|
|
200
|
+
'ArrayBufferView',
|
|
201
|
+
'ArrayLike',
|
|
202
|
+
'BigInt64Array',
|
|
203
|
+
'BigUint64Array',
|
|
204
|
+
'DataView',
|
|
205
|
+
'Date',
|
|
206
|
+
'Error',
|
|
207
|
+
'Float32Array',
|
|
208
|
+
'Float64Array',
|
|
209
|
+
'Function',
|
|
210
|
+
'Int8Array',
|
|
211
|
+
'Int16Array',
|
|
212
|
+
'Int32Array',
|
|
213
|
+
'Map',
|
|
214
|
+
'Partial',
|
|
215
|
+
'Promise',
|
|
216
|
+
'Readonly',
|
|
217
|
+
'ReadonlyArray',
|
|
218
|
+
'ReadonlyMap',
|
|
219
|
+
'ReadonlySet',
|
|
220
|
+
'Record',
|
|
221
|
+
'RegExp',
|
|
222
|
+
'Set',
|
|
223
|
+
'Uint8Array',
|
|
224
|
+
'Uint8ClampedArray',
|
|
225
|
+
'Uint16Array',
|
|
226
|
+
'Uint32Array',
|
|
227
|
+
'WeakMap',
|
|
228
|
+
'WeakSet'
|
|
229
|
+
]);
|
|
230
|
+
/** The nearest ancestor directory that owns a `package.json`, or `null`. */
|
|
231
|
+
const packageRootFor = (filePath) => {
|
|
232
|
+
let dir = dirname(resolve(filePath));
|
|
233
|
+
for (;;) {
|
|
234
|
+
if (existsSync(join(dir, 'package.json')))
|
|
235
|
+
return dir;
|
|
236
|
+
const parent = dirname(dir);
|
|
237
|
+
if (parent === dir)
|
|
238
|
+
return null;
|
|
239
|
+
dir = parent;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Which files a package root HOLDS, as against what any of them contain.
|
|
244
|
+
*
|
|
245
|
+
* The index built from this list is already cached per `DeclarerReader`, which
|
|
246
|
+
* means once per compilation -- and a harness that compiles many programs out
|
|
247
|
+
* of one package (`scripts/emit-corpus.mjs`: 180 programs, all rooted at this
|
|
248
|
+
* repository) re-walked the whole tree for each of them. That walk was 27% of
|
|
249
|
+
* the corpus gate's entire run while yielding almost nothing: the directories
|
|
250
|
+
* it descends are dominated by gitignored build output (`measurements/` alone
|
|
251
|
+
* holds ~14,000 entries) that contains no `.js` at all.
|
|
252
|
+
*
|
|
253
|
+
* Only the enumeration is shared. Every file is still re-read and re-parsed
|
|
254
|
+
* through `read` for each compilation, so changed CONTENT is always seen, and
|
|
255
|
+
* a file that has since been deleted simply fails its read and is skipped. The
|
|
256
|
+
* one thing a second compilation in the same process would miss is a `.js`
|
|
257
|
+
* file ADDED to the package after the first -- which `compile()` , a one-shot
|
|
258
|
+
* batch entry point, has no way to be in the middle of.
|
|
259
|
+
*/
|
|
260
|
+
const sourceFilesByRoot = new Map();
|
|
261
|
+
/**
|
|
262
|
+
* Every ancestor directory from `filePath`'s own directory up to (and
|
|
263
|
+
* including) `root`, as absolute paths.
|
|
264
|
+
*
|
|
265
|
+
* `collectSourceFiles` below skips a `SKIP_DIRS` name unconditionally, which
|
|
266
|
+
* is correct for a real package's vendored/build/test-harness scenery -- but
|
|
267
|
+
* wrong for the directory that HOLDS the file this compilation is actually
|
|
268
|
+
* compiling: that file is by definition part of the program, whatever its
|
|
269
|
+
* directory happens to be named. `compiler/test/runtime/*` is exactly this:
|
|
270
|
+
* moved under `test/` in 608ce6e52, its programs stopped being indexed
|
|
271
|
+
* because `test` is (correctly, for everyone else) skipped, `baseInfo`
|
|
272
|
+
* silently went undefined, and the overlay this whole module exists for
|
|
273
|
+
* became a no-op for them. The fix is not to stop skipping `test` -- that
|
|
274
|
+
* would re-admit a real package's own test fixtures into its class index --
|
|
275
|
+
* it is to never skip an ancestor of the file actually being compiled.
|
|
276
|
+
*/
|
|
277
|
+
const ancestryBetween = (root, filePath) => {
|
|
278
|
+
const stop = resolve(root);
|
|
279
|
+
const out = new Set();
|
|
280
|
+
let dir = dirname(resolve(filePath));
|
|
281
|
+
for (;;) {
|
|
282
|
+
out.add(dir);
|
|
283
|
+
if (dir === stop)
|
|
284
|
+
break;
|
|
285
|
+
const parent = dirname(dir);
|
|
286
|
+
if (parent === dir)
|
|
287
|
+
break;
|
|
288
|
+
dir = parent;
|
|
289
|
+
}
|
|
290
|
+
return out;
|
|
291
|
+
};
|
|
292
|
+
/** The cache key `collectSourceFiles`/`buildPackageIndex` share: identical to `root` in the common case (no override), so the shared walk cache is unaffected for every package that needs none. */
|
|
293
|
+
const indexKey = (root, neverSkip) => neverSkip.size === 0 ? root : `${root}${[...neverSkip].sort().join('')}`;
|
|
294
|
+
/**
|
|
295
|
+
* Every `.js`/`.mjs` file under `root`, skipping vendored/build directories
|
|
296
|
+
* -- except a directory named in `SKIP_DIRS` that is also in `neverSkip`
|
|
297
|
+
* (see `ancestryBetween`), which this walk descends into regardless.
|
|
298
|
+
*
|
|
299
|
+
* Cached by `(root, neverSkip)`: this list is shared across every program a
|
|
300
|
+
* single process compiles against the same package root (`emit-corpus.mjs`
|
|
301
|
+
* compiles the whole corpus in one process; see this cache's original
|
|
302
|
+
* comment), so a `neverSkip` override must be part of the key -- keying on
|
|
303
|
+
* `root` alone would let the FIRST program compiled from a directory decide,
|
|
304
|
+
* for every later one, whether `test/runtime` exists.
|
|
305
|
+
*/
|
|
306
|
+
const collectSourceFiles = (root, neverSkip) => {
|
|
307
|
+
const key = indexKey(root, neverSkip);
|
|
308
|
+
const known = sourceFilesByRoot.get(key);
|
|
309
|
+
if (known)
|
|
310
|
+
return known;
|
|
311
|
+
const out = [];
|
|
312
|
+
const walk = (dir) => {
|
|
313
|
+
let entries;
|
|
314
|
+
try {
|
|
315
|
+
entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' });
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
for (const entry of entries) {
|
|
321
|
+
if (entry.name.startsWith('.'))
|
|
322
|
+
continue;
|
|
323
|
+
if (entry.isDirectory()) {
|
|
324
|
+
const childPath = join(dir, entry.name);
|
|
325
|
+
if (SKIP_DIRS.has(entry.name) && !neverSkip.has(childPath))
|
|
326
|
+
continue;
|
|
327
|
+
walk(childPath);
|
|
328
|
+
}
|
|
329
|
+
else if (/\.m?js$/.test(entry.name)) {
|
|
330
|
+
out.push(join(dir, entry.name));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
walk(root);
|
|
335
|
+
sourceFilesByRoot.set(key, out);
|
|
336
|
+
return out;
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* JSDoc's own vague-object special case, spelled as plain text: `{Object}`
|
|
340
|
+
* (capitalized) resolves to `any` in the checker's own JSDoc mapping
|
|
341
|
+
* (`jsDocTypeIsUninformative` in `derived-expression-type.ts` documents the
|
|
342
|
+
* same fact once a checker exists to ask; this is the purely-textual
|
|
343
|
+
* analogue this transform needs, since it runs before any checker does).
|
|
344
|
+
* `{object}` (lowercase) resolves to a real but EMPTY structural type --
|
|
345
|
+
* carrying exactly as little as `any` does about what the value holds (see
|
|
346
|
+
* that same file's own comment distinguishing the two spellings). Three.js
|
|
347
|
+
* spells almost every `this.parameters = {...}` assignment with exactly
|
|
348
|
+
* `@type {Object}` directly above it; trusting that tag verbatim would
|
|
349
|
+
* overlay `Base` with a field whose declared type answers nothing, when the
|
|
350
|
+
* assignment's own literal shape states the real answer just below it. Only
|
|
351
|
+
* the bare, exact token is treated as vague -- a real type that merely
|
|
352
|
+
* contains the word (`SomeObjectPool`) is left untouched.
|
|
353
|
+
*/
|
|
354
|
+
const isVagueObjectTag = (text) => text === 'Object' || text === 'object';
|
|
355
|
+
/**
|
|
356
|
+
* The type text a constructor PARAMETER's own JSDoc `@param {Type} name` tag
|
|
357
|
+
* states, or -- when the constructor carries none for this parameter -- the
|
|
358
|
+
* literal shape of its own default value. Exists for exactly one caller,
|
|
359
|
+
* `objectLiteralShapeOf` below: `this.parameters = { width: width, height:
|
|
360
|
+
* height }` is an object literal whose property VALUES are references to
|
|
361
|
+
* the constructor's own parameters, not literals in their own right --
|
|
362
|
+
* three.js's universal geometry-constructor idiom. The same text-not-checker
|
|
363
|
+
* reasoning as the rest of this file applies (see the file header's "Why the
|
|
364
|
+
* type text is read from the SOURCE"): there is no checker yet at this stage
|
|
365
|
+
* to ask what `width`'s inferred type is.
|
|
366
|
+
*/
|
|
367
|
+
const constructorParamTypeTextOf = (param, file) => {
|
|
368
|
+
for (const tag of ts.getJSDocParameterTags(param)) {
|
|
369
|
+
const typeNode = tag.typeExpression?.type;
|
|
370
|
+
if (!typeNode)
|
|
371
|
+
continue;
|
|
372
|
+
const text = typeNode.getText(file).replace(/\s+/g, ' ').trim();
|
|
373
|
+
if (text.length > 0 && !text.includes('*/'))
|
|
374
|
+
return text;
|
|
375
|
+
}
|
|
376
|
+
return param.initializer ? literalShapeText(param.initializer) : null;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Parameter name -> type text, for every parameter of `ctor` this scan
|
|
380
|
+
* could read one for. A parameter this cannot read contributes nothing --
|
|
381
|
+
* absent from the map, not a poisoning `null` -- so a property naming it
|
|
382
|
+
* simply fails to resolve later, the same granularity as every other
|
|
383
|
+
* per-candidate refusal in this file.
|
|
384
|
+
*/
|
|
385
|
+
const constructorParamTypesOf = (ctor, file) => {
|
|
386
|
+
const map = new Map();
|
|
387
|
+
for (const param of ctor.parameters) {
|
|
388
|
+
if (!ts.isIdentifier(param.name))
|
|
389
|
+
continue;
|
|
390
|
+
const text = constructorParamTypeTextOf(param, file);
|
|
391
|
+
if (text !== null)
|
|
392
|
+
map.set(param.name.text, text);
|
|
393
|
+
}
|
|
394
|
+
return map;
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* `expr`'s own shape as a property-name -> type-text map, when `expr` is an
|
|
398
|
+
* object literal every one of whose properties this scan can read as text:
|
|
399
|
+
* a plain (non-computed, non-spread, non-method) property whose value is
|
|
400
|
+
* either a recognized literal shape (`literalShapeText`) or a reference to
|
|
401
|
+
* one of the enclosing constructor's own parameters (`paramTypes`, from
|
|
402
|
+
* `constructorParamTypesOf`) -- three.js's `this.parameters = { width:
|
|
403
|
+
* width, height: height }` idiom, this module's whole motivating case for
|
|
404
|
+
* the object-literal extension (see the file header's "Scope" section). A
|
|
405
|
+
* single property this scan cannot read poisons the WHOLE shape, exactly
|
|
406
|
+
* like a class's own `ownMembers` text candidates: a partial record would
|
|
407
|
+
* under-state what the literal actually holds, not merely omit evidence.
|
|
408
|
+
*/
|
|
409
|
+
const objectLiteralShapeOf = (expr, paramTypes) => {
|
|
410
|
+
const shape = new Map();
|
|
411
|
+
for (const property of expr.properties) {
|
|
412
|
+
let name;
|
|
413
|
+
let valueExpr;
|
|
414
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
415
|
+
name = property.name.text;
|
|
416
|
+
valueExpr = property.name;
|
|
417
|
+
}
|
|
418
|
+
else if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name)) {
|
|
419
|
+
name = property.name.text;
|
|
420
|
+
valueExpr = property.initializer;
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// A spread, a computed/string-literal key, or a method/getter/setter
|
|
424
|
+
// member: not a shape this scan can spell as a plain record field.
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
if (shape.has(name))
|
|
428
|
+
return null;
|
|
429
|
+
const text = literalShapeText(valueExpr) ?? (ts.isIdentifier(valueExpr) ? (paramTypes.get(valueExpr.text) ?? null) : null);
|
|
430
|
+
if (text === null)
|
|
431
|
+
return null;
|
|
432
|
+
shape.set(name, text);
|
|
433
|
+
}
|
|
434
|
+
// An empty object literal states nothing worth overlaying.
|
|
435
|
+
return shape.size > 0 ? shape : null;
|
|
436
|
+
};
|
|
437
|
+
/** The raw text of a node's own `@type {...}` JSDoc tag, or `null`. */
|
|
438
|
+
const jsDocTypeTextOn = (node, file) => {
|
|
439
|
+
const tag = ts.getJSDocTypeTag(node);
|
|
440
|
+
const typeNode = tag?.typeExpression?.type;
|
|
441
|
+
if (!typeNode)
|
|
442
|
+
return null;
|
|
443
|
+
const text = typeNode.getText(file).replace(/\s+/g, ' ').trim();
|
|
444
|
+
return text.length === 0 || text.includes('*/') ? null : text;
|
|
445
|
+
};
|
|
446
|
+
/** A type text for `expr`'s own literal shape, when it is one this scan trusts without an annotation. */
|
|
447
|
+
const literalShapeText = (expr) => {
|
|
448
|
+
// A mutable field's initializer states its primitive domain, not a
|
|
449
|
+
// permanent literal. The same widening already applies to numbers and
|
|
450
|
+
// strings below; explicit literal JSDoc annotations remain authoritative.
|
|
451
|
+
if (expr.kind === ts.SyntaxKind.TrueKeyword || expr.kind === ts.SyntaxKind.FalseKeyword)
|
|
452
|
+
return 'boolean';
|
|
453
|
+
if (expr.kind === ts.SyntaxKind.NullKeyword)
|
|
454
|
+
return 'null';
|
|
455
|
+
if (ts.isNumericLiteral(expr))
|
|
456
|
+
return 'number';
|
|
457
|
+
if (ts.isStringLiteralLike(expr))
|
|
458
|
+
return 'string';
|
|
459
|
+
if (ts.isNewExpression(expr) && ts.isIdentifier(expr.expression))
|
|
460
|
+
return expr.expression.text;
|
|
461
|
+
return null;
|
|
462
|
+
};
|
|
463
|
+
/** An identifier-safe literal member name, or `null` for a computed/non-field key. */
|
|
464
|
+
const descriptorMemberNameOf = (name) => {
|
|
465
|
+
if (ts.isIdentifier(name))
|
|
466
|
+
return name.text;
|
|
467
|
+
if (!ts.isStringLiteralLike(name))
|
|
468
|
+
return null;
|
|
469
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name.text) ? name.text : null;
|
|
470
|
+
};
|
|
471
|
+
/**
|
|
472
|
+
* The value expression a closed data-descriptor literal states for type
|
|
473
|
+
* evidence only. Descriptor attributes deliberately do not have to be
|
|
474
|
+
* assignment-compatible here: this scan never replaces the runtime call.
|
|
475
|
+
*/
|
|
476
|
+
const dataDescriptorValueOf = (descriptor) => {
|
|
477
|
+
const allowed = new Set(['value', 'writable', 'enumerable', 'configurable']);
|
|
478
|
+
const seen = new Set();
|
|
479
|
+
let value = null;
|
|
480
|
+
for (const property of descriptor.properties) {
|
|
481
|
+
if (!ts.isPropertyAssignment(property))
|
|
482
|
+
return null;
|
|
483
|
+
const key = descriptorMemberNameOf(property.name);
|
|
484
|
+
if (key === null || !allowed.has(key) || seen.has(key))
|
|
485
|
+
return null;
|
|
486
|
+
seen.add(key);
|
|
487
|
+
if (key === 'value')
|
|
488
|
+
value = property.initializer;
|
|
489
|
+
}
|
|
490
|
+
return value;
|
|
491
|
+
};
|
|
492
|
+
/**
|
|
493
|
+
* Descriptor-backed own fields whose value types the package census may
|
|
494
|
+
* restate without flattening their runtime property attributes.
|
|
495
|
+
*/
|
|
496
|
+
const descriptorMemberEvidenceOf = (statement) => {
|
|
497
|
+
if (!ts.isCallExpression(statement.expression))
|
|
498
|
+
return null;
|
|
499
|
+
const call = statement.expression;
|
|
500
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
501
|
+
return null;
|
|
502
|
+
if (!ts.isIdentifier(call.expression.expression) || call.expression.expression.text !== 'Object')
|
|
503
|
+
return null;
|
|
504
|
+
const member = call.expression.name.text;
|
|
505
|
+
if (member === 'defineProperty') {
|
|
506
|
+
if (call.arguments.length !== 3 || call.arguments[0]?.kind !== ts.SyntaxKind.ThisKeyword)
|
|
507
|
+
return null;
|
|
508
|
+
const key = call.arguments[1];
|
|
509
|
+
const descriptor = call.arguments[2];
|
|
510
|
+
if (!key || !ts.isStringLiteralLike(key) || !descriptor || !ts.isObjectLiteralExpression(descriptor))
|
|
511
|
+
return null;
|
|
512
|
+
const name = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key.text) ? key.text : null;
|
|
513
|
+
const value = dataDescriptorValueOf(descriptor);
|
|
514
|
+
return name !== null && value !== null ? [{ name, annotation: statement, value }] : null;
|
|
515
|
+
}
|
|
516
|
+
if (member !== 'defineProperties')
|
|
517
|
+
return null;
|
|
518
|
+
if (call.arguments.length !== 2 || call.arguments[0]?.kind !== ts.SyntaxKind.ThisKeyword)
|
|
519
|
+
return null;
|
|
520
|
+
const descriptors = call.arguments[1];
|
|
521
|
+
if (!descriptors || !ts.isObjectLiteralExpression(descriptors))
|
|
522
|
+
return null;
|
|
523
|
+
const evidence = [];
|
|
524
|
+
const seen = new Set();
|
|
525
|
+
for (const property of descriptors.properties) {
|
|
526
|
+
if (!ts.isPropertyAssignment(property))
|
|
527
|
+
return null;
|
|
528
|
+
const name = descriptorMemberNameOf(property.name);
|
|
529
|
+
if (name === null || seen.has(name) || !ts.isObjectLiteralExpression(property.initializer))
|
|
530
|
+
return null;
|
|
531
|
+
const value = dataDescriptorValueOf(property.initializer);
|
|
532
|
+
if (value === null)
|
|
533
|
+
return null;
|
|
534
|
+
seen.add(name);
|
|
535
|
+
evidence.push({ name, annotation: property, value });
|
|
536
|
+
}
|
|
537
|
+
return evidence.length > 0 ? evidence : null;
|
|
538
|
+
};
|
|
539
|
+
const memberTypeTextsOf = (klass, file) => {
|
|
540
|
+
const state = new Map();
|
|
541
|
+
const methodNames = new Set();
|
|
542
|
+
const declaredNames = new Set();
|
|
543
|
+
// Only the CONSTRUCTOR is trusted to ESTABLISH a field's shape (see below,
|
|
544
|
+
// where its body is walked). Its own parameters are also the source
|
|
545
|
+
// `objectLiteralShapeOf` reads for `this.parameters = { width: width }`
|
|
546
|
+
// style object literals, so the lookup is built once, here, and threaded
|
|
547
|
+
// through every assignment this class's own scan reads.
|
|
548
|
+
const ctor = klass.members.find((m) => ts.isConstructorDeclaration(m));
|
|
549
|
+
const paramTypes = ctor ? constructorParamTypesOf(ctor, file) : new Map();
|
|
550
|
+
const recordText = (name, text) => {
|
|
551
|
+
const cur = state.get(name);
|
|
552
|
+
if (cur?.kind === 'poisoned')
|
|
553
|
+
return;
|
|
554
|
+
if (text === null) {
|
|
555
|
+
state.set(name, { kind: 'poisoned' });
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (cur?.kind === 'object') {
|
|
559
|
+
state.set(name, { kind: 'poisoned' });
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
if (cur?.kind === 'text') {
|
|
563
|
+
if (!cur.texts.includes(text))
|
|
564
|
+
cur.texts.push(text);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
state.set(name, { kind: 'text', texts: [text] });
|
|
568
|
+
};
|
|
569
|
+
const recordObjectLiteral = (name, expr) => {
|
|
570
|
+
const cur = state.get(name);
|
|
571
|
+
if (cur?.kind === 'poisoned')
|
|
572
|
+
return;
|
|
573
|
+
if (cur) {
|
|
574
|
+
// A second assignment (a scalar OR another object literal) for the
|
|
575
|
+
// same member is ambiguous evidence -- poison rather than guess which
|
|
576
|
+
// one a caller reaching the member actually sees.
|
|
577
|
+
state.set(name, { kind: 'poisoned' });
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
const shape = objectLiteralShapeOf(expr, paramTypes);
|
|
581
|
+
state.set(name, shape ? { kind: 'object', shape } : { kind: 'poisoned' });
|
|
582
|
+
};
|
|
583
|
+
// A JSDoc `@type` tag wins when it states something real; three.js's own
|
|
584
|
+
// `@type {Object}` above almost every `this.parameters = {...}` states
|
|
585
|
+
// nothing (`isVagueObjectTag`), so an object-literal RHS is read for its
|
|
586
|
+
// own shape instead of trusting that tag verbatim.
|
|
587
|
+
const resolveAssignment = (name, node, rhsExpr) => {
|
|
588
|
+
const tagText = jsDocTypeTextOn(node, file);
|
|
589
|
+
if (tagText !== null && !isVagueObjectTag(tagText)) {
|
|
590
|
+
recordText(name, tagText);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
if (rhsExpr && ts.isObjectLiteralExpression(rhsExpr)) {
|
|
594
|
+
recordObjectLiteral(name, rhsExpr);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
recordText(name, rhsExpr ? literalShapeText(rhsExpr) : null);
|
|
598
|
+
};
|
|
599
|
+
for (const member of klass.members) {
|
|
600
|
+
if (member.name && ts.isIdentifier(member.name))
|
|
601
|
+
declaredNames.add(member.name.text);
|
|
602
|
+
if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name)) {
|
|
603
|
+
resolveAssignment(member.name.text, member, member.initializer);
|
|
604
|
+
}
|
|
605
|
+
else if ((ts.isMethodDeclaration(member) || ts.isGetAccessor(member) || ts.isSetAccessor(member)) && ts.isIdentifier(member.name)) {
|
|
606
|
+
methodNames.add(member.name.text);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const walkBody = (node) => {
|
|
610
|
+
if (ts.isExpressionStatement(node)) {
|
|
611
|
+
const descriptorEvidence = descriptorMemberEvidenceOf(node);
|
|
612
|
+
if (descriptorEvidence !== null) {
|
|
613
|
+
for (const evidence of descriptorEvidence)
|
|
614
|
+
resolveAssignment(evidence.name, evidence.annotation, evidence.value);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (ts.isExpressionStatement(node) &&
|
|
619
|
+
ts.isBinaryExpression(node.expression) &&
|
|
620
|
+
node.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
621
|
+
ts.isPropertyAccessExpression(node.expression.left) &&
|
|
622
|
+
node.expression.left.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
623
|
+
ts.isIdentifier(node.expression.left.name)) {
|
|
624
|
+
resolveAssignment(node.expression.left.name.text, node, node.expression.right);
|
|
625
|
+
}
|
|
626
|
+
ts.forEachChild(node, walkBody);
|
|
627
|
+
};
|
|
628
|
+
// A later method reassigning the field (three.js's own `copy()`/`clone()`
|
|
629
|
+
// idiom: `this.shadow = source.shadow.clone();`) is almost always
|
|
630
|
+
// type-preserving but syntactically opaque to this scan -- treating it as
|
|
631
|
+
// poisoning evidence dropped `Light.shadow` (and most other real targets)
|
|
632
|
+
// entirely, because every real field this pattern applies to also has a
|
|
633
|
+
// `copy()` method that reassigns it this way. So only the constructor body
|
|
634
|
+
// is walked.
|
|
635
|
+
if (ctor?.body)
|
|
636
|
+
walkBody(ctor.body);
|
|
637
|
+
const text = new Map();
|
|
638
|
+
const objectShape = new Map();
|
|
639
|
+
for (const [name, entry] of state) {
|
|
640
|
+
if (methodNames.has(name))
|
|
641
|
+
continue;
|
|
642
|
+
if (entry.kind === 'text')
|
|
643
|
+
text.set(name, entry.texts);
|
|
644
|
+
else if (entry.kind === 'object')
|
|
645
|
+
objectShape.set(name, entry.shape);
|
|
646
|
+
}
|
|
647
|
+
return { declaredNames, text, objectShape };
|
|
648
|
+
};
|
|
649
|
+
const readerCaches = new WeakMap();
|
|
650
|
+
const cachesFor = (read) => {
|
|
651
|
+
const cached = readerCaches.get(read);
|
|
652
|
+
if (cached)
|
|
653
|
+
return cached;
|
|
654
|
+
const fresh = { index: new Map(), imports: new Map(), reach: new Map() };
|
|
655
|
+
readerCaches.set(read, fresh);
|
|
656
|
+
return fresh;
|
|
657
|
+
};
|
|
658
|
+
/** The identifier name of the class whose prototype `node` dynamically mutates, or `null`. */
|
|
659
|
+
const prototypeMutationTarget = (node) => {
|
|
660
|
+
if (ts.isCallExpression(node)) {
|
|
661
|
+
const callee = node.expression;
|
|
662
|
+
if (ts.isPropertyAccessExpression(callee) &&
|
|
663
|
+
ts.isIdentifier(callee.expression) &&
|
|
664
|
+
callee.expression.text === 'Object' &&
|
|
665
|
+
callee.name.text === 'assign') {
|
|
666
|
+
const first = node.arguments[0];
|
|
667
|
+
if (first &&
|
|
668
|
+
ts.isPropertyAccessExpression(first) &&
|
|
669
|
+
ts.isIdentifier(first.expression) &&
|
|
670
|
+
ts.isIdentifier(first.name) &&
|
|
671
|
+
first.name.text === 'prototype') {
|
|
672
|
+
return first.expression.text;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isPropertyAccessExpression(node.left)) {
|
|
678
|
+
if (ts.isIdentifier(node.left.expression) && ts.isIdentifier(node.left.name) && node.left.name.text === 'prototype')
|
|
679
|
+
return node.left.expression.text;
|
|
680
|
+
const inner = node.left.expression;
|
|
681
|
+
if (ts.isPropertyAccessExpression(inner) &&
|
|
682
|
+
ts.isIdentifier(inner.expression) &&
|
|
683
|
+
ts.isIdentifier(inner.name) &&
|
|
684
|
+
inner.name.text === 'prototype') {
|
|
685
|
+
return inner.expression.text;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
};
|
|
690
|
+
const wholeWordPresent = (haystack, word) => new RegExp(`\\b${word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(haystack);
|
|
691
|
+
/** A local class is importable only through a binding its module actually exports. */
|
|
692
|
+
const classExportName = (file, declaration) => {
|
|
693
|
+
const name = declaration.name?.text;
|
|
694
|
+
if (!name)
|
|
695
|
+
return null;
|
|
696
|
+
if (declaration.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
|
|
697
|
+
return declaration.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) ? 'default' : name;
|
|
698
|
+
for (const statement of file.statements) {
|
|
699
|
+
if (ts.isExportAssignment(statement) &&
|
|
700
|
+
!statement.isExportEquals &&
|
|
701
|
+
ts.isIdentifier(statement.expression) &&
|
|
702
|
+
statement.expression.text === name)
|
|
703
|
+
return 'default';
|
|
704
|
+
if (!ts.isExportDeclaration(statement) ||
|
|
705
|
+
statement.moduleSpecifier ||
|
|
706
|
+
statement.isTypeOnly ||
|
|
707
|
+
!statement.exportClause ||
|
|
708
|
+
!ts.isNamedExports(statement.exportClause))
|
|
709
|
+
continue;
|
|
710
|
+
for (const element of statement.exportClause.elements) {
|
|
711
|
+
if (!element.isTypeOnly && (element.propertyName ?? element.name).text === name)
|
|
712
|
+
return element.name.text;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
};
|
|
717
|
+
const classImportLine = (info, hereDir) => {
|
|
718
|
+
const rel = relative(hereDir, info.filePath).split(sep).join('/');
|
|
719
|
+
const specifier = rel.startsWith('.') ? rel : `./${rel}`;
|
|
720
|
+
const exported = info.exportName === info.name ? info.name : `${info.exportName} as ${info.name}`;
|
|
721
|
+
return `@import { ${exported} } from '${specifier}'`;
|
|
722
|
+
};
|
|
723
|
+
const buildPackageIndex = (root, read, neverSkip) => {
|
|
724
|
+
const key = indexKey(root, neverSkip);
|
|
725
|
+
const cached = cachesFor(read).index.get(key);
|
|
726
|
+
if (cached)
|
|
727
|
+
return cached;
|
|
728
|
+
const classesByName = new Map();
|
|
729
|
+
const duplicateNames = new Set();
|
|
730
|
+
const untrustedClassNames = new Set();
|
|
731
|
+
const unresolvedHeritageTexts = [];
|
|
732
|
+
const externallyReadNames = new Set();
|
|
733
|
+
const constantDomainsByName = new Map();
|
|
734
|
+
const duplicateConstants = new Set();
|
|
735
|
+
for (const filePath of collectSourceFiles(root, neverSkip)) {
|
|
736
|
+
let text;
|
|
737
|
+
try {
|
|
738
|
+
text = read(filePath);
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const file = ts.createSourceFile(filePath, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
744
|
+
const scanForMutation = (node) => {
|
|
745
|
+
const target = prototypeMutationTarget(node);
|
|
746
|
+
if (target)
|
|
747
|
+
untrustedClassNames.add(target);
|
|
748
|
+
if (ts.isPropertyAccessExpression(node) && node.expression.kind !== ts.SyntaxKind.ThisKeyword && ts.isIdentifier(node.name)) {
|
|
749
|
+
externallyReadNames.add(node.name.text);
|
|
750
|
+
}
|
|
751
|
+
ts.forEachChild(node, scanForMutation);
|
|
752
|
+
};
|
|
753
|
+
scanForMutation(file);
|
|
754
|
+
for (const statement of file.statements) {
|
|
755
|
+
if (!ts.isVariableStatement(statement) || (statement.declarationList.flags & ts.NodeFlags.Const) === 0)
|
|
756
|
+
continue;
|
|
757
|
+
if (!statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
|
|
758
|
+
continue;
|
|
759
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
760
|
+
const domain = declaration.initializer ? literalShapeText(declaration.initializer) : null;
|
|
761
|
+
if (!ts.isIdentifier(declaration.name) || (domain !== 'number' && domain !== 'string' && domain !== 'boolean'))
|
|
762
|
+
continue;
|
|
763
|
+
if (constantDomainsByName.has(declaration.name.text))
|
|
764
|
+
duplicateConstants.add(declaration.name.text);
|
|
765
|
+
constantDomainsByName.set(declaration.name.text, domain);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
for (const statement of file.statements) {
|
|
769
|
+
if (!ts.isClassDeclaration(statement) || !statement.name)
|
|
770
|
+
continue;
|
|
771
|
+
const className = statement.name.text;
|
|
772
|
+
let baseName = null;
|
|
773
|
+
const heritage = statement.heritageClauses?.find((h) => h.token === ts.SyntaxKind.ExtendsKeyword);
|
|
774
|
+
const heritageExpr = heritage?.types[0]?.expression;
|
|
775
|
+
if (heritageExpr) {
|
|
776
|
+
if (ts.isIdentifier(heritageExpr))
|
|
777
|
+
baseName = heritageExpr.text;
|
|
778
|
+
// Anything else -- a call, a property access, a mixin factory -- is
|
|
779
|
+
// a base this scan cannot name outright; recorded so any base whose
|
|
780
|
+
// name it mentions can be refused (see `unresolvedHeritageTexts`).
|
|
781
|
+
else
|
|
782
|
+
unresolvedHeritageTexts.push(heritageExpr.getText(file));
|
|
783
|
+
}
|
|
784
|
+
const evidence = memberTypeTextsOf(statement, file);
|
|
785
|
+
const info = {
|
|
786
|
+
name: className,
|
|
787
|
+
filePath,
|
|
788
|
+
exportName: classExportName(file, statement),
|
|
789
|
+
baseName,
|
|
790
|
+
declaredNames: evidence.declaredNames,
|
|
791
|
+
ownMembers: evidence.text,
|
|
792
|
+
ownObjectShapes: evidence.objectShape
|
|
793
|
+
};
|
|
794
|
+
if (classesByName.has(className))
|
|
795
|
+
duplicateNames.add(className);
|
|
796
|
+
classesByName.set(className, info);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
for (const name of duplicateNames)
|
|
800
|
+
classesByName.delete(name);
|
|
801
|
+
for (const name of [...duplicateConstants, ...duplicateNames, ...classesByName.keys()])
|
|
802
|
+
constantDomainsByName.delete(name);
|
|
803
|
+
const directSubclassesOf = new Map();
|
|
804
|
+
for (const info of classesByName.values()) {
|
|
805
|
+
if (!info.baseName)
|
|
806
|
+
continue;
|
|
807
|
+
const list = directSubclassesOf.get(info.baseName);
|
|
808
|
+
if (list)
|
|
809
|
+
list.push(info);
|
|
810
|
+
else
|
|
811
|
+
directSubclassesOf.set(info.baseName, [info]);
|
|
812
|
+
}
|
|
813
|
+
const index = {
|
|
814
|
+
classesByName,
|
|
815
|
+
directSubclassesOf,
|
|
816
|
+
untrustedClassNames,
|
|
817
|
+
unresolvedHeritageTexts,
|
|
818
|
+
externallyReadNames,
|
|
819
|
+
constantDomainsByName
|
|
820
|
+
};
|
|
821
|
+
cachesFor(read).index.set(key, index);
|
|
822
|
+
return index;
|
|
823
|
+
};
|
|
824
|
+
const transitiveSubclassesOf = (index, baseName) => {
|
|
825
|
+
const result = [];
|
|
826
|
+
const seen = new Set([baseName]);
|
|
827
|
+
const queue = [baseName];
|
|
828
|
+
while (queue.length > 0) {
|
|
829
|
+
const current = queue.shift();
|
|
830
|
+
for (const sub of index.directSubclassesOf.get(current) ?? []) {
|
|
831
|
+
if (seen.has(sub.name))
|
|
832
|
+
continue;
|
|
833
|
+
seen.add(sub.name);
|
|
834
|
+
result.push(sub);
|
|
835
|
+
queue.push(sub.name);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return result;
|
|
839
|
+
};
|
|
840
|
+
/**
|
|
841
|
+
* `className`'s own ancestor chain, INCLUDING itself, walked through
|
|
842
|
+
* `baseName` up to a root (a class this package has no `ClassInfo` for, or
|
|
843
|
+
* one with no `extends` clause). Cycle-guarded by construction: `chain` is
|
|
844
|
+
* checked before each step, so a hierarchy loop (never legitimate JS, but
|
|
845
|
+
* this scan trusts nothing) simply stops rather than looping forever.
|
|
846
|
+
*/
|
|
847
|
+
const ancestorChainOf = (index, className) => {
|
|
848
|
+
const chain = new Set();
|
|
849
|
+
let current = className;
|
|
850
|
+
while (current !== null && !chain.has(current)) {
|
|
851
|
+
chain.add(current);
|
|
852
|
+
current = index.classesByName.get(current)?.baseName ?? null;
|
|
853
|
+
}
|
|
854
|
+
return chain;
|
|
855
|
+
};
|
|
856
|
+
/**
|
|
857
|
+
* Whether every name in `names` is drawn from ONE inheritance lineage --
|
|
858
|
+
* there exists a class (possibly one of `names` itself, possibly further up)
|
|
859
|
+
* that is an ancestor of every one of them.
|
|
860
|
+
*
|
|
861
|
+
* This is the general test behind restricting a reference-typed candidate:
|
|
862
|
+
* `Light.shadow`'s three declarers (`DirectionalLightShadow`,
|
|
863
|
+
* `PointLightShadow`, `SpotLightShadow`, this file's own motivating example)
|
|
864
|
+
* all extend one `LightShadow`, so every method a caller reaches through the
|
|
865
|
+
* union is the SAME inherited method -- TypeScript resolves a union member
|
|
866
|
+
* access against a shared base member exactly once, no synthesis involved.
|
|
867
|
+
* Two classes with NO common ancestor (three.js's own `Matrix3`/`Matrix4`:
|
|
868
|
+
* both plain root classes, unrelated beyond sharing a field NAME by
|
|
869
|
+
* coincidence across two distant branches of a near-universal base) each
|
|
870
|
+
* contribute their OWN same-named method with a DIFFERENT signature; calling
|
|
871
|
+
* it through the union then requires TypeScript to synthesize an
|
|
872
|
+
* intersection of the two parameter types for the call to type-check at
|
|
873
|
+
* all, and `derive.ts` -- correctly, by this file's own architectural rule
|
|
874
|
+
* of never relaxing a guard -- has no record shape to reduce that against
|
|
875
|
+
* every member is nominal, not structural (`unresolved-reaches-materialization`
|
|
876
|
+
* fires). This is a purely structural check over the package's own class
|
|
877
|
+
* index, exactly like `wholeWordPresent`/`prototypeMutationTarget` above --
|
|
878
|
+
* no library name, no member name, no checker call.
|
|
879
|
+
*/
|
|
880
|
+
const shareCommonAncestor = (index, names) => {
|
|
881
|
+
const distinct = [...new Set(names)];
|
|
882
|
+
if (distinct.length <= 1)
|
|
883
|
+
return true;
|
|
884
|
+
const chains = distinct.map((name) => ancestorChainOf(index, name));
|
|
885
|
+
const [first, ...rest] = chains;
|
|
886
|
+
if (!first)
|
|
887
|
+
return true;
|
|
888
|
+
for (const candidate of first) {
|
|
889
|
+
if (rest.every((chain) => chain.has(candidate)))
|
|
890
|
+
return true;
|
|
891
|
+
}
|
|
892
|
+
return false;
|
|
893
|
+
};
|
|
894
|
+
/**
|
|
895
|
+
* The modules a JS file imports at RUNTIME, as absolute paths.
|
|
896
|
+
*
|
|
897
|
+
* Only relative specifiers are followed: a bare specifier leaves the
|
|
898
|
+
* package, and nothing this module reasons about crosses that line. Mirrors
|
|
899
|
+
* `declaration-overlay-transform.ts`'s own `runtimeImportsOf` -- read
|
|
900
|
+
* straight from the file's own text with `ts.preProcessFile`, never through
|
|
901
|
+
* this scan's own `ClassInfo`, which only ever names DECLARED classes, not
|
|
902
|
+
* every module edge a file has.
|
|
903
|
+
*/
|
|
904
|
+
const runtimeImportsOf = (fileName, read) => {
|
|
905
|
+
const cached = cachesFor(read).imports.get(fileName);
|
|
906
|
+
if (cached)
|
|
907
|
+
return cached;
|
|
908
|
+
let targets = [];
|
|
909
|
+
try {
|
|
910
|
+
const info = ts.preProcessFile(read(fileName), true, true);
|
|
911
|
+
targets = info.importedFiles
|
|
912
|
+
.map((imported) => imported.fileName)
|
|
913
|
+
.filter((specifier) => specifier.startsWith('.'))
|
|
914
|
+
.map((specifier) => resolve(dirname(fileName), specifier))
|
|
915
|
+
.filter((path) => existsSync(path));
|
|
916
|
+
}
|
|
917
|
+
catch {
|
|
918
|
+
targets = [];
|
|
919
|
+
}
|
|
920
|
+
cachesFor(read).imports.set(fileName, targets);
|
|
921
|
+
return targets;
|
|
922
|
+
};
|
|
923
|
+
/**
|
|
924
|
+
* Every module reachable from `start` by following runtime imports
|
|
925
|
+
* transitively.
|
|
926
|
+
*
|
|
927
|
+
* ⛔ THE guard on every `@import` this module writes, same as in
|
|
928
|
+
* `declaration-overlay-transform.ts` (see that file's own comment on its
|
|
929
|
+
* `modulesReachableFrom`, word for word the same hazard here): an `@import`
|
|
930
|
+
* is a real module edge, and three's runtime graph is carefully acyclic.
|
|
931
|
+
* Every candidate this module overlays names the field's VALUE type, not the
|
|
932
|
+
* declaring subclass (`Light.shadow`'s import is `DirectionalLightShadow`,
|
|
933
|
+
* never `DirectionalLight`), so this rarely closes a cycle in practice -- but
|
|
934
|
+
* "rarely" is not "never", and an overlay field whose value type happens to
|
|
935
|
+
* import back toward `Base` (directly, or through a chain) would close one
|
|
936
|
+
* silently. Fail-closed: an unreadable file contributes no edges, so a
|
|
937
|
+
* specifier whose module cannot be read is refused by the caller rather than
|
|
938
|
+
* assumed safe.
|
|
939
|
+
*/
|
|
940
|
+
const modulesReachableFrom = (start, read) => {
|
|
941
|
+
const cached = cachesFor(read).reach.get(start);
|
|
942
|
+
if (cached)
|
|
943
|
+
return cached;
|
|
944
|
+
const seen = new Set();
|
|
945
|
+
const queue = [start];
|
|
946
|
+
while (queue.length > 0) {
|
|
947
|
+
const current = queue.shift();
|
|
948
|
+
if (current === undefined)
|
|
949
|
+
break;
|
|
950
|
+
for (const next of runtimeImportsOf(current, read)) {
|
|
951
|
+
if (seen.has(next))
|
|
952
|
+
continue;
|
|
953
|
+
seen.add(next);
|
|
954
|
+
queue.push(next);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
cachesFor(read).reach.set(start, seen);
|
|
958
|
+
return seen;
|
|
959
|
+
};
|
|
960
|
+
/**
|
|
961
|
+
* `text` with each name that is one of the package's exported primitive
|
|
962
|
+
* constants spelled as that constant's primitive domain.
|
|
963
|
+
*
|
|
964
|
+
* A JSDoc type naming a value means the value's type, and three states its
|
|
965
|
+
* enum-valued members that way: `MeshBasicMaterial.combine` is
|
|
966
|
+
* `@type {(MultiplyOperation|MixOperation|AddOperation)}`, three `number`
|
|
967
|
+
* constants from `constants.js` -- two of which that file never imports. Read
|
|
968
|
+
* as class names they refused the only declarers `Material.combine` has, and
|
|
969
|
+
* every base-typed read of it stayed `any`. The domain, not the literal, is
|
|
970
|
+
* spelled, for the reason `literalShapeText` gives: the field is mutable
|
|
971
|
+
* storage. A quoted literal or a qualified name (`THREE.X`) is left alone.
|
|
972
|
+
*/
|
|
973
|
+
const withConstantDomains = (index, text) => text.replace(/(['"`])(?:\\.|(?!\1)[^\\])*\1|[A-Za-z_$][A-Za-z0-9_$]*/g, (token, quote, offset) => quote !== undefined || text[offset - 1] === '.' ? token : (index.constantDomainsByName.get(token) ?? token));
|
|
974
|
+
/** Every identifier token in `text` that is not an ambient/global name -- the names a caller must bring into scope, or refuse over. */
|
|
975
|
+
const foreignNamesIn = (text) => {
|
|
976
|
+
const tokens = text.match(/[A-Za-z_$][A-Za-z0-9_$]*/g) ?? [];
|
|
977
|
+
const out = [];
|
|
978
|
+
for (const token of tokens) {
|
|
979
|
+
if (AMBIENT_TOKENS.has(token))
|
|
980
|
+
continue;
|
|
981
|
+
if (!out.includes(token))
|
|
982
|
+
out.push(token);
|
|
983
|
+
}
|
|
984
|
+
return out;
|
|
985
|
+
};
|
|
986
|
+
/**
|
|
987
|
+
* The joined record TYPE TEXT for a top-level member whose EVERY
|
|
988
|
+
* contributing descendant assigns it as a plain object literal --
|
|
989
|
+
* `this.parameters = { width: width, height: height }`, three.js's geometry
|
|
990
|
+
* idiom this extension exists for (see the file header's "Scope" section,
|
|
991
|
+
* object-literal case). Not a raw union of the declaring shapes
|
|
992
|
+
* (`{width...} | {radius...} | undefined`, which corrupts a named-property
|
|
993
|
+
* read that expects ONE shape -- `data[key] = parameters[key]` in
|
|
994
|
+
* `BufferGeometry.toJSON` has no arm to narrow against) but a single JOIN:
|
|
995
|
+
*
|
|
996
|
+
* - Every property NAME across every shape is included.
|
|
997
|
+
* - When EVERY shape carries the exact same name set (license (a)), each
|
|
998
|
+
* property is required -- every declarer sets it. Otherwise (license (b))
|
|
999
|
+
* every property is OPTIONAL, because an instance reached through the
|
|
1000
|
+
* widened `Base` type may be of a subclass that never touched this
|
|
1001
|
+
* particular field.
|
|
1002
|
+
* - A property's own TYPE is the join of what every shape that has it
|
|
1003
|
+
* states: identical texts need no work; texts that are only boolean
|
|
1004
|
+
* literals widen to `boolean` (over-approximating costs nothing -- `Base`
|
|
1005
|
+
* never had a narrower answer to begin with); texts that are all class
|
|
1006
|
+
* references sharing one inheritance lineage (`shareCommonAncestor`, the
|
|
1007
|
+
* same guard the top-level member union uses, applied here per PROPERTY
|
|
1008
|
+
* rather than per member) union safely; anything else is a genuine type
|
|
1009
|
+
* disagreement on one name -- license (c), refuses the WHOLE member (this
|
|
1010
|
+
* function returns `null`), mirroring the top-level `shareCommonAncestor`
|
|
1011
|
+
* refusal one level up: a partial record would still corrupt the
|
|
1012
|
+
* declarers whose narrower answer it silently widened.
|
|
1013
|
+
* - A property whose joined type needs an import this scan cannot resolve,
|
|
1014
|
+
* or that would close a module cycle back to `here`, is DROPPED --
|
|
1015
|
+
* narrower granularity than the type-disagreement case above, because
|
|
1016
|
+
* this is an infrastructure limit (three.js's own `@param
|
|
1017
|
+
* {ExtrudeGeometry~Options} options` names a JSDoc namepath this scan has
|
|
1018
|
+
* no class for), not evidence of two unrelated facts sharing a name; the
|
|
1019
|
+
* record is simply missing that one field, still sound as an
|
|
1020
|
+
* over-approximation, and the member's other properties are unaffected.
|
|
1021
|
+
*/
|
|
1022
|
+
const joinedObjectRecordText = (index, shapes, ctx) => {
|
|
1023
|
+
if (shapes.length === 0)
|
|
1024
|
+
return null;
|
|
1025
|
+
const allNames = new Set();
|
|
1026
|
+
for (const shape of shapes)
|
|
1027
|
+
for (const key of shape.keys())
|
|
1028
|
+
allNames.add(key);
|
|
1029
|
+
const sameNameSetForAll = shapes.every((shape) => shape.size === allNames.size && [...allNames].every((n) => shape.has(n)));
|
|
1030
|
+
const fields = [];
|
|
1031
|
+
for (const propName of [...allNames].sort()) {
|
|
1032
|
+
const texts = new Set();
|
|
1033
|
+
for (const shape of shapes) {
|
|
1034
|
+
const propText = shape.get(propName);
|
|
1035
|
+
if (propText !== undefined)
|
|
1036
|
+
texts.add(propText);
|
|
1037
|
+
}
|
|
1038
|
+
const distinct = [...texts];
|
|
1039
|
+
let joined;
|
|
1040
|
+
if (distinct.length === 1) {
|
|
1041
|
+
joined = distinct[0];
|
|
1042
|
+
}
|
|
1043
|
+
else if (distinct.every((t) => t === 'true' || t === 'false')) {
|
|
1044
|
+
joined = 'boolean';
|
|
1045
|
+
}
|
|
1046
|
+
else if (distinct.every((t) => index.classesByName.has(t)) && shareCommonAncestor(index, distinct)) {
|
|
1047
|
+
joined = distinct.join(' | ');
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
// A genuine disagreement on one property name -- e.g. `radius: number`
|
|
1051
|
+
// in one declarer's literal against an unrelated `radius: SomeClass`
|
|
1052
|
+
// in another's -- corrupts the whole record; see this function's own
|
|
1053
|
+
// header.
|
|
1054
|
+
return null;
|
|
1055
|
+
}
|
|
1056
|
+
const foreignNames = foreignNamesIn(joined);
|
|
1057
|
+
let resolvable = true;
|
|
1058
|
+
for (const foreignName of foreignNames) {
|
|
1059
|
+
const info = index.classesByName.get(foreignName);
|
|
1060
|
+
if (!info) {
|
|
1061
|
+
resolvable = false;
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1064
|
+
if (ctx.boundHere.has(foreignName) && !ctx.importLines.has(foreignName)) {
|
|
1065
|
+
resolvable = false;
|
|
1066
|
+
break;
|
|
1067
|
+
}
|
|
1068
|
+
const targetPath = resolve(info.filePath);
|
|
1069
|
+
if (targetPath !== ctx.here && info.exportName === null) {
|
|
1070
|
+
resolvable = false;
|
|
1071
|
+
break;
|
|
1072
|
+
}
|
|
1073
|
+
if (targetPath !== ctx.here && modulesReachableFrom(targetPath, ctx.read).has(ctx.here)) {
|
|
1074
|
+
resolvable = false;
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (!resolvable)
|
|
1079
|
+
continue;
|
|
1080
|
+
for (const foreignName of foreignNames) {
|
|
1081
|
+
if (ctx.importLines.has(foreignName))
|
|
1082
|
+
continue;
|
|
1083
|
+
const info = index.classesByName.get(foreignName);
|
|
1084
|
+
if (resolve(info.filePath) === ctx.here)
|
|
1085
|
+
continue;
|
|
1086
|
+
ctx.importLines.set(foreignName, classImportLine(info, ctx.hereDir));
|
|
1087
|
+
}
|
|
1088
|
+
fields.push(sameNameSetForAll ? `${propName}: ${joined}` : `${propName}?: ${joined}`);
|
|
1089
|
+
}
|
|
1090
|
+
return fields.length > 0 ? `{${fields.join('; ')}}` : null;
|
|
1091
|
+
};
|
|
1092
|
+
/**
|
|
1093
|
+
* The overlay, reading declarers through `read` -- see `DeclarerReader`.
|
|
1094
|
+
* `compiler.ts` builds one per compilation with that compilation's plugin
|
|
1095
|
+
* transforms; a caller with no plugins may pass `readFileSync` itself.
|
|
1096
|
+
*/
|
|
1097
|
+
export const createSubclassMemberOverlayTransform = (read) => (input) => {
|
|
1098
|
+
if (!/\.m?js$/.test(input.fileName))
|
|
1099
|
+
return null;
|
|
1100
|
+
const root = packageRootFor(input.fileName);
|
|
1101
|
+
if (!root)
|
|
1102
|
+
return null;
|
|
1103
|
+
const index = buildPackageIndex(root, read, ancestryBetween(root, input.fileName));
|
|
1104
|
+
const here = resolve(input.fileName);
|
|
1105
|
+
const file = ts.createSourceFile(input.fileName, input.text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
|
|
1106
|
+
const boundHere = new Set();
|
|
1107
|
+
let leadingImportEnd = 0;
|
|
1108
|
+
let stillLeading = true;
|
|
1109
|
+
for (const statement of file.statements) {
|
|
1110
|
+
if (ts.isImportDeclaration(statement)) {
|
|
1111
|
+
if (stillLeading)
|
|
1112
|
+
leadingImportEnd = statement.getEnd();
|
|
1113
|
+
if (statement.importClause) {
|
|
1114
|
+
const bindings = statement.importClause.namedBindings;
|
|
1115
|
+
if (bindings && ts.isNamedImports(bindings))
|
|
1116
|
+
for (const element of bindings.elements)
|
|
1117
|
+
boundHere.add(element.name.text);
|
|
1118
|
+
if (statement.importClause.name)
|
|
1119
|
+
boundHere.add(statement.importClause.name.text);
|
|
1120
|
+
}
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
stillLeading = false;
|
|
1124
|
+
if ((ts.isClassDeclaration(statement) || ts.isFunctionDeclaration(statement)) && statement.name)
|
|
1125
|
+
boundHere.add(statement.name.text);
|
|
1126
|
+
else if (ts.isVariableStatement(statement)) {
|
|
1127
|
+
for (const declaration of statement.declarationList.declarations)
|
|
1128
|
+
if (ts.isIdentifier(declaration.name))
|
|
1129
|
+
boundHere.add(declaration.name.text);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
// TypeScript does not attach a field's JSDoc when its comment starts on
|
|
1133
|
+
// the class opening-brace line. Every member insertion starts a new line
|
|
1134
|
+
// so the first generated field retains the type this transform states.
|
|
1135
|
+
const edits = [];
|
|
1136
|
+
const importLines = new Map();
|
|
1137
|
+
/**
|
|
1138
|
+
* RESTATE what this class declares for itself.
|
|
1139
|
+
*
|
|
1140
|
+
* The overlay above writes a member onto an ANCESTOR, and TypeScript treats
|
|
1141
|
+
* a JS `this.x = ...` whose base declares `x` as an ASSIGNMENT rather than
|
|
1142
|
+
* a declaration -- so the ancestor's field silently replaces the declarer's
|
|
1143
|
+
* own `@type` as the answer for the declarer's own reads. On three, with
|
|
1144
|
+
* the near-universal `EventDispatcher` as that ancestor, `Object3D.uuid`
|
|
1145
|
+
* (`@type {string}`) read back `string | undefined` and `Object3D.pivot`
|
|
1146
|
+
* (`@type {?Vector3}`) read back `Vector3 | null | undefined` -- the
|
|
1147
|
+
* `| undefined` this module adds for soundness at a BASE-typed read,
|
|
1148
|
+
* charged to a class where the constructor assigns the member
|
|
1149
|
+
* unconditionally and it can never be absent.
|
|
1150
|
+
*
|
|
1151
|
+
* A class may redeclare an inherited property with a narrower type, so
|
|
1152
|
+
* both facts can be stated at once: the base keeps the union that makes a
|
|
1153
|
+
* base-typed read resolve, and the declarer restates its own, which is
|
|
1154
|
+
* what its own reads then see. Only a member with ONE unambiguous text and
|
|
1155
|
+
* no unresolvable or not-yet-imported name in it -- this adds no `@import`
|
|
1156
|
+
* of its own, so a name must already be in scope in the declarer's file.
|
|
1157
|
+
*/
|
|
1158
|
+
const restatementsFor = (statement, info) => {
|
|
1159
|
+
if (process.env['GEA_NO_RESTATE'])
|
|
1160
|
+
return [];
|
|
1161
|
+
if (!info.baseName || !index.classesByName.has(info.baseName))
|
|
1162
|
+
return [];
|
|
1163
|
+
if (index.untrustedClassNames.has(info.name))
|
|
1164
|
+
return [];
|
|
1165
|
+
const declaredHere = new Set(statement.members.map((member) => (member.name && ts.isIdentifier(member.name) ? member.name.text : '')));
|
|
1166
|
+
const out = [];
|
|
1167
|
+
for (const name of [...info.ownMembers.keys()].sort()) {
|
|
1168
|
+
if (!index.externallyReadNames.has(name))
|
|
1169
|
+
continue;
|
|
1170
|
+
if (declaredHere.has(name))
|
|
1171
|
+
continue;
|
|
1172
|
+
const texts = info.ownMembers.get(name);
|
|
1173
|
+
if (!texts || texts.length !== 1)
|
|
1174
|
+
continue;
|
|
1175
|
+
const text = texts[0];
|
|
1176
|
+
if (text.length === 0 || text.includes('*/'))
|
|
1177
|
+
continue;
|
|
1178
|
+
const foreign = foreignNamesIn(text);
|
|
1179
|
+
if (!foreign.every((foreignName) => index.classesByName.has(foreignName) && boundHere.has(foreignName)))
|
|
1180
|
+
continue;
|
|
1181
|
+
out.push(`\t/** @type {${text}} */\n\t${name};\n`);
|
|
1182
|
+
}
|
|
1183
|
+
return out;
|
|
1184
|
+
};
|
|
1185
|
+
for (const statement of file.statements) {
|
|
1186
|
+
if (!ts.isClassDeclaration(statement) || !statement.name)
|
|
1187
|
+
continue;
|
|
1188
|
+
const baseInfo = index.classesByName.get(statement.name.text);
|
|
1189
|
+
if (!baseInfo || resolve(baseInfo.filePath) !== here)
|
|
1190
|
+
continue;
|
|
1191
|
+
const restated = restatementsFor(statement, baseInfo);
|
|
1192
|
+
const descendants = transitiveSubclassesOf(index, statement.name.text);
|
|
1193
|
+
if (descendants.length === 0) {
|
|
1194
|
+
if (restated.length > 0)
|
|
1195
|
+
edits.push({ at: statement.members.pos, text: '\n' + restated.join('') });
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
// Refuse the WHOLE base when its own name or a descendant's could be the
|
|
1199
|
+
// target of a heritage clause this scan could not resolve -- there may
|
|
1200
|
+
// be a subclass in this hierarchy it never found.
|
|
1201
|
+
const hierarchyNames = [statement.name.text, ...descendants.map((d) => d.name)];
|
|
1202
|
+
const refusedHierarchy = index.unresolvedHeritageTexts.some((text) => hierarchyNames.some((name) => wholeWordPresent(text, name))) ||
|
|
1203
|
+
index.untrustedClassNames.has(statement.name.text);
|
|
1204
|
+
if (refusedHierarchy) {
|
|
1205
|
+
if (restated.length > 0)
|
|
1206
|
+
edits.push({ at: statement.members.pos, text: '\n' + restated.join('') });
|
|
1207
|
+
continue;
|
|
1208
|
+
}
|
|
1209
|
+
const liveEvidence = memberTypeTextsOf(statement, file);
|
|
1210
|
+
const alreadyDeclared = new Set([
|
|
1211
|
+
...liveEvidence.declaredNames,
|
|
1212
|
+
...baseInfo.declaredNames,
|
|
1213
|
+
...liveEvidence.text.keys(),
|
|
1214
|
+
...liveEvidence.objectShape.keys(),
|
|
1215
|
+
...baseInfo.ownMembers.keys(),
|
|
1216
|
+
...baseInfo.ownObjectShapes.keys()
|
|
1217
|
+
]);
|
|
1218
|
+
// A member an ancestor already declares is already readable through this
|
|
1219
|
+
// class. Re-declaring it here from a descendant's writes does more than
|
|
1220
|
+
// make that evidence visible: it shadows the inherited declaration with
|
|
1221
|
+
// the descendant union. Three's `Mesh` was given
|
|
1222
|
+
// `matrixAutoUpdate: false | undefined` from one specialized descendant,
|
|
1223
|
+
// replacing `Object3D.matrixAutoUpdate: boolean` and making every Mesh
|
|
1224
|
+
// structurally incompatible with Object3D. Walk the real heritage chain
|
|
1225
|
+
// and keep those inherited declarations authoritative at every
|
|
1226
|
+
// intermediate class.
|
|
1227
|
+
let ancestorName = baseInfo.baseName;
|
|
1228
|
+
while (ancestorName) {
|
|
1229
|
+
const ancestor = index.classesByName.get(ancestorName);
|
|
1230
|
+
if (!ancestor)
|
|
1231
|
+
break;
|
|
1232
|
+
for (const name of ancestor.declaredNames)
|
|
1233
|
+
alreadyDeclared.add(name);
|
|
1234
|
+
for (const name of ancestor.ownMembers.keys())
|
|
1235
|
+
alreadyDeclared.add(name);
|
|
1236
|
+
for (const name of ancestor.ownObjectShapes.keys())
|
|
1237
|
+
alreadyDeclared.add(name);
|
|
1238
|
+
ancestorName = ancestor.baseName;
|
|
1239
|
+
}
|
|
1240
|
+
const candidateNames = new Set();
|
|
1241
|
+
for (const descendant of descendants) {
|
|
1242
|
+
if (index.untrustedClassNames.has(descendant.name))
|
|
1243
|
+
continue;
|
|
1244
|
+
for (const name of descendant.ownMembers.keys()) {
|
|
1245
|
+
if (index.externallyReadNames.has(name))
|
|
1246
|
+
candidateNames.add(name);
|
|
1247
|
+
}
|
|
1248
|
+
for (const name of descendant.ownObjectShapes.keys()) {
|
|
1249
|
+
if (index.externallyReadNames.has(name))
|
|
1250
|
+
candidateNames.add(name);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
for (const name of alreadyDeclared)
|
|
1254
|
+
candidateNames.delete(name);
|
|
1255
|
+
if (candidateNames.size === 0) {
|
|
1256
|
+
if (restated.length > 0)
|
|
1257
|
+
edits.push({ at: statement.members.pos, text: '\n' + restated.join('') });
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
const hereDir = dirname(here);
|
|
1261
|
+
const fieldTexts = [...restated];
|
|
1262
|
+
for (const name of [...candidateNames].sort()) {
|
|
1263
|
+
const objectShapeDescendants = descendants.filter((d) => !index.untrustedClassNames.has(d.name) && d.ownObjectShapes.has(name));
|
|
1264
|
+
const textShapeDescendants = descendants.filter((d) => !index.untrustedClassNames.has(d.name) && d.ownMembers.has(name));
|
|
1265
|
+
// Mixed evidence -- some declarer states a scalar/reference, another
|
|
1266
|
+
// an object literal, for the same name -- is ambiguous the same way a
|
|
1267
|
+
// second differently-shaped assignment within ONE class is
|
|
1268
|
+
// (`memberTypeTextsOf`'s own `recordObjectLiteral`): refuse rather
|
|
1269
|
+
// than guess which shape a caller reaching the member actually sees.
|
|
1270
|
+
if (objectShapeDescendants.length > 0 && textShapeDescendants.length > 0)
|
|
1271
|
+
continue;
|
|
1272
|
+
if (objectShapeDescendants.length > 0) {
|
|
1273
|
+
const joined = joinedObjectRecordText(index, objectShapeDescendants.map((d) => d.ownObjectShapes.get(name)), { read, boundHere, importLines, hereDir, here });
|
|
1274
|
+
if (joined)
|
|
1275
|
+
fieldTexts.push(`\t/** @type {${joined} | undefined}\n\t * @geaSubclassMemberOverlay */\n\t${name};\n`);
|
|
1276
|
+
continue;
|
|
1277
|
+
}
|
|
1278
|
+
const typeParts = [];
|
|
1279
|
+
const neededImports = [];
|
|
1280
|
+
// ALL-OR-NONE.
|
|
1281
|
+
//
|
|
1282
|
+
// Every per-candidate refusal below used to `continue` and let the
|
|
1283
|
+
// REMAINING declarers form the union. That is not the smaller answer it
|
|
1284
|
+
// reads as -- it is a DIFFERENT one. The fact this module states is
|
|
1285
|
+
// "the member holds what SOME declarer put there, or `undefined`", and
|
|
1286
|
+
// it is sound only as an over-approximation; dropping a declarer makes
|
|
1287
|
+
// it a SUBSET, and the field it writes onto `Base` then shadows every
|
|
1288
|
+
// declarer's own precise declaration with a type that does not contain
|
|
1289
|
+
// what that declarer actually assigns.
|
|
1290
|
+
//
|
|
1291
|
+
// Measured on three: `Object3D.parent` is `@type {?Object3D}`, and that
|
|
1292
|
+
// candidate is refused by `modulesReachableFrom` (importing `Object3D`
|
|
1293
|
+
// into `EventDispatcher.js` closes a cycle) -- while an unrelated
|
|
1294
|
+
// class's boolean `parent` survives. The overlay wrote `/** @type
|
|
1295
|
+
// {boolean | undefined} */ parent;` onto `EventDispatcher`, and because
|
|
1296
|
+
// TypeScript treats a JS `this.x = ...` whose base declares `x` as an
|
|
1297
|
+
// ASSIGNMENT rather than a declaration, `Object3D`'s own
|
|
1298
|
+
// `@type {?Object3D}` stopped meaning anything: `this.parent` in
|
|
1299
|
+
// `Object3D.js` typed `boolean | undefined`. Not a widening -- a wrong
|
|
1300
|
+
// answer, and one no downstream census can see is wrong.
|
|
1301
|
+
//
|
|
1302
|
+
// The header already stated the intended rule for the whole-member case
|
|
1303
|
+
// ("if EVERY declarer refuses, the member is left exactly as `any`");
|
|
1304
|
+
// this is the same rule applied to a PARTIAL refusal, which is the only
|
|
1305
|
+
// reading under which the union is still the fact the header claims.
|
|
1306
|
+
let refusedDeclarer = false;
|
|
1307
|
+
for (const descendant of descendants) {
|
|
1308
|
+
const texts = descendant.ownMembers.get(name);
|
|
1309
|
+
if (!texts)
|
|
1310
|
+
continue;
|
|
1311
|
+
if (index.untrustedClassNames.has(descendant.name)) {
|
|
1312
|
+
refusedDeclarer = true;
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
for (const statedText of texts) {
|
|
1316
|
+
const candidateText = withConstantDomains(index, statedText);
|
|
1317
|
+
const foreignTypeNames = foreignNamesIn(candidateText);
|
|
1318
|
+
// Every foreign name the text ITSELF mentions (a boolean literal
|
|
1319
|
+
// mentions none) must resolve to a class this package actually
|
|
1320
|
+
// declares -- an unresolvable one (an external library type, a
|
|
1321
|
+
// type alias, a generic parameter) refuses just this ONE
|
|
1322
|
+
// candidate rather than guessing at it. The declaring subclass's
|
|
1323
|
+
// OWN name is never needed here: the text names what the field
|
|
1324
|
+
// holds, not who assigned it.
|
|
1325
|
+
if (!foreignTypeNames.every((foreignName) => {
|
|
1326
|
+
const info = index.classesByName.get(foreignName);
|
|
1327
|
+
return info !== undefined && (resolve(info.filePath) === here || info.exportName !== null);
|
|
1328
|
+
})) {
|
|
1329
|
+
refusedDeclarer = true;
|
|
1330
|
+
continue;
|
|
1331
|
+
}
|
|
1332
|
+
if (foreignTypeNames.some((foreignName) => boundHere.has(foreignName) && !importLines.has(foreignName))) {
|
|
1333
|
+
refusedDeclarer = true;
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1336
|
+
// An import edge this candidate would need must not close a cycle:
|
|
1337
|
+
// if the class the candidate names is a file that can ALREADY
|
|
1338
|
+
// reach `here` (this base's own file) through the package's real
|
|
1339
|
+
// runtime imports, adding the reverse edge closes a loop and the
|
|
1340
|
+
// checker answers `any` for everything caught in it -- see
|
|
1341
|
+
// `modulesReachableFrom`'s own comment. Refuses just this ONE
|
|
1342
|
+
// candidate, the same granularity as the unresolvable-name check
|
|
1343
|
+
// above: a different candidate for the same member that names an
|
|
1344
|
+
// acyclic type is unaffected.
|
|
1345
|
+
if (foreignTypeNames.some((foreignName) => {
|
|
1346
|
+
const info = index.classesByName.get(foreignName);
|
|
1347
|
+
if (!info)
|
|
1348
|
+
return false;
|
|
1349
|
+
const targetPath = resolve(info.filePath);
|
|
1350
|
+
return targetPath !== here && modulesReachableFrom(targetPath, read).has(here);
|
|
1351
|
+
})) {
|
|
1352
|
+
refusedDeclarer = true;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
typeParts.push(candidateText);
|
|
1356
|
+
for (const className of foreignTypeNames) {
|
|
1357
|
+
const info = index.classesByName.get(className);
|
|
1358
|
+
if (info)
|
|
1359
|
+
neededImports.push(info);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
if (refusedDeclarer || typeParts.length === 0)
|
|
1364
|
+
continue;
|
|
1365
|
+
// A reference-typed candidate is sound to STATE (the union over-
|
|
1366
|
+
// approximates, per this file's own header) but is only sound to
|
|
1367
|
+
// ADD to Base without also corrupting what its OWN declaring
|
|
1368
|
+
// subclasses read: TypeScript's checker gives an unannotated
|
|
1369
|
+
// `this.x = ...` in a subclass the type Base now declares, not the
|
|
1370
|
+
// narrower type that assignment's own shape implies. When every
|
|
1371
|
+
// declarer of this member is drawn from the SAME inheritance lineage
|
|
1372
|
+
// (`shareCommonAncestor`), a caller reaching the member through any
|
|
1373
|
+
// union member still resolves the SAME inherited method -- no
|
|
1374
|
+
// precision lost, no signature ambiguity. When two declarers are
|
|
1375
|
+
// UNRELATED classes that merely reuse a member NAME (three.js's own
|
|
1376
|
+
// `Object3D.matrix: Matrix4` vs `Texture.matrix: Matrix3` -- both root
|
|
1377
|
+
// classes, both direct descendants of the near-universal
|
|
1378
|
+
// `EventDispatcher`, sharing a name by coincidence, not a relationship),
|
|
1379
|
+
// each contributes its own same-named method with a different
|
|
1380
|
+
// signature; overlaying the union onto `EventDispatcher` silently
|
|
1381
|
+
// widens `Object3D`'s own `this.matrix` from a precise `Matrix4` to
|
|
1382
|
+
// `Matrix3 | Matrix4 | undefined`, and calling a matrix-only method
|
|
1383
|
+
// through that union asks `derive.ts` for a carrier no nominal class
|
|
1384
|
+
// reduction covers -- `unresolved-reaches-materialization` fires,
|
|
1385
|
+
// correctly (measured on the three.js app before this check existed: viol
|
|
1386
|
+
// 0->13, unres 0->3, all four `.matrix.copy`/`.matrix.premultiply`
|
|
1387
|
+
// call sites in `Object3D.js`/`Texture.js`/`WebXRManager.js`). This is
|
|
1388
|
+
// a purely structural class-hierarchy test -- see
|
|
1389
|
+
// `shareCommonAncestor`'s own comment -- never a name or library check.
|
|
1390
|
+
if (!shareCommonAncestor(index, neededImports.map((entry) => entry.name)))
|
|
1391
|
+
continue;
|
|
1392
|
+
for (const info of neededImports) {
|
|
1393
|
+
if (resolve(info.filePath) === here || importLines.has(info.name))
|
|
1394
|
+
continue;
|
|
1395
|
+
importLines.set(info.name, classImportLine(info, hereDir));
|
|
1396
|
+
}
|
|
1397
|
+
typeParts.push('undefined');
|
|
1398
|
+
fieldTexts.push(`\t/** @type {${typeParts.join(' | ')}}\n\t * @geaSubclassMemberOverlay */\n\t${name};\n`);
|
|
1399
|
+
}
|
|
1400
|
+
if (fieldTexts.length === 0)
|
|
1401
|
+
continue;
|
|
1402
|
+
edits.push({ at: statement.members.pos, text: '\n' + fieldTexts.join('') });
|
|
1403
|
+
}
|
|
1404
|
+
if (edits.length === 0)
|
|
1405
|
+
return null;
|
|
1406
|
+
if (importLines.size > 0) {
|
|
1407
|
+
const block = `\n/**\n${[...importLines.values()]
|
|
1408
|
+
.sort()
|
|
1409
|
+
.map((line) => ` * ${line}`)
|
|
1410
|
+
.join('\n')}\n */\n`;
|
|
1411
|
+
edits.push({ at: leadingImportEnd, text: block });
|
|
1412
|
+
}
|
|
1413
|
+
edits.sort((a, b) => b.at - a.at);
|
|
1414
|
+
let text = input.text;
|
|
1415
|
+
for (const edit of edits)
|
|
1416
|
+
text = text.slice(0, edit.at) + edit.text + text.slice(edit.at);
|
|
1417
|
+
return text;
|
|
1418
|
+
};
|