@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,1376 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#pragma once
|
|
3
|
+
#include <cctype>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <unordered_map>
|
|
6
|
+
#include <unordered_set>
|
|
7
|
+
|
|
8
|
+
// Runtime source is parsed once, including unreachable code. Evaluation only
|
|
9
|
+
// walks the resulting tree; consuming tokens must never execute JS effects.
|
|
10
|
+
namespace gea::eval_detail {
|
|
11
|
+
using Args = Ref<ArrayObject<Value>>;
|
|
12
|
+
using Function = CallableObject<Value(Value, Args)>;
|
|
13
|
+
inline Value number(double n) { return Value::box(Value::Tag::Number, n); }
|
|
14
|
+
inline Value string(std::string s) { return Value::box(Value::Tag::String, std::move(s)); }
|
|
15
|
+
inline Value boolean(bool b) { return Value::box(Value::Tag::Boolean, b); }
|
|
16
|
+
[[noreturn]] inline void error(const char* name, const std::string& message) { host::throwRuntimeError(name, message); }
|
|
17
|
+
[[noreturn]] inline void unsupported(const std::string& message) { error("EvalUnsupportedError", message); }
|
|
18
|
+
inline bool truth(const Value& value) { return host::detail::toBoolean(value); }
|
|
19
|
+
inline bool nullish(const Value& value) { return value.tag() == Value::Tag::Null || value.tag() == Value::Tag::Undefined; }
|
|
20
|
+
|
|
21
|
+
struct Token {
|
|
22
|
+
enum Kind { End, Identifier, Number, String, Punctuation } kind = End;
|
|
23
|
+
std::string text;
|
|
24
|
+
std::size_t offset = 0;
|
|
25
|
+
bool newline = false;
|
|
26
|
+
bool escaped = false;
|
|
27
|
+
};
|
|
28
|
+
struct Lexer {
|
|
29
|
+
const std::string& source;
|
|
30
|
+
std::size_t offset = 0;
|
|
31
|
+
static bool start(unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$'; }
|
|
32
|
+
static bool digit(unsigned char c) { return c >= '0' && c <= '9'; }
|
|
33
|
+
static bool part(unsigned char c) { return start(c) || digit(c); }
|
|
34
|
+
[[noreturn]] void syntax(const char* message) const { error("SyntaxError", std::string(message) + " at byte " + std::to_string(offset)); }
|
|
35
|
+
unsigned hex(std::size_t count) {
|
|
36
|
+
unsigned result = 0;
|
|
37
|
+
for (std::size_t i = 0; i < count; ++i) {
|
|
38
|
+
if (offset == source.size()) syntax("Incomplete escape");
|
|
39
|
+
const char c = source[offset++];
|
|
40
|
+
unsigned d = c >= '0' && c <= '9' ? c - '0' : c >= 'a' && c <= 'f' ? c - 'a' + 10 : c >= 'A' && c <= 'F' ? c - 'A' + 10 : 16;
|
|
41
|
+
if (d == 16) syntax("Invalid escape");
|
|
42
|
+
result = result * 16 + d;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
Token next() {
|
|
47
|
+
bool newline = false;
|
|
48
|
+
for (;;) {
|
|
49
|
+
if (offset == source.size()) return {Token::End, "", offset, newline};
|
|
50
|
+
const char c = source[offset];
|
|
51
|
+
if (c == '\n' || c == '\r') {
|
|
52
|
+
newline = true;
|
|
53
|
+
++offset;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (c == ' ' || c == '\t' || c == '\v' || c == '\f') {
|
|
57
|
+
++offset;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (source.compare(offset, 2, "//") == 0) {
|
|
61
|
+
offset += 2;
|
|
62
|
+
while (offset < source.size() && source[offset] != '\n' && source[offset] != '\r') ++offset;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (source.compare(offset, 2, "/*") == 0) {
|
|
66
|
+
offset += 2;
|
|
67
|
+
while (offset < source.size() && source.compare(offset, 2, "*/") != 0) {
|
|
68
|
+
newline = newline || source[offset] == '\n' || source[offset] == '\r';
|
|
69
|
+
++offset;
|
|
70
|
+
}
|
|
71
|
+
if (offset == source.size()) syntax("Unterminated comment");
|
|
72
|
+
offset += 2;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
Token out{Token::Punctuation, "", offset, newline};
|
|
78
|
+
const unsigned char c = source[offset];
|
|
79
|
+
if (start(c)) {
|
|
80
|
+
out.kind = Token::Identifier;
|
|
81
|
+
do {
|
|
82
|
+
out.text += source[offset++];
|
|
83
|
+
} while (offset < source.size() && part(source[offset]));
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
if (digit(c) || (c == '.' && offset + 1 < source.size() && digit(source[offset + 1]))) {
|
|
87
|
+
out.kind = Token::Number;
|
|
88
|
+
const auto begin = offset;
|
|
89
|
+
if (c == '0' && offset + 1 < source.size() && part(source[offset + 1]) && source[offset + 1] != 'e' && source[offset + 1] != 'E')
|
|
90
|
+
unsupported("Non-decimal and legacy numeric literals");
|
|
91
|
+
while (offset < source.size() && digit(source[offset])) ++offset;
|
|
92
|
+
if (offset < source.size() && source[offset] == '.') {
|
|
93
|
+
++offset;
|
|
94
|
+
while (offset < source.size() && digit(source[offset])) ++offset;
|
|
95
|
+
}
|
|
96
|
+
if (offset < source.size() && (source[offset] == 'e' || source[offset] == 'E')) {
|
|
97
|
+
++offset;
|
|
98
|
+
if (offset < source.size() && (source[offset] == '+' || source[offset] == '-')) ++offset;
|
|
99
|
+
if (offset == source.size() || !digit(source[offset])) syntax("Missing exponent digits");
|
|
100
|
+
while (offset < source.size() && digit(source[offset])) ++offset;
|
|
101
|
+
}
|
|
102
|
+
if (offset < source.size() && part(source[offset])) syntax("Invalid numeric literal");
|
|
103
|
+
out.text = source.substr(begin, offset - begin);
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
if (c == '\'' || c == '"') {
|
|
107
|
+
out.kind = Token::String;
|
|
108
|
+
++offset;
|
|
109
|
+
while (offset < source.size() && source[offset] != c) {
|
|
110
|
+
char ch = source[offset++];
|
|
111
|
+
if (ch == '\n' || ch == '\r') syntax("Newline in string");
|
|
112
|
+
if (ch != '\\') {
|
|
113
|
+
out.text += ch;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
out.escaped = true;
|
|
117
|
+
if (offset == source.size()) syntax("Unterminated string");
|
|
118
|
+
ch = source[offset++];
|
|
119
|
+
switch (ch) {
|
|
120
|
+
case '\n':
|
|
121
|
+
break;
|
|
122
|
+
case '\r':
|
|
123
|
+
if (offset < source.size() && source[offset] == '\n') ++offset;
|
|
124
|
+
break;
|
|
125
|
+
case 'n':
|
|
126
|
+
out.text += '\n';
|
|
127
|
+
break;
|
|
128
|
+
case 'r':
|
|
129
|
+
out.text += '\r';
|
|
130
|
+
break;
|
|
131
|
+
case 't':
|
|
132
|
+
out.text += '\t';
|
|
133
|
+
break;
|
|
134
|
+
case 'b':
|
|
135
|
+
out.text += '\b';
|
|
136
|
+
break;
|
|
137
|
+
case 'f':
|
|
138
|
+
out.text += '\f';
|
|
139
|
+
break;
|
|
140
|
+
case 'v':
|
|
141
|
+
out.text += '\v';
|
|
142
|
+
break;
|
|
143
|
+
case 'x':
|
|
144
|
+
runtime::string::appendUtf8CodeUnit(out.text, static_cast<uint16_t>(hex(2)));
|
|
145
|
+
break;
|
|
146
|
+
case 'u':
|
|
147
|
+
if (offset < source.size() && source[offset] == '{') unsupported("Unicode code-point escapes");
|
|
148
|
+
runtime::string::appendUtf8CodeUnit(out.text, static_cast<uint16_t>(hex(4)));
|
|
149
|
+
break;
|
|
150
|
+
case '0':
|
|
151
|
+
if (offset < source.size() && digit(source[offset])) unsupported("Legacy octal escapes");
|
|
152
|
+
out.text += '\0';
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
if (digit(ch)) unsupported("Legacy numeric escapes");
|
|
156
|
+
out.text += ch;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (offset == source.size()) syntax("Unterminated string");
|
|
160
|
+
++offset;
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
if (c >= 128 || c == '\\' || c == '`') unsupported("Unicode identifiers, Unicode whitespace, and template literals");
|
|
164
|
+
for (const char* op : {">>>=",
|
|
165
|
+
"===",
|
|
166
|
+
"!==",
|
|
167
|
+
">>>",
|
|
168
|
+
"**=",
|
|
169
|
+
"&&=",
|
|
170
|
+
"||=",
|
|
171
|
+
"?"
|
|
172
|
+
"?=",
|
|
173
|
+
"<<=",
|
|
174
|
+
">>=",
|
|
175
|
+
"...",
|
|
176
|
+
"=>",
|
|
177
|
+
"?.",
|
|
178
|
+
"==",
|
|
179
|
+
"!=",
|
|
180
|
+
"<=",
|
|
181
|
+
">=",
|
|
182
|
+
"&&",
|
|
183
|
+
"||",
|
|
184
|
+
"??",
|
|
185
|
+
"++",
|
|
186
|
+
"--",
|
|
187
|
+
"+=",
|
|
188
|
+
"-=",
|
|
189
|
+
"*=",
|
|
190
|
+
"/=",
|
|
191
|
+
"%=",
|
|
192
|
+
"<<",
|
|
193
|
+
">>",
|
|
194
|
+
"&=",
|
|
195
|
+
"|=",
|
|
196
|
+
"^=",
|
|
197
|
+
"**"}) {
|
|
198
|
+
const std::string text(op);
|
|
199
|
+
if (source.compare(offset, text.size(), text) == 0) {
|
|
200
|
+
out.text = text;
|
|
201
|
+
offset += text.size();
|
|
202
|
+
return out;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
out.text += source[offset++];
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
struct Node {
|
|
211
|
+
enum Kind {
|
|
212
|
+
Literal,
|
|
213
|
+
Name,
|
|
214
|
+
This,
|
|
215
|
+
Unary,
|
|
216
|
+
Binary,
|
|
217
|
+
Conditional,
|
|
218
|
+
Assign,
|
|
219
|
+
Update,
|
|
220
|
+
Member,
|
|
221
|
+
Call,
|
|
222
|
+
Construct,
|
|
223
|
+
Array,
|
|
224
|
+
Object,
|
|
225
|
+
FunctionExpr,
|
|
226
|
+
Empty,
|
|
227
|
+
Expression,
|
|
228
|
+
Block,
|
|
229
|
+
Declaration,
|
|
230
|
+
Return,
|
|
231
|
+
If,
|
|
232
|
+
While,
|
|
233
|
+
For,
|
|
234
|
+
Break,
|
|
235
|
+
Continue,
|
|
236
|
+
Throw
|
|
237
|
+
} kind;
|
|
238
|
+
std::string text;
|
|
239
|
+
Value value;
|
|
240
|
+
std::vector<std::shared_ptr<Node>> children;
|
|
241
|
+
std::vector<std::string> names;
|
|
242
|
+
bool flag = false;
|
|
243
|
+
bool strict = false;
|
|
244
|
+
bool grouped = false;
|
|
245
|
+
unsigned depth = 1;
|
|
246
|
+
explicit Node(Kind kind_) : kind(kind_) {}
|
|
247
|
+
};
|
|
248
|
+
using Tree = std::shared_ptr<Node>;
|
|
249
|
+
inline Tree node(Node::Kind kind, std::string text = {}, std::vector<Tree> children = {}) {
|
|
250
|
+
auto out = std::make_shared<Node>(kind);
|
|
251
|
+
out->text = std::move(text);
|
|
252
|
+
out->children = std::move(children);
|
|
253
|
+
for (const auto& child : out->children) out->depth = std::max(out->depth, child->depth + 1);
|
|
254
|
+
if (out->depth > 256) unsupported("Eval syntax tree depth exceeds 256");
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
257
|
+
inline Tree literal(Value value) {
|
|
258
|
+
auto out = node(Node::Literal);
|
|
259
|
+
out->value = std::move(value);
|
|
260
|
+
return out;
|
|
261
|
+
}
|
|
262
|
+
inline bool reserved(const std::string& name) {
|
|
263
|
+
static const std::unordered_set<std::string> words = {
|
|
264
|
+
"break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else", "enum",
|
|
265
|
+
"export", "extends", "false", "finally", "for", "function", "if", "import", "in", "instanceof", "let", "new",
|
|
266
|
+
"null", "return", "super", "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while",
|
|
267
|
+
"with", "yield", "await", "implements", "interface", "package", "private", "protected", "public", "static"};
|
|
268
|
+
return words.count(name) != 0;
|
|
269
|
+
}
|
|
270
|
+
struct Parser {
|
|
271
|
+
Lexer lexer;
|
|
272
|
+
Token token;
|
|
273
|
+
bool functionBody;
|
|
274
|
+
bool strict = false;
|
|
275
|
+
unsigned loops = 0;
|
|
276
|
+
unsigned depth = 0;
|
|
277
|
+
struct Depth {
|
|
278
|
+
Parser& parser;
|
|
279
|
+
explicit Depth(Parser& p) : parser(p) {
|
|
280
|
+
if (++parser.depth > 256) unsupported("Source nesting exceeds Eval's parser limit");
|
|
281
|
+
}
|
|
282
|
+
~Depth() { --parser.depth; }
|
|
283
|
+
};
|
|
284
|
+
Parser(const std::string& source, bool function) : lexer{source}, functionBody(function) {
|
|
285
|
+
if (source.size() > 65536) unsupported("Eval source exceeds 64 KiB limit");
|
|
286
|
+
token = lexer.next();
|
|
287
|
+
}
|
|
288
|
+
[[noreturn]] void syntax(const std::string& text) { error("SyntaxError", text + " at byte " + std::to_string(token.offset)); }
|
|
289
|
+
bool is(const char* text) const { return token.kind != Token::String && token.text == text; }
|
|
290
|
+
void advance() { token = lexer.next(); }
|
|
291
|
+
bool eat(const char* text) {
|
|
292
|
+
if (!is(text)) return false;
|
|
293
|
+
advance();
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
void expect(const char* text) {
|
|
297
|
+
if (!eat(text)) syntax(std::string("Expected '") + text + "'");
|
|
298
|
+
}
|
|
299
|
+
std::string identifier() {
|
|
300
|
+
if (token.kind != Token::Identifier || reserved(token.text)) syntax("Expected binding identifier");
|
|
301
|
+
auto out = token.text;
|
|
302
|
+
if (out == "eval" || out == "arguments") unsupported("Bindings named eval or arguments");
|
|
303
|
+
advance();
|
|
304
|
+
return out;
|
|
305
|
+
}
|
|
306
|
+
void semi() {
|
|
307
|
+
if (!eat(";") && !is("}") && token.kind != Token::End && !token.newline) syntax("Expected semicolon");
|
|
308
|
+
}
|
|
309
|
+
static bool target(const Tree& tree) { return tree->kind == Node::Name || tree->kind == Node::Member; }
|
|
310
|
+
Tree body(bool brace) {
|
|
311
|
+
auto out = node(Node::Block);
|
|
312
|
+
bool directives = true;
|
|
313
|
+
while (token.kind != Token::End && !(brace && is("}"))) {
|
|
314
|
+
const bool strictDirective = directives && token.kind == Token::String && token.text == "use strict" && !token.escaped;
|
|
315
|
+
auto stmt = statement();
|
|
316
|
+
if (strictDirective && stmt->kind == Node::Expression && stmt->children[0]->kind == Node::Literal && !stmt->children[0]->grouped)
|
|
317
|
+
strict = true;
|
|
318
|
+
directives = directives && stmt->kind == Node::Expression && stmt->children[0]->kind == Node::Literal &&
|
|
319
|
+
stmt->children[0]->value.tag() == Value::Tag::String && !stmt->children[0]->grouped;
|
|
320
|
+
out->children.push_back(stmt);
|
|
321
|
+
}
|
|
322
|
+
if (brace) expect("}");
|
|
323
|
+
out->strict = strict;
|
|
324
|
+
return out;
|
|
325
|
+
}
|
|
326
|
+
Tree declaration(bool inFor = false) {
|
|
327
|
+
auto out = node(Node::Declaration, token.text);
|
|
328
|
+
advance();
|
|
329
|
+
do {
|
|
330
|
+
out->names.push_back(identifier());
|
|
331
|
+
out->children.push_back(eat("=") ? expression(2) : node(Node::Empty));
|
|
332
|
+
if (out->text == "const" && out->children.back()->kind == Node::Empty) syntax("Missing const initializer");
|
|
333
|
+
} while (eat(","));
|
|
334
|
+
if (!inFor) semi();
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
Tree statement() {
|
|
338
|
+
Depth guard(*this);
|
|
339
|
+
if (eat(";")) return node(Node::Empty);
|
|
340
|
+
if (eat("{")) {
|
|
341
|
+
// A block cannot introduce a directive prologue.
|
|
342
|
+
auto out = node(Node::Block);
|
|
343
|
+
while (!is("}") && token.kind != Token::End) out->children.push_back(statement());
|
|
344
|
+
expect("}");
|
|
345
|
+
return out;
|
|
346
|
+
}
|
|
347
|
+
if (is("var") || is("let") || is("const")) return declaration();
|
|
348
|
+
if (eat("return")) {
|
|
349
|
+
if (!functionBody) syntax("Return outside function");
|
|
350
|
+
auto out = node(Node::Return);
|
|
351
|
+
if (!token.newline && !is(";") && !is("}") && token.kind != Token::End) out->children.push_back(expression());
|
|
352
|
+
semi();
|
|
353
|
+
return out;
|
|
354
|
+
}
|
|
355
|
+
if (eat("throw")) {
|
|
356
|
+
if (token.newline) syntax("Newline after throw");
|
|
357
|
+
auto out = node(Node::Throw, {}, {expression()});
|
|
358
|
+
semi();
|
|
359
|
+
return out;
|
|
360
|
+
}
|
|
361
|
+
if (eat("if")) {
|
|
362
|
+
expect("(");
|
|
363
|
+
auto cond = expression();
|
|
364
|
+
expect(")");
|
|
365
|
+
auto yes = statement();
|
|
366
|
+
if (yes->kind == Node::Declaration && yes->text != "var") syntax("Lexical declaration requires a block");
|
|
367
|
+
auto no = eat("else") ? statement() : node(Node::Empty);
|
|
368
|
+
if (no->kind == Node::Declaration && no->text != "var") syntax("Lexical declaration requires a block");
|
|
369
|
+
return node(Node::If, {}, {cond, yes, no});
|
|
370
|
+
}
|
|
371
|
+
if (eat("while")) {
|
|
372
|
+
expect("(");
|
|
373
|
+
auto cond = expression();
|
|
374
|
+
expect(")");
|
|
375
|
+
++loops;
|
|
376
|
+
auto loop = statement();
|
|
377
|
+
--loops;
|
|
378
|
+
if (loop->kind == Node::Declaration && loop->text != "var") syntax("Lexical declaration requires a block");
|
|
379
|
+
return node(Node::While, {}, {cond, loop});
|
|
380
|
+
}
|
|
381
|
+
if (eat("for")) {
|
|
382
|
+
expect("(");
|
|
383
|
+
auto init = is(";") ? node(Node::Empty)
|
|
384
|
+
: (is("var") || is("let") || is("const")) ? declaration(true)
|
|
385
|
+
: node(Node::Expression, {}, {expression()});
|
|
386
|
+
expect(";");
|
|
387
|
+
auto cond = is(";") ? literal(boolean(true)) : expression();
|
|
388
|
+
expect(";");
|
|
389
|
+
auto step = is(")") ? node(Node::Empty) : expression();
|
|
390
|
+
expect(")");
|
|
391
|
+
++loops;
|
|
392
|
+
auto loop = statement();
|
|
393
|
+
--loops;
|
|
394
|
+
if (loop->kind == Node::Declaration && loop->text != "var") syntax("Lexical declaration requires a block");
|
|
395
|
+
return node(Node::For, {}, {init, cond, step, loop});
|
|
396
|
+
}
|
|
397
|
+
if (is("break") || is("continue")) {
|
|
398
|
+
auto out = node(is("break") ? Node::Break : Node::Continue);
|
|
399
|
+
advance();
|
|
400
|
+
if (!loops) syntax("Loop control outside loop");
|
|
401
|
+
semi();
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
if (is("function") || is("class") || is("try") || is("switch") || is("do") || is("with") || is("debugger") || is("import") ||
|
|
405
|
+
is("export"))
|
|
406
|
+
unsupported("Statement '" + token.text + "'");
|
|
407
|
+
auto out = node(Node::Expression, {}, {expression()});
|
|
408
|
+
semi();
|
|
409
|
+
return out;
|
|
410
|
+
}
|
|
411
|
+
static int precedence(const std::string& op) {
|
|
412
|
+
if (op == ",") return 1;
|
|
413
|
+
if (op == "=" || op == "+=" || op == "-=" || op == "*=" || op == "/=" || op == "%=" || op == "&=" || op == "|=" || op == "^=" ||
|
|
414
|
+
op == "<<=" || op == ">>=" || op == ">>>=")
|
|
415
|
+
return 2;
|
|
416
|
+
if (op == "?") return 3;
|
|
417
|
+
if (op == "||" || op == "??") return 4;
|
|
418
|
+
if (op == "&&") return 5;
|
|
419
|
+
if (op == "|") return 6;
|
|
420
|
+
if (op == "^") return 7;
|
|
421
|
+
if (op == "&") return 8;
|
|
422
|
+
if (op == "==" || op == "!=" || op == "===" || op == "!==") return 9;
|
|
423
|
+
if (op == "<" || op == ">" || op == "<=" || op == ">=" || op == "in" || op == "instanceof") return 10;
|
|
424
|
+
if (op == "<<" || op == ">>" || op == ">>>") return 11;
|
|
425
|
+
if (op == "+" || op == "-") return 12;
|
|
426
|
+
if (op == "*" || op == "/" || op == "%") return 13;
|
|
427
|
+
return 0;
|
|
428
|
+
}
|
|
429
|
+
Tree expression(int min = 1) {
|
|
430
|
+
Depth guard(*this);
|
|
431
|
+
auto left = unary();
|
|
432
|
+
for (;;) {
|
|
433
|
+
const int p = token.kind == Token::String ? 0 : precedence(token.text);
|
|
434
|
+
if (p < min || p == 0) {
|
|
435
|
+
if (is("**") || is("**=") || is("&&=") || is("||=") ||
|
|
436
|
+
is("?"
|
|
437
|
+
"?=") ||
|
|
438
|
+
is("=>") || is("?."))
|
|
439
|
+
unsupported("Operator '" + token.text + "'");
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
const auto op = token.text;
|
|
443
|
+
advance();
|
|
444
|
+
if (op == "instanceof") unsupported("instanceof in evaluated source");
|
|
445
|
+
if (op == "?") {
|
|
446
|
+
auto yes = expression(2);
|
|
447
|
+
expect(":");
|
|
448
|
+
left = node(Node::Conditional, {}, {left, yes, expression(2)});
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
auto right = expression(p == 2 ? p : p + 1);
|
|
452
|
+
if (p == 2 && !target(left)) syntax("Invalid assignment target");
|
|
453
|
+
if (p == 2 && left->kind == Node::Name && (left->text == "eval" || left->text == "arguments"))
|
|
454
|
+
unsupported("Assignment to eval or arguments");
|
|
455
|
+
const auto mixed = [&](const Tree& child) {
|
|
456
|
+
return !child->grouped && child->kind == Node::Binary &&
|
|
457
|
+
((op == "??" && (child->text == "||" || child->text == "&&")) || ((op == "||" || op == "&&") && child->text == "??"));
|
|
458
|
+
};
|
|
459
|
+
if (mixed(left) || mixed(right)) syntax("Nullish coalescing mixed with logical operators");
|
|
460
|
+
left = node(p == 2 ? Node::Assign : Node::Binary, op, {left, right});
|
|
461
|
+
}
|
|
462
|
+
return left;
|
|
463
|
+
}
|
|
464
|
+
Tree unary() {
|
|
465
|
+
Depth guard(*this);
|
|
466
|
+
if (is("!") || is("~") || is("+") || is("-") || is("typeof") || is("void") || is("delete") || is("++") || is("--")) {
|
|
467
|
+
const auto op = token.text;
|
|
468
|
+
advance();
|
|
469
|
+
auto operand = unary();
|
|
470
|
+
if (op == "delete" && operand->kind == Node::Name) unsupported("Unqualified delete");
|
|
471
|
+
if ((op == "++" || op == "--") && !target(operand)) syntax("Invalid update target");
|
|
472
|
+
return node(op == "++" || op == "--" ? Node::Update : Node::Unary, op, {operand});
|
|
473
|
+
}
|
|
474
|
+
bool construct = eat("new");
|
|
475
|
+
auto left = primary();
|
|
476
|
+
for (;;) {
|
|
477
|
+
if (eat(".")) {
|
|
478
|
+
if (token.kind != Token::Identifier) syntax("Expected property name");
|
|
479
|
+
const auto name = token.text;
|
|
480
|
+
advance();
|
|
481
|
+
left = node(Node::Member, {}, {left, literal(string(name))});
|
|
482
|
+
} else if (eat("[")) {
|
|
483
|
+
auto key = expression();
|
|
484
|
+
expect("]");
|
|
485
|
+
left = node(Node::Member, {}, {left, key});
|
|
486
|
+
} else if (eat("(")) {
|
|
487
|
+
std::vector<Tree> children{left};
|
|
488
|
+
if (!is(")")) do {
|
|
489
|
+
children.push_back(expression(2));
|
|
490
|
+
} while (eat(",") && !is(")"));
|
|
491
|
+
expect(")");
|
|
492
|
+
if (!construct && left->kind == Node::Name && left->text == "eval")
|
|
493
|
+
unsupported("Direct eval requires a caller lexical environment");
|
|
494
|
+
left = node(construct ? Node::Construct : Node::Call, {}, std::move(children));
|
|
495
|
+
construct = false;
|
|
496
|
+
} else
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
if (construct) left = node(Node::Construct, {}, {left});
|
|
500
|
+
if (!token.newline && (is("++") || is("--"))) {
|
|
501
|
+
if (!target(left)) syntax("Invalid update target");
|
|
502
|
+
const auto op = token.text;
|
|
503
|
+
advance();
|
|
504
|
+
left = node(Node::Update, op, {left});
|
|
505
|
+
left->flag = true;
|
|
506
|
+
}
|
|
507
|
+
return left;
|
|
508
|
+
}
|
|
509
|
+
Tree primary() {
|
|
510
|
+
if (token.kind == Token::Number) {
|
|
511
|
+
auto text = token.text;
|
|
512
|
+
advance();
|
|
513
|
+
return literal(number(std::strtod(text.c_str(), nullptr)));
|
|
514
|
+
}
|
|
515
|
+
if (token.kind == Token::String) {
|
|
516
|
+
auto text = token.text;
|
|
517
|
+
advance();
|
|
518
|
+
return literal(string(text));
|
|
519
|
+
}
|
|
520
|
+
if (eat("(")) {
|
|
521
|
+
auto out = expression();
|
|
522
|
+
expect(")");
|
|
523
|
+
out->grouped = true;
|
|
524
|
+
return out;
|
|
525
|
+
}
|
|
526
|
+
if (eat("true")) return literal(boolean(true));
|
|
527
|
+
if (eat("false")) return literal(boolean(false));
|
|
528
|
+
if (eat("null")) return literal(Value::box(Value::Tag::Null, nullptr));
|
|
529
|
+
if (eat("this")) return node(Node::This);
|
|
530
|
+
if (eat("[")) {
|
|
531
|
+
auto out = node(Node::Array);
|
|
532
|
+
while (!is("]")) {
|
|
533
|
+
if (is(","))
|
|
534
|
+
out->children.push_back(node(Node::Empty));
|
|
535
|
+
else
|
|
536
|
+
out->children.push_back(expression(2));
|
|
537
|
+
if (!eat(",")) break;
|
|
538
|
+
}
|
|
539
|
+
expect("]");
|
|
540
|
+
return out;
|
|
541
|
+
}
|
|
542
|
+
if (eat("{")) {
|
|
543
|
+
auto out = node(Node::Object);
|
|
544
|
+
while (!is("}")) {
|
|
545
|
+
if (token.kind != Token::String && token.kind != Token::Identifier && token.kind != Token::Number)
|
|
546
|
+
unsupported("Computed properties or object spread");
|
|
547
|
+
const bool shorthand = token.kind == Token::Identifier && !reserved(token.text);
|
|
548
|
+
auto name = token.text;
|
|
549
|
+
if (token.kind == Token::Number) name = host::detail::toString(std::strtod(name.c_str(), nullptr));
|
|
550
|
+
advance();
|
|
551
|
+
if (name == "__proto__") unsupported("Object literal prototype setters");
|
|
552
|
+
out->names.push_back(name);
|
|
553
|
+
if (eat(":"))
|
|
554
|
+
out->children.push_back(expression(2));
|
|
555
|
+
else if (shorthand)
|
|
556
|
+
out->children.push_back(node(Node::Name, name));
|
|
557
|
+
else
|
|
558
|
+
syntax("Expected property initializer");
|
|
559
|
+
if (!eat(",")) break;
|
|
560
|
+
}
|
|
561
|
+
expect("}");
|
|
562
|
+
return out;
|
|
563
|
+
}
|
|
564
|
+
if (eat("function")) {
|
|
565
|
+
auto out = node(Node::FunctionExpr);
|
|
566
|
+
if (!is("(")) out->text = identifier();
|
|
567
|
+
expect("(");
|
|
568
|
+
if (!is(")")) do {
|
|
569
|
+
out->names.push_back(identifier());
|
|
570
|
+
} while (eat(",") && !is(")"));
|
|
571
|
+
if (!is(")")) unsupported("Non-simple function parameters");
|
|
572
|
+
expect(")");
|
|
573
|
+
expect("{");
|
|
574
|
+
bool savedFunction = functionBody, savedStrict = strict;
|
|
575
|
+
unsigned savedLoops = loops;
|
|
576
|
+
functionBody = true;
|
|
577
|
+
loops = 0;
|
|
578
|
+
out->children.push_back(body(true));
|
|
579
|
+
out->strict = strict;
|
|
580
|
+
functionBody = savedFunction;
|
|
581
|
+
strict = savedStrict;
|
|
582
|
+
loops = savedLoops;
|
|
583
|
+
return out;
|
|
584
|
+
}
|
|
585
|
+
if (token.kind == Token::Identifier && !reserved(token.text)) {
|
|
586
|
+
const auto name = token.text;
|
|
587
|
+
if (name == "arguments") unsupported("The arguments object");
|
|
588
|
+
advance();
|
|
589
|
+
return node(Node::Name, name);
|
|
590
|
+
}
|
|
591
|
+
if (is("/") || is("...") || is("class") || is("new") || is("await") || is("yield") || is("super"))
|
|
592
|
+
unsupported("Expression token '" + token.text + "'");
|
|
593
|
+
syntax("Unexpected token '" + token.text + "'");
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
// Validate declarations for every scope before effects. In particular var is
|
|
598
|
+
// function scoped, while lexical bindings exist uninitialised from block entry.
|
|
599
|
+
inline void vars(const Tree& tree, std::unordered_set<std::string>& names) {
|
|
600
|
+
if (tree->kind == Node::FunctionExpr) return;
|
|
601
|
+
if (tree->kind == Node::Declaration && tree->text == "var") names.insert(tree->names.begin(), tree->names.end());
|
|
602
|
+
for (const auto& child : tree->children) vars(child, names);
|
|
603
|
+
}
|
|
604
|
+
inline void validate(const Tree& tree, const std::vector<std::string>& parameters = {}) {
|
|
605
|
+
if (tree->kind == Node::Block || tree->kind == Node::For) {
|
|
606
|
+
std::unordered_set<std::string> lexical, variables;
|
|
607
|
+
vars(tree, variables);
|
|
608
|
+
for (const auto& child : tree->children) {
|
|
609
|
+
if (child->kind != Node::Declaration || child->text == "var") continue;
|
|
610
|
+
for (const auto& name : child->names) {
|
|
611
|
+
if (!lexical.insert(name).second || variables.count(name) ||
|
|
612
|
+
std::find(parameters.begin(), parameters.end(), name) != parameters.end())
|
|
613
|
+
error("SyntaxError", "Conflicting declaration of " + name);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (tree->kind == Node::FunctionExpr) {
|
|
618
|
+
std::unordered_set<std::string> seen;
|
|
619
|
+
for (const auto& name : tree->names)
|
|
620
|
+
if (!seen.insert(name).second) unsupported("Duplicate function parameters");
|
|
621
|
+
validate(tree->children[0], tree->names);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
for (const auto& child : tree->children) validate(child);
|
|
625
|
+
}
|
|
626
|
+
struct Binding {
|
|
627
|
+
Value value;
|
|
628
|
+
bool initialized = false;
|
|
629
|
+
bool constant = false;
|
|
630
|
+
bool silentImmutable = false;
|
|
631
|
+
};
|
|
632
|
+
struct Scope {
|
|
633
|
+
Ref<Scope> parent;
|
|
634
|
+
std::unordered_map<std::string, Binding> bindings;
|
|
635
|
+
bool function = false;
|
|
636
|
+
friend void geaTraceRefs(const Scope& scope, detail::RefVisitor& visitor) {
|
|
637
|
+
detail::traceRefs(scope.parent, visitor);
|
|
638
|
+
for (const auto& entry : scope.bindings) detail::traceRefs(entry.second.value, visitor);
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
struct Context {
|
|
642
|
+
Value global;
|
|
643
|
+
Value objectPrototype;
|
|
644
|
+
friend void geaTraceRefs(const Context& context, detail::RefVisitor& visitor) {
|
|
645
|
+
detail::traceRefs(context.global, visitor);
|
|
646
|
+
detail::traceRefs(context.objectPrototype, visitor);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
struct Closure {
|
|
650
|
+
Tree body;
|
|
651
|
+
std::vector<std::string> parameters;
|
|
652
|
+
Ref<Scope> scope;
|
|
653
|
+
Ref<Context> context;
|
|
654
|
+
bool strict = false;
|
|
655
|
+
friend void geaTraceRefs(const Closure& closure, detail::RefVisitor& visitor) {
|
|
656
|
+
detail::traceRefs(closure.scope, visitor);
|
|
657
|
+
detail::traceRefs(closure.context, visitor);
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
inline std::uint32_t uint32(double n) {
|
|
661
|
+
if (!std::isfinite(n) || n == 0) return 0;
|
|
662
|
+
double v = std::fmod(std::trunc(n), 4294967296.0);
|
|
663
|
+
return static_cast<uint32_t>(v < 0 ? v + 4294967296.0 : v);
|
|
664
|
+
}
|
|
665
|
+
inline double signed32(uint32_t n) { return n >= 2147483648u ? static_cast<double>(n) - 4294967296.0 : static_cast<double>(n); }
|
|
666
|
+
Value read(const Value& object, const PropertyKey& key);
|
|
667
|
+
inline Value primitive(const Value& value, bool textHint = false, bool defaultHint = false) {
|
|
668
|
+
if (!isObjectValue(value)) return value;
|
|
669
|
+
const auto exotic = read(value, PropertyKey::symbol(wellKnownSymbol(detail::WellKnownSymbol::ToPrimitive)));
|
|
670
|
+
if (!nullish(exotic)) {
|
|
671
|
+
const auto result = exotic.callWithReceiver(value, {string(defaultHint ? "default" : textHint ? "string" : "number")});
|
|
672
|
+
if (isObjectValue(result)) error("TypeError", "Symbol.toPrimitive returned an object");
|
|
673
|
+
return result;
|
|
674
|
+
}
|
|
675
|
+
for (const char* name :
|
|
676
|
+
textHint ? std::initializer_list<const char*>{"toString", "valueOf"} : std::initializer_list<const char*>{"valueOf", "toString"}) {
|
|
677
|
+
const auto method = read(value, PropertyKey::string(name));
|
|
678
|
+
if (method.tag() != Value::Tag::Function) continue;
|
|
679
|
+
const auto result = method.callWithReceiver(value, {});
|
|
680
|
+
if (!isObjectValue(result)) return result;
|
|
681
|
+
}
|
|
682
|
+
error("TypeError", "Cannot convert object to primitive");
|
|
683
|
+
}
|
|
684
|
+
inline double numeric(const Value& v) {
|
|
685
|
+
const auto p = primitive(v);
|
|
686
|
+
if (p.tag() == Value::Tag::BigInt) unsupported("BigInt arithmetic in Eval");
|
|
687
|
+
return dynamicToNumber(p);
|
|
688
|
+
}
|
|
689
|
+
inline std::string text(const Value& v) {
|
|
690
|
+
const auto p = primitive(v, true);
|
|
691
|
+
if (p.tag() == Value::Tag::Symbol) error("TypeError", "Cannot convert Symbol to string");
|
|
692
|
+
return host::detail::toString(p);
|
|
693
|
+
}
|
|
694
|
+
inline PropertyKey keyOf(const Value& value) {
|
|
695
|
+
const auto p = primitive(value, true);
|
|
696
|
+
return p.tag() == Value::Tag::Symbol ? PropertyKey::symbol(p.as<Symbol>()) : PropertyKey::string(text(p));
|
|
697
|
+
}
|
|
698
|
+
inline bool looseEqual(Value a, Value b) {
|
|
699
|
+
if (a.tag() == Value::Tag::BigInt || b.tag() == Value::Tag::BigInt) unsupported("BigInt equality in Eval");
|
|
700
|
+
if (a.tag() == b.tag()) return Value::strictEquals(a, b);
|
|
701
|
+
if (nullish(a) && nullish(b)) return true;
|
|
702
|
+
if (a.tag() == Value::Tag::Boolean) return looseEqual(number(numeric(a)), b);
|
|
703
|
+
if (b.tag() == Value::Tag::Boolean) return looseEqual(a, number(numeric(b)));
|
|
704
|
+
if ((a.tag() == Value::Tag::String && b.tag() == Value::Tag::Number) || (a.tag() == Value::Tag::Number && b.tag() == Value::Tag::String))
|
|
705
|
+
return numeric(a) == numeric(b);
|
|
706
|
+
if (isObjectValue(a) && !isObjectValue(b) && !nullish(b)) return looseEqual(primitive(a), b);
|
|
707
|
+
if (isObjectValue(b) && !isObjectValue(a) && !nullish(a)) return looseEqual(a, primitive(b));
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
inline int compareText(const std::string& a, const std::string& b) {
|
|
711
|
+
const auto an = runtime::string::utf16Length(a), bn = runtime::string::utf16Length(b);
|
|
712
|
+
for (std::size_t i = 0; i < std::min(an, bn); ++i) {
|
|
713
|
+
const auto ac = runtime::string::charCodeAtUtf16(a, i), bc = runtime::string::charCodeAtUtf16(b, i);
|
|
714
|
+
if (ac != bc) return ac < bc ? -1 : 1;
|
|
715
|
+
}
|
|
716
|
+
return an == bn ? 0 : an < bn ? -1 : 1;
|
|
717
|
+
}
|
|
718
|
+
inline Value binary(const std::string& op, const Value& a, const Value& b) {
|
|
719
|
+
if (op == "===") return boolean(Value::strictEquals(a, b));
|
|
720
|
+
if (op == "!==") return boolean(!Value::strictEquals(a, b));
|
|
721
|
+
if (op == "==") return boolean(looseEqual(a, b));
|
|
722
|
+
if (op == "!=") return boolean(!looseEqual(a, b));
|
|
723
|
+
if (op == "in") {
|
|
724
|
+
if (!isObjectValue(b)) error("TypeError", "Right operand of in must be an object");
|
|
725
|
+
return boolean(b.hasProperty(keyOf(a)));
|
|
726
|
+
}
|
|
727
|
+
const auto left = primitive(a, false, op == "+"), right = primitive(b, false, op == "+");
|
|
728
|
+
if (op == "+" && (left.tag() == Value::Tag::String || right.tag() == Value::Tag::String)) return string(text(left) + text(right));
|
|
729
|
+
if (op == "<" || op == ">" || op == "<=" || op == ">=") {
|
|
730
|
+
if (left.tag() == Value::Tag::String && right.tag() == Value::Tag::String) {
|
|
731
|
+
const int c = compareText(left.as<std::string>(), right.as<std::string>());
|
|
732
|
+
return boolean(op == "<" ? c < 0 : op == ">" ? c > 0 : op == "<=" ? c <= 0 : c >= 0);
|
|
733
|
+
}
|
|
734
|
+
const double x = numeric(left), y = numeric(right);
|
|
735
|
+
return boolean(op == "<" ? x < y : op == ">" ? x > y : op == "<=" ? x <= y : x >= y);
|
|
736
|
+
}
|
|
737
|
+
const double x = numeric(left), y = numeric(right);
|
|
738
|
+
if (op == "+") return number(x + y);
|
|
739
|
+
if (op == "-") return number(x - y);
|
|
740
|
+
if (op == "*") return number(x * y);
|
|
741
|
+
if (op == "/") return number(x / y);
|
|
742
|
+
if (op == "%") return number(std::fmod(x, y));
|
|
743
|
+
const auto u = uint32(x), v = uint32(y), shift = v & 31u;
|
|
744
|
+
if (op == "&") return number(signed32(u & v));
|
|
745
|
+
if (op == "|") return number(signed32(u | v));
|
|
746
|
+
if (op == "^") return number(signed32(u ^ v));
|
|
747
|
+
if (op == "<<") return number(signed32(u << shift));
|
|
748
|
+
if (op == ">>>") return number(static_cast<double>(u >> shift));
|
|
749
|
+
if (op == ">>") return number(signed32(shift && (u & 0x80000000u) ? (u >> shift) | (~uint32_t(0) << (32 - shift)) : u >> shift));
|
|
750
|
+
unsupported("Binary operator " + op);
|
|
751
|
+
}
|
|
752
|
+
Value read(const Value& object, const PropertyKey& key);
|
|
753
|
+
Value invoke(void* environment, Value receiver, Args arguments);
|
|
754
|
+
Value makeFunction(const Tree& body, const std::vector<std::string>& params, Ref<Scope> scope, Ref<Context> context, bool strict,
|
|
755
|
+
const std::string& name = "");
|
|
756
|
+
struct Reference {
|
|
757
|
+
Ref<Scope> scope;
|
|
758
|
+
std::string name;
|
|
759
|
+
Value receiver;
|
|
760
|
+
PropertyKey key = PropertyKey::string("");
|
|
761
|
+
bool property = false;
|
|
762
|
+
};
|
|
763
|
+
struct Completion {
|
|
764
|
+
enum Kind { Normal, Returned, Broken, Continued } kind = Normal;
|
|
765
|
+
Value value;
|
|
766
|
+
bool empty = true;
|
|
767
|
+
};
|
|
768
|
+
struct Machine {
|
|
769
|
+
Ref<Scope> scope;
|
|
770
|
+
Ref<Scope> functionScope;
|
|
771
|
+
Ref<Context> context;
|
|
772
|
+
Value receiver;
|
|
773
|
+
bool strict;
|
|
774
|
+
Reference reference(const Tree& tree) {
|
|
775
|
+
if (tree->kind == Node::Name) {
|
|
776
|
+
for (auto current = scope; current; current = current->parent) {
|
|
777
|
+
if (current->bindings.count(tree->text)) return {current, tree->text, {}, PropertyKey::string(""), false};
|
|
778
|
+
}
|
|
779
|
+
return {{}, tree->text, context->global, PropertyKey::string(tree->text), true};
|
|
780
|
+
}
|
|
781
|
+
if (tree->kind != Node::Member) error("ReferenceError", "Invalid reference");
|
|
782
|
+
auto object = eval(tree->children[0]);
|
|
783
|
+
// The key expression runs before RequireObjectCoercible, but key coercion
|
|
784
|
+
// runs after it. Both can have observable effects.
|
|
785
|
+
auto key = eval(tree->children[1]);
|
|
786
|
+
if (nullish(object)) error("TypeError", "Cannot access a nullish value");
|
|
787
|
+
return {{}, {}, object, keyOf(key), true};
|
|
788
|
+
}
|
|
789
|
+
Value get(const Reference& ref, bool typeofName = false) {
|
|
790
|
+
if (!ref.property) {
|
|
791
|
+
const auto& binding = ref.scope->bindings.at(ref.name);
|
|
792
|
+
if (!binding.initialized) error("ReferenceError", "Cannot access " + ref.name + " before initialization");
|
|
793
|
+
return binding.value;
|
|
794
|
+
}
|
|
795
|
+
if (!ref.name.empty() && !ref.receiver.hasProperty(ref.key)) {
|
|
796
|
+
if (typeofName) return Value();
|
|
797
|
+
error("ReferenceError", ref.name + " is not defined");
|
|
798
|
+
}
|
|
799
|
+
return read(ref.receiver, ref.key);
|
|
800
|
+
}
|
|
801
|
+
void put(const Reference& ref, const Value& value) {
|
|
802
|
+
if (!ref.property) {
|
|
803
|
+
auto& binding = ref.scope->bindings.at(ref.name);
|
|
804
|
+
if (!binding.initialized) error("ReferenceError", "Cannot access " + ref.name + " before initialization");
|
|
805
|
+
if (binding.constant) {
|
|
806
|
+
if (binding.silentImmutable && !strict) return;
|
|
807
|
+
error("TypeError", "Assignment to constant " + ref.name);
|
|
808
|
+
}
|
|
809
|
+
binding.value = value;
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
if (strict && !ref.name.empty() && !ref.receiver.hasProperty(ref.key)) error("ReferenceError", ref.name + " is not defined");
|
|
813
|
+
if (!isObjectValue(ref.receiver)) {
|
|
814
|
+
if (strict) error("TypeError", "Cannot assign a property on a primitive");
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
// The compiler's active global is an open Dictionary<Value>, not an Eval
|
|
818
|
+
// DynamicObject. It still has ordinary writable data-property semantics;
|
|
819
|
+
// route writes into that same table so a sloppy unresolvable assignment
|
|
820
|
+
// and `this.x = value` remain visible to compiled globalThis reads.
|
|
821
|
+
if (ref.receiver.isDynamicDictionaryPayload()) {
|
|
822
|
+
Value(ref.receiver).setProperty(ref.key, value);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
if (!Value(ref.receiver).reflectSet(ref.key, value, ref.receiver) && strict) error("TypeError", "Property assignment rejected");
|
|
826
|
+
}
|
|
827
|
+
void inferName(const Tree& tree, Value fn, const std::string& name) {
|
|
828
|
+
if (tree->kind != Node::FunctionExpr || !tree->text.empty()) return;
|
|
829
|
+
auto descriptor = PropertyDescriptor::assignment(string(name));
|
|
830
|
+
descriptor.writable = descriptor.enumerable = false;
|
|
831
|
+
fn.defineProperty(PropertyKey::string("name"), descriptor);
|
|
832
|
+
}
|
|
833
|
+
Value eval(const Tree& tree) {
|
|
834
|
+
static thread_local unsigned depth = 0;
|
|
835
|
+
struct Guard {
|
|
836
|
+
unsigned& count;
|
|
837
|
+
~Guard() { --count; }
|
|
838
|
+
} guard{depth};
|
|
839
|
+
if (++depth > 512) error("RangeError", "Eval expression depth exceeded");
|
|
840
|
+
switch (tree->kind) {
|
|
841
|
+
case Node::Empty:
|
|
842
|
+
return Value();
|
|
843
|
+
case Node::Literal:
|
|
844
|
+
return tree->value;
|
|
845
|
+
case Node::Name:
|
|
846
|
+
case Node::Member:
|
|
847
|
+
return get(reference(tree));
|
|
848
|
+
case Node::This:
|
|
849
|
+
return receiver;
|
|
850
|
+
case Node::Unary: {
|
|
851
|
+
const auto& op = tree->text;
|
|
852
|
+
if (op == "typeof" && tree->children[0]->kind == Node::Name)
|
|
853
|
+
return string(host::detail::typeOf(get(reference(tree->children[0]), true)));
|
|
854
|
+
if (op == "delete") {
|
|
855
|
+
if (tree->children[0]->kind != Node::Member) {
|
|
856
|
+
eval(tree->children[0]);
|
|
857
|
+
return boolean(true);
|
|
858
|
+
}
|
|
859
|
+
const auto ref = reference(tree->children[0]);
|
|
860
|
+
if (!isObjectValue(ref.receiver)) unsupported("Deleting primitive properties");
|
|
861
|
+
auto object = ref.receiver;
|
|
862
|
+
bool result = object.deleteProperty(ref.key);
|
|
863
|
+
if (!result && strict) error("TypeError", "Property deletion rejected");
|
|
864
|
+
return boolean(result);
|
|
865
|
+
}
|
|
866
|
+
const auto v = eval(tree->children[0]);
|
|
867
|
+
if (op == "typeof") return string(host::detail::typeOf(v));
|
|
868
|
+
if (op == "void") return Value();
|
|
869
|
+
if (op == "!") return boolean(!truth(v));
|
|
870
|
+
if (op == "+") return number(numeric(v));
|
|
871
|
+
if (op == "-") return number(-numeric(v));
|
|
872
|
+
if (op == "~") return number(signed32(~uint32(numeric(v))));
|
|
873
|
+
unsupported("Unary operator " + op);
|
|
874
|
+
}
|
|
875
|
+
case Node::Binary: {
|
|
876
|
+
const auto left = eval(tree->children[0]);
|
|
877
|
+
if (tree->text == "&&" && !truth(left)) return left;
|
|
878
|
+
if (tree->text == "||" && truth(left)) return left;
|
|
879
|
+
if (tree->text == "??" && !nullish(left)) return left;
|
|
880
|
+
const auto right = eval(tree->children[1]);
|
|
881
|
+
if (tree->text == "," || tree->text == "&&" || tree->text == "||" || tree->text == "??") return right;
|
|
882
|
+
return binary(tree->text, left, right);
|
|
883
|
+
}
|
|
884
|
+
case Node::Conditional:
|
|
885
|
+
return eval(tree->children[truth(eval(tree->children[0])) ? 1 : 2]);
|
|
886
|
+
case Node::Assign: {
|
|
887
|
+
const auto ref = reference(tree->children[0]);
|
|
888
|
+
Value left;
|
|
889
|
+
if (tree->text != "=") left = get(ref);
|
|
890
|
+
auto right = eval(tree->children[1]);
|
|
891
|
+
if (tree->text != "=") right = binary(tree->text.substr(0, tree->text.size() - 1), left, right);
|
|
892
|
+
if (tree->text == "=" && tree->children[0]->kind == Node::Name) inferName(tree->children[1], right, tree->children[0]->text);
|
|
893
|
+
put(ref, right);
|
|
894
|
+
return right;
|
|
895
|
+
}
|
|
896
|
+
case Node::Update: {
|
|
897
|
+
const auto ref = reference(tree->children[0]);
|
|
898
|
+
const double old = numeric(get(ref));
|
|
899
|
+
auto value = number(old + (tree->text == "++" ? 1 : -1));
|
|
900
|
+
put(ref, value);
|
|
901
|
+
return tree->flag ? number(old) : value;
|
|
902
|
+
}
|
|
903
|
+
case Node::Call:
|
|
904
|
+
case Node::Construct: {
|
|
905
|
+
Value callee, self;
|
|
906
|
+
const auto& target = tree->children[0];
|
|
907
|
+
if (target->kind == Node::Name || target->kind == Node::Member) {
|
|
908
|
+
auto ref = reference(target);
|
|
909
|
+
callee = get(ref);
|
|
910
|
+
if (target->kind == Node::Member) self = ref.receiver;
|
|
911
|
+
} else
|
|
912
|
+
callee = eval(target);
|
|
913
|
+
std::vector<Value> args;
|
|
914
|
+
for (std::size_t i = 1; i < tree->children.size(); ++i) args.push_back(eval(tree->children[i]));
|
|
915
|
+
if (tree->kind == Node::Construct) {
|
|
916
|
+
if (callee.tag() != Value::Tag::Function) error("TypeError", "Value is not a constructor");
|
|
917
|
+
if (callee.payloadType() != detail::payloadTypeTagFor<Function>() || callee.as<Function>().invoke != invoke)
|
|
918
|
+
unsupported("Constructing an external callable requires a native construct adapter");
|
|
919
|
+
self = Value::object();
|
|
920
|
+
auto proto = read(callee, PropertyKey::string("prototype"));
|
|
921
|
+
if (!proto.isDynamicObject()) proto = context->objectPrototype;
|
|
922
|
+
self.asDynamicObject()->setPrototype(proto.asDynamicObject());
|
|
923
|
+
const auto result = callee.callWithReceiver(self, args);
|
|
924
|
+
return isObjectValue(result) ? result : self;
|
|
925
|
+
}
|
|
926
|
+
return callee.callWithReceiver(self, args);
|
|
927
|
+
}
|
|
928
|
+
case Node::Array: {
|
|
929
|
+
auto array = makeRef<ArrayObject<Value>>();
|
|
930
|
+
for (const auto& item : tree->children) {
|
|
931
|
+
if (item->kind == Node::Empty)
|
|
932
|
+
array->pushHole();
|
|
933
|
+
else
|
|
934
|
+
array->push(eval(item));
|
|
935
|
+
}
|
|
936
|
+
return Value::box(Value::Tag::Object, array);
|
|
937
|
+
}
|
|
938
|
+
case Node::Object: {
|
|
939
|
+
auto object = Value::object();
|
|
940
|
+
object.asDynamicObject()->setPrototype(context->objectPrototype.asDynamicObject());
|
|
941
|
+
for (std::size_t i = 0; i < tree->names.size(); ++i) {
|
|
942
|
+
auto value = eval(tree->children[i]);
|
|
943
|
+
inferName(tree->children[i], value, tree->names[i]);
|
|
944
|
+
object.defineProperty(PropertyKey::string(tree->names[i]), PropertyDescriptor::assignment(value));
|
|
945
|
+
}
|
|
946
|
+
return object;
|
|
947
|
+
}
|
|
948
|
+
case Node::FunctionExpr: {
|
|
949
|
+
auto closureScope = scope;
|
|
950
|
+
if (!tree->text.empty()) {
|
|
951
|
+
closureScope = makeRef<Scope>();
|
|
952
|
+
closureScope->parent = scope;
|
|
953
|
+
}
|
|
954
|
+
auto fn = makeFunction(tree->children[0], tree->names, closureScope, context, tree->strict || strict, tree->text);
|
|
955
|
+
if (!tree->text.empty()) closureScope->bindings[tree->text] = {fn, true, true, true};
|
|
956
|
+
return fn;
|
|
957
|
+
}
|
|
958
|
+
default:
|
|
959
|
+
unsupported("Statement used as expression");
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
void lexical(const Tree& block) {
|
|
963
|
+
for (const auto& stmt : block->children)
|
|
964
|
+
if (stmt->kind == Node::Declaration && stmt->text != "var")
|
|
965
|
+
for (const auto& name : stmt->names) scope->bindings.emplace(name, Binding{{}, false, stmt->text == "const"});
|
|
966
|
+
}
|
|
967
|
+
Completion execute(const Tree& tree, bool root = false) {
|
|
968
|
+
switch (tree->kind) {
|
|
969
|
+
case Node::Empty:
|
|
970
|
+
return {};
|
|
971
|
+
case Node::Expression:
|
|
972
|
+
return {Completion::Normal, eval(tree->children[0]), false};
|
|
973
|
+
case Node::Return:
|
|
974
|
+
return {Completion::Returned, tree->children.empty() ? Value() : eval(tree->children[0]), false};
|
|
975
|
+
case Node::Throw:
|
|
976
|
+
throw eval(tree->children[0]);
|
|
977
|
+
case Node::Break:
|
|
978
|
+
return {Completion::Broken, {}, true};
|
|
979
|
+
case Node::Continue:
|
|
980
|
+
return {Completion::Continued, {}, true};
|
|
981
|
+
case Node::Declaration: {
|
|
982
|
+
for (std::size_t i = 0; i < tree->names.size(); ++i) {
|
|
983
|
+
if (tree->text == "var") {
|
|
984
|
+
if (tree->children[i]->kind != Node::Empty) {
|
|
985
|
+
auto value = eval(tree->children[i]);
|
|
986
|
+
inferName(tree->children[i], value, tree->names[i]);
|
|
987
|
+
put(reference(node(Node::Name, tree->names[i])), value);
|
|
988
|
+
}
|
|
989
|
+
} else {
|
|
990
|
+
auto value = eval(tree->children[i]);
|
|
991
|
+
inferName(tree->children[i], value, tree->names[i]);
|
|
992
|
+
auto& binding = scope->bindings.at(tree->names[i]);
|
|
993
|
+
binding.value = value;
|
|
994
|
+
binding.initialized = true;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return {};
|
|
998
|
+
}
|
|
999
|
+
case Node::Block: {
|
|
1000
|
+
auto previous = scope;
|
|
1001
|
+
if (!root) {
|
|
1002
|
+
scope = makeRef<Scope>();
|
|
1003
|
+
scope->parent = previous;
|
|
1004
|
+
}
|
|
1005
|
+
lexical(tree);
|
|
1006
|
+
Completion result;
|
|
1007
|
+
try {
|
|
1008
|
+
for (const auto& stmt : tree->children) {
|
|
1009
|
+
auto current = execute(stmt);
|
|
1010
|
+
if (current.empty && !result.empty) {
|
|
1011
|
+
current.value = result.value;
|
|
1012
|
+
current.empty = false;
|
|
1013
|
+
}
|
|
1014
|
+
result = current;
|
|
1015
|
+
if (result.kind != Completion::Normal) break;
|
|
1016
|
+
}
|
|
1017
|
+
} catch (...) {
|
|
1018
|
+
scope = previous;
|
|
1019
|
+
throw;
|
|
1020
|
+
}
|
|
1021
|
+
scope = previous;
|
|
1022
|
+
return result;
|
|
1023
|
+
}
|
|
1024
|
+
case Node::If: {
|
|
1025
|
+
auto result = execute(tree->children[truth(eval(tree->children[0])) ? 1 : 2]);
|
|
1026
|
+
if (result.empty) {
|
|
1027
|
+
result.value = Value();
|
|
1028
|
+
result.empty = false;
|
|
1029
|
+
}
|
|
1030
|
+
return result;
|
|
1031
|
+
}
|
|
1032
|
+
case Node::While:
|
|
1033
|
+
case Node::For: {
|
|
1034
|
+
auto previous = scope;
|
|
1035
|
+
const bool forLoop = tree->kind == Node::For;
|
|
1036
|
+
if (forLoop) {
|
|
1037
|
+
scope = makeRef<Scope>();
|
|
1038
|
+
scope->parent = previous;
|
|
1039
|
+
if (tree->children[0]->kind == Node::Declaration && tree->children[0]->text != "var") {
|
|
1040
|
+
for (const auto& name : tree->children[0]->names)
|
|
1041
|
+
scope->bindings.emplace(name, Binding{{}, false, tree->children[0]->text == "const"});
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
Completion result{Completion::Normal, {}, false};
|
|
1045
|
+
try {
|
|
1046
|
+
if (forLoop) execute(tree->children[0]);
|
|
1047
|
+
auto nextIteration = [&] {
|
|
1048
|
+
if (!forLoop || tree->children[0]->kind != Node::Declaration || tree->children[0]->text != "let") return;
|
|
1049
|
+
auto next = makeRef<Scope>();
|
|
1050
|
+
next->parent = previous;
|
|
1051
|
+
next->bindings = scope->bindings;
|
|
1052
|
+
scope = next;
|
|
1053
|
+
};
|
|
1054
|
+
nextIteration();
|
|
1055
|
+
while (truth(eval(tree->children[forLoop ? 1 : 0]))) {
|
|
1056
|
+
auto current = execute(tree->children[forLoop ? 3 : 1]);
|
|
1057
|
+
if (!current.empty) {
|
|
1058
|
+
result.value = current.value;
|
|
1059
|
+
result.empty = false;
|
|
1060
|
+
}
|
|
1061
|
+
if (current.kind == Completion::Returned) {
|
|
1062
|
+
scope = previous;
|
|
1063
|
+
return current;
|
|
1064
|
+
}
|
|
1065
|
+
if (current.kind == Completion::Broken) break;
|
|
1066
|
+
nextIteration();
|
|
1067
|
+
if (forLoop) eval(tree->children[2]);
|
|
1068
|
+
}
|
|
1069
|
+
} catch (...) {
|
|
1070
|
+
scope = previous;
|
|
1071
|
+
throw;
|
|
1072
|
+
}
|
|
1073
|
+
scope = previous;
|
|
1074
|
+
return result;
|
|
1075
|
+
}
|
|
1076
|
+
default:
|
|
1077
|
+
unsupported("Unsupported statement execution");
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
inline Value invoke(void* environment, Value receiver, Args arguments) {
|
|
1082
|
+
gea::collectCyclesIfNeeded();
|
|
1083
|
+
// Native recursive callbacks must not turn untrusted source into a C++ stack overflow.
|
|
1084
|
+
static thread_local unsigned calls = 0;
|
|
1085
|
+
static thread_local const char* outermost = nullptr;
|
|
1086
|
+
struct Guard {
|
|
1087
|
+
unsigned& count;
|
|
1088
|
+
~Guard() { --count; }
|
|
1089
|
+
} guard{calls};
|
|
1090
|
+
if (++calls > 128) error("RangeError", "Eval call stack limit exceeded");
|
|
1091
|
+
// The call count alone assumes a frame size. It is a fine bound for an
|
|
1092
|
+
// optimized build and a wrong one for a sanitized -O0 build, whose frames
|
|
1093
|
+
// for one eval call run past 64 KiB, so 128 of them overflowed the 8 MiB
|
|
1094
|
+
// main-thread stack before the count ever fired. Measure the stack the eval
|
|
1095
|
+
// recursion has actually consumed since its outermost entry and refuse
|
|
1096
|
+
// there too; the direction of growth is the same on every target we ship.
|
|
1097
|
+
char probe;
|
|
1098
|
+
if (calls == 1) outermost = &probe;
|
|
1099
|
+
else if (outermost != nullptr) {
|
|
1100
|
+
#ifdef _WIN32
|
|
1101
|
+
constexpr std::ptrdiff_t budget = 512 * 1024;
|
|
1102
|
+
#else
|
|
1103
|
+
constexpr std::ptrdiff_t budget = 4 * 1024 * 1024;
|
|
1104
|
+
#endif
|
|
1105
|
+
const std::ptrdiff_t consumed = outermost > &probe ? outermost - &probe : &probe - outermost;
|
|
1106
|
+
if (consumed > budget) error("RangeError", "Eval call stack limit exceeded");
|
|
1107
|
+
}
|
|
1108
|
+
const auto& closure = *static_cast<Closure*>(environment);
|
|
1109
|
+
auto scope = makeRef<Scope>();
|
|
1110
|
+
scope->parent = closure.scope;
|
|
1111
|
+
scope->function = true;
|
|
1112
|
+
if (!closure.strict && nullish(receiver)) receiver = closure.context->global;
|
|
1113
|
+
if (!closure.strict && !isObjectValue(receiver)) unsupported("Sloppy this boxing for primitive receivers");
|
|
1114
|
+
for (std::size_t i = 0; i < closure.parameters.size(); ++i)
|
|
1115
|
+
scope->bindings[closure.parameters[i]] = {(i < arguments->size() ? arguments->at(i) : Value()), true, false};
|
|
1116
|
+
std::unordered_set<std::string> names;
|
|
1117
|
+
vars(closure.body, names);
|
|
1118
|
+
for (const auto& name : names) scope->bindings.emplace(name, Binding{{}, true, false});
|
|
1119
|
+
Machine machine{scope, scope, closure.context, receiver, closure.strict};
|
|
1120
|
+
auto result = machine.execute(closure.body, true);
|
|
1121
|
+
return result.kind == Completion::Returned ? result.value : Value();
|
|
1122
|
+
}
|
|
1123
|
+
inline Value makeFunction(const Tree& body, const std::vector<std::string>& params, Ref<Scope> scope, Ref<Context> context, bool strict,
|
|
1124
|
+
const std::string& name) {
|
|
1125
|
+
auto closure = makeRef<Closure>(Closure{body, params, scope, context, strict});
|
|
1126
|
+
auto fn = Value::boxMethod<1>(Function(invoke, PackedEnvironment{closure.get(), refCastToVoid(closure)}));
|
|
1127
|
+
auto prototype = Value::object();
|
|
1128
|
+
prototype.asDynamicObject()->setPrototype(context->objectPrototype.asDynamicObject());
|
|
1129
|
+
auto prototypeDescriptor = PropertyDescriptor::assignment(prototype);
|
|
1130
|
+
prototypeDescriptor.enumerable = prototypeDescriptor.configurable = false;
|
|
1131
|
+
fn.defineProperty(PropertyKey::string("prototype"), prototypeDescriptor);
|
|
1132
|
+
auto constructorDescriptor = PropertyDescriptor::assignment(fn);
|
|
1133
|
+
constructorDescriptor.enumerable = false;
|
|
1134
|
+
prototype.defineProperty(PropertyKey::string("constructor"), constructorDescriptor);
|
|
1135
|
+
auto nameDescriptor = PropertyDescriptor::assignment(string(name));
|
|
1136
|
+
nameDescriptor.writable = nameDescriptor.enumerable = false;
|
|
1137
|
+
fn.defineProperty(PropertyKey::string("name"), nameDescriptor);
|
|
1138
|
+
auto descriptor = PropertyDescriptor::assignment(number(static_cast<double>(params.size())));
|
|
1139
|
+
descriptor.writable = descriptor.enumerable = false;
|
|
1140
|
+
fn.defineProperty(PropertyKey::string("length"), descriptor);
|
|
1141
|
+
return fn;
|
|
1142
|
+
}
|
|
1143
|
+
inline Value method(Function::Invoke entry) { return Value::boxMethod<1>(Function(entry, nullptr)); }
|
|
1144
|
+
inline Value argument(const Args& args, std::size_t i) { return i < args->size() ? args->at(i) : Value(); }
|
|
1145
|
+
inline std::vector<Value> list(const Args& args, std::size_t begin = 0) {
|
|
1146
|
+
std::vector<Value> result;
|
|
1147
|
+
for (std::size_t i = begin; i < args->size(); ++i) result.push_back(args->at(i));
|
|
1148
|
+
return result;
|
|
1149
|
+
}
|
|
1150
|
+
struct Bound {
|
|
1151
|
+
Value target, receiver;
|
|
1152
|
+
std::vector<Value> arguments;
|
|
1153
|
+
friend void geaTraceRefs(const Bound& bound, detail::RefVisitor& visitor) {
|
|
1154
|
+
detail::traceRefs(bound.target, visitor);
|
|
1155
|
+
detail::traceRefs(bound.receiver, visitor);
|
|
1156
|
+
for (const auto& arg : bound.arguments) detail::traceRefs(arg, visitor);
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
inline Value functionPrototype(const PropertyKey& key) {
|
|
1160
|
+
if (!key.isSymbol() && key.text() == "call")
|
|
1161
|
+
return method(+[](void*, Value fn, Args args) { return fn.callWithReceiver(argument(args, 0), list(args, 1)); });
|
|
1162
|
+
if (!key.isSymbol() && key.text() == "apply")
|
|
1163
|
+
return method(+[](void*, Value fn, Args args) {
|
|
1164
|
+
const auto input = argument(args, 1);
|
|
1165
|
+
std::vector<Value> values;
|
|
1166
|
+
if (!nullish(input)) {
|
|
1167
|
+
if (!isObjectValue(input)) error("TypeError", "apply arguments must be an object");
|
|
1168
|
+
const double size = numeric(read(input, PropertyKey::string("length")));
|
|
1169
|
+
if (size > 1000000) unsupported("apply argument count exceeds Eval limit");
|
|
1170
|
+
const auto n = std::isnan(size) || size < 0 ? 0 : static_cast<std::size_t>(std::floor(size));
|
|
1171
|
+
for (std::size_t i = 0; i < n; ++i) values.push_back(read(input, PropertyKey::string(std::to_string(i))));
|
|
1172
|
+
}
|
|
1173
|
+
return fn.callWithReceiver(argument(args, 0), values);
|
|
1174
|
+
});
|
|
1175
|
+
if (!key.isSymbol() && key.text() == "bind")
|
|
1176
|
+
return method(+[](void*, Value fn, Args args) {
|
|
1177
|
+
if (fn.tag() != Value::Tag::Function) error("TypeError", "bind receiver is not callable");
|
|
1178
|
+
auto bound = makeRef<Bound>(Bound{fn, argument(args, 0), list(args, 1)});
|
|
1179
|
+
return Value::boxMethod<1>(Function(
|
|
1180
|
+
+[](void* env, Value, Args rest) {
|
|
1181
|
+
const auto& state = *static_cast<Bound*>(env);
|
|
1182
|
+
auto args = state.arguments;
|
|
1183
|
+
const auto more = list(rest);
|
|
1184
|
+
args.insert(args.end(), more.begin(), more.end());
|
|
1185
|
+
return state.target.callWithReceiver(state.receiver, args);
|
|
1186
|
+
},
|
|
1187
|
+
PackedEnvironment{bound.get(), refCastToVoid(bound)}));
|
|
1188
|
+
});
|
|
1189
|
+
if (!key.isSymbol() && (key.text() == "caller" || key.text() == "arguments" || key.text() == "constructor" || key.text() == "toString" ||
|
|
1190
|
+
key.text() == "name" || key.text() == "length" || key.text() == "prototype"))
|
|
1191
|
+
unsupported("Function reflection: " + key.text());
|
|
1192
|
+
return Value();
|
|
1193
|
+
}
|
|
1194
|
+
inline Value read(const Value& object, const PropertyKey& key) {
|
|
1195
|
+
if (object.tag() == Value::Tag::String && !key.isSymbol()) {
|
|
1196
|
+
const auto& source = object.as<std::string>();
|
|
1197
|
+
if (key.text() == "length") return number(static_cast<double>(runtime::string::utf16Length(source)));
|
|
1198
|
+
std::size_t index = 0;
|
|
1199
|
+
if (detail::arrayIndexOfKey(key, index))
|
|
1200
|
+
return index < runtime::string::utf16Length(source) ? string(runtime::string::substringUtf16(source, index, index + 1)) : Value();
|
|
1201
|
+
if (key.text() == "charCodeAt" || key.text() == "charAt" || key.text() == "slice" || key.text() == "substring") {
|
|
1202
|
+
const auto name = makeRef<std::string>(key.text());
|
|
1203
|
+
return Value::boxMethod<1>(Function(
|
|
1204
|
+
+[](void* env, Value self, Args args) {
|
|
1205
|
+
if (nullish(self)) error("TypeError", "String method on nullish receiver");
|
|
1206
|
+
const auto s = text(self);
|
|
1207
|
+
const auto& name = *static_cast<std::string*>(env);
|
|
1208
|
+
const double length = static_cast<double>(runtime::string::utf16Length(s));
|
|
1209
|
+
auto integer = [](double n) { return std::isnan(n) || n == 0 ? 0.0 : std::trunc(n); };
|
|
1210
|
+
const double first = integer(numeric(argument(args, 0)));
|
|
1211
|
+
if (name == "charCodeAt" || name == "charAt") {
|
|
1212
|
+
if (first < 0 || first >= length) return name == "charAt" ? string("") : number(std::nan(""));
|
|
1213
|
+
return name == "charAt" ? string(runtime::string::substringUtf16(s, first, first + 1))
|
|
1214
|
+
: number(runtime::string::charCodeAtUtf16(s, first));
|
|
1215
|
+
}
|
|
1216
|
+
const auto end = argument(args, 1);
|
|
1217
|
+
const double last = end.tag() == Value::Tag::Undefined ? length : integer(numeric(end));
|
|
1218
|
+
auto index = [&](double n) {
|
|
1219
|
+
return name == "slice" && n < 0 ? std::max(length + n, 0.0) : std::min(std::max(n, 0.0), length);
|
|
1220
|
+
};
|
|
1221
|
+
double start = index(first), finish = index(last);
|
|
1222
|
+
if (name == "substring" && start > finish) std::swap(start, finish);
|
|
1223
|
+
return string(runtime::string::substringUtf16(s, start, std::max(start, finish)));
|
|
1224
|
+
},
|
|
1225
|
+
PackedEnvironment{name.get(), refCastToVoid(name)}));
|
|
1226
|
+
}
|
|
1227
|
+
// Missing standard methods are capabilities, not properties proven absent.
|
|
1228
|
+
if (key.text() != "then") unsupported("String property '" + key.text() + "'");
|
|
1229
|
+
}
|
|
1230
|
+
return object.getProperty(key);
|
|
1231
|
+
}
|
|
1232
|
+
inline Ref<Context> realm(Value globals) {
|
|
1233
|
+
auto context = makeRef<Context>();
|
|
1234
|
+
context->global = globals;
|
|
1235
|
+
context->objectPrototype = Value::object();
|
|
1236
|
+
context->objectPrototype.setProperty(PropertyKey::string("valueOf"), method(+[](void*, Value self, Args) {
|
|
1237
|
+
if (!isObjectValue(self)) unsupported("Object.prototype.valueOf primitive boxing");
|
|
1238
|
+
return self;
|
|
1239
|
+
}));
|
|
1240
|
+
context->objectPrototype.setProperty(
|
|
1241
|
+
PropertyKey::string("toString"), method(+[](void*, Value self, Args) {
|
|
1242
|
+
if (!self.isDynamicObject()) unsupported("Object.prototype.toString on an external object");
|
|
1243
|
+
auto tag = self.getProperty(PropertyKey::symbol(wellKnownSymbol(detail::WellKnownSymbol::ToStringTag)));
|
|
1244
|
+
return string("[object " + (tag.tag() == Value::Tag::String ? tag.as<std::string>() : std::string("Object")) + "]");
|
|
1245
|
+
}));
|
|
1246
|
+
return context;
|
|
1247
|
+
}
|
|
1248
|
+
inline Value initializeRealmGlobal(Value global) {
|
|
1249
|
+
auto define = [&](const std::string& name, Value value, bool writable = true) {
|
|
1250
|
+
const auto key = PropertyKey::string(name);
|
|
1251
|
+
// An active compiler realm may already have observed writes before its
|
|
1252
|
+
// first Function construction. Realm initialization supplies missing
|
|
1253
|
+
// intrinsics; it must never overwrite those live global properties.
|
|
1254
|
+
if (global.hasProperty(key)) return;
|
|
1255
|
+
auto descriptor = PropertyDescriptor::assignment(value);
|
|
1256
|
+
descriptor.enumerable = false;
|
|
1257
|
+
descriptor.writable = writable;
|
|
1258
|
+
descriptor.configurable = writable;
|
|
1259
|
+
if (global.isDynamicObject()) global.defineProperty(key, descriptor);
|
|
1260
|
+
else global.setProperty(key, value);
|
|
1261
|
+
};
|
|
1262
|
+
define("undefined", Value(), false);
|
|
1263
|
+
define("NaN", number(std::nan("")), false);
|
|
1264
|
+
define("Infinity", number(INFINITY), false);
|
|
1265
|
+
define("globalThis", global);
|
|
1266
|
+
auto math = Value::object();
|
|
1267
|
+
math.setProperty(PropertyKey::string("clz32"), method(+[](void*, Value, Args args) {
|
|
1268
|
+
uint32_t value = uint32(numeric(argument(args, 0)));
|
|
1269
|
+
unsigned count = 0;
|
|
1270
|
+
if (!value) return number(32);
|
|
1271
|
+
while (!(value & 0x80000000u)) {
|
|
1272
|
+
value <<= 1;
|
|
1273
|
+
++count;
|
|
1274
|
+
}
|
|
1275
|
+
return number(count);
|
|
1276
|
+
}));
|
|
1277
|
+
math.setProperty(PropertyKey::string("floor"),
|
|
1278
|
+
method(+[](void*, Value, Args args) { return number(std::floor(numeric(argument(args, 0)))); }));
|
|
1279
|
+
math.setProperty(PropertyKey::string("ceil"),
|
|
1280
|
+
method(+[](void*, Value, Args args) { return number(std::ceil(numeric(argument(args, 0)))); }));
|
|
1281
|
+
math.setProperty(PropertyKey::string("abs"),
|
|
1282
|
+
method(+[](void*, Value, Args args) { return number(std::fabs(numeric(argument(args, 0)))); }));
|
|
1283
|
+
define("Math", math);
|
|
1284
|
+
define("Number", method(+[](void*, Value, Args args) { return args->size() ? number(numeric(args->at(0))) : number(0); }));
|
|
1285
|
+
define("String", method(+[](void*, Value, Args args) {
|
|
1286
|
+
if (!args->size()) return string("");
|
|
1287
|
+
if (args->at(0).tag() == Value::Tag::Symbol) unsupported("String(Symbol) in Eval");
|
|
1288
|
+
return string(text(args->at(0)));
|
|
1289
|
+
}));
|
|
1290
|
+
define("Boolean", method(+[](void*, Value, Args args) { return boolean(truth(argument(args, 0))); }));
|
|
1291
|
+
return global;
|
|
1292
|
+
}
|
|
1293
|
+
inline Value defaultGlobals() { return initializeRealmGlobal(Value::object()); }
|
|
1294
|
+
} // namespace gea::eval_detail
|
|
1295
|
+
|
|
1296
|
+
namespace gea {
|
|
1297
|
+
// A realm is explicit: generated Function bodies never capture a C++ caller's
|
|
1298
|
+
// locals. Direct JS eval needs compiler-published bindings and is not this API.
|
|
1299
|
+
class Eval {
|
|
1300
|
+
Ref<eval_detail::Context> context_;
|
|
1301
|
+
|
|
1302
|
+
public:
|
|
1303
|
+
class FunctionArgument {
|
|
1304
|
+
std::string nativeString_;
|
|
1305
|
+
Value dynamicValue_;
|
|
1306
|
+
bool dynamic_ = false;
|
|
1307
|
+
|
|
1308
|
+
public:
|
|
1309
|
+
explicit FunctionArgument(std::string value) : nativeString_(std::move(value)) {}
|
|
1310
|
+
explicit FunctionArgument(Value value) : dynamicValue_(std::move(value)), dynamic_(true) {}
|
|
1311
|
+
|
|
1312
|
+
std::string text() const { return dynamic_ ? eval_detail::text(dynamicValue_) : nativeString_; }
|
|
1313
|
+
};
|
|
1314
|
+
|
|
1315
|
+
Eval() : context_(eval_detail::realm(eval_detail::defaultGlobals())) {}
|
|
1316
|
+
explicit Eval(Value globals) : context_(eval_detail::realm(eval_detail::initializeRealmGlobal(std::move(globals)))) {
|
|
1317
|
+
if (!isObjectValue(context_->global)) eval_detail::error("TypeError", "Eval globals must be an object");
|
|
1318
|
+
}
|
|
1319
|
+
Value globals() const { return context_->global; }
|
|
1320
|
+
Value function(const std::vector<std::string>& parameters, const std::string& body) const {
|
|
1321
|
+
using namespace eval_detail;
|
|
1322
|
+
std::string joined;
|
|
1323
|
+
for (std::size_t i = 0; i < parameters.size(); ++i) {
|
|
1324
|
+
if (i) joined += ',';
|
|
1325
|
+
joined += parameters[i];
|
|
1326
|
+
}
|
|
1327
|
+
Parser paramParser(joined, false);
|
|
1328
|
+
std::vector<std::string> names;
|
|
1329
|
+
if (paramParser.token.kind != Token::End) do {
|
|
1330
|
+
names.push_back(paramParser.identifier());
|
|
1331
|
+
} while (paramParser.eat(",") && paramParser.token.kind != Token::End);
|
|
1332
|
+
if (paramParser.token.kind != Token::End) unsupported("Default, rest or destructured Function parameters");
|
|
1333
|
+
std::unordered_set<std::string> unique;
|
|
1334
|
+
for (const auto& name : names)
|
|
1335
|
+
if (!unique.insert(name).second) unsupported("Duplicate Function parameters");
|
|
1336
|
+
Parser parser(body, true);
|
|
1337
|
+
auto tree = parser.body(false);
|
|
1338
|
+
validate(tree, names);
|
|
1339
|
+
return makeFunction(tree, names, {}, context_, parser.strict, "anonymous");
|
|
1340
|
+
}
|
|
1341
|
+
Value run(const std::string& source) const {
|
|
1342
|
+
using namespace eval_detail;
|
|
1343
|
+
Parser parser(source, false);
|
|
1344
|
+
auto tree = parser.body(false);
|
|
1345
|
+
validate(tree);
|
|
1346
|
+
// Script var/global declaration persistence has a different environment
|
|
1347
|
+
// record from Function. Until implemented, do not pretend local cells are
|
|
1348
|
+
// observable global properties.
|
|
1349
|
+
std::unordered_set<std::string> declarations;
|
|
1350
|
+
vars(tree, declarations);
|
|
1351
|
+
if (!declarations.empty()) unsupported("Global var declarations in Eval::run");
|
|
1352
|
+
auto scope = makeRef<Scope>();
|
|
1353
|
+
Machine machine{scope, scope, context_, context_->global, parser.strict};
|
|
1354
|
+
return machine.execute(tree, true).value;
|
|
1355
|
+
}
|
|
1356
|
+
static FunctionArgument functionArgument(std::string value) { return FunctionArgument(std::move(value)); }
|
|
1357
|
+
static FunctionArgument functionArgument(Value value) { return FunctionArgument(std::move(value)); }
|
|
1358
|
+
static Value constructFunction(const std::vector<FunctionArgument>& arguments) {
|
|
1359
|
+
// The compiler has one process-wide ECMAScript realm. Adapt its open
|
|
1360
|
+
// global dictionary into Eval without copying it: every generated
|
|
1361
|
+
// Function and every compiled `globalThis` therefore sees one identity.
|
|
1362
|
+
// The closure retains this Eval context, but `function()` still begins
|
|
1363
|
+
// with an empty lexical scope, as Function construction requires.
|
|
1364
|
+
static Eval evaluator(Value::box(Value::Tag::Object, runtime::globalThis()));
|
|
1365
|
+
std::vector<std::string> parameters;
|
|
1366
|
+
// ToString proceeds left to right, including before body parsing fails.
|
|
1367
|
+
for (std::size_t i = 0; i + 1 < arguments.size(); ++i) parameters.push_back(arguments[i].text());
|
|
1368
|
+
const auto body = arguments.empty() ? std::string() : arguments.back().text();
|
|
1369
|
+
return evaluator.function(parameters, body);
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
} // namespace gea
|
|
1373
|
+
|
|
1374
|
+
namespace gea {
|
|
1375
|
+
inline Value dynamicFunctionPrototypeGet(const PropertyKey& key) { return eval_detail::functionPrototype(key); }
|
|
1376
|
+
} // namespace gea
|