@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,2206 @@
|
|
|
1
|
+
import { passingOf, representationKey } from '../../../representation/model.js';
|
|
2
|
+
import { hostMemberTemplateOf } from '../../../representation/host-templates.js';
|
|
3
|
+
import { createCppEmitBlockedError, operandText } from '../emit-context.js';
|
|
4
|
+
import { canonicalIndexLiteral, memberAccessOperator } from '../emit-carrier-members.js';
|
|
5
|
+
import { classMemberOf, lazyArrowFieldPlanOf } from '../class-layout.js';
|
|
6
|
+
import { alignedValueText, recipeText } from '../emit-narrowing.js';
|
|
7
|
+
import { getOwnValue, objectViewFrom, objectViewOf, ownEnumerableKeysText, ownKeyFields, ownKeyPresenceText, refuseDictionaryArm, refuseObjectCarrier, setOwnCallableText, setOwnText } from './object-protocol.js';
|
|
8
|
+
import { hostIntrinsicLengthOf, hostMemberOf } from './host-members.js';
|
|
9
|
+
import { hostFunctionValueText, hostPrototypeMethodValueText } from './emit-host-value.js';
|
|
10
|
+
import { armAt, armIs } from '../emit-union-properties.js';
|
|
11
|
+
import { recordFieldsOfShape, recordIndexesOfShape } from '../records.js';
|
|
12
|
+
import { cppArrayExtensionStructName, cppBodyName, cppRecordFieldAttributesName, cppRecordFieldName, cppRecordFieldPresenceName, cppRecordStructName, cppStringLiteral, cppTypeOf, cppUndefinedValue } from '../types.js';
|
|
13
|
+
import { isNativeCallableCarrier, propertyKeyText as propertyKeyOperandText, stringKeyPreludeText } from '../emit-dynamic-properties.js';
|
|
14
|
+
import { regexpRoleOf } from '../prototype/emit-prototype-regexp.js';
|
|
15
|
+
/**
|
|
16
|
+
* `Object`'s statics -- the call-site half of the `ObjectConstructor@1`
|
|
17
|
+
* boundary.
|
|
18
|
+
*
|
|
19
|
+
* Its own module rather than another block in `emit-host-invoke.ts` because
|
|
20
|
+
* every member here answers the same question that file's other renderers do
|
|
21
|
+
* not have to: *what is the receiver's carrier*. `Promise.resolve` renders
|
|
22
|
+
* from the result's payload and `Symbol.for` from a literal's text, but
|
|
23
|
+
* `Object.keys(x)` is two completely different programs depending on whether
|
|
24
|
+
* the checker knows `x`'s shape -- and the split runs through all ten members,
|
|
25
|
+
* so it is one file's subject rather than ten paragraphs in someone else's.
|
|
26
|
+
*
|
|
27
|
+
* ## Every member is a loop over three primitives
|
|
28
|
+
*
|
|
29
|
+
* The receiver question, the key list, the read and the store are not this
|
|
30
|
+
* file's -- they are `object-protocol.ts`'s, which states them once as
|
|
31
|
+
* `objectViewOf`, `ownEnumerableKeysText`, `getOwnValue` and `setOwnText`.
|
|
32
|
+
* What is left here is what each member actually IS in terms of them, which is
|
|
33
|
+
* the shape ECMA-262 gives it: `keys` is primitive 1, `values` is 1 then 2 per
|
|
34
|
+
* key, `assign` is 1 then 2 then 3 per key, `hasOwn` is membership in 1.
|
|
35
|
+
*
|
|
36
|
+
* Before that split, each member rediscovered the receiver question and they
|
|
37
|
+
* had drifted: `keys` and `values` grew a static arm, `entries`, `assign` and
|
|
38
|
+
* `defineProperty` refused every known shape, and `values` enumerated in
|
|
39
|
+
* DECLARATION order while `keys` enumerated in ECMA-262 10.1.11.1 order -- two
|
|
40
|
+
* answers about one object's keys, which is the defect this whole file exists
|
|
41
|
+
* to avoid.
|
|
42
|
+
*
|
|
43
|
+
* ## What still refuses, and why each refusal is its own
|
|
44
|
+
*
|
|
45
|
+
* A member whose static arm needs a capability beyond the three primitives
|
|
46
|
+
* refuses NAMING THAT CAPABILITY rather than borrowing the enumeration
|
|
47
|
+
* refusal. `freeze` needs an integrity level a C++ struct has no slot for;
|
|
48
|
+
* `getOwnPropertyDescriptor` needs a descriptor synthesized from a field;
|
|
49
|
+
* `defineProperty` needs the non-default attributes its own semantics install.
|
|
50
|
+
* Those are three different missing features, and reporting all three as "this
|
|
51
|
+
* carrier has no own-key enumeration" sent them to one wrong cure.
|
|
52
|
+
*/
|
|
53
|
+
/** A `dynamic` carrier, built where a member has to state the box it widens a known field into. */
|
|
54
|
+
const dynamicCarrier = { kind: 'dynamic', reason: 'declared-any-never-narrowed' };
|
|
55
|
+
const objectValueConversionText = (ctx, operation, role, argument, field, source, text) => {
|
|
56
|
+
const citation = operation.objectValueConversions?.find((value) => value.role === role && value.argument === argument && value.field === field);
|
|
57
|
+
const node = citation && ctx.conversions.nodeById(citation.conversion);
|
|
58
|
+
if (!citation || !node || representationKey(citation.source) !== representationKey(source))
|
|
59
|
+
throw createCppEmitBlockedError('call-abi:object-value-conversions', 'Object field value has no matching certified conversion citation');
|
|
60
|
+
const rendered = recipeText(ctx, node, text);
|
|
61
|
+
if (rendered === null)
|
|
62
|
+
throw createCppEmitBlockedError(`conversion:${citation.conversion}`, 'Object field value conversion has no rendering');
|
|
63
|
+
return rendered;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* The receiver's argument, or a refusal naming the member that has no
|
|
67
|
+
* receiver to work on.
|
|
68
|
+
*
|
|
69
|
+
* Every member here takes its target as the FIRST argument -- `Object` itself
|
|
70
|
+
* is the callee, not the receiver -- so this is the one shape check they share.
|
|
71
|
+
*
|
|
72
|
+
* The argument is read THROUGH the box lowering put in front of it. The
|
|
73
|
+
* declared parameter is `any`, so the slot census answers `dynamic` and
|
|
74
|
+
* lowering converts a typed receiver (`Math`, an array, a callable) into a
|
|
75
|
+
* `gea::Value` before this renderer sees it. The arms below are not callers of
|
|
76
|
+
* that `any` parameter: each expands the member over the receiver's own
|
|
77
|
+
* carrier (the intrinsic's member table, the array's elements, the function's
|
|
78
|
+
* own properties), and only the arm for a receiver nothing else names goes
|
|
79
|
+
* through the runtime's boxed entry point. Rendering the box instead of the
|
|
80
|
+
* source lost the Math member table: `Object.getOwnPropertyDescriptor(Math,
|
|
81
|
+
* "abs")` boxed `Math` to a `Value` with no own properties and answered
|
|
82
|
+
* `undefined`. Until the census names these calls as expansions of the
|
|
83
|
+
* receiver (Phase 3's `CallOperation.target`), the source is looked up the way
|
|
84
|
+
* `emit-jsx.ts` looks up a slot's history -- `EmitContext.conversionSources`.
|
|
85
|
+
*/
|
|
86
|
+
const targetOf = (ctx, member, operation) => {
|
|
87
|
+
const target = operation.arguments[0];
|
|
88
|
+
if (target === undefined) {
|
|
89
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" takes a target object, and this call passes none`);
|
|
90
|
+
}
|
|
91
|
+
if (target.representation.kind !== 'dynamic')
|
|
92
|
+
return target;
|
|
93
|
+
const source = ctx.conversionSources.get(target.value);
|
|
94
|
+
return source !== undefined && source.representation.kind !== 'dynamic' ? source : target;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* THE ENUMERATION OF A UNION IS THE ENUMERATION OF WHICHEVER ARM IS LIVE.
|
|
98
|
+
*
|
|
99
|
+
* A `tagged-union` receiver has no own properties of its own -- it is a
|
|
100
|
+
* discriminated carrier over several shapes, each of which answers the
|
|
101
|
+
* receiver question by itself. So the member renders once PER ARM and
|
|
102
|
+
* dispatches on the discriminant, exactly as `emit-union-properties.ts`
|
|
103
|
+
* renders a `get` over one: the arms all produce the member's own result type
|
|
104
|
+
* (an `ArrayObject` of keys, of values, of entry structs), so the conditional
|
|
105
|
+
* chain is well typed whatever mix of records and dictionaries the union
|
|
106
|
+
* holds.
|
|
107
|
+
*
|
|
108
|
+
* hono's `#newResponse` is the measured case: `Object.entries( headers )`
|
|
109
|
+
* where `headers: HeaderRecord` is `Record<'Content-Type', BaseMime> |
|
|
110
|
+
* Record<ResponseHeader, string> | Record<string, string>` -- two records and
|
|
111
|
+
* a dictionary, and refusing the union outright refused a program in which
|
|
112
|
+
* every arm on its own is renderable.
|
|
113
|
+
*
|
|
114
|
+
* An arm that CANNOT be enumerated still refuses, and now says which arm and
|
|
115
|
+
* why rather than reporting the union as one unenumerable carrier.
|
|
116
|
+
*/
|
|
117
|
+
const overCarrier = (ctx, member, operation, render) => {
|
|
118
|
+
const target = targetOf(ctx, member, operation);
|
|
119
|
+
const representation = target.representation;
|
|
120
|
+
if (representation.kind !== 'tagged-union')
|
|
121
|
+
return render(objectViewOf(ctx, member, target, 'object'));
|
|
122
|
+
const receiver = operandText(ctx, target);
|
|
123
|
+
const arms = representation.arms.map((arm, index) => render(objectViewFrom(ctx, member, arm.value, armAt(receiver, index), 'object')));
|
|
124
|
+
const dispatched = arms.reduceRight((rest, text, index) => (rest === null ? text : `${armIs(receiver, index)} ? ${text} : (${rest})`), null);
|
|
125
|
+
if (dispatched === null) {
|
|
126
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a tagged union with no arms has nothing to enumerate`);
|
|
127
|
+
}
|
|
128
|
+
return arms.length > 1 ? `(${dispatched})` : dispatched;
|
|
129
|
+
};
|
|
130
|
+
/** `Object.keys` / `Object.getOwnPropertyNames` -- primitive 1 alone, because a record has no non-enumerable member for the two to differ over. */
|
|
131
|
+
const keysText = (ctx, member, operation) => {
|
|
132
|
+
const target = targetOf(ctx, member, operation);
|
|
133
|
+
const keysOf = (representation, receiver) => {
|
|
134
|
+
if (representation.kind === 'scalar' || representation.kind === 'symbol') {
|
|
135
|
+
return `((void)(${receiver}), gea::host::ObjectConstructor::staticKeys({}))`;
|
|
136
|
+
}
|
|
137
|
+
if (representation.kind === 'native-handle') {
|
|
138
|
+
// `Object.keys` answers empty: ECMA-262 declares every one of a host
|
|
139
|
+
// intrinsic's own members non-enumerable (21.3.1's constants, 10.2.4's
|
|
140
|
+
// builtin methods), the identical fact `emitNativeHandleEnumerateIterator`
|
|
141
|
+
// (emit-iterator.ts) already renders as an always-empty `for`-`in` walk.
|
|
142
|
+
// `Object.getOwnPropertyNames` is NOT enumerable-filtered (6.1.7.1) --
|
|
143
|
+
// it answers every own key regardless -- so it reads the full static
|
|
144
|
+
// list `nativeHandleShapeCallText`'s own `hasOwnProperty` reads
|
|
145
|
+
// (`ctx.hosts.intrinsicMembers`), never a hand-listed name.
|
|
146
|
+
const protocol = representation.native ?? representation.protocol;
|
|
147
|
+
const names = member === 'keys' ? [] : (ctx.hosts.intrinsicMembers.get(protocol) ?? []).map((found) => found.name);
|
|
148
|
+
return `((void)(${receiver}), gea::host::ObjectConstructor::staticKeys({${names.map((name) => cppStringLiteral(name)).join(', ')}}))`;
|
|
149
|
+
}
|
|
150
|
+
if (representation.kind === 'array-object') {
|
|
151
|
+
const helper = member === 'keys' ? 'arrayOwnEnumerableKeys' : 'arrayOwnPropertyNames';
|
|
152
|
+
return `gea::host::ObjectConstructor::staticKeys(gea::${helper}(${receiver}))`;
|
|
153
|
+
}
|
|
154
|
+
if (regexpRoleOf(representation) === 'pattern') {
|
|
155
|
+
const helper = member === 'keys' ? 'nativeDynamicKeys' : 'nativeOwnPropertyNames';
|
|
156
|
+
return `gea::host::ObjectConstructor::staticKeys(gea::${helper}(${receiver}))`;
|
|
157
|
+
}
|
|
158
|
+
return ownEnumerableKeysText(member, objectViewFrom(ctx, member, representation, receiver, 'object'), member === 'keys' ? 'keys' : 'getOwnPropertyNames');
|
|
159
|
+
};
|
|
160
|
+
if (target.representation.kind !== 'tagged-union')
|
|
161
|
+
return keysOf(target.representation, operandText(ctx, target));
|
|
162
|
+
const receiver = operandText(ctx, target);
|
|
163
|
+
const arms = target.representation.arms.map((arm, index) => keysOf(arm.value, armAt(receiver, index)));
|
|
164
|
+
const dispatched = arms.reduceRight((rest, text, index) => (rest === null ? text : `${armIs(receiver, index)} ? ${text} : (${rest})`), null);
|
|
165
|
+
if (dispatched === null)
|
|
166
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a tagged union with no arms has nothing to enumerate`);
|
|
167
|
+
return arms.length > 1 ? `(${dispatched})` : dispatched;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* `Object.values` -- primitive 1 for the order, primitive 2 for each entry.
|
|
171
|
+
*
|
|
172
|
+
* The static arm needs one more agreement than `keys` does: every field has to
|
|
173
|
+
* carry the array's own element type, because a `std::vector<E>` has one
|
|
174
|
+
* element type and a record's fields need not share one. A heterogeneous
|
|
175
|
+
* record's `Object.values` is typed `(number | string)[]` by the checker, whose
|
|
176
|
+
* element carrier is a `tagged-union` -- and building one arm-by-arm from a
|
|
177
|
+
* struct field is a conversion per field this does not write, so it refuses
|
|
178
|
+
* with the disagreement named instead of picking an arm.
|
|
179
|
+
*/
|
|
180
|
+
const valuesText = (ctx, operation) => overCarrier(ctx, 'values', operation, (view) => valuesOfView(ctx, operation, view));
|
|
181
|
+
const valuesOfView = (ctx, operation, view) => {
|
|
182
|
+
if (view.kind === 'dynamic')
|
|
183
|
+
return `gea::host::ObjectConstructor::values(${view.receiver})`;
|
|
184
|
+
const result = operation.result?.representation;
|
|
185
|
+
if (view.kind === 'dictionary') {
|
|
186
|
+
if (view.representation.key === 'symbol') {
|
|
187
|
+
if (result === undefined || result.kind !== 'array-object') {
|
|
188
|
+
throw createCppEmitBlockedError('host-member-call:Object.values', `"Object.values" of a symbol dictionary mints an empty array, and this call's result carries ` +
|
|
189
|
+
`"${result === undefined ? 'nothing' : representationKey(result)}"`);
|
|
190
|
+
}
|
|
191
|
+
return `gea::detail::hostArrayResult(std::vector<${cppTypeOf(result.element)}>{})`;
|
|
192
|
+
}
|
|
193
|
+
// A dictionary's values all carry ONE type -- the table's own `V` -- so
|
|
194
|
+
// the per-field disagreement the known-shape arm below refuses on cannot
|
|
195
|
+
// arise. What has to agree is the result's element with that `V`; a
|
|
196
|
+
// program whose `Object.values` result was typed wider than the table
|
|
197
|
+
// would need a per-entry conversion, which is a real feature and not this
|
|
198
|
+
// one.
|
|
199
|
+
if (result === undefined || result.kind !== 'array-object' || representationKey(result.element) !== representationKey(view.value)) {
|
|
200
|
+
return refuseDictionaryArm('values', view, `its values all carry "${representationKey(view.value)}" and this call's result carries ` +
|
|
201
|
+
`"${result === undefined ? 'nothing' : representationKey(result)}" -- converting each entry into a different ` +
|
|
202
|
+
'element carrier is a per-entry conversion this arm does not write');
|
|
203
|
+
}
|
|
204
|
+
return `gea::host::ObjectConstructor::valuesOf(${view.receiver})`;
|
|
205
|
+
}
|
|
206
|
+
if (result === undefined || result.kind !== 'array-object') {
|
|
207
|
+
throw createCppEmitBlockedError('host-member-call:Object.values', `"Object.values" of a known shape mints an array, and this call's result carries ` +
|
|
208
|
+
`"${result === undefined ? 'nothing' : representationKey(result)}"`);
|
|
209
|
+
}
|
|
210
|
+
const element = representationKey(result.element);
|
|
211
|
+
const ordered = ownKeyFields(view);
|
|
212
|
+
for (const field of ordered) {
|
|
213
|
+
if (!field.required) {
|
|
214
|
+
throw createCppEmitBlockedError('host-member-call:Object.values', `"Object.values" cannot include the optional field "${field.key}": an absent field contributes no element, and ` +
|
|
215
|
+
'the length of the array would then depend on a presence flag this arm does not test');
|
|
216
|
+
}
|
|
217
|
+
if (representationKey(field.value) !== element) {
|
|
218
|
+
throw createCppEmitBlockedError('host-member-call:Object.values', `"Object.values" would build a std::vector<${cppTypeOf(result.element)}> from the field "${field.key}", which ` +
|
|
219
|
+
`carries "${representationKey(field.value)}" -- one array has one element type, and converting each field into ` +
|
|
220
|
+
"the result's element carrier is a per-field conversion this arm does not write");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const reads = ordered.map((field) => getOwnValue(ctx, view, field).text);
|
|
224
|
+
return `gea::detail::hostArrayResult(std::vector<${cppTypeOf(result.element)}>{${reads.join(', ')}})`;
|
|
225
|
+
};
|
|
226
|
+
/** Consume the representation already selected for the entry's [string, T] tuple. */
|
|
227
|
+
const entryCarrierOf = (ctx, operation) => {
|
|
228
|
+
const result = operation.result?.representation;
|
|
229
|
+
if (result === undefined || result.kind !== 'array-object') {
|
|
230
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" mints an array of entries, and this call's result carries ` +
|
|
231
|
+
`"${result === undefined ? 'nothing' : representationKey(result)}"`);
|
|
232
|
+
}
|
|
233
|
+
const element = result.element;
|
|
234
|
+
// Homogeneous tuples share the native Array carrier with their array views.
|
|
235
|
+
// The first entry position is always a string, so this carrier is valid only
|
|
236
|
+
// when the value position is also a string. No record layout is invented.
|
|
237
|
+
if (element.kind === 'array-object' &&
|
|
238
|
+
element.element.kind === 'string' &&
|
|
239
|
+
element.ownership === 'shared-refcount' &&
|
|
240
|
+
element.extension === null &&
|
|
241
|
+
!element.recursive) {
|
|
242
|
+
return { kind: 'array', element, value: element.element };
|
|
243
|
+
}
|
|
244
|
+
const fields = element.kind === 'record'
|
|
245
|
+
? element.fields
|
|
246
|
+
: element.kind === 'native-record-ref' && element.native === null
|
|
247
|
+
? recordFieldsOfShape(ctx.deriver, element.shapeId)
|
|
248
|
+
: null;
|
|
249
|
+
// A host-stated name wins where there is one -- `records.ts` emits no
|
|
250
|
+
// definition for such a shape, so minting a `gea_record_type_N` name for it
|
|
251
|
+
// would name a struct nothing declares.
|
|
252
|
+
const name = element.kind === 'native-record-ref'
|
|
253
|
+
? (element.native ?? cppRecordStructName(element.shapeId))
|
|
254
|
+
: element.kind === 'record'
|
|
255
|
+
? cppRecordStructName(element.shapeId)
|
|
256
|
+
: null;
|
|
257
|
+
if (fields === null || name === null || fields.length !== 2) {
|
|
258
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" builds each entry as the two-position tuple the checker typed it, and this call's element carries ` +
|
|
259
|
+
`"${representationKey(element)}", which is not a two-field record`);
|
|
260
|
+
}
|
|
261
|
+
const [first, second] = fields;
|
|
262
|
+
if (!first || !second || first.key !== '0' || second.key !== '1') {
|
|
263
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" expects its entry record to be keyed by tuple position ("0", "1"); this one is keyed ` +
|
|
264
|
+
`"${fields.map((field) => field.key).join('", "')}"`);
|
|
265
|
+
}
|
|
266
|
+
// The KEY has to be a string -- `OwnPropertyKeys` yields one and there is
|
|
267
|
+
// nothing to convert it into. The VALUE slot is whatever the checker typed
|
|
268
|
+
// it: `dynamic` for a target the program declared `any`, and a real carrier
|
|
269
|
+
// wherever the source's own values have one -- hono's `HeaderRecord` entries
|
|
270
|
+
// are `[string, string | string[]]`, a tagged union and not a box. Demanding
|
|
271
|
+
// `dynamic` here refused that program for having stated MORE than the arm
|
|
272
|
+
// expected; each value is reconciled into the slot by `convertedValueText`
|
|
273
|
+
// instead, which answers the `dynamic` case with the same widen this used to
|
|
274
|
+
// require and every other case with the conversion it needs.
|
|
275
|
+
if (first.value.kind !== 'string') {
|
|
276
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" yields a string key, and this call's entry carries "${representationKey(first.value)}" in its first ` +
|
|
277
|
+
`position (its second carries "${representationKey(second.value)}")`);
|
|
278
|
+
}
|
|
279
|
+
// `->` when the element is held behind a pointer, `.` when it is a value:
|
|
280
|
+
// the same ownership question every other struct write in this backend asks,
|
|
281
|
+
// and the reason the allocation differs too.
|
|
282
|
+
const ownership = element.kind === 'record' || element.kind === 'native-record-ref' ? element.ownership : 'owned';
|
|
283
|
+
return { kind: 'record', name, element, value: second.value, shared: memberAccessOperator(ownership) === '->' };
|
|
284
|
+
};
|
|
285
|
+
/** One entry, with both positions already converted to their selected carriers. */
|
|
286
|
+
const entryText = (entry, key, value) => {
|
|
287
|
+
if (entry.kind === 'array')
|
|
288
|
+
return `return gea::arrayOf<${cppTypeOf(entry.value)}>({${key}, ${value}});`;
|
|
289
|
+
// `gea::makeRef` and not `std::make_shared`: `gea::Ref` is its own handle
|
|
290
|
+
// (gea_runtime.h), a `shared_ptr` does not convert to one, and every other
|
|
291
|
+
// allocation in this backend already spells it this way -- so the entry
|
|
292
|
+
// struct was the one place that built a handle no `std::vector<gea::Ref<T>>`
|
|
293
|
+
// would take.
|
|
294
|
+
const allocate = entry.shared ? `auto __gea_entry = gea::makeRef<${entry.name}>();` : `${entry.name} __gea_entry{};`;
|
|
295
|
+
const write = entry.shared ? '__gea_entry->' : '__gea_entry.';
|
|
296
|
+
return `${allocate} ${write}${cppRecordFieldName('0')} = ${key}; ${write}${cppRecordFieldName('1')} = ${value}; return __gea_entry;`;
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* `Object.entries` -- primitive 1 for the keys, primitive 2 for each value.
|
|
300
|
+
*
|
|
301
|
+
* The static arm's one extra obligation is the entry's second slot: whatever
|
|
302
|
+
* the checker typed it, each own value has to be reconciled into it. That is
|
|
303
|
+
* `convertedValueText` -- a widen where the slot really is `dynamic` (the
|
|
304
|
+
* target the program declared `any`), an arm store where the source's values
|
|
305
|
+
* have a type of their own, and a refusal by name where neither is licensed.
|
|
306
|
+
*
|
|
307
|
+
* An optional field refuses for the same reason it does in `values`: an absent
|
|
308
|
+
* key contributes no entry, so the array's LENGTH would depend on a presence
|
|
309
|
+
* flag, and a `std::vector` built from a brace list has its length fixed
|
|
310
|
+
* before any flag is read.
|
|
311
|
+
*/
|
|
312
|
+
const entriesText = (ctx, operation) => overCarrier(ctx, 'entries', operation, (view) => entriesOfView(ctx, operation, view));
|
|
313
|
+
const entriesOfView = (ctx, operation, view) => {
|
|
314
|
+
const entry = entryCarrierOf(ctx, operation);
|
|
315
|
+
/**
|
|
316
|
+
* One own value, reconciled into the entry's second slot.
|
|
317
|
+
*
|
|
318
|
+
* `convertedValueText` and not `widenedStoreText`: the slot is `dynamic`
|
|
319
|
+
* only where the program declared the target `any`, and a widen is then
|
|
320
|
+
* exactly what this returns -- but a typed source has a typed slot, and
|
|
321
|
+
* `HeaderRecord`'s `string | string[]` needs an arm store rather than a box.
|
|
322
|
+
*/
|
|
323
|
+
const intoSlot = (source, text, describe) => {
|
|
324
|
+
const converted = alignedValueText(ctx, 'host/emit-host-object.ts:371', source, entry.value, text);
|
|
325
|
+
if (converted !== null)
|
|
326
|
+
return converted;
|
|
327
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" would put ${describe}, carried as "${representationKey(source)}", into an entry's value slot ` +
|
|
328
|
+
`carried as "${representationKey(entry.value)}", and no conversion between those is licensed`);
|
|
329
|
+
};
|
|
330
|
+
if (view.kind === 'dynamic') {
|
|
331
|
+
const value = intoSlot(dynamicCarrier, '__gea_value', 'a dynamic own value');
|
|
332
|
+
return (`gea::host::ObjectConstructor::entriesAs<${cppTypeOf(entry.element)}>(${view.receiver}, ` +
|
|
333
|
+
`[](std::string __gea_key, gea::Value __gea_value) { ${entryText(entry, '__gea_key', value)} })`);
|
|
334
|
+
}
|
|
335
|
+
if (view.kind === 'dictionary') {
|
|
336
|
+
if (view.representation.key === 'symbol') {
|
|
337
|
+
return `gea::detail::hostArrayResult(std::vector<${cppTypeOf(entry.element)}>{})`;
|
|
338
|
+
}
|
|
339
|
+
// The same maker the dynamic arm passes, over the table's own entries: the
|
|
340
|
+
// key comes from `propertyKeys()` (10.1.11 order, stated on the container)
|
|
341
|
+
// and the value keeps the table's own `V` right up to the entry slot.
|
|
342
|
+
const value = intoSlot(view.value, '__gea_value', 'a dictionary entry');
|
|
343
|
+
return (`gea::host::ObjectConstructor::entriesOf<${cppTypeOf(entry.element)}>(${view.receiver}, ` +
|
|
344
|
+
`[](std::string __gea_key, ${cppTypeOf(view.value)} __gea_value) { ${entryText(entry, '__gea_key', value)} })`);
|
|
345
|
+
}
|
|
346
|
+
const built = ownKeyFields(view).map((field) => {
|
|
347
|
+
if (!field.required) {
|
|
348
|
+
throw createCppEmitBlockedError('host-member-call:Object.entries', `"Object.entries" cannot include the optional field "${field.key}": an absent key contributes no entry, and the ` +
|
|
349
|
+
'length of the array would then depend on a presence flag a braced vector has already fixed');
|
|
350
|
+
}
|
|
351
|
+
const read = getOwnValue(ctx, view, field);
|
|
352
|
+
const value = intoSlot(read.representation, read.text, `the field "${field.key}"`);
|
|
353
|
+
return `[&]() { ${entryText(entry, cppStringLiteral(field.key), value)} }()`;
|
|
354
|
+
});
|
|
355
|
+
return `gea::detail::hostArrayResult(std::vector<${cppTypeOf(entry.element)}>{${built.join(', ')}})`;
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* A property key argument, as `gea::PropertyKey`.
|
|
359
|
+
*
|
|
360
|
+
* ECMA-262 6.1.7 admits a string or a symbol and nothing else, and
|
|
361
|
+
* ToPropertyKey of anything else is a conversion that can run user code
|
|
362
|
+
* (`ToPrimitive`), which this backend does not perform anywhere. So a `number`
|
|
363
|
+
* key -- legal in the language, and `o[0]` really is the string key `"0"` --
|
|
364
|
+
* refuses here rather than being spelled through a `std::to_string` that would
|
|
365
|
+
* be right for an integer and wrong for `1e21`, `-0` and `NaN`.
|
|
366
|
+
*/
|
|
367
|
+
const propertyKeyText = (ctx, member, key) => {
|
|
368
|
+
return propertyKeyOperandText(ctx, key, `Object.${member}`);
|
|
369
|
+
};
|
|
370
|
+
/**
|
|
371
|
+
* The native object expression for a generated record index sidecar.
|
|
372
|
+
*
|
|
373
|
+
* Enumeration still needs a single interleaved creation-order stream and is
|
|
374
|
+
* deliberately not claimed for this carrier. Descriptor operations do not:
|
|
375
|
+
* they address exactly one own key, so they can use the generated record's
|
|
376
|
+
* authenticated index hooks without inventing an enumeration contract.
|
|
377
|
+
*/
|
|
378
|
+
const indexedRecordReceiver = (ctx, member, representation, receiver) => {
|
|
379
|
+
const indexed = representation.kind === 'record-with-index' ||
|
|
380
|
+
(representation.kind === 'native-record-ref' &&
|
|
381
|
+
representation.native === null &&
|
|
382
|
+
recordIndexesOfShape(ctx.deriver, representation.shapeId).length > 0);
|
|
383
|
+
if (!indexed)
|
|
384
|
+
return null;
|
|
385
|
+
const ownership = representation.ownership;
|
|
386
|
+
if (ownership !== 'shared-refcount') {
|
|
387
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a "${representationKey(representation)}" carrier needs an object identity for its descriptor sidecar, ` +
|
|
388
|
+
`but this receiver is "${ownership}" rather than shared-refcount`);
|
|
389
|
+
}
|
|
390
|
+
return receiver;
|
|
391
|
+
};
|
|
392
|
+
/** A generated shared record's fixed slots and typed index sidecar share one native [[DefineOwnProperty]] dispatch. */
|
|
393
|
+
const generatedRecordReceiver = (representation, receiver) => {
|
|
394
|
+
const generated = representation.kind === 'record' ||
|
|
395
|
+
representation.kind === 'record-with-index' ||
|
|
396
|
+
representation.kind === 'class-ref' ||
|
|
397
|
+
(representation.kind === 'native-record-ref' && representation.native === null);
|
|
398
|
+
return generated && representation.ownership === 'shared-refcount' ? receiver : null;
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* A literal key naming a declared fixed field of one of `generatedRecordReceiver`'s
|
|
402
|
+
* own four carrier kinds -- asked directly against the shape rather than through
|
|
403
|
+
* `objectViewOf`, which answers identically for these but can also THROW for a
|
|
404
|
+
* fifth case that predicate matches (a `native-record-ref` deriving no record
|
|
405
|
+
* layout at all), which must fall through to the generic dispatch below unchanged
|
|
406
|
+
* rather than refuse.
|
|
407
|
+
*
|
|
408
|
+
* `definePropertyText` asks this BEFORE `generatedRecordReceiver`'s own
|
|
409
|
+
* unconditional match: a key naming a declared field belongs to
|
|
410
|
+
* `fixedFieldDefinePropertyText`'s per-field typed store (the one place that
|
|
411
|
+
* knows the field's real C++ carrier and its own `existing`-vs-new distinction),
|
|
412
|
+
* never to the class's generic index-descriptor virtual dispatch
|
|
413
|
+
* (`gea_matchesOwnField`/`gea_defineOwnField`) that dispatch was built for
|
|
414
|
+
* OTHER keys -- an index-sidecar entry, or a runtime one this static check
|
|
415
|
+
* cannot name. Every declared field also has a `gea_present_<key>` bit for
|
|
416
|
+
* that generic dispatch, and it defaults to `true` for a required field
|
|
417
|
+
* (correct for a field a plain initializer or a `this.x =` sets before any
|
|
418
|
+
* other code observes it) -- but a field established ONLY by
|
|
419
|
+
* `Object.defineProperty` has no such write, so treating it as already
|
|
420
|
+
* present there applies 6.2.5.6's REDEFINE rule to what is really a FIRST
|
|
421
|
+
* definition, and a generic descriptor stating only "value" then short-circuits
|
|
422
|
+
* against a `NativeIndexAttributes` default of writable/enumerable/configurable
|
|
423
|
+
* all `true` -- silently granting three attributes the call never stated.
|
|
424
|
+
*/
|
|
425
|
+
const declaredFixedFieldOf = (ctx, representation, key) => {
|
|
426
|
+
const fields = representation.kind === 'record' || representation.kind === 'record-with-index'
|
|
427
|
+
? representation.fields
|
|
428
|
+
: representation.kind === 'class-ref'
|
|
429
|
+
? recordFieldsOfShape(ctx.deriver, representation.shapeId)
|
|
430
|
+
: representation.kind === 'native-record-ref' && representation.native === null
|
|
431
|
+
? recordFieldsOfShape(ctx.deriver, representation.shapeId)
|
|
432
|
+
: null;
|
|
433
|
+
return fields?.find((field) => field.key === key) ?? null;
|
|
434
|
+
};
|
|
435
|
+
/**
|
|
436
|
+
* Do not send a named native slot through nativeDynamicDefineProperty first:
|
|
437
|
+
* a deleted configurable fixed field no longer reads as present, but it is
|
|
438
|
+
* still a declared slot and must be redefined there rather than shadowed in
|
|
439
|
+
* the expando. The generated match hooks retain that distinction.
|
|
440
|
+
*/
|
|
441
|
+
const generatedDefineOwnText = (receiver, key, descriptor) => `([&]() -> bool { const gea::PropertyKey __gea_key = ${key}; ` +
|
|
442
|
+
`if (${receiver}->gea_matchesOwnField(__gea_key)) return ${receiver}->gea_defineOwnField(__gea_key, ${descriptor}, gea::nativeIsExtensible(${receiver})); ` +
|
|
443
|
+
`if (${receiver}->gea_matchesOwnIndex(__gea_key)) return ${receiver}->gea_defineOwnIndex(__gea_key, ${descriptor}, gea::nativeIsExtensible(${receiver})); ` +
|
|
444
|
+
`return gea::nativeDynamicDefineProperty(${receiver}, __gea_key, ${descriptor}); })()`;
|
|
445
|
+
/**
|
|
446
|
+
* `Object.freeze` / `Object.isFrozen` -- the two members of this family that
|
|
447
|
+
* are NOT a loop over the three primitives.
|
|
448
|
+
*
|
|
449
|
+
* A generated shared object keeps this state in its identity-keyed native
|
|
450
|
+
* sidecar. Static, computed and boxed writes all consult that same state, so
|
|
451
|
+
* the object keeps its native carrier while `freeze` makes its declared fields
|
|
452
|
+
* non-writable and its expando table non-extensible.
|
|
453
|
+
*/
|
|
454
|
+
const integrityText = (ctx, member, operation, call) => {
|
|
455
|
+
const target = targetOf(ctx, member, operation);
|
|
456
|
+
if (target.representation.kind === 'array-object' && target.representation.ownership === 'shared-refcount') {
|
|
457
|
+
if (call === 'seal' || call === 'isSealed' || call === 'preventExtensions') {
|
|
458
|
+
return refuseObjectCarrier(member, target.representation, 'this array path has no native seal/preventExtensions implementation');
|
|
459
|
+
}
|
|
460
|
+
const helper = call === 'freeze' ? 'Freeze' : call === 'isFrozen' ? 'IsFrozen' : 'IsExtensible';
|
|
461
|
+
return `gea::native${helper}(${operandText(ctx, target)})`;
|
|
462
|
+
}
|
|
463
|
+
if (regexpRoleOf(target.representation) === 'pattern') {
|
|
464
|
+
const receiver = operandText(ctx, target);
|
|
465
|
+
const expando = `gea::detail::expandoFor(gea::refCastToVoid(${receiver}), true)`;
|
|
466
|
+
if (call === 'freeze')
|
|
467
|
+
return `gea::nativeFreeze(${receiver})`;
|
|
468
|
+
if (call === 'isFrozen')
|
|
469
|
+
return `gea::nativeIsFrozen(${receiver})`;
|
|
470
|
+
if (call === 'isExtensible')
|
|
471
|
+
return `gea::nativeIsExtensible(${receiver})`;
|
|
472
|
+
if (call === 'preventExtensions')
|
|
473
|
+
return `([&]() { ${expando}->preventExtensions(); return ${receiver}; })()`;
|
|
474
|
+
if (call === 'seal') {
|
|
475
|
+
return (`([&]() { const auto __gea_sidecar = ${expando}; ` +
|
|
476
|
+
'for (const auto& __gea_key : __gea_sidecar->ownKeys()) { gea::PropertyDescriptor __gea_update; __gea_update.hasConfigurable = true; __gea_update.configurable = false; ' +
|
|
477
|
+
'if (!__gea_sidecar->defineOwnProperty(__gea_key, __gea_update)) gea::host::throwRuntimeError("TypeError", "Cannot seal Pattern own property"); } ' +
|
|
478
|
+
`__gea_sidecar->preventExtensions(); return ${receiver}; })()`);
|
|
479
|
+
}
|
|
480
|
+
return (`([&]() -> bool { const auto __gea_sidecar = gea::detail::expandoFor(gea::refCastToVoid(${receiver}), false); ` +
|
|
481
|
+
'if (!__gea_sidecar || __gea_sidecar->extensible()) return false; for (const auto& __gea_key : __gea_sidecar->ownKeys()) { ' +
|
|
482
|
+
'const gea::PropertyDescriptor* __gea_descriptor = __gea_sidecar->ownProperty(__gea_key); if (__gea_descriptor != nullptr && __gea_descriptor->configurable) return false; } return true; })()');
|
|
483
|
+
}
|
|
484
|
+
const view = objectViewOf(ctx, member, target, 'object');
|
|
485
|
+
if (view.kind === 'dynamic') {
|
|
486
|
+
if (call === 'seal' || call === 'isSealed' || call === 'preventExtensions') {
|
|
487
|
+
return refuseObjectCarrier(member, target.representation, 'the dynamic Object runtime has no seal/preventExtensions member');
|
|
488
|
+
}
|
|
489
|
+
return `gea::host::ObjectConstructor::${call}(${view.receiver})`;
|
|
490
|
+
}
|
|
491
|
+
if (view.kind === 'known' &&
|
|
492
|
+
(view.representation.kind === 'record' ||
|
|
493
|
+
view.representation.kind === 'record-with-index' ||
|
|
494
|
+
view.representation.kind === 'native-record-ref' ||
|
|
495
|
+
view.representation.kind === 'class-ref') &&
|
|
496
|
+
view.representation.ownership === 'shared-refcount') {
|
|
497
|
+
const generated = view.representation.kind === 'record' ||
|
|
498
|
+
view.representation.kind === 'record-with-index' ||
|
|
499
|
+
view.representation.kind === 'class-ref' ||
|
|
500
|
+
(view.representation.kind === 'native-record-ref' && view.representation.native === null);
|
|
501
|
+
const receiver = view.receiver;
|
|
502
|
+
const expando = `gea::detail::expandoFor(gea::refCastToVoid(${receiver}), true)`;
|
|
503
|
+
if (call === 'freeze') {
|
|
504
|
+
const fields = generated ? `${receiver}->gea_freezeOwnFields(); ${receiver}->gea_freezeOwnIndex(); ` : '';
|
|
505
|
+
return `([&]() { ${fields}gea::nativeFreeze(${receiver}); return ${receiver}; })()`;
|
|
506
|
+
}
|
|
507
|
+
if (call === 'isFrozen') {
|
|
508
|
+
const fields = generated ? `${receiver}->gea_ownFieldsFrozen() && ${receiver}->gea_ownIndexFrozen() && ` : '';
|
|
509
|
+
return `${fields}gea::nativeIsFrozen(${receiver})`;
|
|
510
|
+
}
|
|
511
|
+
if (call === 'isExtensible')
|
|
512
|
+
return `gea::nativeIsExtensible(${receiver})`;
|
|
513
|
+
if (call === 'preventExtensions')
|
|
514
|
+
return `([&]() { ${expando}->preventExtensions(); return ${receiver}; })()`;
|
|
515
|
+
if (call === 'seal') {
|
|
516
|
+
const fields = generated ? `${receiver}->gea_sealOwnFields(); ${receiver}->gea_sealOwnIndex(); ` : '';
|
|
517
|
+
return (`([&]() { ${fields}const auto __gea_sidecar = ${expando}; ` +
|
|
518
|
+
'for (const auto& __gea_key : __gea_sidecar->ownKeys()) { gea::PropertyDescriptor __gea_update; __gea_update.hasConfigurable = true; __gea_update.configurable = false; ' +
|
|
519
|
+
'if (!__gea_sidecar->defineOwnProperty(__gea_key, __gea_update)) gea::host::throwRuntimeError("TypeError", "Cannot seal native own property"); } ' +
|
|
520
|
+
`__gea_sidecar->preventExtensions(); return ${receiver}; })()`);
|
|
521
|
+
}
|
|
522
|
+
const fields = generated ? `if (!${receiver}->gea_ownFieldsSealed() || !${receiver}->gea_ownIndexSealed()) return false; ` : '';
|
|
523
|
+
return (`([&]() -> bool { ${fields}const auto __gea_sidecar = gea::detail::expandoFor(gea::refCastToVoid(${receiver}), false); ` +
|
|
524
|
+
'if (!__gea_sidecar || __gea_sidecar->extensible()) return false; for (const auto& __gea_key : __gea_sidecar->ownKeys()) { ' +
|
|
525
|
+
'const gea::PropertyDescriptor* __gea_descriptor = __gea_sidecar->ownProperty(__gea_key); if (__gea_descriptor != nullptr && __gea_descriptor->configurable) return false; } return true; })()');
|
|
526
|
+
}
|
|
527
|
+
return refuseObjectCarrier(member, view.representation, 'an integrity level needs a stable object identity; this carrier is held by value, so no identity-keyed native ' +
|
|
528
|
+
'sidecar can preserve the state across aliases');
|
|
529
|
+
};
|
|
530
|
+
/**
|
|
531
|
+
* `Object.getPrototypeOf(o)` -- the target's own `[[Prototype]]` slot
|
|
532
|
+
* (ECMA-262 20.1.2.9), for the one receiver shape that actually HAS one at
|
|
533
|
+
* runtime: a value the program declared `any`/`unknown`, whose own
|
|
534
|
+
* `gea::DynamicObject` already carries and honours a real `[[Prototype]]`
|
|
535
|
+
* link (`instanceof`/`in` already walk it). A statically typed receiver --
|
|
536
|
+
* a record, a class instance -- has no such slot this backend models at all
|
|
537
|
+
* (this compiler's classes carry no runtime prototype chain, per this file's
|
|
538
|
+
* own header comment), so those refuse by name rather than fabricating
|
|
539
|
+
* `null` or `Object.prototype`.
|
|
540
|
+
*/
|
|
541
|
+
const getPrototypeOfText = (ctx, operation) => {
|
|
542
|
+
const member = 'getPrototypeOf';
|
|
543
|
+
const view = objectViewOf(ctx, member, targetOf(ctx, member, operation), 'object');
|
|
544
|
+
if (view.kind === 'dynamic')
|
|
545
|
+
return `gea::host::ObjectConstructor::getPrototypeOf(${view.receiver})`;
|
|
546
|
+
if (view.kind === 'dictionary') {
|
|
547
|
+
return refuseDictionaryArm(member, view, 'a native Dictionary carries no [[Prototype]] slot this backend models');
|
|
548
|
+
}
|
|
549
|
+
return refuseObjectCarrier(member, view.representation, 'this backend gives no statically typed carrier a runtime [[Prototype]] slot -- only a value the program itself ' +
|
|
550
|
+
'declared dynamic carries one');
|
|
551
|
+
};
|
|
552
|
+
/**
|
|
553
|
+
* `Object.hasOwn(array, key)` for an Array exotic receiver -- its own
|
|
554
|
+
* dedicated arm for the same reason `keysText` has one: an Array's own keys
|
|
555
|
+
* are never a `RecordField` list `objectViewOf` could hand back, they are its
|
|
556
|
+
* indices, `length`, and whatever the extended interface (`raw`) declares.
|
|
557
|
+
*
|
|
558
|
+
* Only a spelled-constant key answers: an index and `length` are exactly the
|
|
559
|
+
* facts `arrayOwnPropertyNames` above already enumerates, checked here
|
|
560
|
+
* directly rather than by building and scanning that list. `array->present`
|
|
561
|
+
* is the same presence bit that distinguishes a `pushUndefined`-installed
|
|
562
|
+
* cooked slot (present, valued `undefined`) from a hole -- ECMA-262's
|
|
563
|
+
* invalid-escape cooked value is a real own property, not an absence, and
|
|
564
|
+
* this has to agree with `Object.keys`/`getOwnPropertyNames` about that or
|
|
565
|
+
* the two would disagree over the one array they both read.
|
|
566
|
+
*/
|
|
567
|
+
const arrayHasOwnText = (ctx, array, receiver, key) => {
|
|
568
|
+
const spelled = ctx.staticKeyTexts.get(key.value);
|
|
569
|
+
if (spelled === undefined) {
|
|
570
|
+
return refuseObjectCarrier('hasOwn', array, "the key is not a constant this program spells, so the answer is a search over the array's own index/length/extension " +
|
|
571
|
+
'keys, which is not installed');
|
|
572
|
+
}
|
|
573
|
+
if (spelled === 'length')
|
|
574
|
+
return 'true';
|
|
575
|
+
const extensionField = array.extension?.find((field) => field.key === spelled);
|
|
576
|
+
if (extensionField !== undefined) {
|
|
577
|
+
if (extensionField.required)
|
|
578
|
+
return 'true';
|
|
579
|
+
const struct = cppArrayExtensionStructName(array.extension ?? []);
|
|
580
|
+
return `${receiver}->template extensionFields<${struct}>().${cppRecordFieldPresenceName(extensionField.key)}`;
|
|
581
|
+
}
|
|
582
|
+
const index = canonicalIndexLiteral(spelled);
|
|
583
|
+
if (index === null)
|
|
584
|
+
return 'false';
|
|
585
|
+
return `(static_cast<std::size_t>(${index}) < ${receiver}->size() && ${receiver}->present(${index}))`;
|
|
586
|
+
};
|
|
587
|
+
/**
|
|
588
|
+
* `Object.hasOwn(o, key)` -- membership in primitive 1.
|
|
589
|
+
*
|
|
590
|
+
* With a literal key against a known shape the answer is a compile-time
|
|
591
|
+
* constant, except for an optional field, where it is exactly the presence
|
|
592
|
+
* test primitive 1 already uses to decide whether that key is in the list. A
|
|
593
|
+
* key this program does not spell as a constant refuses: the answer would be
|
|
594
|
+
* a search over the struct's key set, which is what the emitted struct's own
|
|
595
|
+
* `gea_readOwnField` is for, and reaching it needs the receiver boxed.
|
|
596
|
+
*/
|
|
597
|
+
const hasOwnText = (ctx, operation) => {
|
|
598
|
+
const target = targetOf(ctx, 'hasOwn', operation);
|
|
599
|
+
const key = operation.arguments[1];
|
|
600
|
+
if (key === undefined)
|
|
601
|
+
throw createCppEmitBlockedError('host-member-call:Object.hasOwn', '"Object.hasOwn" takes a property key, and this call passes none');
|
|
602
|
+
if (regexpRoleOf(target.representation) === 'pattern') {
|
|
603
|
+
return `gea::nativeDynamicHas(${operandText(ctx, target)}, ${propertyKeyText(ctx, 'hasOwn', key)})`;
|
|
604
|
+
}
|
|
605
|
+
if (target.representation.kind === 'array-object')
|
|
606
|
+
return arrayHasOwnText(ctx, target.representation, operandText(ctx, target), key);
|
|
607
|
+
const view = objectViewOf(ctx, 'hasOwn', target, 'object');
|
|
608
|
+
if (view.kind === 'dynamic')
|
|
609
|
+
return `gea::host::ObjectConstructor::hasOwn(${view.receiver}, ${propertyKeyText(ctx, 'hasOwn', key)})`;
|
|
610
|
+
if (view.kind === 'dictionary') {
|
|
611
|
+
// A dictionary answers membership itself, and for ANY key rather than only
|
|
612
|
+
// a constant one: `has` is the table's own lookup, which is what
|
|
613
|
+
// `HasOwnProperty` over an ordinary object with no prototype means.
|
|
614
|
+
//
|
|
615
|
+
// A number-keyed table's OWN Representation.kind is never literally
|
|
616
|
+
// `'number'` -- there is no such carrier kind, a JS number is `scalar`
|
|
617
|
+
// with `domain: 'number'` -- so it is matched by domain instead of by the
|
|
618
|
+
// string/symbol carriers' direct kind equality below.
|
|
619
|
+
const matches = view.representation.key === 'number'
|
|
620
|
+
? key.representation.kind === 'scalar' && key.representation.domain === 'number'
|
|
621
|
+
: key.representation.kind === view.representation.key;
|
|
622
|
+
if (!matches) {
|
|
623
|
+
return refuseDictionaryArm('hasOwn', view, `the key carries "${representationKey(key.representation)}" rather than the table's "${view.representation.key}" key domain`);
|
|
624
|
+
}
|
|
625
|
+
return `${view.receiver}.has(${operandText(ctx, key)})`;
|
|
626
|
+
}
|
|
627
|
+
// A claim, not a fold: this decides whether the key is a name this backend
|
|
628
|
+
// can resolve at compile time or must refuse below, so it must not see a
|
|
629
|
+
// key text `constantTexts` only holds because the render minted it (e.g. a
|
|
630
|
+
// folded `typeof` result reaching here as the tested key).
|
|
631
|
+
const spelled = ctx.staticKeyTexts.get(key.value);
|
|
632
|
+
if (spelled === undefined) {
|
|
633
|
+
return refuseObjectCarrier('hasOwn', view.representation, "the key is not a constant this program spells, so the answer is a search over the struct's own key set -- which " +
|
|
634
|
+
'its `gea_readOwnField` dispatcher performs, and reaching that needs the receiver to be the dynamic value it is not');
|
|
635
|
+
}
|
|
636
|
+
const field = view.fields.find((candidate) => candidate.key === spelled);
|
|
637
|
+
if (field === undefined)
|
|
638
|
+
return 'false';
|
|
639
|
+
return ownKeyPresenceText('hasOwn', view, field) ?? 'true';
|
|
640
|
+
};
|
|
641
|
+
/**
|
|
642
|
+
* A Math-shaped host method, materialized as a genuine captureless callable
|
|
643
|
+
* VALUE rather than called -- for `getOwnPropertyDescriptor`'s own `.value`,
|
|
644
|
+
* ECMA-262's declared `any` position (6.1.7.1), one of the four boundaries
|
|
645
|
+
* where boxing is the correct carrier rather than the forbidden shortcut.
|
|
646
|
+
*
|
|
647
|
+
* The ABI is SYNTHESIZED rather than read off any declared signature, because
|
|
648
|
+
* `HostMember`'s own `'method'` row states only a spelling and an arity, not
|
|
649
|
+
* C++ parameter/result types -- and every intrinsic this arm reaches today
|
|
650
|
+
* (`Math`'s own methods) really is `(number...) -> number`, the assumption
|
|
651
|
+
* `gea_runtime.h`'s whole `Math` namespace and every one of its
|
|
652
|
+
* `host-members.ts` rows already bakes in. A future protocol whose methods
|
|
653
|
+
* are NOT all-double would need real per-member ABI data threaded through
|
|
654
|
+
* `HostIntrinsicMember` -- this does not invent one, and would produce C++
|
|
655
|
+
* that fails to compile for such a member rather than a silently wrong value,
|
|
656
|
+
* which `hostFunctionValueText` returning `null` for an unbuilt shape already
|
|
657
|
+
* guarantees.
|
|
658
|
+
*/
|
|
659
|
+
const mathShapedHostMethodValueText = (arity, spelling) => {
|
|
660
|
+
const parameter = { kind: 'scalar', domain: 'number' };
|
|
661
|
+
const abi = {
|
|
662
|
+
parameters: Array.from({ length: arity }, () => ({
|
|
663
|
+
value: parameter,
|
|
664
|
+
ownership: 'owned',
|
|
665
|
+
passing: passingOf(parameter, 'owned')
|
|
666
|
+
})),
|
|
667
|
+
result: parameter,
|
|
668
|
+
receiver: null,
|
|
669
|
+
restFrom: null
|
|
670
|
+
};
|
|
671
|
+
return hostFunctionValueText({ kind: 'function-value-dispatch', abi }, { kind: 'path', text: spelling });
|
|
672
|
+
};
|
|
673
|
+
/**
|
|
674
|
+
* `Math.max`/`Math.min`/`Math.hypot` are the one exception `mathShapedHostMethodValueText`'s
|
|
675
|
+
* own comment already flags as unbuilt: ECMA-262 declares each with a REST
|
|
676
|
+
* parameter (`...values: number[]`), so `requiredArityOf` (host-protocols.ts)
|
|
677
|
+
* correctly counts zero REQUIRED params -- but `gea_runtime.h` implements all
|
|
678
|
+
* three as `gea::CallableObject<double(gea::Ref<gea::ArrayObject<double>>)>`
|
|
679
|
+
* (`Math::max`/`min`/`hypot`, gea_runtime.h), one PACKED-ARRAY parameter, not
|
|
680
|
+
* zero scalar ones. A zero-arity all-double wrapper compiles clean (nothing
|
|
681
|
+
* checks a `CallableObject`'s signature against `arity` at build time) and
|
|
682
|
+
* then fails to LINK the moment C++ actually resolves the call inside it --
|
|
683
|
+
* `max_invoke`/`min_invoke`/`hypot_invoke` all take exactly one
|
|
684
|
+
* `Ref<ArrayObject<double>>`, so `gea::host::Math::max()` (zero args) has no
|
|
685
|
+
* overload. Named by protocol member rather than inferred from a signature
|
|
686
|
+
* shape, for the same reason `mathShapedHostMethodValueText` does not invent
|
|
687
|
+
* one: this is the one contained special case, not a general rule.
|
|
688
|
+
*/
|
|
689
|
+
const mathPackedRestMethods = new Set(['max', 'min', 'hypot']);
|
|
690
|
+
const mathPackedRestHostMethodValueText = (spelling) => {
|
|
691
|
+
const element = { kind: 'scalar', domain: 'number' };
|
|
692
|
+
const parameter = { kind: 'array-object', element, ownership: 'shared-refcount', extension: null };
|
|
693
|
+
const abi = {
|
|
694
|
+
// `ownership` here is the ABI's own passing-mode override
|
|
695
|
+
// (`cppAbiParameterType`, `types.ts`), separate from `parameter`'s own
|
|
696
|
+
// representation ownership -- the real runtime signature takes a
|
|
697
|
+
// `gea::Ref<gea::ArrayObject<double>>` (gea_runtime.h's own
|
|
698
|
+
// `max`/`min`/`hypot` `CallableObject`), so this must match that
|
|
699
|
+
// shared-refcount passing mode, not fall to `cppTypeOf`'s bare-value
|
|
700
|
+
// default for `'owned'`.
|
|
701
|
+
parameters: [{ value: parameter, ownership: 'shared-refcount', passing: passingOf(parameter, 'shared-refcount') }],
|
|
702
|
+
result: element,
|
|
703
|
+
receiver: null,
|
|
704
|
+
restFrom: null
|
|
705
|
+
};
|
|
706
|
+
return hostFunctionValueText({ kind: 'function-value-dispatch', abi }, { kind: 'path', text: spelling });
|
|
707
|
+
};
|
|
708
|
+
/**
|
|
709
|
+
* The shared machinery `nativeHandleDescriptorText` and
|
|
710
|
+
* `arrayObjectDescriptorText` both need: build the
|
|
711
|
+
* `Object.getOwnPropertyDescriptor` result DIRECTLY in whatever record shape
|
|
712
|
+
* the checker published for the call (`operation.result.representation` --
|
|
713
|
+
* TS's own ambient `PropertyDescriptor | undefined`), rather than a native
|
|
714
|
+
* `Descriptor` handle. Nothing converts a native record into the checker's
|
|
715
|
+
* chosen shape (`hostResultText`, `emit-host-arity.ts`, only crosses
|
|
716
|
+
* array/typed-array carriers), so building the wrong type here is a link
|
|
717
|
+
* error, not a runtime one.
|
|
718
|
+
*
|
|
719
|
+
* A `record`/`record-with-index` carries its own `fields` inline; a
|
|
720
|
+
* `native-record-ref` names a shape and goes through `recordFieldsOfShape`
|
|
721
|
+
* instead, the same authority `knownDescriptorText` and
|
|
722
|
+
* `cppRecordDeclarations` both read from (`records.ts`'s own header comment
|
|
723
|
+
* on `recordFieldsOfShape`) -- so this is never a second, independently
|
|
724
|
+
* drifting opinion about the descriptor's own layout.
|
|
725
|
+
*
|
|
726
|
+
* `aggregateOf`'s designated-init pattern mirrors `knownDescriptorText`'s
|
|
727
|
+
* own a few lines below: every field not explicitly named defaults to its
|
|
728
|
+
* declared type's own default (`gea::Optional<T>()` is absent, matching "no
|
|
729
|
+
* accessor" for `get`/`set`, and "no id yet" for whichever `writable` /
|
|
730
|
+
* `enumerable` / `configurable` field is not among the three passed).
|
|
731
|
+
*/
|
|
732
|
+
const descriptorAggregateBuilder = (ctx, resultRepresentation, contextLabel) => {
|
|
733
|
+
const optional = resultRepresentation.kind === 'optional' ? resultRepresentation : null;
|
|
734
|
+
const recordRepresentation = optional ? optional.payload : resultRepresentation;
|
|
735
|
+
const structNameAndFields = (() => {
|
|
736
|
+
if (recordRepresentation.kind === 'record' || recordRepresentation.kind === 'record-with-index') {
|
|
737
|
+
return {
|
|
738
|
+
structName: cppRecordStructName(recordRepresentation.shapeId),
|
|
739
|
+
fields: recordRepresentation.fields,
|
|
740
|
+
ownership: recordRepresentation.ownership
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
if (recordRepresentation.kind === 'native-record-ref') {
|
|
744
|
+
const fields = recordFieldsOfShape(ctx.deriver, recordRepresentation.shapeId);
|
|
745
|
+
if (fields === null)
|
|
746
|
+
return null;
|
|
747
|
+
return {
|
|
748
|
+
structName: recordRepresentation.native ?? cppRecordStructName(recordRepresentation.shapeId),
|
|
749
|
+
fields,
|
|
750
|
+
ownership: recordRepresentation.ownership
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
return null;
|
|
754
|
+
})();
|
|
755
|
+
if (structNameAndFields === null) {
|
|
756
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', `${contextLabel} builds the descriptor as a native record, and the call's own published result is carried as ` +
|
|
757
|
+
`"${representationKey(recordRepresentation)}" instead`);
|
|
758
|
+
}
|
|
759
|
+
const { structName, fields, ownership } = structNameAndFields;
|
|
760
|
+
const resultType = cppTypeOf(resultRepresentation);
|
|
761
|
+
const someText = (aggregate) => (optional ? `${resultType}(${aggregate})` : aggregate);
|
|
762
|
+
const absentText = () => {
|
|
763
|
+
if (optional === null) {
|
|
764
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', `${contextLabel} whose result is not optional has no way to answer an absent key`);
|
|
765
|
+
}
|
|
766
|
+
return `${resultType}()`;
|
|
767
|
+
};
|
|
768
|
+
// `records.ts`'s own struct-emission comment: presence bits follow every
|
|
769
|
+
// value/index member "so existing aggregate initializers keep their
|
|
770
|
+
// positional field layout; the conversion emitters that construct an
|
|
771
|
+
// optional shape set these trailing bits explicitly after construction."
|
|
772
|
+
// A field this arm actually populates (`value`/`writable`/`enumerable`/
|
|
773
|
+
// `configurable` for a real descriptor) is meaningless without ALSO
|
|
774
|
+
// setting its presence bit -- `d.value` and every other optional-field
|
|
775
|
+
// read the emitter builds gates through `gea_present_<field>` before ever
|
|
776
|
+
// looking at the value member (`emit-properties.ts`'s finite-record read),
|
|
777
|
+
// so leaving it at its `= false` default answers `undefined` regardless of
|
|
778
|
+
// what the value member holds. `present` states, per field key, the
|
|
779
|
+
// boolean EXPRESSION its presence bit should hold (usually the literal
|
|
780
|
+
// `'true'`, but a genuinely dynamic descriptor -- `dynamicDescriptorConversionText`
|
|
781
|
+
// -- mirrors the native `Descriptor`'s own `hasX` flags instead).
|
|
782
|
+
const aggregateOf = (overrides, present) => {
|
|
783
|
+
const fieldsText = fields
|
|
784
|
+
.map((field) => `.${cppRecordFieldName(field.key)} = ${overrides[field.key] ?? `${cppTypeOf(field.value)}()`}`)
|
|
785
|
+
.join(', ');
|
|
786
|
+
const aggregate = `${structName}{${fieldsText}}`;
|
|
787
|
+
const built = ownership === 'shared-refcount' ? `gea::makeRef<${structName}>(${aggregate})` : aggregate;
|
|
788
|
+
// A field this record marks `required` was never given a presence bit at
|
|
789
|
+
// all (`records.ts`'s own struct emission: `if (!field.required) ... bool
|
|
790
|
+
// gea_present_<key>`), which is exactly the case for a descriptor whose
|
|
791
|
+
// attributes are ALWAYS fully known -- an array's own "length", or a user
|
|
792
|
+
// function's "name"/"length" -- so gate on the field's own required-ness,
|
|
793
|
+
// not merely on whether `present` names it (every caller here states all
|
|
794
|
+
// four keys in `present` unconditionally; a struct with no such member
|
|
795
|
+
// would otherwise fail to compile, "no member named gea_present_<key>").
|
|
796
|
+
const presentKeys = fields.filter((field) => present[field.key] !== undefined).map((field) => field.key);
|
|
797
|
+
if (presentKeys.length === 0)
|
|
798
|
+
return built;
|
|
799
|
+
const accessor = ownership === 'shared-refcount' ? '->' : '.';
|
|
800
|
+
// `__gea_record`, not `__gea_desc`: the sidecar reader below binds
|
|
801
|
+
// `const gea::PropertyDescriptor* __gea_desc` in the enclosing lambda and
|
|
802
|
+
// then builds this record FROM it, so a same-named local here would shadow
|
|
803
|
+
// the source inside its own initializer -- clang refuses "variable declared
|
|
804
|
+
// with deduced type 'auto' cannot appear in its own initializer", which is
|
|
805
|
+
// exactly how composed-field-descriptor.runtime.js failed to compile.
|
|
806
|
+
const statements = presentKeys.map((key) => `__gea_record${accessor}${cppRecordFieldPresenceName(key)} = ${present[key]};`).join(' ');
|
|
807
|
+
return `([&]() { auto __gea_record = ${built}; ${statements} return __gea_record; })()`;
|
|
808
|
+
};
|
|
809
|
+
// The record's own `value` field carries whatever `objectDescriptorReturnTypeAt`
|
|
810
|
+
// minted for the WHOLE call site -- a union across receivers when one call
|
|
811
|
+
// (`describe`'s runtime key) reaches more than one arm here. A single arm's
|
|
812
|
+
// own value text (a bare `double` cast, a boxed `gea::Value`, ...) carries a
|
|
813
|
+
// narrower type than that union, so it must widen through the same
|
|
814
|
+
// conversion `knownDescriptorText` already uses for its own "value" field,
|
|
815
|
+
// rather than an implicit struct-literal conversion clang has none for.
|
|
816
|
+
const valueField = fields.find((field) => field.key === 'value');
|
|
817
|
+
const valueFieldRepresentation = valueField?.value ?? null;
|
|
818
|
+
// An attribute read back off a runtime `gea::PropertyDescriptor` (a
|
|
819
|
+
// sidecar's own property) is a `bool` plus its presence flag. The record it
|
|
820
|
+
// lands in spells the attribute either way: the ambient `PropertyDescriptor`
|
|
821
|
+
// declares `writable?: boolean` (an `optional`, absent when the flag is
|
|
822
|
+
// off), while the record `objectDescriptorReturnTypeAt` mints for an array
|
|
823
|
+
// or object literal receiver declares it a required `boolean`. Only the
|
|
824
|
+
// field's own carrier says which, so the spelling is read from it.
|
|
825
|
+
const attributeText = (key, has, value) => {
|
|
826
|
+
const field = fields.find((candidate) => candidate.key === key);
|
|
827
|
+
if (field === undefined || field.value.kind !== 'optional')
|
|
828
|
+
return value;
|
|
829
|
+
const type = cppTypeOf(field.value);
|
|
830
|
+
return `(${has} ? ${type}(${value}) : ${type}())`;
|
|
831
|
+
};
|
|
832
|
+
const convertValueField = (source, text) => {
|
|
833
|
+
if (valueFieldRepresentation === null) {
|
|
834
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', `${contextLabel} descriptor names no "value" field to store into`);
|
|
835
|
+
}
|
|
836
|
+
if (representationKey(source) === representationKey(valueFieldRepresentation))
|
|
837
|
+
return text;
|
|
838
|
+
const converted = alignedValueText(ctx, 'host/emit-host-object.ts:853', source, valueFieldRepresentation, text);
|
|
839
|
+
if (converted === null) {
|
|
840
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', `${contextLabel} would store "${representationKey(source)}" into the descriptor's own "value" field carried as ` +
|
|
841
|
+
`"${representationKey(valueFieldRepresentation)}", and no installed conversion performs that`);
|
|
842
|
+
}
|
|
843
|
+
return converted;
|
|
844
|
+
};
|
|
845
|
+
return { resultType, someText, absentText, aggregateOf, convertValueField, attributeText, valueFieldRepresentation };
|
|
846
|
+
};
|
|
847
|
+
export const intrinsicMemberValueOf = (ctx, protocol, found, site) => {
|
|
848
|
+
const host = hostMemberOf(ctx.hosts.members, protocol, found.name);
|
|
849
|
+
if (found.kind === 'value') {
|
|
850
|
+
if (host?.kind !== 'property' || host.emit === null) {
|
|
851
|
+
throw createCppEmitBlockedError(`host-invocation:${protocol}.${found.name}`, `${site}: "${protocol}.${found.name}" is a reflectable data member with no host property row to read its value from`);
|
|
852
|
+
}
|
|
853
|
+
return {
|
|
854
|
+
value: `gea::Value::box(gea::Value::Tag::Number, static_cast<double>(${host.emit}))`,
|
|
855
|
+
writable: false,
|
|
856
|
+
enumerable: false,
|
|
857
|
+
configurable: false
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
if (host === undefined && protocol.endsWith('.prototype')) {
|
|
861
|
+
const callable = hostPrototypeMethodValueText('void()', protocol, found.name, hostIntrinsicLengthOf(protocol, found.name, found.arity));
|
|
862
|
+
return { value: `gea::Value::box(gea::Value::Tag::Function, ${callable})`, writable: true, enumerable: false, configurable: true };
|
|
863
|
+
}
|
|
864
|
+
const emit = host?.kind === 'property' ? host.emit : host?.kind === 'method' ? host.emit : null;
|
|
865
|
+
if (emit === null) {
|
|
866
|
+
throw createCppEmitBlockedError(`host-invocation:${protocol}.${found.name}`, `${site}: "${protocol}.${found.name}" is a reflectable method with no host row stating a callable spelling to build a value from`);
|
|
867
|
+
}
|
|
868
|
+
const arity = host?.kind === 'method' && typeof host.arity === 'number' ? host.arity : (found.arity ?? 0);
|
|
869
|
+
const callable = protocol === 'Math' && mathPackedRestMethods.has(found.name)
|
|
870
|
+
? mathPackedRestHostMethodValueText(emit)
|
|
871
|
+
: mathShapedHostMethodValueText(arity, emit);
|
|
872
|
+
if (callable === null) {
|
|
873
|
+
throw createCppEmitBlockedError(`host-invocation:${protocol}.${found.name}`, `${site}: "${protocol}.${found.name}" has no callable-value rendering for its own value`);
|
|
874
|
+
}
|
|
875
|
+
return { value: `gea::Value::box(gea::Value::Tag::Function, ${callable})`, writable: true, enumerable: false, configurable: true };
|
|
876
|
+
};
|
|
877
|
+
const nativeHandleDescriptorText = (ctx, protocol, key, operation) => {
|
|
878
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
879
|
+
if (resultRepresentation === null) {
|
|
880
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', `"Object.getOwnPropertyDescriptor" of "${protocol}" published no result to build a descriptor into`);
|
|
881
|
+
}
|
|
882
|
+
const { resultType, someText, absentText, aggregateOf, attributeText, convertValueField } = descriptorAggregateBuilder(ctx, resultRepresentation, `"Object.getOwnPropertyDescriptor" of "${protocol}"`);
|
|
883
|
+
const absent = absentText();
|
|
884
|
+
// Every value here is a box (a member's own boxed value, or the sidecar's
|
|
885
|
+
// stored one); the published `value` field may be the union of the
|
|
886
|
+
// intrinsic's member types with a boxed remainder, so each is converted
|
|
887
|
+
// into the field's own carrier rather than assigned as a bare `gea::Value`.
|
|
888
|
+
const boxed = (text) => convertValueField(dynamicCarrier, text);
|
|
889
|
+
const descriptorOf = (found) => {
|
|
890
|
+
const member = intrinsicMemberValueOf(ctx, protocol, found, `"Object.getOwnPropertyDescriptor" of "${protocol}"`);
|
|
891
|
+
return someText(aggregateOf({
|
|
892
|
+
value: boxed(member.value),
|
|
893
|
+
writable: String(member.writable),
|
|
894
|
+
enumerable: String(member.enumerable),
|
|
895
|
+
configurable: String(member.configurable)
|
|
896
|
+
}, { value: 'true', writable: 'true', enumerable: 'true', configurable: 'true' }));
|
|
897
|
+
};
|
|
898
|
+
const members = ctx.hosts.intrinsicMembers.get(protocol) ?? [];
|
|
899
|
+
const site = `"Object.getOwnPropertyDescriptor" of "${protocol}"`;
|
|
900
|
+
// A claim, not a fold: this decides whether a non-configurable member folds
|
|
901
|
+
// to a compile-time descriptor below or falls through to the sidecar/switch
|
|
902
|
+
// dispatch, so it must not see a key text `constantTexts` only holds because
|
|
903
|
+
// the render minted it (e.g. a folded `typeof` result reaching here as the key).
|
|
904
|
+
const spelled = ctx.staticKeyTexts.get(key.value);
|
|
905
|
+
const named = spelled === undefined ? undefined : members.find((candidate) => candidate.name === spelled);
|
|
906
|
+
// A non-configurable, non-writable member is the one own property nothing
|
|
907
|
+
// can change, so its descriptor folds at compile time. Every other key is
|
|
908
|
+
// asked of the intrinsic's dynamic-property sidecar first: a member
|
|
909
|
+
// `delete`d through a runtime key is absent, and one overridden (or a key
|
|
910
|
+
// `Object.defineProperty` added) answers with the descriptor the sidecar
|
|
911
|
+
// holds -- `hasOwnProperty` (`object-protocol.ts`) consults the same table
|
|
912
|
+
// in the same order, so the two never disagree about membership.
|
|
913
|
+
if (named !== undefined) {
|
|
914
|
+
const fixed = intrinsicMemberValueOf(ctx, protocol, named, site);
|
|
915
|
+
if (!fixed.configurable && !fixed.writable)
|
|
916
|
+
return descriptorOf(named);
|
|
917
|
+
}
|
|
918
|
+
if (members.length === 0)
|
|
919
|
+
return absent;
|
|
920
|
+
const sidecarDescriptor = someText(aggregateOf({
|
|
921
|
+
value: boxed('__gea_own.value'),
|
|
922
|
+
writable: attributeText('writable', '__gea_own.hasWritable', '__gea_own.writable'),
|
|
923
|
+
enumerable: attributeText('enumerable', '__gea_own.hasEnumerable', '__gea_own.enumerable'),
|
|
924
|
+
configurable: attributeText('configurable', '__gea_own.hasConfigurable', '__gea_own.configurable')
|
|
925
|
+
}, {
|
|
926
|
+
value: '__gea_own.hasValue',
|
|
927
|
+
writable: '__gea_own.hasWritable',
|
|
928
|
+
enumerable: '__gea_own.hasEnumerable',
|
|
929
|
+
configurable: '__gea_own.hasConfigurable'
|
|
930
|
+
}));
|
|
931
|
+
const arms = members
|
|
932
|
+
.map((candidate) => `if (__gea_name == ${cppStringLiteral(candidate.name)}) return ${descriptorOf(candidate)};`)
|
|
933
|
+
.join(' ');
|
|
934
|
+
return (`([&]() -> ${resultType} { const gea::PropertyKey __gea_key = ${propertyKeyOperandText(ctx, key, site)}; ` +
|
|
935
|
+
`auto& __gea_side = gea::detail::hostIntrinsicSidecar(${cppStringLiteral(protocol)}); ` +
|
|
936
|
+
`{ gea::PropertyDescriptor __gea_own; if (__gea_side.ownDescriptor(__gea_key, __gea_own)) return ${sidecarDescriptor}; } ` +
|
|
937
|
+
`if (__gea_side.isRemoved(__gea_key) || __gea_key.isSymbol()) return ${absent}; ` +
|
|
938
|
+
`const std::string& __gea_name = __gea_key.text(); ${arms} return ${absent}; })()`);
|
|
939
|
+
};
|
|
940
|
+
/**
|
|
941
|
+
* The descriptor an `array-object` receiver answers with -- built the same
|
|
942
|
+
* way `nativeHandleDescriptorText` builds its own, directly into whatever
|
|
943
|
+
* record shape the checker published for this call rather than a native
|
|
944
|
+
* `Descriptor` handle (see that function's own header comment for why).
|
|
945
|
+
*
|
|
946
|
+
* The TRUE intrinsic own-property set of an Array instance (ECMA-262
|
|
947
|
+
* 10.4.1) is its numeric indices and its own `length`. `join`, `push`, and
|
|
948
|
+
* every other `Array.prototype` member are inherited, never an array
|
|
949
|
+
* INSTANCE's own property. Additional own properties installed through the
|
|
950
|
+
* native identity sidecar (notably GetTemplateObject's non-enumerable `raw`)
|
|
951
|
+
* are read from that same sidecar rather than being guessed absent.
|
|
952
|
+
*
|
|
953
|
+
* `Array.prototype` uses the same native array carrier. Its own method
|
|
954
|
+
* descriptors are installed on its stable identity sidecar, so this lookup
|
|
955
|
+
* also serves the intrinsic without guessing its origin from a source name.
|
|
956
|
+
*
|
|
957
|
+
* A canonical index literal (`arr[0]`, `arr.getOwnPropertyDescriptor(arr,
|
|
958
|
+
* "0")`) answers a REAL data descriptor -- ECMA-262 10.4.1: `{writable: true,
|
|
959
|
+
* enumerable: true, configurable: true}` -- guarded at runtime by
|
|
960
|
+
* `ArrayObject::hasElement`, the exact presence test `elementAt` aborts on the
|
|
961
|
+
* negation of (`emit-carrier-members.ts`'s own `absentCapableElementText`
|
|
962
|
+
* uses the same pair for an ordinary `arr[i]` read), so "present" can never
|
|
963
|
+
* drift between an ordinary element read and this descriptor. A runtime key
|
|
964
|
+
* goes through the runtime's one canonical Array-index parser before the
|
|
965
|
+
* identity sidecar fallback, so `"0"`, `"length"`, `"raw"`, and an absent
|
|
966
|
+
* string key all observe the same own-property set as their literal forms.
|
|
967
|
+
*/
|
|
968
|
+
const arrayObjectDescriptorText = (ctx, receiver, representation, key, operation) => {
|
|
969
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
970
|
+
if (resultRepresentation === null) {
|
|
971
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', '"Object.getOwnPropertyDescriptor" of an array published no result to build a descriptor into');
|
|
972
|
+
}
|
|
973
|
+
const { resultType, someText, absentText, aggregateOf, convertValueField, attributeText, valueFieldRepresentation } = descriptorAggregateBuilder(ctx, resultRepresentation, '"Object.getOwnPropertyDescriptor" of an array');
|
|
974
|
+
const absent = absentText();
|
|
975
|
+
const accessor = memberAccessOperator(representation.ownership);
|
|
976
|
+
const writable = `gea::nativeOwnFieldsWritable(${receiver})`;
|
|
977
|
+
const sidecarDescriptor = () => {
|
|
978
|
+
const aggregate = aggregateOf({
|
|
979
|
+
value: convertValueField({ kind: 'dynamic', reason: 'opt-in-fallback' }, '__gea_native->value'),
|
|
980
|
+
writable: attributeText('writable', '__gea_native->hasWritable', '__gea_native->writable'),
|
|
981
|
+
enumerable: attributeText('enumerable', '__gea_native->hasEnumerable', '__gea_native->enumerable'),
|
|
982
|
+
configurable: attributeText('configurable', '__gea_native->hasConfigurable', '__gea_native->configurable')
|
|
983
|
+
}, {
|
|
984
|
+
value: '__gea_native->hasValue',
|
|
985
|
+
writable: '__gea_native->hasWritable',
|
|
986
|
+
enumerable: '__gea_native->hasEnumerable',
|
|
987
|
+
configurable: '__gea_native->hasConfigurable'
|
|
988
|
+
});
|
|
989
|
+
const call = `gea::nativeOwnPropertyDescriptor(${receiver}, ${propertyKeyText(ctx, 'getOwnPropertyDescriptor', key)})`;
|
|
990
|
+
return (`([&]() -> ${resultType} { const auto __gea_native = ${call}; ` +
|
|
991
|
+
`if (!__gea_native.has_value()) return ${absent}; return ${someText(aggregate)}; })()`);
|
|
992
|
+
};
|
|
993
|
+
const lengthDescriptor = () => {
|
|
994
|
+
// The raw read is always a plain `double` -- `length()`'s own C++ return
|
|
995
|
+
// type -- widened into whatever the descriptor's own "value" field is
|
|
996
|
+
// ACTUALLY carried as for this call (a bare `double` when this is the
|
|
997
|
+
// only arm reaching the call site, a wider union when `describe`'s
|
|
998
|
+
// runtime key also reaches an object/function arm).
|
|
999
|
+
const value = convertValueField({ kind: 'scalar', domain: 'number' }, `static_cast<double>(${receiver}${accessor}length())`);
|
|
1000
|
+
// ECMA-262 10.4.1: an Array's own "length" is {writable: true, enumerable: false, configurable: false}.
|
|
1001
|
+
return someText(aggregateOf({ value, writable, enumerable: 'false', configurable: 'false' }, { value: 'true', writable: 'true', enumerable: 'true', configurable: 'true' }));
|
|
1002
|
+
};
|
|
1003
|
+
// ECMA-262 10.4.1: a numeric index is {writable: true, enumerable: true,
|
|
1004
|
+
// configurable: true} when present, absent (never a partial descriptor)
|
|
1005
|
+
// otherwise -- `hasElement` is the exact presence test `elementAt` aborts
|
|
1006
|
+
// on the negation of, so the guard and the read can never disagree.
|
|
1007
|
+
const indexDescriptor = (index) => {
|
|
1008
|
+
const descriptorWith = (value) => someText(aggregateOf({ value, writable, enumerable: 'true', configurable: writable }, { value: 'true', writable: 'true', enumerable: 'true', configurable: 'true' }));
|
|
1009
|
+
const value = convertValueField(representation.element, `${receiver}${accessor}elementAt(${index})`);
|
|
1010
|
+
// A malformed escape creates a PRESENT index whose value is undefined.
|
|
1011
|
+
// `elementAt` intentionally refuses that value under the checker's
|
|
1012
|
+
// string-only indexed type, so reflection must consult the explicit bit
|
|
1013
|
+
// first and build the descriptor's dynamic value without reading the
|
|
1014
|
+
// placeholder string cell. That bit is only ever set on a template's
|
|
1015
|
+
// raw-strings array; a descriptor whose "value" field cannot hold
|
|
1016
|
+
// `undefined` at all (a `number[]` literal's own minted record) is one
|
|
1017
|
+
// no such array reaches, and the branch is not spelled for it.
|
|
1018
|
+
const undefinedValue = valueFieldRepresentation === null
|
|
1019
|
+
? null
|
|
1020
|
+
: alignedValueText(ctx, 'host/emit-host-object.ts:1145', { kind: 'undefined' }, valueFieldRepresentation, cppUndefinedValue);
|
|
1021
|
+
if (undefinedValue === null)
|
|
1022
|
+
return descriptorWith(value);
|
|
1023
|
+
return `(${receiver}${accessor}elementIsUndefined(static_cast<std::size_t>(${index})) ? ${descriptorWith(undefinedValue)} : ${descriptorWith(value)})`;
|
|
1024
|
+
};
|
|
1025
|
+
// A claim, not a fold: this decides whether the key is "length", a canonical
|
|
1026
|
+
// index, or falls through to the runtime prelude below, so it must not see a
|
|
1027
|
+
// key text `constantTexts` only holds because the render minted it (e.g. a
|
|
1028
|
+
// folded `typeof` result reaching here as the tested key).
|
|
1029
|
+
const spelled = ctx.staticKeyTexts.get(key.value);
|
|
1030
|
+
if (spelled !== undefined) {
|
|
1031
|
+
if (spelled === 'length')
|
|
1032
|
+
return lengthDescriptor();
|
|
1033
|
+
const index = canonicalIndexLiteral(spelled);
|
|
1034
|
+
return index === null ? sidecarDescriptor() : `(${receiver}${accessor}hasElement(${index}) ? ${indexDescriptor(index)} : ${absent})`;
|
|
1035
|
+
}
|
|
1036
|
+
const prelude = stringKeyPreludeText(ctx, key, '"Object.getOwnPropertyDescriptor" of an array', absent);
|
|
1037
|
+
const runtimeIndex = 'static_cast<double>(__gea_index)';
|
|
1038
|
+
return (`([&]() -> ${resultType} { ${prelude} if (__gea_key == "length") return ${lengthDescriptor()}; ` +
|
|
1039
|
+
`std::size_t __gea_index = 0; if (gea::detail::arrayIndexOfKey(gea::PropertyKey::string(__gea_key), __gea_index)) ` +
|
|
1040
|
+
`return ${receiver}${accessor}hasElement(${runtimeIndex}) ? ${indexDescriptor(runtimeIndex)} : ${absent}; ` +
|
|
1041
|
+
`return ${sidecarDescriptor()}; })()`);
|
|
1042
|
+
};
|
|
1043
|
+
/**
|
|
1044
|
+
* `Object.getOwnPropertyDescriptor` over a KNOWN (record, class-instance)
|
|
1045
|
+
* receiver -- the static half `emit-dynamic-properties.ts`'s
|
|
1046
|
+
* `finiteRecordUnionGetText` already renders for an ordinary member read,
|
|
1047
|
+
* adapted to build the four-field descriptor
|
|
1048
|
+
* `objectDescriptorReturnTypeAt` (`normalize/producers/shared.ts`) minted
|
|
1049
|
+
* for THIS call, rather than a bare member value.
|
|
1050
|
+
*
|
|
1051
|
+
* A literal key naming a declared field answers from that field directly,
|
|
1052
|
+
* with the ECMA-262 default data-descriptor attributes a plain object
|
|
1053
|
+
* literal's own property gets (10.1.11: `{writable:true, enumerable:true,
|
|
1054
|
+
* configurable:true}` -- this arm never runs for a key a `defineProperty`
|
|
1055
|
+
* call gave non-default attributes, because such a key names no declared
|
|
1056
|
+
* field and takes the sidecar arm below instead), gated by the field's own
|
|
1057
|
+
* presence bit when the field is declared optional. A runtime key switches
|
|
1058
|
+
* over the receiver's declared fields the same way `finiteRecordUnionGetText`
|
|
1059
|
+
* does for a plain read. A key -- literal or runtime -- naming no declared
|
|
1060
|
+
* field falls through to the object's dynamic-property sidecar, the one
|
|
1061
|
+
* place a key `Object.defineProperty` added after the fact lives, and reads
|
|
1062
|
+
* its `gea::PropertyDescriptor` back field-for-field: that boxed `value` is
|
|
1063
|
+
* the one accepted, bounded exception this feature carries (matching the
|
|
1064
|
+
* sidecar's own storage, `objectDescriptorReturnTypeAt`'s own header), never
|
|
1065
|
+
* a widening of a field this compiler already knows the type of.
|
|
1066
|
+
*/
|
|
1067
|
+
const knownDescriptorText = (ctx, member, view, key, operation) => {
|
|
1068
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
1069
|
+
if (resultRepresentation === null) {
|
|
1070
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" published no result to build a descriptor into`);
|
|
1071
|
+
}
|
|
1072
|
+
const { resultType, someText, absentText, aggregateOf, convertValueField, attributeText } = descriptorAggregateBuilder(ctx, resultRepresentation, `"Object.${member}" of a known receiver`);
|
|
1073
|
+
const aggregateFor = (valueSource, valueText, attributes) => aggregateOf({
|
|
1074
|
+
value: convertValueField(valueSource, valueText),
|
|
1075
|
+
writable: attributeText('writable', 'true', `${attributes}.writable`),
|
|
1076
|
+
enumerable: attributeText('enumerable', 'true', `${attributes}.enumerable`),
|
|
1077
|
+
configurable: attributeText('configurable', 'true', `${attributes}.configurable`)
|
|
1078
|
+
}, { value: 'true', writable: 'true', enumerable: 'true', configurable: 'true' });
|
|
1079
|
+
// `gea::PropertyDescriptor::value` (gea_runtime.h) is a bare `gea::Value` --
|
|
1080
|
+
// ECMA-262's own descriptor stores `value` as `any`, and `Object.defineProperty`
|
|
1081
|
+
// only ever reaches the sidecar for a key with no declared field to type it
|
|
1082
|
+
// from (`definePropertyText`'s "known" arm), so a boxed carrier is this
|
|
1083
|
+
// path's genuinely correct, bounded source.
|
|
1084
|
+
const dynamicValueRepresentation = { kind: 'dynamic', reason: 'declared-any-never-narrowed' };
|
|
1085
|
+
const sidecarText = () => {
|
|
1086
|
+
if (view.accessor !== '->') {
|
|
1087
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a "${representationKey(view.representation)}" carrier has an "owned" receiver; a ` +
|
|
1088
|
+
"dynamic-property sidecar needs the object's own shared identity to key on");
|
|
1089
|
+
}
|
|
1090
|
+
const propertyKey = propertyKeyText(ctx, member, key);
|
|
1091
|
+
const fromDescriptor = aggregateOf({
|
|
1092
|
+
value: convertValueField(dynamicValueRepresentation, '__gea_desc->value'),
|
|
1093
|
+
writable: attributeText('writable', '__gea_desc->hasWritable', '__gea_desc->writable'),
|
|
1094
|
+
enumerable: attributeText('enumerable', '__gea_desc->hasEnumerable', '__gea_desc->enumerable'),
|
|
1095
|
+
configurable: attributeText('configurable', '__gea_desc->hasConfigurable', '__gea_desc->configurable')
|
|
1096
|
+
}, {
|
|
1097
|
+
value: '__gea_desc->hasValue',
|
|
1098
|
+
writable: '__gea_desc->hasWritable',
|
|
1099
|
+
enumerable: '__gea_desc->hasEnumerable',
|
|
1100
|
+
configurable: '__gea_desc->hasConfigurable'
|
|
1101
|
+
});
|
|
1102
|
+
return (`([&]() -> ${resultType} { const auto __gea_expando = gea::detail::expandoFor(gea::refCastToVoid(${view.receiver}), false); ` +
|
|
1103
|
+
`if (!__gea_expando) return ${absentText()}; ` +
|
|
1104
|
+
`const gea::PropertyDescriptor* __gea_desc = __gea_expando->ownProperty(${propertyKey}); ` +
|
|
1105
|
+
`if (__gea_desc == nullptr) return ${absentText()}; ` +
|
|
1106
|
+
`return ${someText(fromDescriptor)}; })()`);
|
|
1107
|
+
};
|
|
1108
|
+
// A claim, not a fold: this decides whether the key names a declared field
|
|
1109
|
+
// below or falls through to the dynamic-property sidecar, so it must not see
|
|
1110
|
+
// a key text `constantTexts` only holds because the render minted it (e.g. a
|
|
1111
|
+
// folded `typeof` result reaching here as the tested key).
|
|
1112
|
+
const literalKey = ctx.staticKeyTexts.get(key.value);
|
|
1113
|
+
if (literalKey !== undefined) {
|
|
1114
|
+
const field = view.fields.find((candidate) => candidate.key === literalKey);
|
|
1115
|
+
if (field === undefined)
|
|
1116
|
+
return sidecarText();
|
|
1117
|
+
const { text, representation: valueSource } = getOwnValue(ctx, view, field);
|
|
1118
|
+
const attributes = `${view.receiver}${view.accessor}${cppRecordFieldAttributesName(field.key)}`;
|
|
1119
|
+
const aggregate = someText(aggregateFor(valueSource, text, attributes));
|
|
1120
|
+
const presence = ownKeyPresenceText(member, view, field);
|
|
1121
|
+
return presence === null ? aggregate : `(${presence} ? ${aggregate} : ${absentText()})`;
|
|
1122
|
+
}
|
|
1123
|
+
if (key.representation.kind !== 'string') {
|
|
1124
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a known receiver received a key carried as "${representationKey(key.representation)}" rather ` +
|
|
1125
|
+
'than a string, and ToPropertyKey of anything else runs ToPrimitive, which this backend does not perform');
|
|
1126
|
+
}
|
|
1127
|
+
const fields = ownKeyFields(view);
|
|
1128
|
+
if (fields.length === 0)
|
|
1129
|
+
return sidecarText();
|
|
1130
|
+
const runtimeKey = operandText(ctx, key);
|
|
1131
|
+
const arms = fields
|
|
1132
|
+
.map((field) => {
|
|
1133
|
+
const { text, representation: valueSource } = getOwnValue(ctx, view, field);
|
|
1134
|
+
const attributes = `${view.receiver}${view.accessor}${cppRecordFieldAttributesName(field.key)}`;
|
|
1135
|
+
const aggregate = someText(aggregateFor(valueSource, text, attributes));
|
|
1136
|
+
const presence = ownKeyPresenceText(member, view, field);
|
|
1137
|
+
const answer = presence === null ? aggregate : `(${presence} ? ${aggregate} : ${absentText()})`;
|
|
1138
|
+
return `if (__gea_key == ${cppStringLiteral(field.key)}) return ${answer};`;
|
|
1139
|
+
})
|
|
1140
|
+
.join(' ');
|
|
1141
|
+
return `([&]() -> ${resultType} { const std::string& __gea_key = ${runtimeKey}; ${arms} return ${sidecarText()}; })()`;
|
|
1142
|
+
};
|
|
1143
|
+
/**
|
|
1144
|
+
* `Object.getOwnPropertyDescriptor` of a genuinely dynamic (boxed
|
|
1145
|
+
* `gea::Value`) receiver -- e.g. `Array.from`, built as a real boxed
|
|
1146
|
+
* function value by `dynamicHostFunctionValueText` because its call-site
|
|
1147
|
+
* arity has no fixed ABI (one of the four sanctioned dynamic boundaries).
|
|
1148
|
+
* The runtime answers with its OWN `gea::Optional<Descriptor>`
|
|
1149
|
+
* (`Descriptor` inherits `PropertyDescriptor`'s real fields, `gea_runtime.h`
|
|
1150
|
+
* ~line 7790) computed at RUNTIME, since a dynamic receiver's own property
|
|
1151
|
+
* set cannot be enumerated statically -- but every arm a single call site
|
|
1152
|
+
* dispatches across (via `describe`'s own unioned parameter, when Math,
|
|
1153
|
+
* Array.prototype AND a dynamic function value all reach the same
|
|
1154
|
+
* `getOwnPropertyDescriptor` call) must share ONE C++ return type, so this
|
|
1155
|
+
* converts that native descriptor into the SAME checker-published record
|
|
1156
|
+
* shape `nativeHandleDescriptorText`/`arrayObjectDescriptorText` build into,
|
|
1157
|
+
* field for field, off `Descriptor`'s own `hasX` presence flags (6.2.6:
|
|
1158
|
+
* "states false" and "states nothing" are different, so a bare `bool` read
|
|
1159
|
+
* would silently invent an attribute the descriptor never claimed).
|
|
1160
|
+
*
|
|
1161
|
+
* `get`/`set` are left at their default absent: converting a native
|
|
1162
|
+
* `std::function` accessor into this record's `Optional<CallableObject<...>>`
|
|
1163
|
+
* field needs a std::function-to-CallableObject bridge this arm does not
|
|
1164
|
+
* build, and no consumer in this probe reads a descriptor's accessors.
|
|
1165
|
+
*/
|
|
1166
|
+
const dynamicDescriptorConversionText = (ctx, member, receiver, key, operation) => {
|
|
1167
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
1168
|
+
if (resultRepresentation === null) {
|
|
1169
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a dynamic receiver published no result to build a descriptor into`);
|
|
1170
|
+
}
|
|
1171
|
+
const { resultType, someText, absentText, aggregateOf, attributeText, convertValueField } = descriptorAggregateBuilder(ctx, resultRepresentation, `"Object.${member}" of a dynamic receiver`);
|
|
1172
|
+
const nativeCall = `gea::host::ObjectConstructor::${member}(${receiver}, ${propertyKeyText(ctx, member, key)})`;
|
|
1173
|
+
const aggregate = aggregateOf({
|
|
1174
|
+
// The runtime's own descriptor keeps `value` boxed (`gea::Value`) even
|
|
1175
|
+
// though the call-site result may have narrowed the field to a typed
|
|
1176
|
+
// carrier -- exactly the widening `nativeHandleDescriptorText`'s `boxed`
|
|
1177
|
+
// helper already performs for a host member's own value. Without this,
|
|
1178
|
+
// an unboxed `gea::Value` reaches a struct literal typed `double` or
|
|
1179
|
+
// `std::string` and clang refuses the initializer outright.
|
|
1180
|
+
value: convertValueField(dynamicCarrier, '__gea_native->value'),
|
|
1181
|
+
writable: attributeText('writable', '__gea_native->hasWritable', '__gea_native->writable'),
|
|
1182
|
+
enumerable: attributeText('enumerable', '__gea_native->hasEnumerable', '__gea_native->enumerable'),
|
|
1183
|
+
configurable: attributeText('configurable', '__gea_native->hasConfigurable', '__gea_native->configurable')
|
|
1184
|
+
}, {
|
|
1185
|
+
value: '__gea_native->hasValue',
|
|
1186
|
+
writable: '__gea_native->hasWritable',
|
|
1187
|
+
enumerable: '__gea_native->hasEnumerable',
|
|
1188
|
+
configurable: '__gea_native->hasConfigurable'
|
|
1189
|
+
});
|
|
1190
|
+
return (`([&]() -> ${resultType} { const auto __gea_native = ${nativeCall}; ` +
|
|
1191
|
+
`if (!__gea_native.has_value()) return ${absentText()}; ` +
|
|
1192
|
+
`return ${someText(aggregate)}; })()`);
|
|
1193
|
+
};
|
|
1194
|
+
/** The same descriptor projection for a native object that keeps its concrete carrier (Pattern's lastIndex is the measured case). */
|
|
1195
|
+
const nativeDescriptorConversionText = (ctx, member, receiver, key, operation) => {
|
|
1196
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
1197
|
+
if (resultRepresentation === null) {
|
|
1198
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a native receiver published no result to build a descriptor into`);
|
|
1199
|
+
}
|
|
1200
|
+
const { resultType, someText, absentText, aggregateOf, attributeText, convertValueField } = descriptorAggregateBuilder(ctx, resultRepresentation, `"Object.${member}" of a native receiver`);
|
|
1201
|
+
const aggregate = aggregateOf({
|
|
1202
|
+
// Same widening `dynamicDescriptorConversionText` performs, for the
|
|
1203
|
+
// identical reason: `gea::nativeOwnPropertyDescriptor` answers with a
|
|
1204
|
+
// boxed `Descriptor` regardless of what typed carrier the call site's
|
|
1205
|
+
// own result narrowed "value" to.
|
|
1206
|
+
value: convertValueField(dynamicCarrier, '__gea_native->value'),
|
|
1207
|
+
writable: attributeText('writable', '__gea_native->hasWritable', '__gea_native->writable'),
|
|
1208
|
+
enumerable: attributeText('enumerable', '__gea_native->hasEnumerable', '__gea_native->enumerable'),
|
|
1209
|
+
configurable: attributeText('configurable', '__gea_native->hasConfigurable', '__gea_native->configurable')
|
|
1210
|
+
}, {
|
|
1211
|
+
value: '__gea_native->hasValue',
|
|
1212
|
+
writable: '__gea_native->hasWritable',
|
|
1213
|
+
enumerable: '__gea_native->hasEnumerable',
|
|
1214
|
+
configurable: '__gea_native->hasConfigurable'
|
|
1215
|
+
});
|
|
1216
|
+
return (`([&]() -> ${resultType} { const auto __gea_native = gea::nativeOwnPropertyDescriptor(${receiver}, ` +
|
|
1217
|
+
`${propertyKeyText(ctx, member, key)}); if (!__gea_native.has_value()) return ${absentText()}; return ${someText(aggregate)}; })()`);
|
|
1218
|
+
};
|
|
1219
|
+
/**
|
|
1220
|
+
* Every native callable carrier whose identity owns an ordinary Function
|
|
1221
|
+
* property table -- including the one that is nothing BUT that identity. A
|
|
1222
|
+
* builtin with no single calling convention (`Array.from`) is carried as
|
|
1223
|
+
* `callable-identity`, and the table a descriptor read walks is the same
|
|
1224
|
+
* table; only the step that reaches it differs, since there is no thunk to
|
|
1225
|
+
* ask for `name`/`length` and no callable to box as the accessor receiver.
|
|
1226
|
+
*/
|
|
1227
|
+
const callableObjectCarrier = (representation) => representation.kind === 'function' ||
|
|
1228
|
+
representation.kind === 'function-family' ||
|
|
1229
|
+
representation.kind === 'function-value-family' ||
|
|
1230
|
+
representation.kind === 'function-value-dispatch' ||
|
|
1231
|
+
representation.kind === 'function-and-constructor' ||
|
|
1232
|
+
representation.kind === 'callable-identity';
|
|
1233
|
+
/**
|
|
1234
|
+
* `Object.getOwnPropertyDescriptor` over a callable's CURRENT identity-owned
|
|
1235
|
+
* property table.
|
|
1236
|
+
*
|
|
1237
|
+
* `name` and `length` begin with their 10.2.10 descriptors, but both are
|
|
1238
|
+
* configurable: delete/redefine must therefore be observed from the table,
|
|
1239
|
+
* not reconstructed from immutable thunk facts. The same lookup also covers
|
|
1240
|
+
* expandos and the non-configurable `prototype` installed for a carrier that
|
|
1241
|
+
* retains both [[Call]] and [[Construct]]. The callable itself never widens to
|
|
1242
|
+
* Value; only a descriptor's language-level `value: any` field is dynamic.
|
|
1243
|
+
*/
|
|
1244
|
+
const callableDescriptorText = (ctx, representation, receiver, key, operation) => {
|
|
1245
|
+
const resultRepresentation = operation.result?.representation ?? null;
|
|
1246
|
+
if (resultRepresentation === null) {
|
|
1247
|
+
throw createCppEmitBlockedError('host-member-call:Object.getOwnPropertyDescriptor', '"Object.getOwnPropertyDescriptor" of a function published no result to build a descriptor into');
|
|
1248
|
+
}
|
|
1249
|
+
const { resultType, someText, absentText, aggregateOf, convertValueField, attributeText } = descriptorAggregateBuilder(ctx, resultRepresentation, '"Object.getOwnPropertyDescriptor" of a function');
|
|
1250
|
+
const dynamic = { kind: 'dynamic', reason: 'declared-any-never-narrowed' };
|
|
1251
|
+
const aggregate = aggregateOf({
|
|
1252
|
+
value: convertValueField(dynamic, '__gea_descriptor->value'),
|
|
1253
|
+
writable: attributeText('writable', '__gea_descriptor->hasWritable', '__gea_descriptor->writable'),
|
|
1254
|
+
enumerable: attributeText('enumerable', '__gea_descriptor->hasEnumerable', '__gea_descriptor->enumerable'),
|
|
1255
|
+
configurable: attributeText('configurable', '__gea_descriptor->hasConfigurable', '__gea_descriptor->configurable')
|
|
1256
|
+
}, {
|
|
1257
|
+
value: '__gea_descriptor->hasValue',
|
|
1258
|
+
writable: '__gea_descriptor->hasWritable',
|
|
1259
|
+
enumerable: '__gea_descriptor->hasEnumerable',
|
|
1260
|
+
configurable: '__gea_descriptor->hasConfigurable'
|
|
1261
|
+
});
|
|
1262
|
+
// The identity half arrives with its facts already installed (the runtime's
|
|
1263
|
+
// `builtinFunctionIdentity` installs them where the object is first made),
|
|
1264
|
+
// and has no thunk to read a `name`/`length` back off, so it walks straight
|
|
1265
|
+
// to the table every other arm reaches through its callable.
|
|
1266
|
+
if (representation.kind === 'callable-identity') {
|
|
1267
|
+
return (`([&]() -> ${resultType} { const auto& __gea_identity = ${receiver}; ` +
|
|
1268
|
+
`const gea::PropertyKey __gea_key = ${propertyKeyOperandText(ctx, key, '"Object.getOwnPropertyDescriptor" of a callable')}; ` +
|
|
1269
|
+
'const gea::PropertyDescriptor* __gea_descriptor = __gea_identity->properties->ownProperty(__gea_key); ' +
|
|
1270
|
+
`if (__gea_descriptor == nullptr) return ${absentText()}; return ${someText(aggregate)}; })()`);
|
|
1271
|
+
}
|
|
1272
|
+
const constructorSetup = representation.kind === 'function-and-constructor'
|
|
1273
|
+
? 'if (!__gea_key.isSymbol() && __gea_key.text() == "prototype") gea::installCallableConstructorPrototype(__gea_callable); '
|
|
1274
|
+
: '';
|
|
1275
|
+
return (`([&]() -> ${resultType} { const auto& __gea_callable = ${receiver}; ` +
|
|
1276
|
+
// A heap-environment callable anchors its identity lazily in its
|
|
1277
|
+
// environment block (`gea_runtime.h`'s `EnvironmentIdentityHeader`), not
|
|
1278
|
+
// in the `functionObject` field itself, so the field is not necessarily
|
|
1279
|
+
// what `functionObjectIdentity()` just resolved -- bind its result
|
|
1280
|
+
// instead of re-reading `functionObject` directly afterward.
|
|
1281
|
+
'const auto& __gea_callable_identity = __gea_callable.functionObjectIdentity(); ' +
|
|
1282
|
+
'gea::installCallableOwnFacts(__gea_callable_identity, __gea_callable.name(), __gea_callable.length()); ' +
|
|
1283
|
+
`const gea::PropertyKey __gea_key = ${propertyKeyOperandText(ctx, key, '"Object.getOwnPropertyDescriptor" of a callable')}; ` +
|
|
1284
|
+
`${constructorSetup}const gea::PropertyDescriptor* __gea_descriptor = ` +
|
|
1285
|
+
`__gea_callable_identity->properties->ownProperty(__gea_key); ` +
|
|
1286
|
+
`if (__gea_descriptor == nullptr) return ${absentText()}; return ${someText(aggregate)}; })()`);
|
|
1287
|
+
};
|
|
1288
|
+
/** Descriptor reflection over one generated typed index entry. */
|
|
1289
|
+
const indexedRecordDescriptorText = (ctx, member, representation, receiver, key, operation) => {
|
|
1290
|
+
const indexedReceiver = indexedRecordReceiver(ctx, member, representation, receiver);
|
|
1291
|
+
if (indexedReceiver === null)
|
|
1292
|
+
return null;
|
|
1293
|
+
return nativeDescriptorConversionText(ctx, member, indexedReceiver, key, operation);
|
|
1294
|
+
};
|
|
1295
|
+
/** `Object.getOwnPropertyDescriptor` -- primitive 2 plus a descriptor this arm does not synthesize. */
|
|
1296
|
+
export const getOwnPropertyDescriptorText = (ctx, operation) => {
|
|
1297
|
+
const member = 'getOwnPropertyDescriptor';
|
|
1298
|
+
const target = targetOf(ctx, member, operation);
|
|
1299
|
+
const key = operation.arguments[1];
|
|
1300
|
+
if (key === undefined)
|
|
1301
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" takes a property key, and this call passes none`);
|
|
1302
|
+
const renderArm = (representation, receiver) => {
|
|
1303
|
+
if (representation.kind === 'array-object')
|
|
1304
|
+
return arrayObjectDescriptorText(ctx, receiver, representation, key, operation);
|
|
1305
|
+
if (representation.kind === 'native-handle') {
|
|
1306
|
+
return nativeHandleDescriptorText(ctx, representation.native ?? representation.protocol, key, operation);
|
|
1307
|
+
}
|
|
1308
|
+
if (callableObjectCarrier(representation))
|
|
1309
|
+
return callableDescriptorText(ctx, representation, receiver, key, operation);
|
|
1310
|
+
if (regexpRoleOf(representation) === 'pattern')
|
|
1311
|
+
return nativeDescriptorConversionText(ctx, member, receiver, key, operation);
|
|
1312
|
+
const indexed = indexedRecordDescriptorText(ctx, member, representation, receiver, key, operation);
|
|
1313
|
+
if (indexed !== null)
|
|
1314
|
+
return indexed;
|
|
1315
|
+
const view = objectViewFrom(ctx, member, representation, receiver, 'object');
|
|
1316
|
+
if (view.kind === 'dynamic')
|
|
1317
|
+
return dynamicDescriptorConversionText(ctx, member, view.receiver, key, operation);
|
|
1318
|
+
if (view.kind === 'dictionary') {
|
|
1319
|
+
return refuseDictionaryArm(member, view, 'what is missing is the same thing the known-shape arm is missing -- minting the `gea::PropertyDescriptor` result, ' +
|
|
1320
|
+
'and the `undefined` a key the table does not hold answers with');
|
|
1321
|
+
}
|
|
1322
|
+
return knownDescriptorText(ctx, member, view, key, operation);
|
|
1323
|
+
};
|
|
1324
|
+
if (target.representation.kind !== 'tagged-union')
|
|
1325
|
+
return renderArm(target.representation, operandText(ctx, target));
|
|
1326
|
+
const receiver = operandText(ctx, target);
|
|
1327
|
+
const arms = target.representation.arms.map((arm, index) => renderArm(arm.value, armAt(receiver, index)));
|
|
1328
|
+
const dispatched = arms.reduceRight((rest, text, index) => (rest === null ? text : `${armIs(receiver, index)} ? ${text} : (${rest})`), null);
|
|
1329
|
+
if (dispatched === null) {
|
|
1330
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"Object.${member}" of a tagged union with no arms has nothing to enumerate`);
|
|
1331
|
+
}
|
|
1332
|
+
return arms.length > 1 ? `(${dispatched})` : dispatched;
|
|
1333
|
+
};
|
|
1334
|
+
/**
|
|
1335
|
+
* `Object.create(proto)`, the one-argument, `proto === null` form only.
|
|
1336
|
+
*
|
|
1337
|
+
* The one member of the ten that is not about an object's properties at all --
|
|
1338
|
+
* it takes a PROTOTYPE, not a target, so it asks no receiver question and
|
|
1339
|
+
* routes through none of the three primitives.
|
|
1340
|
+
*
|
|
1341
|
+
* `gea::Value::object()` (gea_runtime.h) already IS "a fresh ordinary object
|
|
1342
|
+
* with a null `[[Prototype]]`" -- the exact effect 10.1.13's own
|
|
1343
|
+
* OrdinaryObjectCreate has for `Object.create(null)`, since every
|
|
1344
|
+
* `DynamicObject` this runtime constructs starts with a null prototype and
|
|
1345
|
+
* nothing here ever installs a non-null one. So the null-proto call is not an
|
|
1346
|
+
* approximation, it is the operation's own real answer.
|
|
1347
|
+
*
|
|
1348
|
+
* A non-null prototype or a second (`propertiesObject`) argument refuses by
|
|
1349
|
+
* name: a real prototype chain needs `setPrototype` wired to a SOURCE object
|
|
1350
|
+
* this program produced, and a properties object needs the same
|
|
1351
|
+
* `Object.defineProperty`-per-key loop `definePropertyText` already writes --
|
|
1352
|
+
* both real features, neither one this row.
|
|
1353
|
+
*/
|
|
1354
|
+
const createText = (operation) => {
|
|
1355
|
+
const proto = operation.arguments[0];
|
|
1356
|
+
if (proto === undefined) {
|
|
1357
|
+
throw createCppEmitBlockedError('host-member-call:Object.create', '"Object.create" takes a prototype argument, and this call passes none');
|
|
1358
|
+
}
|
|
1359
|
+
if (operation.arguments.length > 1) {
|
|
1360
|
+
throw createCppEmitBlockedError('host-member-call:Object.create', '"Object.create" with a second (properties object) argument is not rendered: it is the same per-key ' +
|
|
1361
|
+
'`Object.defineProperty` loop this file writes for that call, not yet installed for this one');
|
|
1362
|
+
}
|
|
1363
|
+
if (proto.representation.kind !== 'null') {
|
|
1364
|
+
throw createCppEmitBlockedError('host-member-call:Object.create', `"Object.create" was passed a prototype carried as "${representationKey(proto.representation)}"; only the null-` +
|
|
1365
|
+
'prototype form renders, since every dynamic object this runtime builds starts with a null `[[Prototype]]` and ' +
|
|
1366
|
+
'nothing here installs any other one yet');
|
|
1367
|
+
}
|
|
1368
|
+
const result = operation.result?.representation ?? null;
|
|
1369
|
+
// The result's own carrier, whenever the program stated one. 20.1.2.2 makes
|
|
1370
|
+
// this call an OrdinaryObjectCreate with a null prototype and no own
|
|
1371
|
+
// properties -- and an empty `gea::Dictionary<V>` and a value-initialized
|
|
1372
|
+
// record struct are each exactly that object in the carrier the declaration
|
|
1373
|
+
// asked for, not an approximation of it. Boxing first and unboxing at the
|
|
1374
|
+
// store would be the wrong answer twice over: `gea::Value::object()` mints a
|
|
1375
|
+
// `DynamicObject`, so the store's `unboxValue<Ref<Dictionary<V>>>` finds a
|
|
1376
|
+
// payload of a different C++ type and refuses at runtime -- a program that
|
|
1377
|
+
// aborts on its first statement, which is what `const emptyParams: Params =
|
|
1378
|
+
// Object.create(null)` did (hono's pattern router).
|
|
1379
|
+
if (result !== null && (result.kind === 'dictionary' || result.kind === 'record')) {
|
|
1380
|
+
const storage = cppTypeOf(result, 'owned');
|
|
1381
|
+
return result.ownership === 'shared-refcount' ? `gea::makeRef<${storage}>()` : `${storage}{}`;
|
|
1382
|
+
}
|
|
1383
|
+
return 'gea::Value::object()';
|
|
1384
|
+
};
|
|
1385
|
+
/**
|
|
1386
|
+
* `Object.assign(target, source)` -- 7.3.25, which is the three primitives and
|
|
1387
|
+
* nothing else: for each own enumerable key of source, `Set(target, key,
|
|
1388
|
+
* Get(source, key))`.
|
|
1389
|
+
*
|
|
1390
|
+
* The static arm unrolls that loop because its bounds are known, and each
|
|
1391
|
+
* iteration is `setOwnText(target, key, getOwnValue(source, field))` guarded by
|
|
1392
|
+
* `ownKeyPresenceText` -- the guard is the specification's own filter, not an
|
|
1393
|
+
* optimization: an absent optional is NOT an own key, so copying it anyway
|
|
1394
|
+
* would write the absent value over whatever the target already held.
|
|
1395
|
+
*
|
|
1396
|
+
* ## The condition that is `assign`'s own rather than a primitive's
|
|
1397
|
+
*
|
|
1398
|
+
* The RESULT. `Object.assign(a, b)` is typed `T & U` by the checker, an
|
|
1399
|
+
* intersection whose own carrier this compiler derives separately, and a field
|
|
1400
|
+
* copy that did not agree with it would put two answers behind one call. So a
|
|
1401
|
+
* consumed result has to carry the target's own carrier -- which is what the
|
|
1402
|
+
* intersection collapses to when every key of the source has a home in the
|
|
1403
|
+
* target -- and a result carrying anything else refuses rather than being
|
|
1404
|
+
* approximated.
|
|
1405
|
+
*
|
|
1406
|
+
* A `[[Get]]`/`[[Set]]` that runs an accessor is what keeps this arm off any
|
|
1407
|
+
* carrier but a struct's: the primitives render a member read and a member
|
|
1408
|
+
* store, so a source with a getter or a target with a setter is refused by
|
|
1409
|
+
* `setOwnText` naming the accessor rather than copied around it.
|
|
1410
|
+
*/
|
|
1411
|
+
const assignSourceText = (ctx, targetView, sourceView) => {
|
|
1412
|
+
if (targetView.kind === 'dynamic' && sourceView.kind === 'dynamic') {
|
|
1413
|
+
return `gea::host::ObjectConstructor::assign(${targetView.receiver}, ${sourceView.receiver});`;
|
|
1414
|
+
}
|
|
1415
|
+
if (targetView.kind === 'dictionary' && sourceView.kind === 'dictionary') {
|
|
1416
|
+
if (targetView.representation.key !== sourceView.representation.key) {
|
|
1417
|
+
return refuseObjectCarrier('assign', targetView.representation, `a "${sourceView.representation.key}"-keyed dictionary cannot copy its PropertyKeys into a ` +
|
|
1418
|
+
`"${targetView.representation.key}"-keyed target without changing their identity`);
|
|
1419
|
+
}
|
|
1420
|
+
if (targetView.representation.key === 'number') {
|
|
1421
|
+
// `NumericDictionary<V>::assignInto` (gea_runtime.h) takes its
|
|
1422
|
+
// destination as `gea::Dictionary<V2>&`, the SAME string-keyed table a
|
|
1423
|
+
// number-keyed table's own entries live in canonicalized -- there is no
|
|
1424
|
+
// `NumericDictionary<V2>&` overload, so calling it below with a
|
|
1425
|
+
// `NumericDictionary` target would be a C++ type this program never
|
|
1426
|
+
// declared. Own-key enumeration reads that canonicalized table and needs
|
|
1427
|
+
// no such overload (`keysOf`/`valuesOf`/`entriesOf` above); a per-entry
|
|
1428
|
+
// copy INTO one is a real capability nobody has written yet.
|
|
1429
|
+
return refuseDictionaryArm('assign', targetView, 'a number-keyed table has no `assignInto` overload of its own -- only enumerating and reading its canonicalized ' +
|
|
1430
|
+
'keys is written today, not copying entries into one');
|
|
1431
|
+
}
|
|
1432
|
+
const converted = alignedValueText(ctx, 'host/emit-host-object.ts:1639', sourceView.value, targetView.value, '__gea_value');
|
|
1433
|
+
if (converted === null) {
|
|
1434
|
+
return refuseObjectCarrier('assign', targetView.representation, `a dictionary source holds "${representationKey(sourceView.value)}" values while its target holds ` +
|
|
1435
|
+
`"${representationKey(targetView.value)}", and no installed conversion performs that per-entry store`);
|
|
1436
|
+
}
|
|
1437
|
+
// `assignInto` and not `copyInto`: 7.3.25 8.c.ii makes `Object.assign`'s
|
|
1438
|
+
// per-entry step an ordinary `[[Set]]` with Throw, while spread's is
|
|
1439
|
+
// `CreateDataProperty`. The two agreed while no dictionary property could
|
|
1440
|
+
// refuse a write, and this destination is a table the program already
|
|
1441
|
+
// has -- unlike spread's, which is one being built.
|
|
1442
|
+
return (`if (!${sourceView.receiver}.assignInto(${targetView.receiver}, ` +
|
|
1443
|
+
`[](const ${cppTypeOf(sourceView.value)}& __gea_value) { return ${converted}; })) ` +
|
|
1444
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot assign to read only property");');
|
|
1445
|
+
}
|
|
1446
|
+
if (targetView.kind === 'dictionary' && sourceView.kind === 'known') {
|
|
1447
|
+
if (targetView.representation.key === 'symbol') {
|
|
1448
|
+
return refuseDictionaryArm('assign', targetView, 'a statically named source field is a string PropertyKey and cannot be inserted into a symbol-keyed target');
|
|
1449
|
+
}
|
|
1450
|
+
const stores = ownKeyFields(sourceView).map((field) => {
|
|
1451
|
+
const value = getOwnValue(ctx, sourceView, field);
|
|
1452
|
+
const converted = alignedValueText(ctx, 'host/emit-host-object.ts:1660', value.representation, targetView.value, value.text);
|
|
1453
|
+
if (converted === null) {
|
|
1454
|
+
return refuseObjectCarrier('assign', targetView.representation, `the source field "${field.key}" carries "${representationKey(value.representation)}" while the dictionary ` +
|
|
1455
|
+
`target holds "${representationKey(targetView.value)}", and no installed conversion performs that store`);
|
|
1456
|
+
}
|
|
1457
|
+
// 7.3.25 step 8.c.ii is `Set(to, key, value, true)` -- an ordinary
|
|
1458
|
+
// `[[Set]]` with Throw TRUE, so a non-writable destination property is a
|
|
1459
|
+
// TypeError rather than an overwrite. Reachable since a dictionary began
|
|
1460
|
+
// retaining attributes; `operator[]` here would have silently written
|
|
1461
|
+
// through the very flag `Object.defineProperty` installed.
|
|
1462
|
+
const store = `if (!${targetView.receiver}.setProperty(${cppStringLiteral(field.key)}, ${converted})) ` +
|
|
1463
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot assign to read only property");';
|
|
1464
|
+
const presence = ownKeyPresenceText('assign', sourceView, field);
|
|
1465
|
+
return presence === null ? store : `if (${presence}) ${store}`;
|
|
1466
|
+
});
|
|
1467
|
+
return stores.join(' ');
|
|
1468
|
+
}
|
|
1469
|
+
if (targetView.kind === 'dictionary' &&
|
|
1470
|
+
targetView.representation.key === 'string' &&
|
|
1471
|
+
sourceView.kind === 'dynamic' &&
|
|
1472
|
+
targetView.value.kind === 'dynamic') {
|
|
1473
|
+
return `gea::host::ObjectConstructor::assignInto(${targetView.receiver}, ${sourceView.receiver});`;
|
|
1474
|
+
}
|
|
1475
|
+
if (targetView.kind === 'dictionary' || sourceView.kind === 'dictionary') {
|
|
1476
|
+
if (sourceView.kind === 'dictionary' &&
|
|
1477
|
+
// `assignDynamicProperties` (gea_runtime.h) takes its source as
|
|
1478
|
+
// `const gea::Dictionary<gea::Value>&` specifically -- a number-keyed
|
|
1479
|
+
// table's own entries live canonicalized in exactly that container, but
|
|
1480
|
+
// the container itself is `gea::NumericDictionary<V>`, a distinct C++
|
|
1481
|
+
// type with no such overload. Restricting to `key === 'string'` keeps
|
|
1482
|
+
// this arm to the case the runtime function actually accepts.
|
|
1483
|
+
sourceView.representation.key === 'string' &&
|
|
1484
|
+
sourceView.value.kind === 'dynamic' &&
|
|
1485
|
+
targetView.kind === 'known' &&
|
|
1486
|
+
(targetView.representation.kind === 'record' ||
|
|
1487
|
+
targetView.representation.kind === 'native-record-ref' ||
|
|
1488
|
+
targetView.representation.kind === 'class-ref') &&
|
|
1489
|
+
targetView.representation.ownership === 'shared-refcount') {
|
|
1490
|
+
// `Object.assign` returns the target itself. The semantic producer
|
|
1491
|
+
// publishes that identity (rather than TypeScript's descriptive `T & U`
|
|
1492
|
+
// intersection), and the runtime copies each dynamic source entry
|
|
1493
|
+
// through the target struct's field dispatcher or its identity-keyed
|
|
1494
|
+
// expando table. Declared fields and extra keys therefore share the same
|
|
1495
|
+
// [[Set]] path and no typed target is boxed.
|
|
1496
|
+
return `gea::record::assignDynamicProperties(${targetView.receiver}, ${sourceView.receiver});`;
|
|
1497
|
+
}
|
|
1498
|
+
const table = targetView.kind === 'dictionary' ? targetView : sourceView;
|
|
1499
|
+
if (table.kind !== 'dictionary')
|
|
1500
|
+
throw createCppEmitBlockedError('host-member-call:Object.assign', '"Object.assign" reached a dictionary arm with no dictionary side');
|
|
1501
|
+
// Both sides, always. Which arm is missing is decided by the PAIRING, so a
|
|
1502
|
+
// refusal naming only the dictionary half sends a reader to look at the
|
|
1503
|
+
// half that is already fine -- the same complaint this file's header makes
|
|
1504
|
+
// about `assign` refusing "of a class-ref carrier" without saying whether
|
|
1505
|
+
// the class was being enumerated or written into.
|
|
1506
|
+
const describe = (view) => view.kind === 'dynamic' ? 'the dynamic object the runtime walks' : `"${representationKey(view.representation)}"`;
|
|
1507
|
+
return refuseDictionaryArm('assign', table, `this call copies ${describe(sourceView)} into ${describe(targetView)}: a dictionary SOURCE is ` +
|
|
1508
|
+
'`Dictionary::copyInto` (7.3.25 over the creation order it already walks) and a dictionary TARGET is a store per ' +
|
|
1509
|
+
'key -- both real arms, neither written for this pairing');
|
|
1510
|
+
}
|
|
1511
|
+
if (targetView.kind === 'known' &&
|
|
1512
|
+
sourceView.kind === 'dynamic' &&
|
|
1513
|
+
(targetView.representation.kind === 'record' ||
|
|
1514
|
+
targetView.representation.kind === 'native-record-ref' ||
|
|
1515
|
+
targetView.representation.kind === 'class-ref') &&
|
|
1516
|
+
targetView.representation.ownership === 'shared-refcount') {
|
|
1517
|
+
// The source's key set only exists at runtime, while the native target's
|
|
1518
|
+
// generated dispatcher plus expando sidecar is its exact [[Set]]. Bind the
|
|
1519
|
+
// source once because an operand may be a deferred expression, then apply
|
|
1520
|
+
// the same enumerable-string-key loop the dynamic-to-dictionary arm uses.
|
|
1521
|
+
// A declared target field is checked and unboxed by its dispatcher; every
|
|
1522
|
+
// other key stays on the target identity's sidecar.
|
|
1523
|
+
return (`{ const auto& __gea_source = ${sourceView.receiver}; ` +
|
|
1524
|
+
`for (const std::string& __gea_key : __gea_source.ownEnumerableStringKeys()) ` +
|
|
1525
|
+
`gea::nativeDynamicSet(${targetView.receiver}, gea::PropertyKey::string(__gea_key), ` +
|
|
1526
|
+
`__gea_source.getProperty(gea::PropertyKey::string(__gea_key))); }`);
|
|
1527
|
+
}
|
|
1528
|
+
if (targetView.kind === 'dynamic' || sourceView.kind === 'dynamic') {
|
|
1529
|
+
const known = targetView.kind === 'known' ? targetView : sourceView;
|
|
1530
|
+
if (known.kind !== 'known')
|
|
1531
|
+
throw createCppEmitBlockedError('host-member-call:Object.assign', '"Object.assign" reached a mixed arm with no known side');
|
|
1532
|
+
return refuseObjectCarrier('assign', known.representation, 'one side of this copy is the dynamic object the runtime walks and the other is a struct whose keys are known here, ' +
|
|
1533
|
+
"and the two arms render the loop on different sides -- bridging them means walking one object's runtime key " +
|
|
1534
|
+
"table against the other's compile-time one, which is the struct dispatcher's job and not this call's");
|
|
1535
|
+
}
|
|
1536
|
+
const stores = ownKeyFields(sourceView).map((field) => {
|
|
1537
|
+
const store = setOwnText(ctx, 'assign', targetView, field.key, getOwnValue(ctx, sourceView, field));
|
|
1538
|
+
const presence = ownKeyPresenceText('assign', sourceView, field);
|
|
1539
|
+
return presence === null ? store : `if (${presence}) ${store}`;
|
|
1540
|
+
});
|
|
1541
|
+
return stores.join(' ');
|
|
1542
|
+
};
|
|
1543
|
+
/** Copy one source, including the spec's null/undefined skip and a union's live arm. */
|
|
1544
|
+
const assignOperandText = (ctx, targetView, source) => {
|
|
1545
|
+
const representation = source.representation;
|
|
1546
|
+
if (representation.kind === 'null' || representation.kind === 'undefined')
|
|
1547
|
+
return '';
|
|
1548
|
+
if (representation.kind === 'optional') {
|
|
1549
|
+
const receiver = operandText(ctx, source);
|
|
1550
|
+
const payload = objectViewFrom(ctx, 'assign', representation.payload, `(*(${receiver}))`, 'source');
|
|
1551
|
+
return `if ((${receiver}).has_value()) { ${assignSourceText(ctx, targetView, payload)} }`;
|
|
1552
|
+
}
|
|
1553
|
+
if (representation.kind !== 'tagged-union') {
|
|
1554
|
+
return assignSourceText(ctx, targetView, objectViewOf(ctx, 'assign', source, 'source'));
|
|
1555
|
+
}
|
|
1556
|
+
const receiver = operandText(ctx, source);
|
|
1557
|
+
const branches = representation.arms.map((arm, index) => {
|
|
1558
|
+
const body = arm.value.kind === 'null' || arm.value.kind === 'undefined'
|
|
1559
|
+
? ''
|
|
1560
|
+
: assignSourceText(ctx, targetView, objectViewFrom(ctx, 'assign', arm.value, armAt(receiver, index), 'source'));
|
|
1561
|
+
return `${index === 0 ? 'if' : 'else if'} (${armIs(receiver, index)}) { ${body} }`;
|
|
1562
|
+
});
|
|
1563
|
+
return branches.join(' ');
|
|
1564
|
+
};
|
|
1565
|
+
/**
|
|
1566
|
+
* `Object.assign(fn, { ... })` -- the TARGET is a Function object.
|
|
1567
|
+
*
|
|
1568
|
+
* 7.3.25 is the same loop as every other target: for each own enumerable key
|
|
1569
|
+
* of the source, `Set(target, key, Get(source, key))`. What differs is only
|
|
1570
|
+
* where the store lands -- a Function's own properties live on its identity,
|
|
1571
|
+
* which `setOwnCallableText` writes through -- so the source side is read by
|
|
1572
|
+
* the very same `ObjectView` the struct arms use and nothing about enumeration
|
|
1573
|
+
* is duplicated here.
|
|
1574
|
+
*
|
|
1575
|
+
* Only a source whose keys the checker knows is admitted. A dynamic source
|
|
1576
|
+
* would need the runtime key walk the struct arm has (`assignDynamicProperties`
|
|
1577
|
+
* over a `gea::Value` target), and a Function object is not one; that stays
|
|
1578
|
+
* refused by name rather than approximated.
|
|
1579
|
+
*/
|
|
1580
|
+
const assignIntoCallableText = (ctx, operation, target) => {
|
|
1581
|
+
const targetText = operandText(ctx, target);
|
|
1582
|
+
const result = operation.result?.representation;
|
|
1583
|
+
if (result !== undefined && representationKey(result) !== representationKey(target.representation)) {
|
|
1584
|
+
throw createCppEmitBlockedError('host-member-call:Object.assign', `"Object.assign" is typed "T & U" and this call's result carries "${representationKey(result)}", which is not the ` +
|
|
1585
|
+
`Function object target's own "${representationKey(target.representation)}" -- the copy writes into the target and ` +
|
|
1586
|
+
'returns it, so a result carrying anything else is a second answer this renderer may not invent');
|
|
1587
|
+
}
|
|
1588
|
+
const copies = operation.arguments.slice(1).map((source, sourceIndex) => {
|
|
1589
|
+
const sourceView = objectViewOf(ctx, 'assign', source, 'source');
|
|
1590
|
+
if (sourceView.kind !== 'known')
|
|
1591
|
+
return refuseObjectCarrier('assign', source.representation, "the target is a Function object, whose own properties this backend writes one key at a time, and the source's key " +
|
|
1592
|
+
'set is only known at run time -- walking it needs the runtime key loop the struct target has and a Function object ' +
|
|
1593
|
+
'does not');
|
|
1594
|
+
return ownKeyFields(sourceView)
|
|
1595
|
+
.map((field) => {
|
|
1596
|
+
const value = getOwnValue(ctx, sourceView, field);
|
|
1597
|
+
const converted = objectValueConversionText(ctx, operation, 'callable-property', sourceIndex + 1, field.key, value.representation, value.text);
|
|
1598
|
+
const store = setOwnCallableText(targetText, field.key, converted);
|
|
1599
|
+
const presence = ownKeyPresenceText('assign', sourceView, field);
|
|
1600
|
+
return presence === null ? store : `if (${presence}) ${store}`;
|
|
1601
|
+
})
|
|
1602
|
+
.join(' ');
|
|
1603
|
+
});
|
|
1604
|
+
const body = copies.join(' ');
|
|
1605
|
+
if (operation.result === null)
|
|
1606
|
+
return `([&]() { ${body} })()`;
|
|
1607
|
+
return `([&]() { ${body} return ${targetText}; })()`;
|
|
1608
|
+
};
|
|
1609
|
+
const assignText = (ctx, operation) => {
|
|
1610
|
+
const target = targetOf(ctx, 'assign', operation);
|
|
1611
|
+
const targetText = operandText(ctx, target);
|
|
1612
|
+
const sources = operation.arguments.slice(1);
|
|
1613
|
+
if (sources.length === 0)
|
|
1614
|
+
throw createCppEmitBlockedError('host-member-call:Object.assign', '"Object.assign" takes a source object, and this call passes none');
|
|
1615
|
+
if (isNativeCallableCarrier(target.representation.kind))
|
|
1616
|
+
return assignIntoCallableText(ctx, operation, target);
|
|
1617
|
+
const targetView = objectViewOf(ctx, 'assign', target, 'target');
|
|
1618
|
+
if (targetView.kind === 'known') {
|
|
1619
|
+
const result = operation.result?.representation;
|
|
1620
|
+
if (result !== undefined && representationKey(result) !== representationKey(targetView.representation)) {
|
|
1621
|
+
throw createCppEmitBlockedError('host-member-call:Object.assign', `"Object.assign" is typed "T & U" and this call's result carries "${representationKey(result)}", which is not the ` +
|
|
1622
|
+
`target's own "${representationKey(targetView.representation)}" -- the copy writes into the target and returns it, ` +
|
|
1623
|
+
'so a result carrying anything else is a second answer this renderer may not invent');
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
const copies = sources.map((source) => assignOperandText(ctx, targetView, source)).join(' ');
|
|
1627
|
+
if (operation.result === null)
|
|
1628
|
+
return `([&]() { ${copies} })()`;
|
|
1629
|
+
return `([&]() { ${copies} return ${targetText}; })()`;
|
|
1630
|
+
};
|
|
1631
|
+
/**
|
|
1632
|
+
* `Object.defineProperty(target, key, descriptor)`.
|
|
1633
|
+
*
|
|
1634
|
+
* The descriptor argument is where this gets interesting. A program writes it
|
|
1635
|
+
* as an object literal -- `{ value, writable: true, configurable: true,
|
|
1636
|
+
* enumerable: false }` -- and the checker types the parameter
|
|
1637
|
+
* `PropertyDescriptor & ThisType<any>`, so what actually arrives at this call
|
|
1638
|
+
* site is whatever carrier the literal's own type derived. Two shapes are
|
|
1639
|
+
* accepted, and each is spelled from what it is:
|
|
1640
|
+
*
|
|
1641
|
+
* - a `native-handle` on this protocol -- a descriptor the program is passing
|
|
1642
|
+
* THROUGH, the shape `Object.getOwnPropertyDescriptor` hands back. It is
|
|
1643
|
+
* already a `gea::PropertyDescriptor` and passes straight in.
|
|
1644
|
+
* - a `record` -- the object literal, whose fields are read one by one into a
|
|
1645
|
+
* fresh descriptor, each field also SETTING the matching presence flag.
|
|
1646
|
+
* That flag is the whole point: 6.2.6 distinguishes a descriptor that states
|
|
1647
|
+
* `writable: false` from one that says nothing about writability, and a
|
|
1648
|
+
* struct copy that set every field would rewrite attributes the program
|
|
1649
|
+
* never mentioned.
|
|
1650
|
+
*
|
|
1651
|
+
* The ACCESSOR form (`get`/`set` in the literal) is refused by name. The
|
|
1652
|
+
* object model stores accessors as native `std::function`s and invokes them
|
|
1653
|
+
* (`gea::runtime::object::get`), so the model is not the gap -- what is
|
|
1654
|
+
* missing is the conversion from the program's own callable carrier into that
|
|
1655
|
+
* signature, and inventing one that dropped the receiver would make
|
|
1656
|
+
* `get: () => this.x` read the wrong object.
|
|
1657
|
+
*/
|
|
1658
|
+
const defineDescriptorLines = (ctx, operation, descriptor, slot) => descriptorSlotLines(ctx, operation, descriptor.representation, operandText(ctx, descriptor), slot);
|
|
1659
|
+
/**
|
|
1660
|
+
* The descriptor operand of `Object.defineProperty`, in every carrier a
|
|
1661
|
+
* program hands one over as: the host's own `gea::PropertyDescriptor`; an
|
|
1662
|
+
* object literal (a `record`, every stated field present); the record
|
|
1663
|
+
* `Object.getOwnPropertyDescriptor` published (a `native-record-ref` whose
|
|
1664
|
+
* OPTIONAL fields carry a presence bit -- a descriptor read back off an
|
|
1665
|
+
* accessor states no `value`, and `hasValue` must say so rather than copy a
|
|
1666
|
+
* default-constructed one); and an `optional` of that record, which is how
|
|
1667
|
+
* test262's `verifyProperty` holds the descriptor it restores with. The
|
|
1668
|
+
* absent optional is ECMA-262 20.1.2.4 step 3's TypeError
|
|
1669
|
+
* (`ToPropertyDescriptor` of `undefined`), thrown where the language throws it.
|
|
1670
|
+
*/
|
|
1671
|
+
const descriptorSlotLines = (ctx, operation, representation, text, slot) => {
|
|
1672
|
+
if (representation.kind === 'native-handle' && representation.protocol === 'PropertyDescriptor') {
|
|
1673
|
+
return `const gea::PropertyDescriptor& ${slot} = ${text};`;
|
|
1674
|
+
}
|
|
1675
|
+
if (representation.kind === 'optional') {
|
|
1676
|
+
return (`if (!(${text}).has_value()) gea::host::throwRuntimeError("TypeError", "Property description must be an object: ${representation.absence}"); ` +
|
|
1677
|
+
descriptorSlotLines(ctx, operation, representation.payload, `(*${text})`, slot));
|
|
1678
|
+
}
|
|
1679
|
+
const fields = representation.kind === 'record'
|
|
1680
|
+
? representation.fields
|
|
1681
|
+
: representation.kind === 'native-record-ref' && representation.native === null
|
|
1682
|
+
? recordFieldsOfShape(ctx.deriver, representation.shapeId)
|
|
1683
|
+
: null;
|
|
1684
|
+
if (fields === null || (representation.kind !== 'record' && representation.kind !== 'native-record-ref')) {
|
|
1685
|
+
return refuseObjectCarrier('defineProperty', representation, 'a descriptor is either one this program received from Object.getOwnPropertyDescriptor or an object literal whose ' +
|
|
1686
|
+
'fields the checker knows; nothing else states which attributes it means to set');
|
|
1687
|
+
}
|
|
1688
|
+
const accessor = memberAccessOperator(representation.ownership);
|
|
1689
|
+
const assignments = [];
|
|
1690
|
+
const push = (field, assignment) => {
|
|
1691
|
+
assignments.push(field.required ? assignment : `if (${text}${accessor}${cppRecordFieldPresenceName(field.key)}) { ${assignment} }`);
|
|
1692
|
+
};
|
|
1693
|
+
for (const field of fields) {
|
|
1694
|
+
const read = `${text}${accessor}${cppRecordFieldName(field.key)}`;
|
|
1695
|
+
// A field the descriptor record carries as `optional(T, undefined)` -- the
|
|
1696
|
+
// shape `Object.getOwnPropertyDescriptor` publishes for its `value?: any`
|
|
1697
|
+
// and `writable?: boolean` members -- states the attribute exactly when
|
|
1698
|
+
// the optional is present: the presence bit says the field was written,
|
|
1699
|
+
// the optional says it was written with a value rather than `undefined`,
|
|
1700
|
+
// and ECMA-262 6.2.6.5 ToPropertyDescriptor reads an attribute that IS
|
|
1701
|
+
// present but `undefined` as stated-false, which is what the unwrapped
|
|
1702
|
+
// read below yields for the absent optional it never reaches. An object
|
|
1703
|
+
// literal's field is never optional and takes the plain path.
|
|
1704
|
+
const carried = field.value.kind === 'optional' && field.value.absence === 'undefined' ? field.value.payload : field.value;
|
|
1705
|
+
const held = field.value.kind === 'optional' ? `(*${read})` : read;
|
|
1706
|
+
const stated = (assignment) => field.value.kind === 'optional' ? `if ((${read}).has_value()) { ${assignment} }` : assignment;
|
|
1707
|
+
if ((field.key === 'get' || field.key === 'set') && (!field.required || field.value.kind === 'optional')) {
|
|
1708
|
+
// The record `Object.getOwnPropertyDescriptor` publishes declares
|
|
1709
|
+
// `get?`/`set?` beside the data fields, and for every data property --
|
|
1710
|
+
// which is what test262's `verifyProperty` restores -- both are absent.
|
|
1711
|
+
// A PRESENT accessor is the case the compile-time refusal below states,
|
|
1712
|
+
// reached here at runtime rather than at compile time because the same
|
|
1713
|
+
// record carries both kinds; it refuses by name where the language would
|
|
1714
|
+
// have installed the accessor, never installs a data property in its
|
|
1715
|
+
// place. The guards `push`/`stated` wrap this in are exactly the
|
|
1716
|
+
// presence tests, so the throw is dead code for a data descriptor.
|
|
1717
|
+
push(field, stated(`gea::host::throwRuntimeError("TypeError", "Object.defineProperty with an accessor descriptor (${field.key}) is not rendered by this backend");`));
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1720
|
+
// A literal accessor descriptor refuses the same way, at the call rather
|
|
1721
|
+
// than the compile: installing it would have to decide how the receiver
|
|
1722
|
+
// reaches the compiled getter, and a wrong answer reads the wrong object.
|
|
1723
|
+
// `@hono/node-server` installs one only on its TRACE path, so the program
|
|
1724
|
+
// runs and that path throws by name.
|
|
1725
|
+
if (field.key === 'get' || field.key === 'set') {
|
|
1726
|
+
push(field, `gea::host::throwRuntimeError("TypeError", "Object.defineProperty with an accessor descriptor (${field.key}) is not rendered by this backend");`);
|
|
1727
|
+
continue;
|
|
1728
|
+
}
|
|
1729
|
+
if (field.key === 'value') {
|
|
1730
|
+
// A descriptor's `value` is `any` -- ECMAScript's own declaration, and
|
|
1731
|
+
// one of the four boundaries where a box is the correct carrier rather
|
|
1732
|
+
// than a defect. But the LITERAL's field carries whatever the program
|
|
1733
|
+
// wrote (`{ value }` where `value: string` carries `std::string`), so
|
|
1734
|
+
// the widening has to be spelled: `gea::Value` declares no converting
|
|
1735
|
+
// assignment from an arbitrary type, and relying on one would have been
|
|
1736
|
+
// a clang error at every call site rather than a named refusal here.
|
|
1737
|
+
//
|
|
1738
|
+
// A field already carried as `dynamic` assigns straight across -- it is
|
|
1739
|
+
// a `gea::Value` on both sides, and boxing a box would nest two.
|
|
1740
|
+
if (carried.kind === 'dynamic') {
|
|
1741
|
+
push(field, stated(`${slot}.hasValue = true; ${slot}.value = ${held};`));
|
|
1742
|
+
continue;
|
|
1743
|
+
}
|
|
1744
|
+
// The cited conversion retains callable receiver conventions as well as
|
|
1745
|
+
// payload type; the printer never chooses a dynamic box tag here.
|
|
1746
|
+
const boxed = objectValueConversionText(ctx, operation, 'descriptor-value', 2, field.key, carried, held);
|
|
1747
|
+
push(field, stated(`${slot}.hasValue = true; ${slot}.value = ${boxed};`));
|
|
1748
|
+
continue;
|
|
1749
|
+
}
|
|
1750
|
+
if (field.key === 'writable' || field.key === 'enumerable' || field.key === 'configurable') {
|
|
1751
|
+
// The attribute is declared `boolean | undefined`; an optional carrier
|
|
1752
|
+
// was unwrapped above, so what reaches here is the plain boolean or a
|
|
1753
|
+
// carrier this renderer cannot read as one.
|
|
1754
|
+
if (!(carried.kind === 'scalar' && carried.domain === 'boolean')) {
|
|
1755
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', `"Object.defineProperty" was passed a descriptor whose "${field.key}" carries ` +
|
|
1756
|
+
`"${representationKey(carried)}" rather than a plain boolean; a descriptor states an attribute or does not ` +
|
|
1757
|
+
'state it, and an optional-carried attribute would put that fact in two flags at once');
|
|
1758
|
+
}
|
|
1759
|
+
const flag = `has${field.key.charAt(0).toUpperCase()}${field.key.slice(1)}`;
|
|
1760
|
+
push(field, stated(`${slot}.${flag} = true; ${slot}.${field.key} = ${held};`));
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', `"Object.defineProperty" was passed a descriptor with a field "${field.key}", which ECMA-262 6.1.7.1 does not define; ` +
|
|
1764
|
+
'a descriptor field this backend ignored would silently drop what the program asked for');
|
|
1765
|
+
}
|
|
1766
|
+
return `gea::PropertyDescriptor ${slot}; ${assignments.join(' ')}`;
|
|
1767
|
+
};
|
|
1768
|
+
/**
|
|
1769
|
+
* The descriptor's `value`, still in the carrier the program wrote it in.
|
|
1770
|
+
*
|
|
1771
|
+
* A dictionary holds `V`, not `gea::Value`, so the value has to reach it
|
|
1772
|
+
* unboxed -- which the descriptor RECORD cannot supply, because its `value`
|
|
1773
|
+
* field is declared `any` and the allocation has already widened it.
|
|
1774
|
+
* `recordFieldSources` is the emitter's existing record of the literal
|
|
1775
|
+
* operands an object literal was built from, and it is read here for exactly
|
|
1776
|
+
* that: the typed operand behind a widened field.
|
|
1777
|
+
*
|
|
1778
|
+
* The three ATTRIBUTES do not come from here. They come from
|
|
1779
|
+
* `defineDescriptorLines`, the same reader the callable and known-receiver
|
|
1780
|
+
* arms use, so a descriptor states an attribute one way in this backend
|
|
1781
|
+
* rather than one way per receiver kind.
|
|
1782
|
+
*/
|
|
1783
|
+
const dictionaryDefinePropertyValue = (ctx, descriptor) => {
|
|
1784
|
+
if (descriptor.representation.kind !== 'record') {
|
|
1785
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', `"Object.defineProperty" on a dictionary requires an object-literal descriptor whose \`value\` operand is still typed, ` +
|
|
1786
|
+
`but this descriptor carries "${representationKey(descriptor.representation)}" rather than a record`);
|
|
1787
|
+
}
|
|
1788
|
+
const value = ctx.recordFieldSources.get(descriptor.value)?.get('value');
|
|
1789
|
+
if (value === undefined) {
|
|
1790
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', '"Object.defineProperty" on a dictionary needs the descriptor\'s own `value` operand, and this descriptor either ' +
|
|
1791
|
+
'states no `value` or is not the object literal whose fields were recorded before allocation widened them');
|
|
1792
|
+
}
|
|
1793
|
+
return value;
|
|
1794
|
+
};
|
|
1795
|
+
/**
|
|
1796
|
+
* `Object.defineProperty` -- primitive 3 plus the attributes that make it not
|
|
1797
|
+
* a plain store.
|
|
1798
|
+
*
|
|
1799
|
+
* The static arm refuses, and the reason is the member's own semantics rather
|
|
1800
|
+
* than anything about the carrier: 6.2.5.6 defaults every unstated attribute
|
|
1801
|
+
* to FALSE, so `Object.defineProperty(o, 'k', { value: 1 })` installs a
|
|
1802
|
+
* non-writable, non-enumerable, non-configurable property. Primitive 3 renders
|
|
1803
|
+
* a struct member store, which is a writable, enumerable, configurable data
|
|
1804
|
+
* property -- the exact opposite -- so routing this through it would install a
|
|
1805
|
+
* property with three attributes the program did not ask for.
|
|
1806
|
+
*/
|
|
1807
|
+
/**
|
|
1808
|
+
* `Object.defineProperty` aimed at a namespace-shaped host intrinsic (`Math`):
|
|
1809
|
+
* the fourth reflection operation test262's `verifyProperty` performs on one,
|
|
1810
|
+
* restoring a member with the descriptor it read. A non-configurable member
|
|
1811
|
+
* (every 21.3.1 constant) is validated at runtime by
|
|
1812
|
+
* `gea::detail::hostIntrinsicRedefineFixed` -- the one admitted redefinition
|
|
1813
|
+
* is the identical one, anything else is the TypeError 10.1.6.3 specifies --
|
|
1814
|
+
* and every other key defines into the same per-protocol sidecar the computed
|
|
1815
|
+
* get/set/delete consult (`computedNativeHandleGetText`, emit-host-properties.ts,
|
|
1816
|
+
* states the design and its one limit).
|
|
1817
|
+
*/
|
|
1818
|
+
const nativeHandleDefinePropertyText = (ctx, operation, target, key, descriptor) => {
|
|
1819
|
+
const representation = target.representation;
|
|
1820
|
+
if (representation.kind !== 'native-handle' || representation.native !== null)
|
|
1821
|
+
return null;
|
|
1822
|
+
const members = ctx.hosts.intrinsicMembers.get(representation.protocol);
|
|
1823
|
+
if (members === undefined)
|
|
1824
|
+
return null;
|
|
1825
|
+
const { protocol } = representation;
|
|
1826
|
+
const site = `"Object.defineProperty" of "${protocol}"`;
|
|
1827
|
+
const slot = '__gea_descriptor';
|
|
1828
|
+
const targetText = operandText(ctx, target);
|
|
1829
|
+
const arms = members
|
|
1830
|
+
.map((member) => ({ name: member.name, value: intrinsicMemberValueOf(ctx, protocol, member, site) }))
|
|
1831
|
+
.filter((member) => !member.value.configurable)
|
|
1832
|
+
.map((member) => `if (__gea_key == ${cppStringLiteral(member.name)}) { gea::detail::hostIntrinsicRedefineFixed(${cppStringLiteral(member.name)}, ${member.value.value}, ${slot}); return ${targetText}; }`)
|
|
1833
|
+
.join(' ');
|
|
1834
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} const gea::PropertyKey __gea_property_key = ${propertyKeyOperandText(ctx, key, site)}; ` +
|
|
1835
|
+
`if (!__gea_property_key.isSymbol()) { const std::string& __gea_key = __gea_property_key.text(); ${arms} } ` +
|
|
1836
|
+
`gea::detail::hostIntrinsicSidecar(${cppStringLiteral(protocol)}).define(__gea_property_key, ${slot}); return ${targetText}; })()`);
|
|
1837
|
+
};
|
|
1838
|
+
/**
|
|
1839
|
+
* Define one fixed field from a closed data-descriptor record. The value
|
|
1840
|
+
* travels directly from the descriptor record into the field's selected
|
|
1841
|
+
* carrier; only reflective reads ever need the descriptor's dynamic Value
|
|
1842
|
+
* boundary.
|
|
1843
|
+
*
|
|
1844
|
+
* An OPTIONAL field is admitted too. 10.1.6.3 branches on whether the property
|
|
1845
|
+
* is already present -- absent means "create it, and every unstated attribute
|
|
1846
|
+
* defaults to false" (6.2.5.6), present means "validate the redefinition
|
|
1847
|
+
* against the attributes it already has" -- and for an optional field that
|
|
1848
|
+
* presence is a RUNTIME fact, not a compile-time one. It is already carried:
|
|
1849
|
+
* the field's selected carrier is `optional`, whose `has_value()` IS the
|
|
1850
|
+
* presence bit. So the same `exists` argument the required case computes
|
|
1851
|
+
* statically becomes that predicate, and `applyNativeFixedDataDescriptor`'s
|
|
1852
|
+
* two arms are reached exactly as the spec branches. Nothing new has to be
|
|
1853
|
+
* stored, and no second authority learns what "present" means -- the carrier
|
|
1854
|
+
* already answered it.
|
|
1855
|
+
*/
|
|
1856
|
+
const fixedFieldDefinePropertyText = (ctx, view, recipe, descriptor, targetOperand) => {
|
|
1857
|
+
const { field, held } = recipe;
|
|
1858
|
+
const representation = descriptor.representation;
|
|
1859
|
+
if (representation.kind !== 'record' ||
|
|
1860
|
+
recipe.target !== representationKey(targetOperand.representation) ||
|
|
1861
|
+
recipe.descriptor !== representationKey(representation)) {
|
|
1862
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', 'fixed data definition recipe carrier mismatch');
|
|
1863
|
+
}
|
|
1864
|
+
const accessor = memberAccessOperator(representation.ownership);
|
|
1865
|
+
const descriptorText = operandText(ctx, descriptor);
|
|
1866
|
+
const read = (member) => `${descriptorText}${accessor}${cppRecordFieldName(member.key)}`;
|
|
1867
|
+
const node = ctx.conversions.nodeById(recipe.conversion);
|
|
1868
|
+
const incoming = node === null ? null : recipeText(ctx, node, read(recipe.value));
|
|
1869
|
+
if (incoming === null) {
|
|
1870
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', 'fixed data definition conversion has no renderer');
|
|
1871
|
+
}
|
|
1872
|
+
const attribute = (name) => {
|
|
1873
|
+
const member = recipe.attributes.find((candidate) => candidate.key === name);
|
|
1874
|
+
return member === undefined ? ['false', 'false'] : ['true', read(member)];
|
|
1875
|
+
};
|
|
1876
|
+
const [hasWritable, writable] = attribute('writable');
|
|
1877
|
+
const [hasEnumerable, enumerable] = attribute('enumerable');
|
|
1878
|
+
const [hasConfigurable, configurable] = attribute('configurable');
|
|
1879
|
+
const target = view.receiver;
|
|
1880
|
+
const fieldText = `${target}${view.accessor}${cppRecordFieldName(field.key)}`;
|
|
1881
|
+
const attributesText = `${target}${view.accessor}${cppRecordFieldAttributesName(field.key)}`;
|
|
1882
|
+
// A projected C++ field can precede the JavaScript property whose first
|
|
1883
|
+
// definition gives it a value. A real class-field initializer or an earlier
|
|
1884
|
+
// emitted store proves the property already exists; otherwise this call is
|
|
1885
|
+
// its creation and omitted attributes default to false.
|
|
1886
|
+
//
|
|
1887
|
+
// For an OPTIONAL field none of that static reasoning applies or is needed:
|
|
1888
|
+
// the record spends a presence bit precisely so the answer can differ per
|
|
1889
|
+
// execution. Handing the helper a predicate rather than a literal is the
|
|
1890
|
+
// whole of the create-versus-redefine support -- both arms were already
|
|
1891
|
+
// written, only the question was missing.
|
|
1892
|
+
//
|
|
1893
|
+
// The bit to read is `cppRecordFieldPresenceName`, which is what `in`
|
|
1894
|
+
// (emit-in.ts) and `gea_deleteOwnField` already consult -- NOT the payload
|
|
1895
|
+
// `Optional`'s `has_value()`. The two are different questions and this got
|
|
1896
|
+
// written the wrong way round first: `has_value()` asks whether the stored
|
|
1897
|
+
// value is present, the presence bit asks whether the JS PROPERTY exists.
|
|
1898
|
+
// Reading the payload made every define look like a creation, and since
|
|
1899
|
+
// nothing then set the property's own bit, the property never came to exist
|
|
1900
|
+
// at all -- a following `delete` took `gea_deleteOwnField`'s absent-key arm
|
|
1901
|
+
// and returned true instead of throwing on a non-configurable property.
|
|
1902
|
+
// Same class of defect this whole refactor is about: a second authority
|
|
1903
|
+
// answering a question one already owned.
|
|
1904
|
+
const presenceText = `${target}${view.accessor}${cppRecordFieldPresenceName(field.key)}`;
|
|
1905
|
+
const existing = !field.required
|
|
1906
|
+
? presenceText
|
|
1907
|
+
: (() => {
|
|
1908
|
+
if (ctx.recordFieldSources.get(targetOperand.value)?.has(field.key) === true)
|
|
1909
|
+
return 'true';
|
|
1910
|
+
if (view.representation.kind !== 'class-ref')
|
|
1911
|
+
return 'true';
|
|
1912
|
+
const site = classMemberOf(ctx.classes, view.representation.declaration, field.key);
|
|
1913
|
+
if (site?.kind !== 'field')
|
|
1914
|
+
return 'true';
|
|
1915
|
+
const projected = ctx.classes.get(site.owner)?.fields.find((candidate) => candidate.key === field.key);
|
|
1916
|
+
return projected === undefined || projected.initializer !== null ? 'true' : 'false';
|
|
1917
|
+
})();
|
|
1918
|
+
// `convertedValueText` is allowed to spell an authorized implicit widening
|
|
1919
|
+
// as the source text (bare T -> Optional<T>). Materialize the selected field
|
|
1920
|
+
// carrier before template deduction: the runtime helper deliberately takes
|
|
1921
|
+
// one T for both current and incoming values, so it cannot and should not
|
|
1922
|
+
// become a second conversion authority accepting arbitrary C++ sources.
|
|
1923
|
+
const incomingFieldValue = `${cppTypeOf(held)}{${incoming}}`;
|
|
1924
|
+
// A define that CREATES an optional field has to publish the property, or
|
|
1925
|
+
// the value lands in the payload while every other reader -- `in`, `delete`,
|
|
1926
|
+
// `Object.keys`, the descriptor read -- still sees an absent property.
|
|
1927
|
+
const publish = field.required ? '' : ` ${presenceText} = true;`;
|
|
1928
|
+
// `applyNativeFixedDataDescriptor` reads the CURRENT value through
|
|
1929
|
+
// `fieldText` when the field is present, non-configurable and
|
|
1930
|
+
// non-writable (a SameValue check against the incoming value) -- an
|
|
1931
|
+
// un-materialized lazy arrow field would hand it the empty sentinel there
|
|
1932
|
+
// instead of the real callable. `emit-properties.ts`'s
|
|
1933
|
+
// `lazyMaterializedFieldReadText` is the read-side counterpart: `target`
|
|
1934
|
+
// here is already a genuine `gea::Ref<T>` operand (`view.receiver`), not a
|
|
1935
|
+
// `this` pointer inside a const member function, so the call needs no
|
|
1936
|
+
// `Ref::adopt`/`const_cast` recovery the way `records.ts`'s dynamic
|
|
1937
|
+
// dispatcher does -- it can call the initializer thunk with `target`
|
|
1938
|
+
// directly, exactly like that read path calls it with `gea_lazy_receiver`.
|
|
1939
|
+
const lazyOwner = view.representation.kind === 'class-ref' ? classMemberOf(ctx.classes, view.representation.declaration, field.key) : null;
|
|
1940
|
+
const lazyPlan = lazyOwner !== null && lazyOwner.kind === 'field' ? lazyArrowFieldPlanOf(ctx.classes, lazyOwner.owner, field.key) : null;
|
|
1941
|
+
const materialize = lazyPlan !== null ? `if (${fieldText}.invoke == nullptr) { ${fieldText} = ${cppBodyName(lazyPlan.initializer)}(${target}); } ` : '';
|
|
1942
|
+
return (`([&]() { ${materialize}if (!gea::applyNativeFixedDataDescriptor(${fieldText}, ${attributesText}, ${incomingFieldValue}, ${existing}, ` +
|
|
1943
|
+
`${hasWritable}, ${writable}, ${hasEnumerable}, ${enumerable}, ${hasConfigurable}, ${configurable})) ` +
|
|
1944
|
+
`gea::host::throwRuntimeError("TypeError", "Cannot redefine property: ${field.key}");${publish} return ${target}; })()`);
|
|
1945
|
+
};
|
|
1946
|
+
const definePropertyText = (ctx, operation) => {
|
|
1947
|
+
const target = targetOf(ctx, 'defineProperty', operation);
|
|
1948
|
+
const key = operation.arguments[1];
|
|
1949
|
+
const descriptor = operation.arguments[2];
|
|
1950
|
+
if (key === undefined || descriptor === undefined) {
|
|
1951
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', '"Object.defineProperty" takes a target, a key and a descriptor; this call passes fewer');
|
|
1952
|
+
}
|
|
1953
|
+
if (operation.fixedDataDefinition !== undefined) {
|
|
1954
|
+
const view = objectViewOf(ctx, 'defineProperty', target, 'target');
|
|
1955
|
+
if (view.kind !== 'known')
|
|
1956
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', 'fixed data definition requires native storage');
|
|
1957
|
+
return fixedFieldDefinePropertyText(ctx, view, operation.fixedDataDefinition, descriptor, target);
|
|
1958
|
+
}
|
|
1959
|
+
const intrinsic = nativeHandleDefinePropertyText(ctx, operation, target, key, descriptor);
|
|
1960
|
+
if (intrinsic !== null)
|
|
1961
|
+
return intrinsic;
|
|
1962
|
+
// RegExp's `lastIndex` is a native `Value` cell with the real fixed
|
|
1963
|
+
// descriptor, not a generated C++ field. Route it through the native-field
|
|
1964
|
+
// descriptor hook so Object.defineProperty and Object.freeze observe the
|
|
1965
|
+
// same property as static and computed writes.
|
|
1966
|
+
//
|
|
1967
|
+
// A claim, not a fold: this decides whether this dedicated `lastIndex` path
|
|
1968
|
+
// fires at all, so it must not see a key text `constantTexts` only holds
|
|
1969
|
+
// because the render minted it (e.g. a folded `typeof` result reaching here
|
|
1970
|
+
// as the key).
|
|
1971
|
+
if (regexpRoleOf(target.representation) === 'pattern' && ctx.staticKeyTexts.get(key.value) === 'lastIndex') {
|
|
1972
|
+
const slot = '__gea_descriptor';
|
|
1973
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} ` +
|
|
1974
|
+
`if (!gea::nativeDynamicDefineProperty(${operandText(ctx, target)}, ${propertyKeyOperandText(ctx, key, '"Object.defineProperty" of RegExp')}, ${slot})) ` +
|
|
1975
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot redefine RegExp lastIndex"); ' +
|
|
1976
|
+
`return ${operandText(ctx, target)}; })()`);
|
|
1977
|
+
}
|
|
1978
|
+
// Tried before `generatedRecordReceiver` below: that check matches every
|
|
1979
|
+
// shared-refcount record/class/native-record-ref receiver unconditionally,
|
|
1980
|
+
// which used to intercept a defineProperty of a DECLARED field before this
|
|
1981
|
+
// dedicated per-field store ever ran -- see `declaredFixedFieldOf`'s own
|
|
1982
|
+
// comment for why that silently granted three attributes the call withheld.
|
|
1983
|
+
// `key.value`'s constant-ness is asked through `staticKeyTexts`, the same
|
|
1984
|
+
// authority `fixedFieldDefinePropertyText`'s caller below already trusted,
|
|
1985
|
+
// never `constantTexts` (a render-time fold, not something the program wrote).
|
|
1986
|
+
if (key.representation.kind === 'string') {
|
|
1987
|
+
const literalKey = ctx.staticKeyTexts.get(key.value);
|
|
1988
|
+
const fixedField = literalKey === undefined ? null : declaredFixedFieldOf(ctx, target.representation, literalKey);
|
|
1989
|
+
if (fixedField !== null) {
|
|
1990
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', 'fixed data definition has no sealed recipe');
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
const generatedReceiver = generatedRecordReceiver(target.representation, operandText(ctx, target));
|
|
1994
|
+
if (generatedReceiver !== null) {
|
|
1995
|
+
const slot = '__gea_descriptor';
|
|
1996
|
+
const propertyKey = propertyKeyOperandText(ctx, key, '"Object.defineProperty" of a generated record');
|
|
1997
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} ` +
|
|
1998
|
+
`if (!${generatedDefineOwnText(generatedReceiver, propertyKey, slot)}) ` +
|
|
1999
|
+
`gea::host::throwRuntimeError("TypeError", "Cannot define native record property"); ` +
|
|
2000
|
+
`return ${operandText(ctx, target)}; })()`);
|
|
2001
|
+
}
|
|
2002
|
+
if (callableObjectCarrier(target.representation)) {
|
|
2003
|
+
// A callable's own properties live in its one shared function-object
|
|
2004
|
+
// table (`callableDynamicGet`'s); the facts are installed first so a
|
|
2005
|
+
// redefinition of `name`/`length` is checked against the attributes
|
|
2006
|
+
// 10.2.10 gives them rather than against an empty slot.
|
|
2007
|
+
const slot = '__gea_descriptor';
|
|
2008
|
+
const constructorSetup = target.representation.kind === 'function-and-constructor'
|
|
2009
|
+
? 'if (!__gea_key.isSymbol() && __gea_key.text() == "prototype") gea::installCallableConstructorPrototype(__gea_callable); '
|
|
2010
|
+
: '';
|
|
2011
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} const auto& __gea_callable = ${operandText(ctx, target)}; ` +
|
|
2012
|
+
// Same reasoning as `callableDescriptorText`: a heap-environment
|
|
2013
|
+
// callable's identity may be anchored in its environment block rather
|
|
2014
|
+
// than in `functionObject` itself, so bind what `functionObjectIdentity()`
|
|
2015
|
+
// resolved instead of re-reading `functionObject` directly afterward.
|
|
2016
|
+
'const auto& __gea_callable_identity = __gea_callable.functionObjectIdentity(); ' +
|
|
2017
|
+
'gea::installCallableOwnFacts(__gea_callable_identity, __gea_callable.name(), __gea_callable.length()); ' +
|
|
2018
|
+
`const gea::PropertyKey __gea_key = ${propertyKeyOperandText(ctx, key, '"Object.defineProperty" of a callable')}; ${constructorSetup}` +
|
|
2019
|
+
`if (!__gea_callable_identity->properties->defineOwnProperty(__gea_key, ${slot})) ` +
|
|
2020
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot define callable property"); ' +
|
|
2021
|
+
'return __gea_callable; })()');
|
|
2022
|
+
}
|
|
2023
|
+
const view = objectViewOf(ctx, 'defineProperty', target, 'target');
|
|
2024
|
+
if (view.kind === 'dictionary') {
|
|
2025
|
+
if (key.representation.kind !== view.representation.key) {
|
|
2026
|
+
return refuseDictionaryArm('defineProperty', view, `the key carries "${representationKey(key.representation)}" rather than the table's "${view.representation.key}" key domain`);
|
|
2027
|
+
}
|
|
2028
|
+
const value = dictionaryDefinePropertyValue(ctx, descriptor);
|
|
2029
|
+
const raw = operandText(ctx, value);
|
|
2030
|
+
const stored = representationKey(value.representation) === representationKey(view.value)
|
|
2031
|
+
? raw
|
|
2032
|
+
: alignedValueText(ctx, 'host/emit-host-object.ts:2242', value.representation, view.value, raw);
|
|
2033
|
+
if (stored === null) {
|
|
2034
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(value.representation)}->${representationKey(view.value)}`, `"Object.defineProperty" would store "${representationKey(value.representation)}" into a dictionary held as ` +
|
|
2035
|
+
`"${representationKey(view.value)}", and no installed conversion performs that`);
|
|
2036
|
+
}
|
|
2037
|
+
// `[[DefineOwnProperty]]`, not a store. The two differ in three ways a
|
|
2038
|
+
// plain `table[k] = v` cannot express -- the attributes it installs,
|
|
2039
|
+
// 10.1.6.3's refusal to redefine a non-configurable property, and the
|
|
2040
|
+
// TypeError that refusal raises -- and until the table could retain an
|
|
2041
|
+
// attribute this arm proved all three were the ordinary ones and stored.
|
|
2042
|
+
//
|
|
2043
|
+
// The descriptor is read by `defineDescriptorLines`, the same reader the
|
|
2044
|
+
// callable and known-receiver arms use. Only the three attribute FLAGS
|
|
2045
|
+
// are taken from it: a dictionary holds `V`, so the value arrives from
|
|
2046
|
+
// `dictionaryDefinePropertyValue` still typed rather than through the
|
|
2047
|
+
// descriptor's boxed `value` field. `std::optional<bool>` and not a bare
|
|
2048
|
+
// bool because 6.2.5.6 distinguishes an attribute stated false from one
|
|
2049
|
+
// not stated at all, and only the table can complete the second (false on
|
|
2050
|
+
// a new property, unchanged on an existing one).
|
|
2051
|
+
const slot = '__gea_descriptor';
|
|
2052
|
+
const attribute = (name) => `${slot}.has${name.charAt(0).toUpperCase()}${name.slice(1)} ? std::optional<bool>(${slot}.${name}) : std::nullopt`;
|
|
2053
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} ` +
|
|
2054
|
+
`if (!${view.receiver}.definePropertyFrom(${operandText(ctx, key)}, ${stored}, ` +
|
|
2055
|
+
`${attribute('writable')}, ${attribute('enumerable')}, ${attribute('configurable')})) ` +
|
|
2056
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot redefine property"); ' +
|
|
2057
|
+
`return ${operandText(ctx, target)}; })()`);
|
|
2058
|
+
}
|
|
2059
|
+
// A key naming a declared fixed field never reaches here: the early check
|
|
2060
|
+
// above (`declaredFixedFieldOf`) already routed it to
|
|
2061
|
+
// `fixedFieldDefinePropertyText`. A key naming NO declared field is exactly
|
|
2062
|
+
// the shape `knownDescriptorText`'s own sidecar arm reads back
|
|
2063
|
+
// (`Object.getOwnPropertyDescriptor`'s "b" case), so it writes into the
|
|
2064
|
+
// SAME `gea::detail::expandoFor` table that arm reads, via
|
|
2065
|
+
// `gea::nativeDynamicDefineProperty` (gea_runtime.h) -- one sidecar, shared
|
|
2066
|
+
// by both the write and the read, keyed on the object's own identity.
|
|
2067
|
+
if (view.kind === 'known') {
|
|
2068
|
+
if (key.representation.kind !== 'string') {
|
|
2069
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', `"Object.defineProperty" of a known receiver received a key carried as "${representationKey(key.representation)}" rather ` +
|
|
2070
|
+
'than a string, and ToPropertyKey of anything else runs ToPrimitive, which this backend does not perform');
|
|
2071
|
+
}
|
|
2072
|
+
if (view.accessor !== '->') {
|
|
2073
|
+
throw createCppEmitBlockedError('host-member-call:ObjectConstructor.defineProperty', `"Object.defineProperty" of a "${representationKey(view.representation)}" carrier has an "owned" receiver; a ` +
|
|
2074
|
+
"dynamic-property sidecar needs the object's own shared identity to key on");
|
|
2075
|
+
}
|
|
2076
|
+
const slot = '__gea_descriptor';
|
|
2077
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} ` +
|
|
2078
|
+
`if (!gea::nativeDynamicDefineProperty(${view.receiver}, ${propertyKeyText(ctx, 'defineProperty', key)}, ${slot})) ` +
|
|
2079
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot define native property"); ' +
|
|
2080
|
+
`return ${view.receiver}; })()`);
|
|
2081
|
+
}
|
|
2082
|
+
const slot = '__gea_descriptor';
|
|
2083
|
+
return (`([&]() { ${defineDescriptorLines(ctx, operation, descriptor, slot)} ` +
|
|
2084
|
+
`return gea::host::ObjectConstructor::defineProperty(${view.receiver}, ` +
|
|
2085
|
+
`${propertyKeyText(ctx, 'defineProperty', key)}, ${slot}); })()`);
|
|
2086
|
+
};
|
|
2087
|
+
/**
|
|
2088
|
+
* `Object`'s statics, dispatched by member.
|
|
2089
|
+
*
|
|
2090
|
+
* Every member `host-members.ts` claims has an arm here, and every member it
|
|
2091
|
+
* does not claim never reaches this function at all -- `nativeHandleMemberText`
|
|
2092
|
+
* (emit-host-properties.ts) already refused the ACCESS by name. The final
|
|
2093
|
+
* refusal below is therefore for a row that was added to the table without an
|
|
2094
|
+
* arm here, which is a defect in this backend rather than in the program, and
|
|
2095
|
+
* it says so.
|
|
2096
|
+
*/
|
|
2097
|
+
/**
|
|
2098
|
+
* `Object.fromEntries` -- ECMA-262 20.1.2.7.
|
|
2099
|
+
*
|
|
2100
|
+
* The one `Object` static whose SOURCE is an iterable rather than an object, so
|
|
2101
|
+
* it does not go through the three primitives above: there is no own-property
|
|
2102
|
+
* set to enumerate, only entries to walk. What it does with each is primitive 3
|
|
2103
|
+
* (`CreateDataPropertyOrThrow` on a fresh ordinary object), and the fresh
|
|
2104
|
+
* ordinary object is a `gea::Dictionary` -- an insertion-ordered string-keyed
|
|
2105
|
+
* own-property table with no prototype -- so the runtime states the loop once
|
|
2106
|
+
* and this states which sources reach it.
|
|
2107
|
+
*
|
|
2108
|
+
* A `Map` is stated; every other iterable is refused by name. The specification
|
|
2109
|
+
* takes any iterable of entry-like objects, and each other shape this backend
|
|
2110
|
+
* can carry -- an array of pairs, a generator -- has its own iteration
|
|
2111
|
+
* protocol, so reaching a Map overload with one would be a wrong answer rather
|
|
2112
|
+
* than a missing one.
|
|
2113
|
+
*/
|
|
2114
|
+
const fromEntriesText = (ctx, operation) => {
|
|
2115
|
+
const source = targetOf(ctx, 'fromEntries', operation);
|
|
2116
|
+
const representation = source.representation;
|
|
2117
|
+
if (representation.kind !== 'keyed-collection' || representation.family !== 'map') {
|
|
2118
|
+
throw createCppEmitBlockedError('host-member-call:Object.fromEntries', `Object.fromEntries over a "${representationKey(representation)}" source is not rendered: 20.1.2.7 walks any iterable of ` +
|
|
2119
|
+
'entries, and only the Map family has a stated iteration here -- an array of pairs or a generator needs its own');
|
|
2120
|
+
}
|
|
2121
|
+
const text = operandText(ctx, source);
|
|
2122
|
+
// A shared Map carrier is a `gea::Ref<Map<...>>`; the runtime primitive
|
|
2123
|
+
// deliberately consumes the Map itself so its iteration rule is stated
|
|
2124
|
+
// once. Dereference the carrier at this typed boundary rather than adding a
|
|
2125
|
+
// second overload or asking C++ template deduction to see through `Ref`.
|
|
2126
|
+
const entries = representation.ownership === 'shared-refcount' ? `*(${text})` : text;
|
|
2127
|
+
const call = `gea::host::ObjectConstructor::fromEntries(${entries})`;
|
|
2128
|
+
// `Object.fromEntries` is declared to return a dictionary, but a call made
|
|
2129
|
+
// through a genuinely dynamic boundary has a dynamic result cell. The
|
|
2130
|
+
// fresh dictionary is already a reference carrier, so boxing it here keeps
|
|
2131
|
+
// that one object identity while recording the boundary's Object tag.
|
|
2132
|
+
return operation.result?.representation.kind === 'dynamic' ? `gea::Value::box(gea::Value::Tag::Object, ${call})` : call;
|
|
2133
|
+
};
|
|
2134
|
+
/** `Object.is` -- ECMA-262 SameValue over the statically carried operands. */
|
|
2135
|
+
const isText = (ctx, operation) => {
|
|
2136
|
+
const left = operation.arguments[0];
|
|
2137
|
+
const right = operation.arguments[1];
|
|
2138
|
+
if (left === undefined || right === undefined) {
|
|
2139
|
+
throw createCppEmitBlockedError('host-member-call:Object.is', `"Object.is" takes two values, and this call passes ${operation.arguments.length}`);
|
|
2140
|
+
}
|
|
2141
|
+
const leftText = operandText(ctx, left);
|
|
2142
|
+
const rightText = operandText(ctx, right);
|
|
2143
|
+
const leftCarrier = left.representation;
|
|
2144
|
+
const rightCarrier = right.representation;
|
|
2145
|
+
const isNumber = (carrier) => carrier.kind === 'scalar' && carrier.domain !== 'boolean' && carrier.domain !== 'bigint';
|
|
2146
|
+
if (isNumber(leftCarrier) && isNumber(rightCarrier)) {
|
|
2147
|
+
return `gea::sameNumberValue(static_cast<double>(${leftText}), static_cast<double>(${rightText}))`;
|
|
2148
|
+
}
|
|
2149
|
+
if (leftCarrier.kind === 'dynamic' && rightCarrier.kind === 'dynamic') {
|
|
2150
|
+
return `gea::Value::sameValue(${leftText}, ${rightText})`;
|
|
2151
|
+
}
|
|
2152
|
+
if (leftCarrier.kind === 'null' || leftCarrier.kind === 'undefined') {
|
|
2153
|
+
return leftCarrier.kind === rightCarrier.kind ? 'true' : 'false';
|
|
2154
|
+
}
|
|
2155
|
+
if (representationKey(leftCarrier) !== representationKey(rightCarrier))
|
|
2156
|
+
return 'false';
|
|
2157
|
+
if (leftCarrier.kind === 'string' ||
|
|
2158
|
+
leftCarrier.kind === 'symbol' ||
|
|
2159
|
+
leftCarrier.kind === 'scalar' ||
|
|
2160
|
+
leftCarrier.kind === 'array-buffer' ||
|
|
2161
|
+
leftCarrier.kind === 'shared-array-buffer' ||
|
|
2162
|
+
leftCarrier.kind === 'data-view' ||
|
|
2163
|
+
('ownership' in leftCarrier && leftCarrier.ownership === 'shared-refcount')) {
|
|
2164
|
+
return `${leftText} == ${rightText}`;
|
|
2165
|
+
}
|
|
2166
|
+
throw createCppEmitBlockedError('host-member-call:Object.is', `"Object.is" over two "${representationKey(leftCarrier)}" carriers has no SameValue comparison; the backend will not ` +
|
|
2167
|
+
'substitute storage equality for JavaScript value or object identity');
|
|
2168
|
+
};
|
|
2169
|
+
export const objectMemberText = (ctx, member, operation) => {
|
|
2170
|
+
if (member === 'keys' || member === 'getOwnPropertyNames')
|
|
2171
|
+
return keysText(ctx, member, operation);
|
|
2172
|
+
if (member === 'values')
|
|
2173
|
+
return valuesText(ctx, operation);
|
|
2174
|
+
if (member === 'entries')
|
|
2175
|
+
return entriesText(ctx, operation);
|
|
2176
|
+
if (member === 'freeze')
|
|
2177
|
+
return integrityText(ctx, member, operation, 'freeze');
|
|
2178
|
+
if (member === 'isFrozen')
|
|
2179
|
+
return integrityText(ctx, member, operation, 'isFrozen');
|
|
2180
|
+
if (member === 'isExtensible')
|
|
2181
|
+
return integrityText(ctx, member, operation, 'isExtensible');
|
|
2182
|
+
if (member === 'seal')
|
|
2183
|
+
return integrityText(ctx, member, operation, 'seal');
|
|
2184
|
+
if (member === 'isSealed')
|
|
2185
|
+
return integrityText(ctx, member, operation, 'isSealed');
|
|
2186
|
+
if (member === 'preventExtensions')
|
|
2187
|
+
return integrityText(ctx, member, operation, 'preventExtensions');
|
|
2188
|
+
if (member === 'hasOwn')
|
|
2189
|
+
return hasOwnText(ctx, operation);
|
|
2190
|
+
if (member === 'getPrototypeOf')
|
|
2191
|
+
return getPrototypeOfText(ctx, operation);
|
|
2192
|
+
if (member === 'is')
|
|
2193
|
+
return isText(ctx, operation);
|
|
2194
|
+
if (member === 'getOwnPropertyDescriptor')
|
|
2195
|
+
return getOwnPropertyDescriptorText(ctx, operation);
|
|
2196
|
+
if (hostMemberTemplateOf('ObjectConstructor', member) === 'object-assign')
|
|
2197
|
+
return assignText(ctx, operation);
|
|
2198
|
+
if (member === 'fromEntries')
|
|
2199
|
+
return fromEntriesText(ctx, operation);
|
|
2200
|
+
if (member === 'create')
|
|
2201
|
+
return createText(operation);
|
|
2202
|
+
if (member === 'defineProperty')
|
|
2203
|
+
return definePropertyText(ctx, operation);
|
|
2204
|
+
throw createCppEmitBlockedError(`host-member-call:Object.${member}`, `"ObjectConstructor.${member}" is claimed with a call-site spelling in host-members.ts, but this file states no arm ` +
|
|
2205
|
+
'for it -- the row and the renderer have to be added together');
|
|
2206
|
+
};
|