tsc-ts 0.0.4 → 0.0.5
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/README.md +33 -1
- package/dist/api/compiler/ast-utilities.d.ts +82 -0
- package/dist/api/compiler/ast-utilities.js +462 -0
- package/dist/api/compiler/ast.d.ts +2350 -0
- package/dist/api/compiler/ast.js +11206 -0
- package/dist/api/compiler/astnav.d.ts +37 -0
- package/dist/api/compiler/astnav.js +767 -0
- package/dist/api/compiler/binder-utilities.d.ts +182 -0
- package/dist/api/compiler/binder-utilities.js +1240 -0
- package/dist/api/compiler/binder.d.ts +33 -0
- package/dist/api/compiler/binder.js +2358 -0
- package/dist/api/compiler/character-codes.d.ts +161 -0
- package/dist/api/compiler/character-codes.js +160 -0
- package/dist/api/compiler/checker-calls.d.ts +46 -0
- package/dist/api/compiler/checker-calls.js +1640 -0
- package/dist/api/compiler/checker-classes.d.ts +30 -0
- package/dist/api/compiler/checker-classes.js +582 -0
- package/dist/api/compiler/checker-contextual.d.ts +77 -0
- package/dist/api/compiler/checker-contextual.js +1136 -0
- package/dist/api/compiler/checker-declaration-order.d.ts +12 -0
- package/dist/api/compiler/checker-declaration-order.js +356 -0
- package/dist/api/compiler/checker-declarations.d.ts +33 -0
- package/dist/api/compiler/checker-declarations.js +888 -0
- package/dist/api/compiler/checker-declared-types.d.ts +48 -0
- package/dist/api/compiler/checker-declared-types.js +787 -0
- package/dist/api/compiler/checker-decorators.d.ts +26 -0
- package/dist/api/compiler/checker-decorators.js +562 -0
- package/dist/api/compiler/checker-deprecation.d.ts +33 -0
- package/dist/api/compiler/checker-deprecation.js +315 -0
- package/dist/api/compiler/checker-destructuring.d.ts +34 -0
- package/dist/api/compiler/checker-destructuring.js +584 -0
- package/dist/api/compiler/checker-elaboration.d.ts +15 -0
- package/dist/api/compiler/checker-elaboration.js +290 -0
- package/dist/api/compiler/checker-emit-helpers.d.ts +58 -0
- package/dist/api/compiler/checker-emit-helpers.js +154 -0
- package/dist/api/compiler/checker-emit-resolver.d.ts +75 -0
- package/dist/api/compiler/checker-emit-resolver.js +579 -0
- package/dist/api/compiler/checker-evaluator.d.ts +27 -0
- package/dist/api/compiler/checker-evaluator.js +188 -0
- package/dist/api/compiler/checker-expressions.d.ts +67 -0
- package/dist/api/compiler/checker-expressions.js +1351 -0
- package/dist/api/compiler/checker-features.d.ts +6 -0
- package/dist/api/compiler/checker-features.js +354 -0
- package/dist/api/compiler/checker-flow.d.ts +86 -0
- package/dist/api/compiler/checker-flow.js +169 -0
- package/dist/api/compiler/checker-functions.d.ts +43 -0
- package/dist/api/compiler/checker-functions.js +1002 -0
- package/dist/api/compiler/checker-generated-code.d.ts +25 -0
- package/dist/api/compiler/checker-generated-code.js +168 -0
- package/dist/api/compiler/checker-globals.d.ts +14 -0
- package/dist/api/compiler/checker-globals.js +37 -0
- package/dist/api/compiler/checker-grammar.d.ts +35 -0
- package/dist/api/compiler/checker-grammar.js +2573 -0
- package/dist/api/compiler/checker-heritage.d.ts +28 -0
- package/dist/api/compiler/checker-heritage.js +900 -0
- package/dist/api/compiler/checker-inference.d.ts +179 -0
- package/dist/api/compiler/checker-inference.js +2105 -0
- package/dist/api/compiler/checker-iteration.d.ts +115 -0
- package/dist/api/compiler/checker-iteration.js +857 -0
- package/dist/api/compiler/checker-javascript.d.ts +42 -0
- package/dist/api/compiler/checker-javascript.js +441 -0
- package/dist/api/compiler/checker-jsdoc.d.ts +30 -0
- package/dist/api/compiler/checker-jsdoc.js +320 -0
- package/dist/api/compiler/checker-jsx.d.ts +94 -0
- package/dist/api/compiler/checker-jsx.js +1433 -0
- package/dist/api/compiler/checker-literals.d.ts +6 -0
- package/dist/api/compiler/checker-literals.js +43 -0
- package/dist/api/compiler/checker-members.d.ts +198 -0
- package/dist/api/compiler/checker-members.js +2126 -0
- package/dist/api/compiler/checker-modules.d.ts +85 -0
- package/dist/api/compiler/checker-modules.js +2141 -0
- package/dist/api/compiler/checker-narrowing.d.ts +120 -0
- package/dist/api/compiler/checker-narrowing.js +2797 -0
- package/dist/api/compiler/checker-object-literals.d.ts +14 -0
- package/dist/api/compiler/checker-object-literals.js +479 -0
- package/dist/api/compiler/checker-operators.d.ts +33 -0
- package/dist/api/compiler/checker-operators.js +1040 -0
- package/dist/api/compiler/checker-overloads.d.ts +7 -0
- package/dist/api/compiler/checker-overloads.js +270 -0
- package/dist/api/compiler/checker-property-access.d.ts +34 -0
- package/dist/api/compiler/checker-property-access.js +672 -0
- package/dist/api/compiler/checker-services.d.ts +49 -0
- package/dist/api/compiler/checker-services.js +995 -0
- package/dist/api/compiler/checker-signatures.d.ts +55 -0
- package/dist/api/compiler/checker-signatures.js +788 -0
- package/dist/api/compiler/checker-source-file.d.ts +27 -0
- package/dist/api/compiler/checker-source-file.js +619 -0
- package/dist/api/compiler/checker-statements.d.ts +18 -0
- package/dist/api/compiler/checker-statements.js +226 -0
- package/dist/api/compiler/checker-super.d.ts +13 -0
- package/dist/api/compiler/checker-super.js +241 -0
- package/dist/api/compiler/checker-symbol-types.d.ts +67 -0
- package/dist/api/compiler/checker-symbol-types.js +1885 -0
- package/dist/api/compiler/checker-symbols.d.ts +181 -0
- package/dist/api/compiler/checker-symbols.js +1782 -0
- package/dist/api/compiler/checker-type-factory.d.ts +142 -0
- package/dist/api/compiler/checker-type-factory.js +2501 -0
- package/dist/api/compiler/checker-type-nodes.d.ts +26 -0
- package/dist/api/compiler/checker-type-nodes.js +828 -0
- package/dist/api/compiler/checker-type-operators.d.ts +109 -0
- package/dist/api/compiler/checker-type-operators.js +1842 -0
- package/dist/api/compiler/checker-types.d.ts +1027 -0
- package/dist/api/compiler/checker-types.js +1697 -0
- package/dist/api/compiler/checker-unused.d.ts +19 -0
- package/dist/api/compiler/checker-unused.js +524 -0
- package/dist/api/compiler/checker-utilities.d.ts +33 -0
- package/dist/api/compiler/checker-utilities.js +141 -0
- package/dist/api/compiler/checker.d.ts +491 -0
- package/dist/api/compiler/checker.js +912 -0
- package/dist/api/compiler/command-line.d.ts +32 -0
- package/dist/api/compiler/command-line.js +383 -0
- package/dist/api/compiler/compile-program.d.ts +118 -0
- package/dist/api/compiler/compile-program.js +384 -0
- package/dist/api/compiler/diagnostic-locales.d.ts +22 -0
- package/dist/api/compiler/diagnostic-locales.js +64 -0
- package/dist/api/compiler/diagnostic-messages.d.ts +2166 -0
- package/dist/api/compiler/diagnostic-messages.js +184 -0
- package/dist/api/compiler/diagnostics.d.ts +167 -0
- package/dist/api/compiler/diagnostics.js +820 -0
- package/dist/api/compiler/emitter.d.ts +71 -0
- package/dist/api/compiler/emitter.js +327 -0
- package/dist/api/compiler/file-include.d.ts +117 -0
- package/dist/api/compiler/file-include.js +536 -0
- package/dist/api/compiler/file-loader.d.ts +261 -0
- package/dist/api/compiler/file-loader.js +1257 -0
- package/dist/api/compiler/file-system.d.ts +51 -0
- package/dist/api/compiler/file-system.js +132 -0
- package/dist/api/compiler/flow.d.ts +60 -0
- package/dist/api/compiler/flow.js +45 -0
- package/dist/api/compiler/instantiation.d.ts +74 -0
- package/dist/api/compiler/instantiation.js +799 -0
- package/dist/api/compiler/jsdoc.d.ts +75 -0
- package/dist/api/compiler/jsdoc.js +1229 -0
- package/dist/api/compiler/link-tables.d.ts +36 -0
- package/dist/api/compiler/link-tables.js +83 -0
- package/dist/api/compiler/locale-data.d.ts +24 -0
- package/dist/api/compiler/locale-data.js +183 -0
- package/dist/api/compiler/locale.d.ts +4 -0
- package/dist/api/compiler/locale.js +317 -0
- package/dist/api/compiler/locales/cs-CZ.d.ts +2 -0
- package/dist/api/compiler/locales/cs-CZ.js +3 -0
- package/dist/api/compiler/locales/de-DE.d.ts +2 -0
- package/dist/api/compiler/locales/de-DE.js +3 -0
- package/dist/api/compiler/locales/es-ES.d.ts +2 -0
- package/dist/api/compiler/locales/es-ES.js +3 -0
- package/dist/api/compiler/locales/fr-FR.d.ts +2 -0
- package/dist/api/compiler/locales/fr-FR.js +3 -0
- package/dist/api/compiler/locales/it-IT.d.ts +2 -0
- package/dist/api/compiler/locales/it-IT.js +3 -0
- package/dist/api/compiler/locales/ja-JP.d.ts +2 -0
- package/dist/api/compiler/locales/ja-JP.js +3 -0
- package/dist/api/compiler/locales/ko-KR.d.ts +2 -0
- package/dist/api/compiler/locales/ko-KR.js +3 -0
- package/dist/api/compiler/locales/pl-PL.d.ts +2 -0
- package/dist/api/compiler/locales/pl-PL.js +3 -0
- package/dist/api/compiler/locales/pt-BR.d.ts +2 -0
- package/dist/api/compiler/locales/pt-BR.js +3 -0
- package/dist/api/compiler/locales/ru-RU.d.ts +2 -0
- package/dist/api/compiler/locales/ru-RU.js +3 -0
- package/dist/api/compiler/locales/tr-TR.d.ts +2 -0
- package/dist/api/compiler/locales/tr-TR.js +3 -0
- package/dist/api/compiler/locales/zh-CN.d.ts +2 -0
- package/dist/api/compiler/locales/zh-CN.js +3 -0
- package/dist/api/compiler/locales/zh-TW.d.ts +2 -0
- package/dist/api/compiler/locales/zh-TW.js +3 -0
- package/dist/api/compiler/module-resolution-types.d.ts +83 -0
- package/dist/api/compiler/module-resolution-types.js +176 -0
- package/dist/api/compiler/module-resolution.d.ts +71 -0
- package/dist/api/compiler/module-resolution.js +1598 -0
- package/dist/api/compiler/module-specifiers.d.ts +64 -0
- package/dist/api/compiler/module-specifiers.js +1101 -0
- package/dist/api/compiler/name-resolver.d.ts +43 -0
- package/dist/api/compiler/name-resolver.js +509 -0
- package/dist/api/compiler/node-builder-names.d.ts +32 -0
- package/dist/api/compiler/node-builder-names.js +854 -0
- package/dist/api/compiler/node-builder-pseudo.d.ts +36 -0
- package/dist/api/compiler/node-builder-pseudo.js +744 -0
- package/dist/api/compiler/node-builder-reuse.d.ts +4 -0
- package/dist/api/compiler/node-builder-reuse.js +647 -0
- package/dist/api/compiler/node-builder.d.ts +270 -0
- package/dist/api/compiler/node-builder.js +2645 -0
- package/dist/api/compiler/option-declarations.d.ts +90 -0
- package/dist/api/compiler/option-declarations.js +1460 -0
- package/dist/api/compiler/options.d.ts +289 -0
- package/dist/api/compiler/options.js +1197 -0
- package/dist/api/compiler/output-paths.d.ts +42 -0
- package/dist/api/compiler/output-paths.js +195 -0
- package/dist/api/compiler/package-json.d.ts +175 -0
- package/dist/api/compiler/package-json.js +1015 -0
- package/dist/api/compiler/parallel-parse.d.ts +219 -0
- package/dist/api/compiler/parallel-parse.js +537 -0
- package/dist/api/compiler/parser.d.ts +587 -0
- package/dist/api/compiler/parser.js +6407 -0
- package/dist/api/compiler/path.d.ts +91 -0
- package/dist/api/compiler/path.js +705 -0
- package/dist/api/compiler/printer/async-helpers.d.ts +22 -0
- package/dist/api/compiler/printer/async-helpers.js +91 -0
- package/dist/api/compiler/printer/auto-generate.d.ts +13 -0
- package/dist/api/compiler/printer/auto-generate.js +20 -0
- package/dist/api/compiler/printer/decorator-helpers.d.ts +24 -0
- package/dist/api/compiler/printer/decorator-helpers.js +118 -0
- package/dist/api/compiler/printer/emit-context.d.ts +154 -0
- package/dist/api/compiler/printer/emit-context.js +576 -0
- package/dist/api/compiler/printer/emit-flags.d.ts +60 -0
- package/dist/api/compiler/printer/emit-flags.js +2 -0
- package/dist/api/compiler/printer/factory-base.d.ts +171 -0
- package/dist/api/compiler/printer/factory-base.js +1505 -0
- package/dist/api/compiler/printer/factory.d.ts +147 -0
- package/dist/api/compiler/printer/factory.js +542 -0
- package/dist/api/compiler/printer/helpers.d.ts +27 -0
- package/dist/api/compiler/printer/helpers.js +164 -0
- package/dist/api/compiler/printer/name-generator.d.ts +41 -0
- package/dist/api/compiler/printer/name-generator.js +283 -0
- package/dist/api/compiler/printer/printer.d.ts +411 -0
- package/dist/api/compiler/printer/printer.js +4517 -0
- package/dist/api/compiler/printer/text-writer.d.ts +46 -0
- package/dist/api/compiler/printer/text-writer.js +172 -0
- package/dist/api/compiler/printer/utilities.d.ts +82 -0
- package/dist/api/compiler/printer/utilities.js +817 -0
- package/dist/api/compiler/program-checker.d.ts +156 -0
- package/dist/api/compiler/program-checker.js +526 -0
- package/dist/api/compiler/program-utilities.d.ts +52 -0
- package/dist/api/compiler/program-utilities.js +365 -0
- package/dist/api/compiler/program.d.ts +180 -0
- package/dist/api/compiler/program.js +1011 -0
- package/dist/api/compiler/pseudo-bigint.d.ts +5 -0
- package/dist/api/compiler/pseudo-bigint.js +61 -0
- package/dist/api/compiler/regexp-checker.d.ts +38 -0
- package/dist/api/compiler/regexp-checker.js +942 -0
- package/dist/api/compiler/relations.d.ts +263 -0
- package/dist/api/compiler/relations.js +4002 -0
- package/dist/api/compiler/reparser.d.ts +48 -0
- package/dist/api/compiler/reparser.js +1323 -0
- package/dist/api/compiler/scanner.d.ts +256 -0
- package/dist/api/compiler/scanner.js +2853 -0
- package/dist/api/compiler/side-state.d.ts +16 -0
- package/dist/api/compiler/side-state.js +89 -0
- package/dist/api/compiler/sourcemap.d.ts +55 -0
- package/dist/api/compiler/sourcemap.js +340 -0
- package/dist/api/compiler/spelling.d.ts +14 -0
- package/dist/api/compiler/spelling.js +128 -0
- package/dist/api/compiler/symbol-accessibility.d.ts +57 -0
- package/dist/api/compiler/symbol-accessibility.js +894 -0
- package/dist/api/compiler/symbol.d.ts +240 -0
- package/dist/api/compiler/symbol.js +228 -0
- package/dist/api/compiler/symlinks.d.ts +32 -0
- package/dist/api/compiler/symlinks.js +114 -0
- package/dist/api/compiler/syntax-kind.d.ts +389 -0
- package/dist/api/compiler/syntax-kind.js +2 -0
- package/dist/api/compiler/timeline.d.ts +9 -0
- package/dist/api/compiler/timeline.js +54 -0
- package/dist/api/compiler/transformers/alias-references.d.ts +39 -0
- package/dist/api/compiler/transformers/alias-references.js +676 -0
- package/dist/api/compiler/transformers/async-utilities.d.ts +51 -0
- package/dist/api/compiler/transformers/async-utilities.js +260 -0
- package/dist/api/compiler/transformers/async.d.ts +53 -0
- package/dist/api/compiler/transformers/async.js +645 -0
- package/dist/api/compiler/transformers/class-fields.d.ts +206 -0
- package/dist/api/compiler/transformers/class-fields.js +2418 -0
- package/dist/api/compiler/transformers/class-utilities.d.ts +46 -0
- package/dist/api/compiler/transformers/class-utilities.js +261 -0
- package/dist/api/compiler/transformers/commonjs-module.d.ts +103 -0
- package/dist/api/compiler/transformers/commonjs-module.js +1180 -0
- package/dist/api/compiler/transformers/const-enum-inliner.d.ts +11 -0
- package/dist/api/compiler/transformers/const-enum-inliner.js +36 -0
- package/dist/api/compiler/transformers/declarations-diagnostics.d.ts +52 -0
- package/dist/api/compiler/transformers/declarations-diagnostics.js +538 -0
- package/dist/api/compiler/transformers/declarations-pseudo.d.ts +160 -0
- package/dist/api/compiler/transformers/declarations-pseudo.js +797 -0
- package/dist/api/compiler/transformers/declarations-resolver.d.ts +152 -0
- package/dist/api/compiler/transformers/declarations-resolver.js +35 -0
- package/dist/api/compiler/transformers/declarations-syntactic.d.ts +119 -0
- package/dist/api/compiler/transformers/declarations-syntactic.js +1582 -0
- package/dist/api/compiler/transformers/declarations-tracker.d.ts +46 -0
- package/dist/api/compiler/transformers/declarations-tracker.js +197 -0
- package/dist/api/compiler/transformers/declarations.d.ts +175 -0
- package/dist/api/compiler/transformers/declarations.js +2380 -0
- package/dist/api/compiler/transformers/decorator-metadata.d.ts +54 -0
- package/dist/api/compiler/transformers/decorator-metadata.js +554 -0
- package/dist/api/compiler/transformers/decorator-utilities.d.ts +38 -0
- package/dist/api/compiler/transformers/decorator-utilities.js +238 -0
- package/dist/api/compiler/transformers/destructuring.d.ts +25 -0
- package/dist/api/compiler/transformers/destructuring.js +626 -0
- package/dist/api/compiler/transformers/downlevel.d.ts +6 -0
- package/dist/api/compiler/transformers/downlevel.js +45 -0
- package/dist/api/compiler/transformers/emit-resolver.d.ts +61 -0
- package/dist/api/compiler/transformers/emit-resolver.js +197 -0
- package/dist/api/compiler/transformers/es-decorators.d.ts +118 -0
- package/dist/api/compiler/transformers/es-decorators.js +1901 -0
- package/dist/api/compiler/transformers/exponentiation.d.ts +11 -0
- package/dist/api/compiler/transformers/exponentiation.js +76 -0
- package/dist/api/compiler/transformers/external-module-info.d.ts +35 -0
- package/dist/api/compiler/transformers/external-module-info.js +351 -0
- package/dist/api/compiler/transformers/for-await.d.ts +43 -0
- package/dist/api/compiler/transformers/for-await.js +469 -0
- package/dist/api/compiler/transformers/import-elision.d.ts +16 -0
- package/dist/api/compiler/transformers/import-elision.js +124 -0
- package/dist/api/compiler/transformers/jsx-entities.d.ts +1 -0
- package/dist/api/compiler/transformers/jsx-entities.js +256 -0
- package/dist/api/compiler/transformers/jsx.d.ts +71 -0
- package/dist/api/compiler/transformers/jsx.js +700 -0
- package/dist/api/compiler/transformers/legacy-decorators.d.ts +56 -0
- package/dist/api/compiler/transformers/legacy-decorators.js +564 -0
- package/dist/api/compiler/transformers/logical-assignment.d.ts +14 -0
- package/dist/api/compiler/transformers/logical-assignment.js +62 -0
- package/dist/api/compiler/transformers/module-utilities.d.ts +9 -0
- package/dist/api/compiler/transformers/module-utilities.js +36 -0
- package/dist/api/compiler/transformers/module.d.ts +49 -0
- package/dist/api/compiler/transformers/module.js +296 -0
- package/dist/api/compiler/transformers/named-evaluation.d.ts +26 -0
- package/dist/api/compiler/transformers/named-evaluation.js +266 -0
- package/dist/api/compiler/transformers/nullish-coalescing.d.ts +9 -0
- package/dist/api/compiler/transformers/nullish-coalescing.js +26 -0
- package/dist/api/compiler/transformers/object-rest-spread.d.ts +34 -0
- package/dist/api/compiler/transformers/object-rest-spread.js +411 -0
- package/dist/api/compiler/transformers/optional-catch.d.ts +9 -0
- package/dist/api/compiler/transformers/optional-catch.js +20 -0
- package/dist/api/compiler/transformers/optional-chain.d.ts +14 -0
- package/dist/api/compiler/transformers/optional-chain.js +188 -0
- package/dist/api/compiler/transformers/reference-resolver.d.ts +128 -0
- package/dist/api/compiler/transformers/reference-resolver.js +1155 -0
- package/dist/api/compiler/transformers/runtime-syntax.d.ts +71 -0
- package/dist/api/compiler/transformers/runtime-syntax.js +753 -0
- package/dist/api/compiler/transformers/subtree-facts.d.ts +9 -0
- package/dist/api/compiler/transformers/subtree-facts.js +203 -0
- package/dist/api/compiler/transformers/syntax-facts.d.ts +51 -0
- package/dist/api/compiler/transformers/syntax-facts.js +254 -0
- package/dist/api/compiler/transformers/tagged-template.d.ts +17 -0
- package/dist/api/compiler/transformers/tagged-template.js +148 -0
- package/dist/api/compiler/transformers/transformer.d.ts +17 -0
- package/dist/api/compiler/transformers/transformer.js +54 -0
- package/dist/api/compiler/transformers/type-eraser.d.ts +21 -0
- package/dist/api/compiler/transformers/type-eraser.js +346 -0
- package/dist/api/compiler/transformers/type-serialization.d.ts +20 -0
- package/dist/api/compiler/transformers/type-serialization.js +347 -0
- package/dist/api/compiler/transformers/using.d.ts +56 -0
- package/dist/api/compiler/transformers/using.js +453 -0
- package/dist/api/compiler/transformers/utilities.d.ts +50 -0
- package/dist/api/compiler/transformers/utilities.js +347 -0
- package/dist/api/compiler/transformers/visitor-base.d.ts +6 -0
- package/dist/api/compiler/transformers/visitor-base.js +817 -0
- package/dist/api/compiler/transformers/visitor-hooks.d.ts +29 -0
- package/dist/api/compiler/transformers/visitor-hooks.js +189 -0
- package/dist/api/compiler/tsconfig.d.ts +177 -0
- package/dist/api/compiler/tsconfig.js +1311 -0
- package/dist/api/compiler/type-printer.d.ts +15 -0
- package/dist/api/compiler/type-printer.js +74 -0
- package/dist/api/compiler/types.d.ts +87 -0
- package/dist/api/compiler/types.js +23 -0
- package/dist/api/compiler/unicode-identifiers.d.ts +2 -0
- package/dist/api/compiler/unicode-identifiers.js +209 -0
- package/dist/api/compiler/unicode-properties.d.ts +8 -0
- package/dist/api/compiler/unicode-properties.js +531 -0
- package/dist/api/compiler/vfs-match.d.ts +24 -0
- package/dist/api/compiler/vfs-match.js +587 -0
- package/dist/api/library/ast.d.ts +3 -2
- package/dist/api/library/ast.generated.d.ts +127 -139
- package/dist/api/library/checker.d.ts +51 -0
- package/dist/api/library/checker.js +318 -0
- package/dist/api/library/diagnostics.d.ts +13 -0
- package/dist/api/library/diagnostics.js +50 -0
- package/dist/api/library/disk.d.ts +13 -0
- package/dist/api/library/disk.js +66 -0
- package/dist/api/library/errors.d.ts +13 -0
- package/dist/api/library/errors.js +24 -0
- package/dist/api/library/host.d.ts +24 -0
- package/dist/api/library/host.js +52 -0
- package/dist/api/library/index.d.ts +5 -1
- package/dist/api/library/index.js +4 -0
- package/dist/api/library/nodes.d.ts +51 -0
- package/dist/api/library/nodes.js +196 -0
- package/dist/api/library/options.d.ts +144 -0
- package/dist/api/library/options.js +308 -0
- package/dist/api/library/parse.d.ts +19 -0
- package/dist/api/library/parse.js +41 -0
- package/dist/api/library/program.d.ts +21 -0
- package/dist/api/library/program.js +234 -0
- package/dist/api/library/types.d.ts +14 -1
- package/package.json +12 -8
- package/src/compiler/ast-utilities.ts +548 -0
- package/src/compiler/ast.ts +12862 -0
- package/src/compiler/astnav.ts +799 -0
- package/src/compiler/binder-utilities.ts +1392 -0
- package/src/compiler/binder.ts +2703 -0
- package/src/compiler/build-info.ts +1197 -0
- package/src/compiler/character-codes.ts +323 -0
- package/src/compiler/checker-calls.ts +2155 -0
- package/src/compiler/checker-classes.ts +706 -0
- package/src/compiler/checker-contextual.ts +1457 -0
- package/src/compiler/checker-declaration-order.ts +438 -0
- package/src/compiler/checker-declarations.ts +1194 -0
- package/src/compiler/checker-declared-types.ts +919 -0
- package/src/compiler/checker-decorators.ts +694 -0
- package/src/compiler/checker-deprecation.ts +359 -0
- package/src/compiler/checker-destructuring.ts +805 -0
- package/src/compiler/checker-elaboration.ts +477 -0
- package/src/compiler/checker-emit-helpers.ts +224 -0
- package/src/compiler/checker-emit-resolver.ts +769 -0
- package/src/compiler/checker-evaluator.ts +243 -0
- package/src/compiler/checker-expressions.ts +1831 -0
- package/src/compiler/checker-features.ts +361 -0
- package/src/compiler/checker-flow.ts +394 -0
- package/src/compiler/checker-functions.ts +1296 -0
- package/src/compiler/checker-generated-code.ts +227 -0
- package/src/compiler/checker-globals.ts +52 -0
- package/src/compiler/checker-grammar.ts +3584 -0
- package/src/compiler/checker-heritage.ts +1233 -0
- package/src/compiler/checker-inference.ts +2576 -0
- package/src/compiler/checker-iteration.ts +1206 -0
- package/src/compiler/checker-javascript.ts +502 -0
- package/src/compiler/checker-jsdoc.ts +360 -0
- package/src/compiler/checker-jsx.ts +1924 -0
- package/src/compiler/checker-literals.ts +61 -0
- package/src/compiler/checker-members.ts +2436 -0
- package/src/compiler/checker-modules.ts +2886 -0
- package/src/compiler/checker-narrowing.ts +3230 -0
- package/src/compiler/checker-object-literals.ts +575 -0
- package/src/compiler/checker-operators.ts +1422 -0
- package/src/compiler/checker-overloads.ts +328 -0
- package/src/compiler/checker-property-access.ts +906 -0
- package/src/compiler/checker-services.ts +1149 -0
- package/src/compiler/checker-signatures.ts +1032 -0
- package/src/compiler/checker-source-file.ts +732 -0
- package/src/compiler/checker-statements.ts +292 -0
- package/src/compiler/checker-super.ts +261 -0
- package/src/compiler/checker-symbol-types.ts +2107 -0
- package/src/compiler/checker-symbols.ts +2150 -0
- package/src/compiler/checker-type-factory.ts +2579 -0
- package/src/compiler/checker-type-nodes.ts +1033 -0
- package/src/compiler/checker-type-operators.ts +2502 -0
- package/src/compiler/checker-types.ts +2340 -0
- package/src/compiler/checker-unused.ts +642 -0
- package/src/compiler/checker-utilities.ts +161 -0
- package/src/compiler/checker.ts +1116 -0
- package/src/compiler/command-line.ts +436 -0
- package/src/compiler/compile-program.ts +439 -0
- package/src/compiler/decoder.ts +1209 -0
- package/src/compiler/diagnostic-locales.ts +86 -0
- package/src/compiler/diagnostic-messages.ts +2349 -0
- package/src/compiler/diagnostics.ts +897 -0
- package/src/compiler/emitter.ts +434 -0
- package/src/compiler/encoder.ts +1945 -0
- package/src/compiler/file-include.ts +673 -0
- package/src/compiler/file-loader.ts +1528 -0
- package/src/compiler/file-system.ts +143 -0
- package/src/compiler/flow.ts +89 -0
- package/src/compiler/help.ts +473 -0
- package/src/compiler/incremental.ts +2784 -0
- package/src/compiler/init.ts +141 -0
- package/src/compiler/instantiation.ts +894 -0
- package/src/compiler/jsdoc.ts +1386 -0
- package/src/compiler/link-tables.ts +98 -0
- package/src/compiler/locale-data.ts +203 -0
- package/src/compiler/locale.ts +307 -0
- package/src/compiler/locales/cs-CZ.ts +5 -0
- package/src/compiler/locales/de-DE.ts +5 -0
- package/src/compiler/locales/es-ES.ts +5 -0
- package/src/compiler/locales/fr-FR.ts +5 -0
- package/src/compiler/locales/it-IT.ts +5 -0
- package/src/compiler/locales/ja-JP.ts +5 -0
- package/src/compiler/locales/ko-KR.ts +5 -0
- package/src/compiler/locales/pl-PL.ts +5 -0
- package/src/compiler/locales/pt-BR.ts +5 -0
- package/src/compiler/locales/ru-RU.ts +5 -0
- package/src/compiler/locales/tr-TR.ts +5 -0
- package/src/compiler/locales/zh-CN.ts +5 -0
- package/src/compiler/locales/zh-TW.ts +5 -0
- package/src/compiler/module-resolution-types.ts +243 -0
- package/src/compiler/module-resolution.ts +2072 -0
- package/src/compiler/module-specifiers.ts +1491 -0
- package/src/compiler/name-resolver.ts +646 -0
- package/src/compiler/node-builder-names.ts +1069 -0
- package/src/compiler/node-builder-pseudo.ts +892 -0
- package/src/compiler/node-builder-reuse.ts +764 -0
- package/src/compiler/node-builder.ts +3425 -0
- package/src/compiler/option-declarations.ts +1560 -0
- package/src/compiler/options.ts +1576 -0
- package/src/compiler/output-paths.ts +334 -0
- package/src/compiler/package-json.ts +1083 -0
- package/src/compiler/parallel-check.ts +1951 -0
- package/src/compiler/parallel-parse.ts +590 -0
- package/src/compiler/parse-thread.ts +140 -0
- package/src/compiler/parser.ts +7716 -0
- package/src/compiler/path.ts +717 -0
- package/src/compiler/printer/async-helpers.ts +183 -0
- package/src/compiler/printer/auto-generate.ts +27 -0
- package/src/compiler/printer/decorator-helpers.ts +218 -0
- package/src/compiler/printer/emit-context.ts +679 -0
- package/src/compiler/printer/emit-flags.ts +64 -0
- package/src/compiler/printer/factory-base.ts +2577 -0
- package/src/compiler/printer/factory.ts +764 -0
- package/src/compiler/printer/helpers.ts +291 -0
- package/src/compiler/printer/name-generator.ts +372 -0
- package/src/compiler/printer/printer.ts +5072 -0
- package/src/compiler/printer/text-writer.ts +183 -0
- package/src/compiler/printer/utilities.ts +884 -0
- package/src/compiler/program-checker.ts +592 -0
- package/src/compiler/program-utilities.ts +435 -0
- package/src/compiler/program.ts +1419 -0
- package/src/compiler/pseudo-bigint.ts +62 -0
- package/src/compiler/regexp-checker.ts +1142 -0
- package/src/compiler/relations.ts +5149 -0
- package/src/compiler/reparser.ts +1566 -0
- package/src/compiler/scanner.ts +2951 -0
- package/src/compiler/show-config.ts +239 -0
- package/src/compiler/side-state.ts +125 -0
- package/src/compiler/sourcemap.ts +366 -0
- package/src/compiler/spelling.ts +122 -0
- package/src/compiler/symbol-accessibility.ts +1071 -0
- package/src/compiler/symbol.ts +439 -0
- package/src/compiler/symlinks.ts +137 -0
- package/src/compiler/syntax-kind.ts +391 -0
- package/src/compiler/thread-entry.ts +191 -0
- package/src/compiler/timeline.ts +53 -0
- package/src/compiler/transformers/alias-references.ts +757 -0
- package/src/compiler/transformers/async-utilities.ts +335 -0
- package/src/compiler/transformers/async.ts +838 -0
- package/src/compiler/transformers/class-fields.ts +2967 -0
- package/src/compiler/transformers/class-utilities.ts +324 -0
- package/src/compiler/transformers/commonjs-module.ts +1621 -0
- package/src/compiler/transformers/const-enum-inliner.ts +50 -0
- package/src/compiler/transformers/declarations-diagnostics.ts +832 -0
- package/src/compiler/transformers/declarations-pseudo.ts +966 -0
- package/src/compiler/transformers/declarations-resolver.ts +249 -0
- package/src/compiler/transformers/declarations-syntactic.ts +1859 -0
- package/src/compiler/transformers/declarations-tracker.ts +269 -0
- package/src/compiler/transformers/declarations.ts +3120 -0
- package/src/compiler/transformers/decorator-metadata.ts +697 -0
- package/src/compiler/transformers/decorator-utilities.ts +283 -0
- package/src/compiler/transformers/destructuring.ts +708 -0
- package/src/compiler/transformers/downlevel.ts +50 -0
- package/src/compiler/transformers/emit-resolver.ts +258 -0
- package/src/compiler/transformers/es-decorators.ts +2682 -0
- package/src/compiler/transformers/exponentiation.ts +80 -0
- package/src/compiler/transformers/external-module-info.ts +412 -0
- package/src/compiler/transformers/for-await.ts +687 -0
- package/src/compiler/transformers/import-elision.ts +152 -0
- package/src/compiler/transformers/jsx-entities.ts +256 -0
- package/src/compiler/transformers/jsx.ts +824 -0
- package/src/compiler/transformers/legacy-decorators.ts +726 -0
- package/src/compiler/transformers/logical-assignment.ts +75 -0
- package/src/compiler/transformers/module-utilities.ts +42 -0
- package/src/compiler/transformers/module.ts +474 -0
- package/src/compiler/transformers/named-evaluation.ts +389 -0
- package/src/compiler/transformers/nullish-coalescing.ts +35 -0
- package/src/compiler/transformers/object-rest-spread.ts +577 -0
- package/src/compiler/transformers/optional-catch.ts +29 -0
- package/src/compiler/transformers/optional-chain.ts +246 -0
- package/src/compiler/transformers/reference-resolver.ts +1201 -0
- package/src/compiler/transformers/runtime-syntax.ts +942 -0
- package/src/compiler/transformers/subtree-facts.ts +245 -0
- package/src/compiler/transformers/syntax-facts.ts +353 -0
- package/src/compiler/transformers/tagged-template.ts +167 -0
- package/src/compiler/transformers/transformer.ts +56 -0
- package/src/compiler/transformers/type-eraser.ts +520 -0
- package/src/compiler/transformers/type-serialization.ts +374 -0
- package/src/compiler/transformers/using.ts +613 -0
- package/src/compiler/transformers/utilities.ts +419 -0
- package/src/compiler/transformers/visitor-base.ts +1601 -0
- package/src/compiler/transformers/visitor-hooks.ts +252 -0
- package/src/compiler/tsc-build.ts +1418 -0
- package/src/compiler/tsc-cli.ts +666 -0
- package/src/compiler/tsc-compile.ts +437 -0
- package/src/compiler/tsc-watch.ts +854 -0
- package/src/compiler/tsconfig.ts +1574 -0
- package/src/compiler/type-printer.ts +110 -0
- package/src/compiler/types.ts +115 -0
- package/src/compiler/unicode-identifiers.ts +212 -0
- package/src/compiler/unicode-properties.ts +537 -0
- package/src/compiler/vfs-match.ts +597 -0
- package/src/compiler/xxh3.ts +650 -0
- package/src/library/ast.generated.ts +141 -167
- package/src/library/ast.ts +4 -1
- package/src/library/checker.ts +384 -0
- package/src/library/diagnostics.ts +72 -0
- package/src/library/disk.ts +73 -0
- package/src/library/errors.ts +26 -0
- package/src/library/host.ts +63 -0
- package/src/library/index.ts +21 -0
- package/src/library/nodes.ts +232 -0
- package/src/library/options.ts +449 -0
- package/src/library/parse.ts +63 -0
- package/src/library/program.ts +293 -0
- package/src/library/types.ts +14 -1
|
@@ -0,0 +1,2967 @@
|
|
|
1
|
+
// Lowers class fields, private names, static blocks and `accessor` fields: initializers move to
|
|
2
|
+
// the constructor (useDefineForClassFields: false, or targets before ES2022), private members
|
|
3
|
+
// become WeakMaps, WeakSets and hoisted functions, and static `this` and `super` refer to the class.
|
|
4
|
+
import {
|
|
5
|
+
ArrayLiteralExpression,
|
|
6
|
+
BinaryExpression,
|
|
7
|
+
Block,
|
|
8
|
+
CallExpression,
|
|
9
|
+
ClassDeclaration,
|
|
10
|
+
ClassExpression,
|
|
11
|
+
ClassStaticBlockDeclaration,
|
|
12
|
+
ComputedPropertyName,
|
|
13
|
+
ConstructorDeclaration,
|
|
14
|
+
ElementAccessExpression,
|
|
15
|
+
ExportAssignment,
|
|
16
|
+
ExpressionStatement,
|
|
17
|
+
ExpressionWithTypeArguments,
|
|
18
|
+
ForStatement,
|
|
19
|
+
GetAccessorDeclaration,
|
|
20
|
+
HeritageClause,
|
|
21
|
+
Identifier,
|
|
22
|
+
ModifierFlags,
|
|
23
|
+
type ModifierList,
|
|
24
|
+
type Node,
|
|
25
|
+
NodeFlags,
|
|
26
|
+
NodeList,
|
|
27
|
+
ObjectLiteralExpression,
|
|
28
|
+
ParameterDeclaration,
|
|
29
|
+
ParenthesizedExpression,
|
|
30
|
+
PostfixUnaryExpression,
|
|
31
|
+
PrefixUnaryExpression,
|
|
32
|
+
PrivateIdentifier,
|
|
33
|
+
PropertyAccessExpression,
|
|
34
|
+
PropertyAssignment,
|
|
35
|
+
PropertyDeclaration,
|
|
36
|
+
SetAccessorDeclaration,
|
|
37
|
+
ShorthandPropertyAssignment,
|
|
38
|
+
SourceFile,
|
|
39
|
+
SpreadAssignment,
|
|
40
|
+
SpreadElement,
|
|
41
|
+
StringLiteral,
|
|
42
|
+
TaggedTemplateExpression,
|
|
43
|
+
TryStatement,
|
|
44
|
+
VariableStatement,
|
|
45
|
+
NewExpression,
|
|
46
|
+
ArrowFunction,
|
|
47
|
+
CatchClause,
|
|
48
|
+
FunctionExpression,
|
|
49
|
+
MethodDeclaration,
|
|
50
|
+
NodeVisitor,
|
|
51
|
+
VoidExpression,
|
|
52
|
+
getBody,
|
|
53
|
+
getParameters,
|
|
54
|
+
getInitializer,
|
|
55
|
+
getMembers,
|
|
56
|
+
getModifiers,
|
|
57
|
+
getName,
|
|
58
|
+
} from '../ast.js';
|
|
59
|
+
import { isLeftHandSideExpression } from '../ast-utilities.js';
|
|
60
|
+
import {
|
|
61
|
+
getNameOfDeclaration,
|
|
62
|
+
hasStaticModifier,
|
|
63
|
+
isAssignmentExpression,
|
|
64
|
+
isAutoAccessorPropertyDeclaration,
|
|
65
|
+
isClassLike,
|
|
66
|
+
isDestructuringAssignment,
|
|
67
|
+
isMethodOrAccessor,
|
|
68
|
+
isPrivateIdentifierClassElementDeclaration,
|
|
69
|
+
isStatic,
|
|
70
|
+
skipParentheses,
|
|
71
|
+
} from '../binder-utilities.js';
|
|
72
|
+
import { isIdentifierText } from '../scanner.js';
|
|
73
|
+
import type { CompilerOptions } from '../options.js';
|
|
74
|
+
import { ScriptTarget, getEmitScriptTarget, getUseDefineForClassFields } from '../options.js';
|
|
75
|
+
import type { EmitContext } from '../printer/emit-context.js';
|
|
76
|
+
import { EmitFlags, GeneratedIdentifierFlags } from '../printer/emit-flags.js';
|
|
77
|
+
import { NameOptions } from '../printer/factory.js';
|
|
78
|
+
import { isModifier, isPrologueDirective, isStatement, nodeIsSynthesized } from '../printer/utilities.js';
|
|
79
|
+
import { SyntaxKind } from '../syntax-kind.js';
|
|
80
|
+
import { TokenFlags } from '../types.js';
|
|
81
|
+
import {
|
|
82
|
+
classHasClassThisAssignment,
|
|
83
|
+
findSuperStatementIndexPath,
|
|
84
|
+
getClassMembers,
|
|
85
|
+
isClassThisAssignmentBlock,
|
|
86
|
+
} from './class-utilities.js';
|
|
87
|
+
import type { EmitResolver } from './emit-resolver.js';
|
|
88
|
+
import {
|
|
89
|
+
AnonymousFunctionFilter,
|
|
90
|
+
classHasExplicitlyAssignedName,
|
|
91
|
+
isClassNamedEvaluationHelperBlock,
|
|
92
|
+
isNamedEvaluation,
|
|
93
|
+
transformNamedEvaluation,
|
|
94
|
+
} from './named-evaluation.js';
|
|
95
|
+
import { SubtreeFacts, type SyntaxFacts } from './syntax-facts.js';
|
|
96
|
+
import { Transformer } from './transformer.js';
|
|
97
|
+
import {
|
|
98
|
+
OuterExpressionKinds,
|
|
99
|
+
hasDecorators,
|
|
100
|
+
hasSyntacticModifier,
|
|
101
|
+
isParameterPropertyDeclaration,
|
|
102
|
+
isSameNode,
|
|
103
|
+
skipOuterExpressions,
|
|
104
|
+
} from './utilities.js';
|
|
105
|
+
import { VisitorBase } from './visitor-base.js';
|
|
106
|
+
|
|
107
|
+
const enum ClassFacts {
|
|
108
|
+
None = 0,
|
|
109
|
+
ClassWasDecorated = 1 << 0,
|
|
110
|
+
NeedsClassConstructorReference = 1 << 1,
|
|
111
|
+
NeedsClassSuperReference = 1 << 2,
|
|
112
|
+
NeedsSubstitutionForThisInClassStaticField = 1 << 3,
|
|
113
|
+
WillHoistInitializersToConstructor = 1 << 4,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const enum PrivateKind {
|
|
117
|
+
Field,
|
|
118
|
+
Method,
|
|
119
|
+
Accessor,
|
|
120
|
+
/** Declared but left as a private name. */
|
|
121
|
+
Untransformed,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** How a private name is transformed. */
|
|
125
|
+
class PrivateIdentifierInfo {
|
|
126
|
+
kind: PrivateKind;
|
|
127
|
+
/** The WeakMap of an instance field, the WeakSet of instance methods and accessors, or the class for statics. */
|
|
128
|
+
brandCheckIdentifier: Identifier | undefined;
|
|
129
|
+
isStatic: boolean;
|
|
130
|
+
/** False for reserved names such as `#constructor` and duplicates. */
|
|
131
|
+
isValid: boolean;
|
|
132
|
+
/** The `{ value }` holder of a static field. */
|
|
133
|
+
variableName: Identifier | undefined;
|
|
134
|
+
methodName: Identifier | undefined;
|
|
135
|
+
getterName: Identifier | undefined;
|
|
136
|
+
setterName: Identifier | undefined;
|
|
137
|
+
|
|
138
|
+
constructor(kind: PrivateKind, brandCheckIdentifier: Identifier | undefined, isStatic: boolean, isValid: boolean) {
|
|
139
|
+
this.kind = kind;
|
|
140
|
+
this.brandCheckIdentifier = brandCheckIdentifier;
|
|
141
|
+
this.isStatic = isStatic;
|
|
142
|
+
this.isValid = isValid;
|
|
143
|
+
this.variableName = undefined;
|
|
144
|
+
this.methodName = undefined;
|
|
145
|
+
this.getterName = undefined;
|
|
146
|
+
this.setterName = undefined;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** The private names of a class, by text, and generated private names, by the node they're generated for. */
|
|
151
|
+
class PrivateEnvironment {
|
|
152
|
+
/** Prefixes generated variable names. */
|
|
153
|
+
className: Identifier | undefined;
|
|
154
|
+
/** Brand checks instances for private methods and accessors. */
|
|
155
|
+
weakSetName: Identifier | undefined;
|
|
156
|
+
readonly members: Map<string, PrivateIdentifierInfo>;
|
|
157
|
+
readonly generated: Map<Node, PrivateIdentifierInfo>;
|
|
158
|
+
|
|
159
|
+
constructor() {
|
|
160
|
+
this.className = undefined;
|
|
161
|
+
this.weakSetName = undefined;
|
|
162
|
+
this.members = new Map<string, PrivateIdentifierInfo>();
|
|
163
|
+
this.generated = new Map<Node, PrivateIdentifierInfo>();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
class ClassData {
|
|
168
|
+
facts: ClassFacts;
|
|
169
|
+
/** Brand checks static members and replaces `this` in static initializers. */
|
|
170
|
+
classConstructor: Identifier | undefined;
|
|
171
|
+
classThis: Identifier | undefined;
|
|
172
|
+
/** Replaces `super` in static initializers. */
|
|
173
|
+
superClassReference: Identifier | undefined;
|
|
174
|
+
|
|
175
|
+
constructor() {
|
|
176
|
+
this.facts = ClassFacts.None;
|
|
177
|
+
this.classConstructor = undefined;
|
|
178
|
+
this.classThis = undefined;
|
|
179
|
+
this.superClassReference = undefined;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
class ClassEnvironment {
|
|
184
|
+
readonly previous: ClassEnvironment | undefined;
|
|
185
|
+
data: ClassData | undefined;
|
|
186
|
+
privateEnv: PrivateEnvironment | undefined;
|
|
187
|
+
|
|
188
|
+
constructor(previous: ClassEnvironment | undefined) {
|
|
189
|
+
this.previous = previous;
|
|
190
|
+
this.data = undefined;
|
|
191
|
+
this.privateEnv = undefined;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
class ClassMembers {
|
|
196
|
+
readonly members: NodeList;
|
|
197
|
+
/** An assignment to evaluate before the class, from computed names using `this` or `super`. */
|
|
198
|
+
readonly prologue: Node | undefined;
|
|
199
|
+
|
|
200
|
+
constructor(members: NodeList, prologue: Node | undefined) {
|
|
201
|
+
this.members = members;
|
|
202
|
+
this.prologue = prologue;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** A receiver read twice: `read`, assigned by `initialize` first when it had to be cached. */
|
|
207
|
+
class CopiableReceiver {
|
|
208
|
+
readonly read: Node;
|
|
209
|
+
readonly initialize: Node | undefined;
|
|
210
|
+
|
|
211
|
+
constructor(read: Node, initialize: Node | undefined) {
|
|
212
|
+
this.read = read;
|
|
213
|
+
this.initialize = initialize;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
class CallBinding {
|
|
218
|
+
readonly thisArg: Node;
|
|
219
|
+
readonly target: Node;
|
|
220
|
+
|
|
221
|
+
constructor(thisArg: Node, target: Node) {
|
|
222
|
+
this.thisArg = thisArg;
|
|
223
|
+
this.target = target;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const enum VisitMode {
|
|
228
|
+
Modifier,
|
|
229
|
+
Discarded,
|
|
230
|
+
HeritageClause,
|
|
231
|
+
AssignmentTarget,
|
|
232
|
+
ClassElement,
|
|
233
|
+
AccessorFieldResult,
|
|
234
|
+
ArrayAssignmentElement,
|
|
235
|
+
ObjectAssignmentElement,
|
|
236
|
+
Substitution,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Visits children in one of the transform's modes. */
|
|
240
|
+
class ModeVisitor extends VisitorBase {
|
|
241
|
+
readonly owner: ClassFieldsTransformer;
|
|
242
|
+
readonly mode: VisitMode;
|
|
243
|
+
|
|
244
|
+
constructor(owner: ClassFieldsTransformer, mode: VisitMode) {
|
|
245
|
+
super(owner.context);
|
|
246
|
+
this.owner = owner;
|
|
247
|
+
this.mode = mode;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
visit(node: Node): Node | undefined {
|
|
251
|
+
return this.owner.visitInMode(this.mode, node);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const accessorStorageSuffix = '_accessor_storage';
|
|
256
|
+
|
|
257
|
+
export class ClassFieldsTransformer extends Transformer {
|
|
258
|
+
readonly options: CompilerOptions;
|
|
259
|
+
readonly facts: SyntaxFacts;
|
|
260
|
+
readonly resolver: EmitResolver;
|
|
261
|
+
private readonly legacyDecorators: boolean;
|
|
262
|
+
private readonly useDefineForClassFields: boolean;
|
|
263
|
+
private readonly shouldTransformInitializersUsingSet: boolean;
|
|
264
|
+
private readonly shouldTransformInitializersUsingDefine: boolean;
|
|
265
|
+
private readonly shouldTransformInitializers: boolean;
|
|
266
|
+
private readonly shouldTransformPrivateElementsOrClassStaticBlocks: boolean;
|
|
267
|
+
private readonly shouldTransformAutoAccessors: boolean;
|
|
268
|
+
/** Static initializers move out of the class body, so their `this` and `super` must name the class. */
|
|
269
|
+
private readonly shouldTransformThisInStaticInitializers: boolean;
|
|
270
|
+
private shouldTransformPrivateStaticElementsInFile: boolean;
|
|
271
|
+
/** Computed name expressions from elided names, to inline at the next execution site. */
|
|
272
|
+
private pendingExpressions: Node[];
|
|
273
|
+
/** Statements to emit after the current variable statement, for decorated classes. */
|
|
274
|
+
private pendingStatements: Node[];
|
|
275
|
+
private lexicalEnvironment: ClassEnvironment | undefined;
|
|
276
|
+
private currentClassContainer: Node | undefined;
|
|
277
|
+
private currentClassElement: Node | undefined;
|
|
278
|
+
/** Class declarations to aliases replacing references to the class in its static initializers. */
|
|
279
|
+
private readonly classAliases: Map<Node, Identifier>;
|
|
280
|
+
private readonly enclosingClassDeclarations: Set<Node>;
|
|
281
|
+
private inIterationStatement: boolean;
|
|
282
|
+
/** Computed property names evaluate in the scope outside the class. */
|
|
283
|
+
private insideComputedPropertyName: boolean;
|
|
284
|
+
private parentNode: Node | undefined;
|
|
285
|
+
private currentNode: Node | undefined;
|
|
286
|
+
private readonly modifierMode: ModeVisitor;
|
|
287
|
+
private readonly discarded: ModeVisitor;
|
|
288
|
+
private readonly heritageMode: ModeVisitor;
|
|
289
|
+
private readonly assignmentTargetMode: ModeVisitor;
|
|
290
|
+
private readonly classElementMode: ModeVisitor;
|
|
291
|
+
private readonly accessorResultMode: ModeVisitor;
|
|
292
|
+
private readonly arrayElementMode: ModeVisitor;
|
|
293
|
+
private readonly objectElementMode: ModeVisitor;
|
|
294
|
+
private readonly substitutionMode: ModeVisitor;
|
|
295
|
+
/** Anonymous classes that named evaluation must name here. */
|
|
296
|
+
private readonly classesNeedingNames: ClassesNeedingNames;
|
|
297
|
+
|
|
298
|
+
constructor(context: EmitContext, options: CompilerOptions, facts: SyntaxFacts, resolver: EmitResolver) {
|
|
299
|
+
super(context);
|
|
300
|
+
this.options = options;
|
|
301
|
+
this.facts = facts;
|
|
302
|
+
this.resolver = resolver;
|
|
303
|
+
const target = getEmitScriptTarget(options);
|
|
304
|
+
const useDefine = getUseDefineForClassFields(options);
|
|
305
|
+
this.legacyDecorators = options.experimentalDecorators === true;
|
|
306
|
+
this.useDefineForClassFields = useDefine;
|
|
307
|
+
this.shouldTransformInitializersUsingSet = !useDefine;
|
|
308
|
+
this.shouldTransformInitializersUsingDefine = useDefine && target < ScriptTarget.ES2022;
|
|
309
|
+
this.shouldTransformInitializers =
|
|
310
|
+
this.shouldTransformInitializersUsingSet || this.shouldTransformInitializersUsingDefine;
|
|
311
|
+
this.shouldTransformPrivateElementsOrClassStaticBlocks = target < ScriptTarget.ES2022;
|
|
312
|
+
this.shouldTransformAutoAccessors = target < ScriptTarget.ESNext;
|
|
313
|
+
this.shouldTransformThisInStaticInitializers = target < ScriptTarget.ES2022;
|
|
314
|
+
this.shouldTransformPrivateStaticElementsInFile = false;
|
|
315
|
+
this.pendingExpressions = [];
|
|
316
|
+
this.pendingStatements = [];
|
|
317
|
+
this.lexicalEnvironment = undefined;
|
|
318
|
+
this.currentClassContainer = undefined;
|
|
319
|
+
this.currentClassElement = undefined;
|
|
320
|
+
this.classAliases = new Map<Node, Identifier>();
|
|
321
|
+
this.enclosingClassDeclarations = new Set<Node>();
|
|
322
|
+
this.inIterationStatement = false;
|
|
323
|
+
this.insideComputedPropertyName = false;
|
|
324
|
+
this.parentNode = undefined;
|
|
325
|
+
this.currentNode = undefined;
|
|
326
|
+
this.modifierMode = new ModeVisitor(this, VisitMode.Modifier);
|
|
327
|
+
this.discarded = new ModeVisitor(this, VisitMode.Discarded);
|
|
328
|
+
this.heritageMode = new ModeVisitor(this, VisitMode.HeritageClause);
|
|
329
|
+
this.assignmentTargetMode = new ModeVisitor(this, VisitMode.AssignmentTarget);
|
|
330
|
+
this.classElementMode = new ModeVisitor(this, VisitMode.ClassElement);
|
|
331
|
+
this.accessorResultMode = new ModeVisitor(this, VisitMode.AccessorFieldResult);
|
|
332
|
+
this.arrayElementMode = new ModeVisitor(this, VisitMode.ArrayAssignmentElement);
|
|
333
|
+
this.objectElementMode = new ModeVisitor(this, VisitMode.ObjectAssignmentElement);
|
|
334
|
+
this.substitutionMode = new ModeVisitor(this, VisitMode.Substitution);
|
|
335
|
+
this.classesNeedingNames = new ClassesNeedingNames(this);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
visitInMode(mode: VisitMode, node: Node): Node | undefined {
|
|
339
|
+
switch (mode) {
|
|
340
|
+
case VisitMode.Modifier:
|
|
341
|
+
return this.visitModifier(node);
|
|
342
|
+
case VisitMode.Discarded:
|
|
343
|
+
return this.visitDiscardedValue(node);
|
|
344
|
+
case VisitMode.HeritageClause:
|
|
345
|
+
return this.visitHeritageClause(node);
|
|
346
|
+
case VisitMode.AssignmentTarget:
|
|
347
|
+
if (node instanceof ObjectLiteralExpression || node instanceof ArrayLiteralExpression)
|
|
348
|
+
return this.visitAssignmentPattern(node);
|
|
349
|
+
return this.visit(node);
|
|
350
|
+
case VisitMode.ClassElement:
|
|
351
|
+
return this.visitClassElement(node);
|
|
352
|
+
case VisitMode.AccessorFieldResult:
|
|
353
|
+
return this.visitAccessorFieldResult(node);
|
|
354
|
+
case VisitMode.ArrayAssignmentElement:
|
|
355
|
+
return this.visitArrayAssignmentElement(node);
|
|
356
|
+
case VisitMode.ObjectAssignmentElement:
|
|
357
|
+
return this.visitObjectAssignmentElement(node);
|
|
358
|
+
case VisitMode.Substitution:
|
|
359
|
+
return this.visitForSubstitution(node);
|
|
360
|
+
}
|
|
361
|
+
return node;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Whether an auto-accessor, a `#x in` check or a private access needs WeakMaps and WeakSets. */
|
|
365
|
+
private requiresBlockScopedVar(): boolean {
|
|
366
|
+
const container = this.currentClassContainer;
|
|
367
|
+
return this.inIterationStatement && container !== undefined && container.kind === SyntaxKind.ClassExpression;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Whether a class expression's temporary is block scoped: it's in a loop and has an instance field with a computed name. */
|
|
371
|
+
private classExpressionNeedsBlockScopedTemp(): boolean {
|
|
372
|
+
if (!this.requiresBlockScopedVar()) return false;
|
|
373
|
+
const members = membersOf(this.currentClassContainer!);
|
|
374
|
+
for (let i = 0; i < members.length; i++) {
|
|
375
|
+
const member = members[i];
|
|
376
|
+
if (
|
|
377
|
+
member instanceof PropertyDeclaration &&
|
|
378
|
+
!hasStaticModifier(member) &&
|
|
379
|
+
member.name instanceof ComputedPropertyName
|
|
380
|
+
)
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private addHoisted(name: Identifier, blockScoped: boolean): Identifier {
|
|
387
|
+
if (blockScoped) this.context.addLexicalDeclaration(name);
|
|
388
|
+
else this.context.addVariableDeclaration(name);
|
|
389
|
+
return name;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private visitSourceFile(node: SourceFile): Node {
|
|
393
|
+
if (node.isDeclarationFile) return node;
|
|
394
|
+
const context = this.context;
|
|
395
|
+
this.lexicalEnvironment = undefined;
|
|
396
|
+
this.shouldTransformPrivateStaticElementsInFile =
|
|
397
|
+
(context.getEmitFlags(node) & EmitFlags.TransformPrivateStaticElements) !== 0;
|
|
398
|
+
this.classAliases.clear();
|
|
399
|
+
this.enclosingClassDeclarations.clear();
|
|
400
|
+
const visited = this.visitEachChild(node);
|
|
401
|
+
const helpers = context.readEmitHelpers();
|
|
402
|
+
for (let i = 0; i < helpers.length; i++) context.addEmitHelper(visited, helpers[i]);
|
|
403
|
+
this.classAliases.clear();
|
|
404
|
+
this.enclosingClassDeclarations.clear();
|
|
405
|
+
return visited;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private visitModifier(node: Node): Node | undefined {
|
|
409
|
+
if (node.kind === SyntaxKind.AccessorKeyword)
|
|
410
|
+
return this.shouldTransformAutoAccessorsInCurrentClass() ? undefined : node;
|
|
411
|
+
return isModifier(node) ? node : undefined;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Substitutes class aliases in subtrees with nothing else to transform, leaving property names alone. */
|
|
415
|
+
private visitForSubstitution(node: Node): Node | undefined {
|
|
416
|
+
if (node instanceof Identifier) return this.visitIdentifier(node as Identifier);
|
|
417
|
+
if (node instanceof PropertyAccessExpression && node.name instanceof Identifier)
|
|
418
|
+
return this.visitPropertyAccessExpressionForSubstitution(node);
|
|
419
|
+
return this.substitutionMode.visitEachChild(node);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
visit(node: Node): Node | undefined {
|
|
423
|
+
const grandparent = this.parentNode;
|
|
424
|
+
this.parentNode = this.currentNode;
|
|
425
|
+
this.currentNode = node;
|
|
426
|
+
const result = this.visitWorker(node);
|
|
427
|
+
this.currentNode = this.parentNode;
|
|
428
|
+
this.parentNode = grandparent;
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private visitWorker(node: Node): Node | undefined {
|
|
433
|
+
if (!this.facts.has(node, SubtreeFacts.ContainsClassFields | SubtreeFacts.ContainsLexicalThisOrSuper)) {
|
|
434
|
+
if (this.currentClassContainer !== undefined && this.classAliases.size > 0)
|
|
435
|
+
return this.visitForSubstitution(node);
|
|
436
|
+
return node;
|
|
437
|
+
}
|
|
438
|
+
switch (node.kind) {
|
|
439
|
+
case SyntaxKind.SourceFile:
|
|
440
|
+
return this.visitSourceFile(node as SourceFile);
|
|
441
|
+
case SyntaxKind.ClassDeclaration:
|
|
442
|
+
case SyntaxKind.ClassExpression:
|
|
443
|
+
return this.visitClassLike(node);
|
|
444
|
+
case SyntaxKind.ClassStaticBlockDeclaration:
|
|
445
|
+
case SyntaxKind.PropertyDeclaration:
|
|
446
|
+
throw new Error('Class elements are visited in class element mode');
|
|
447
|
+
case SyntaxKind.PropertyAssignment:
|
|
448
|
+
case SyntaxKind.VariableDeclaration:
|
|
449
|
+
case SyntaxKind.Parameter:
|
|
450
|
+
case SyntaxKind.BindingElement:
|
|
451
|
+
return this.visitEachChild(this.transformNamedEvaluationIfNeeded(node, ''));
|
|
452
|
+
case SyntaxKind.VariableStatement:
|
|
453
|
+
return this.visitVariableStatement(node as VariableStatement);
|
|
454
|
+
case SyntaxKind.ExportAssignment:
|
|
455
|
+
return this.visitExportAssignment(node as ExportAssignment);
|
|
456
|
+
case SyntaxKind.PrivateIdentifier:
|
|
457
|
+
return this.visitPrivateIdentifier(node);
|
|
458
|
+
case SyntaxKind.PropertyAccessExpression:
|
|
459
|
+
return this.visitPropertyAccessExpression(node as PropertyAccessExpression);
|
|
460
|
+
case SyntaxKind.ElementAccessExpression:
|
|
461
|
+
return this.visitElementAccessExpression(node as ElementAccessExpression);
|
|
462
|
+
case SyntaxKind.PrefixUnaryExpression:
|
|
463
|
+
case SyntaxKind.PostfixUnaryExpression:
|
|
464
|
+
return this.visitPreOrPostfixUnaryExpression(node, false);
|
|
465
|
+
case SyntaxKind.BinaryExpression:
|
|
466
|
+
return this.visitBinaryExpression(node as BinaryExpression, false);
|
|
467
|
+
case SyntaxKind.ParenthesizedExpression:
|
|
468
|
+
return this.factory.updateParenthesizedExpression(
|
|
469
|
+
node as ParenthesizedExpression,
|
|
470
|
+
this.visitNode((node as ParenthesizedExpression).expression)!,
|
|
471
|
+
);
|
|
472
|
+
case SyntaxKind.CallExpression:
|
|
473
|
+
return this.visitCallExpression(node as CallExpression);
|
|
474
|
+
case SyntaxKind.ExpressionStatement:
|
|
475
|
+
return this.visitExpressionStatement(node as ExpressionStatement);
|
|
476
|
+
case SyntaxKind.TaggedTemplateExpression:
|
|
477
|
+
return this.visitTaggedTemplateExpression(node as TaggedTemplateExpression);
|
|
478
|
+
case SyntaxKind.ForStatement:
|
|
479
|
+
return this.visitForStatement(node as ForStatement);
|
|
480
|
+
case SyntaxKind.ForInStatement:
|
|
481
|
+
case SyntaxKind.ForOfStatement:
|
|
482
|
+
case SyntaxKind.DoStatement:
|
|
483
|
+
case SyntaxKind.WhileStatement:
|
|
484
|
+
return this.visitInIteration(node, true);
|
|
485
|
+
case SyntaxKind.ThisKeyword:
|
|
486
|
+
return this.visitThisExpression(node);
|
|
487
|
+
case SyntaxKind.FunctionDeclaration:
|
|
488
|
+
case SyntaxKind.FunctionExpression:
|
|
489
|
+
return this.visitFunctionExpressionOrDeclaration(node);
|
|
490
|
+
case SyntaxKind.Constructor:
|
|
491
|
+
case SyntaxKind.MethodDeclaration:
|
|
492
|
+
case SyntaxKind.GetAccessor:
|
|
493
|
+
case SyntaxKind.SetAccessor:
|
|
494
|
+
return this.visitInClassElement(node);
|
|
495
|
+
}
|
|
496
|
+
return this.visitEachChild(node);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
private visitInIteration(node: Node, inIteration: boolean): Node {
|
|
500
|
+
const saved = this.inIterationStatement;
|
|
501
|
+
this.inIterationStatement = inIteration;
|
|
502
|
+
const result = this.visitEachChild(node);
|
|
503
|
+
this.inIterationStatement = saved;
|
|
504
|
+
return result;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** Visits the children of a function-like class member with it as the current class element. */
|
|
508
|
+
private visitInClassElement(node: Node): Node {
|
|
509
|
+
const savedIteration = this.inIterationStatement;
|
|
510
|
+
const savedElement = this.currentClassElement;
|
|
511
|
+
this.inIterationStatement = false;
|
|
512
|
+
this.currentClassElement = node;
|
|
513
|
+
const result = this.visitEachChild(node);
|
|
514
|
+
this.currentClassElement = savedElement;
|
|
515
|
+
this.inIterationStatement = savedIteration;
|
|
516
|
+
return result;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Functions get their own `this`, unless synthesized from a static member of the current class,
|
|
521
|
+
* as the ES decorators transform does for static private auto-accessors.
|
|
522
|
+
*/
|
|
523
|
+
private visitFunctionExpressionOrDeclaration(node: Node): Node {
|
|
524
|
+
const savedIteration = this.inIterationStatement;
|
|
525
|
+
this.inIterationStatement = false;
|
|
526
|
+
let keepElement = false;
|
|
527
|
+
const container = this.currentClassContainer;
|
|
528
|
+
if (this.currentClassElement !== undefined && container !== undefined) {
|
|
529
|
+
const original = this.context.mostOriginal(node);
|
|
530
|
+
if (original !== node) {
|
|
531
|
+
const members = membersOf(container);
|
|
532
|
+
for (let i = 0; i < members.length; i++)
|
|
533
|
+
if (this.context.mostOriginal(members[i]) === original && isStatic(members[i])) keepElement = true;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
const savedElement = this.currentClassElement;
|
|
537
|
+
if (!keepElement) this.currentClassElement = undefined;
|
|
538
|
+
const result = this.visitEachChild(node);
|
|
539
|
+
this.currentClassElement = savedElement;
|
|
540
|
+
this.inIterationStatement = savedIteration;
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
private visitDiscardedValue(node: Node): Node | undefined {
|
|
545
|
+
switch (node.kind) {
|
|
546
|
+
case SyntaxKind.PrefixUnaryExpression:
|
|
547
|
+
case SyntaxKind.PostfixUnaryExpression:
|
|
548
|
+
return this.visitPreOrPostfixUnaryExpression(node, true);
|
|
549
|
+
case SyntaxKind.BinaryExpression:
|
|
550
|
+
return this.visitBinaryExpression(node as BinaryExpression, true);
|
|
551
|
+
case SyntaxKind.ParenthesizedExpression:
|
|
552
|
+
return this.factory.updateParenthesizedExpression(
|
|
553
|
+
node as ParenthesizedExpression,
|
|
554
|
+
this.discarded.visitNode((node as ParenthesizedExpression).expression)!,
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
return this.visit(node);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
private visitHeritageClause(node: Node): Node | undefined {
|
|
561
|
+
if (node instanceof HeritageClause) return this.heritageMode.visitEachChild(node);
|
|
562
|
+
if (node instanceof ExpressionWithTypeArguments)
|
|
563
|
+
return this.visitExpressionWithTypeArgumentsInHeritageClause(node as ExpressionWithTypeArguments);
|
|
564
|
+
return this.visit(node);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
private visitClassElement(node: Node): Node | undefined {
|
|
568
|
+
switch (node.kind) {
|
|
569
|
+
case SyntaxKind.Constructor: {
|
|
570
|
+
const saved = this.currentClassElement;
|
|
571
|
+
this.currentClassElement = node;
|
|
572
|
+
const container = this.currentClassContainer;
|
|
573
|
+
const result =
|
|
574
|
+
container !== undefined
|
|
575
|
+
? this.transformConstructor(node as ConstructorDeclaration, container)
|
|
576
|
+
: this.visitEachChild(node);
|
|
577
|
+
this.currentClassElement = saved;
|
|
578
|
+
return result;
|
|
579
|
+
}
|
|
580
|
+
case SyntaxKind.GetAccessor:
|
|
581
|
+
case SyntaxKind.SetAccessor:
|
|
582
|
+
case SyntaxKind.MethodDeclaration: {
|
|
583
|
+
const saved = this.currentClassElement;
|
|
584
|
+
this.currentClassElement = node;
|
|
585
|
+
const result = this.visitMethodOrAccessorDeclaration(node);
|
|
586
|
+
this.currentClassElement = saved;
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
case SyntaxKind.PropertyDeclaration: {
|
|
590
|
+
const saved = this.currentClassElement;
|
|
591
|
+
this.currentClassElement = node;
|
|
592
|
+
const result = this.visitPropertyDeclaration(node as PropertyDeclaration);
|
|
593
|
+
this.currentClassElement = saved;
|
|
594
|
+
return result;
|
|
595
|
+
}
|
|
596
|
+
case SyntaxKind.ClassStaticBlockDeclaration: {
|
|
597
|
+
const saved = this.currentClassElement;
|
|
598
|
+
this.currentClassElement = node;
|
|
599
|
+
const result = this.shouldTransformPrivateElementsOrClassStaticBlocks ? undefined : this.visitEachChild(node);
|
|
600
|
+
this.currentClassElement = saved;
|
|
601
|
+
return result;
|
|
602
|
+
}
|
|
603
|
+
case SyntaxKind.ComputedPropertyName:
|
|
604
|
+
return this.visitComputedPropertyName(node as ComputedPropertyName);
|
|
605
|
+
case SyntaxKind.SemicolonClassElement:
|
|
606
|
+
return node;
|
|
607
|
+
}
|
|
608
|
+
if (isModifier(node) || node.kind === SyntaxKind.Decorator) return this.visitModifier(node);
|
|
609
|
+
return this.visit(node);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
private visitPropertyName(name: Node): Node {
|
|
613
|
+
if (name instanceof ComputedPropertyName) return this.visitComputedPropertyName(name);
|
|
614
|
+
return this.visitNode(name)!;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/** Visits the field and accessors an auto-accessor became. */
|
|
618
|
+
private visitAccessorFieldResult(node: Node): Node | undefined {
|
|
619
|
+
if (node instanceof PropertyDeclaration) return this.transformFieldInitializer(node as PropertyDeclaration);
|
|
620
|
+
if (node instanceof GetAccessorDeclaration || node instanceof SetAccessorDeclaration)
|
|
621
|
+
return this.visitClassElement(node);
|
|
622
|
+
throw new Error('Expected a property declaration or accessor');
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/** A reference to a class from its static initializers, replaced with the class alias. */
|
|
626
|
+
private visitIdentifier(node: Identifier): Node {
|
|
627
|
+
const declaration = this.resolver.getReferencedValueDeclaration(this.mostOriginalIdentifier(node));
|
|
628
|
+
if (declaration === undefined) return node;
|
|
629
|
+
const alias = this.classAliases.get(declaration);
|
|
630
|
+
if (alias === undefined || !this.enclosingClassDeclarations.has(declaration)) return node;
|
|
631
|
+
const clone = this.factory.cloneIdentifier(alias);
|
|
632
|
+
this.context.setSourceMapRange(clone, node.pos, node.end);
|
|
633
|
+
this.context.setCommentRange(clone, node.pos, node.end);
|
|
634
|
+
return clone;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
private mostOriginalIdentifier(node: Identifier): Identifier {
|
|
638
|
+
const original = this.context.mostOriginal(node);
|
|
639
|
+
return original instanceof Identifier ? (original as Identifier) : node;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** An undeclared private name becomes an empty identifier, except as a statement such as `#;`. */
|
|
643
|
+
private visitPrivateIdentifier(node: Node): Node {
|
|
644
|
+
if (!this.shouldTransformPrivateElementsOrClassStaticBlocks) return node;
|
|
645
|
+
const parent = this.parentNode;
|
|
646
|
+
if (parent !== undefined && isStatement(parent)) return node;
|
|
647
|
+
const result = this.factory.createIdentifier('');
|
|
648
|
+
this.context.setOriginal(result, node);
|
|
649
|
+
return result;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** `#x in obj` */
|
|
653
|
+
private transformPrivateIdentifierInInExpression(node: BinaryExpression): Node {
|
|
654
|
+
const info = this.accessPrivateIdentifier(node.left);
|
|
655
|
+
if (info === undefined) return this.visitEachChild(node);
|
|
656
|
+
const receiver = this.visitNode(node.right)!;
|
|
657
|
+
const result = this.factory.createClassPrivateFieldInHelper(info.brandCheckIdentifier!, receiver);
|
|
658
|
+
this.context.setOriginal(result, node);
|
|
659
|
+
return result;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** An anonymous class whose static members move out of its body, so it can't name itself. */
|
|
663
|
+
isAnonymousClassNeedingAssignedName(node: Node): boolean {
|
|
664
|
+
if (!(node instanceof ClassExpression) || node.name !== undefined) return false;
|
|
665
|
+
const statics = staticPropertiesAndClassStaticBlocks(node);
|
|
666
|
+
for (let i = 0; i < statics.length; i++)
|
|
667
|
+
if (isClassNamedEvaluationHelperBlock(this.context, statics[i])) return false;
|
|
668
|
+
return this.hasTransformableStatics(node, statics);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
private hasTransformableStatics(node: Node, statics: Node[]): boolean {
|
|
672
|
+
if (!this.shouldTransformPrivateElementsOrClassStaticBlocks && !this.hasTransformPrivateStaticElementsFlag(node))
|
|
673
|
+
return false;
|
|
674
|
+
for (let i = 0; i < statics.length; i++) {
|
|
675
|
+
const member = statics[i];
|
|
676
|
+
if (
|
|
677
|
+
member.kind === SyntaxKind.ClassStaticBlockDeclaration ||
|
|
678
|
+
isPrivateIdentifierClassElementDeclaration(member) ||
|
|
679
|
+
(this.shouldTransformInitializers && isInitializedProperty(member))
|
|
680
|
+
)
|
|
681
|
+
return true;
|
|
682
|
+
}
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/** `node`, naming an anonymous class whose static members move out of its body. */
|
|
687
|
+
private transformNamedEvaluationIfNeeded(node: Node, assignedName: string): Node {
|
|
688
|
+
if (!isNamedEvaluation(this.context, node, this.classesNeedingNames)) return node;
|
|
689
|
+
return transformNamedEvaluation(this.context, node, assignedName !== '', assignedName);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
private visitVariableStatement(node: VariableStatement): Node {
|
|
693
|
+
const saved = this.pendingStatements;
|
|
694
|
+
this.pendingStatements = [];
|
|
695
|
+
const visited = this.visitEachChild(node);
|
|
696
|
+
const pending = this.pendingStatements;
|
|
697
|
+
this.pendingStatements = saved;
|
|
698
|
+
if (pending.length === 0) return visited;
|
|
699
|
+
return this.factory.createSyntaxList([visited].concat(pending));
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
private visitExportAssignment(node: ExportAssignment): Node {
|
|
703
|
+
let updated: Node = node;
|
|
704
|
+
if (isNamedEvaluation(this.context, node, this.classesNeedingNames))
|
|
705
|
+
updated = transformNamedEvaluation(this.context, node, true, node.isExportEquals ? '' : 'default');
|
|
706
|
+
return this.visitEachChild(updated);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
private injectPendingExpressions(expression: Node): Node {
|
|
710
|
+
if (this.pendingExpressions.length === 0) return expression;
|
|
711
|
+
const factory = this.factory;
|
|
712
|
+
let result: Node;
|
|
713
|
+
if (expression instanceof ParenthesizedExpression) {
|
|
714
|
+
this.pendingExpressions.push(expression.expression);
|
|
715
|
+
result = factory.updateParenthesizedExpression(
|
|
716
|
+
expression as ParenthesizedExpression,
|
|
717
|
+
factory.inlineExpressions(this.pendingExpressions)!,
|
|
718
|
+
) as Node;
|
|
719
|
+
} else {
|
|
720
|
+
this.pendingExpressions.push(expression);
|
|
721
|
+
result = factory.inlineExpressions(this.pendingExpressions)!;
|
|
722
|
+
}
|
|
723
|
+
this.pendingExpressions = [];
|
|
724
|
+
return result;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/** Visits a computed name's expression in the lexical environment outside the class. */
|
|
728
|
+
private visitInOuterEnvironment(expression: Node): Node {
|
|
729
|
+
const savedEnvironment = this.lexicalEnvironment;
|
|
730
|
+
const savedInside = this.insideComputedPropertyName;
|
|
731
|
+
this.insideComputedPropertyName = true;
|
|
732
|
+
if (savedEnvironment !== undefined && savedEnvironment.previous !== undefined)
|
|
733
|
+
this.lexicalEnvironment = savedEnvironment.previous;
|
|
734
|
+
const visited = this.visitNode(expression)!;
|
|
735
|
+
this.lexicalEnvironment = savedEnvironment;
|
|
736
|
+
this.insideComputedPropertyName = savedInside;
|
|
737
|
+
return visited;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
private visitComputedPropertyName(node: ComputedPropertyName): Node {
|
|
741
|
+
const expression = this.visitInOuterEnvironment(node.expression);
|
|
742
|
+
return this.factory.updateComputedPropertyName(node, this.injectPendingExpressions(expression));
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
private shouldTransformClassElementToWeakMap(node: Node): boolean {
|
|
746
|
+
return (
|
|
747
|
+
this.shouldTransformPrivateElementsOrClassStaticBlocks || this.shouldAlwaysTransformPrivateStaticElements(node)
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private shouldAlwaysTransformPrivateStaticElements(node: Node): boolean {
|
|
752
|
+
return hasStaticModifier(node) && this.hasTransformPrivateStaticElementsFlag(node);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
private hasTransformPrivateStaticElementsFlag(node: Node): boolean {
|
|
756
|
+
return (this.context.getEmitFlags(node) & EmitFlags.TransformPrivateStaticElements) !== 0;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/** A private method or accessor becomes a hoisted function; the member is removed. */
|
|
760
|
+
private visitMethodOrAccessorDeclaration(node: Node): Node | undefined {
|
|
761
|
+
if (!isPrivateIdentifierClassElementDeclaration(node) || !this.shouldTransformClassElementToWeakMap(node))
|
|
762
|
+
return this.classElementMode.visitEachChild(node);
|
|
763
|
+
const info = this.accessPrivateIdentifier(getName(node)!);
|
|
764
|
+
if (info === undefined) throw new Error('Undeclared private name for property declaration.');
|
|
765
|
+
if (!info.isValid) return node;
|
|
766
|
+
const functionName = this.getHoistedFunctionName(node, info);
|
|
767
|
+
if (functionName !== undefined) {
|
|
768
|
+
const factory = this.factory;
|
|
769
|
+
const modifiers = this.extractModifiers(getModifiers(node), ~(ModifierFlags.Static | ModifierFlags.Accessor));
|
|
770
|
+
this.context.startVariableEnvironment();
|
|
771
|
+
const saved = this.inIterationStatement;
|
|
772
|
+
this.inIterationStatement = false;
|
|
773
|
+
const body = this.visitFunctionBody(getBody(node));
|
|
774
|
+
const parameters = this.visitNodes(parametersOf(node))!;
|
|
775
|
+
this.inIterationStatement = saved;
|
|
776
|
+
const asterisk = node instanceof MethodDeclaration ? node.asteriskToken : undefined;
|
|
777
|
+
const fn = factory.created(
|
|
778
|
+
new FunctionExpression(
|
|
779
|
+
modifiers,
|
|
780
|
+
asterisk,
|
|
781
|
+
functionName,
|
|
782
|
+
undefined,
|
|
783
|
+
parameters,
|
|
784
|
+
undefined,
|
|
785
|
+
undefined,
|
|
786
|
+
body as Block,
|
|
787
|
+
),
|
|
788
|
+
);
|
|
789
|
+
this.pendingExpressions.push(factory.createAssignment(functionName, fn));
|
|
790
|
+
}
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
private getHoistedFunctionName(node: Node, info: PrivateIdentifierInfo): Identifier | undefined {
|
|
795
|
+
if (info.kind === PrivateKind.Method) return info.methodName;
|
|
796
|
+
if (info.kind === PrivateKind.Accessor) {
|
|
797
|
+
if (node.kind === SyntaxKind.GetAccessor) return info.getterName;
|
|
798
|
+
if (node.kind === SyntaxKind.SetAccessor) return info.setterName;
|
|
799
|
+
}
|
|
800
|
+
return undefined;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/** `this` in a static initializer of the current class: its classThis or constructor alias. */
|
|
804
|
+
private tryGetClassThis(): Node | undefined {
|
|
805
|
+
const classThis = this.tryGetClassThisNoContainer();
|
|
806
|
+
if (classThis !== undefined) return classThis;
|
|
807
|
+
const container = this.currentClassContainer;
|
|
808
|
+
return container !== undefined ? getName(container) : undefined;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
private tryGetClassThisNoContainer(): Identifier | undefined {
|
|
812
|
+
const data = this.getClassData();
|
|
813
|
+
return data.classThis !== undefined ? data.classThis : data.classConstructor;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/** `accessor x = 1` becomes `#x_accessor_storage = 1`, `get x()` and `set x(value)`. */
|
|
817
|
+
private transformAutoAccessor(node: PropertyDeclaration): Node {
|
|
818
|
+
const factory = this.factory;
|
|
819
|
+
const context = this.context;
|
|
820
|
+
const commentPos = context.commentPos(node);
|
|
821
|
+
const commentEnd = context.commentEnd(node);
|
|
822
|
+
const sourceMapPos = context.sourceMapPos(node);
|
|
823
|
+
const sourceMapEnd = context.sourceMapEnd(node);
|
|
824
|
+
// The getter and setter share one evaluation of a computed name.
|
|
825
|
+
const name = node.name;
|
|
826
|
+
let getterName: Node = name;
|
|
827
|
+
let setterName: Node = name;
|
|
828
|
+
if (name instanceof ComputedPropertyName && !isSimpleInlineableExpression(name.expression)) {
|
|
829
|
+
const cacheAssignment = findComputedPropertyNameCacheAssignment(name);
|
|
830
|
+
if (cacheAssignment !== undefined) {
|
|
831
|
+
getterName = factory.updateComputedPropertyName(name, this.visitNode(name.expression)!);
|
|
832
|
+
setterName = factory.updateComputedPropertyName(name, cacheAssignment.left);
|
|
833
|
+
} else {
|
|
834
|
+
const temp = factory.createTempVariable(0);
|
|
835
|
+
context.setSourceMapRange(temp, name.expression.pos, name.expression.end);
|
|
836
|
+
context.addVariableDeclaration(temp);
|
|
837
|
+
const assignment = factory.createAssignment(temp, this.visitNode(name.expression)!);
|
|
838
|
+
context.setSourceMapRange(assignment, name.expression.pos, name.expression.end);
|
|
839
|
+
getterName = factory.updateComputedPropertyName(name, assignment);
|
|
840
|
+
setterName = factory.updateComputedPropertyName(name, temp);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const modifiers = this.modifierMode.visitModifiers(node.modifiers);
|
|
844
|
+
const backingField = factory.updatePropertyDeclaration(
|
|
845
|
+
node,
|
|
846
|
+
modifiers,
|
|
847
|
+
factory.createGeneratedPrivateNameForNode(node.name, '', accessorStorageSuffix),
|
|
848
|
+
undefined,
|
|
849
|
+
undefined,
|
|
850
|
+
node.initializer,
|
|
851
|
+
);
|
|
852
|
+
context.setOriginal(backingField, node);
|
|
853
|
+
context.addEmitFlags(backingField, EmitFlags.NoComments);
|
|
854
|
+
context.setSourceMapRange(backingField, sourceMapPos, sourceMapEnd);
|
|
855
|
+
let receiver: Node | undefined = undefined;
|
|
856
|
+
if (isStatic(node)) receiver = this.tryGetClassThis();
|
|
857
|
+
if (receiver === undefined) receiver = factory.createThisExpression();
|
|
858
|
+
const getter = this.createAccessorPropertyGetRedirector(node, modifiers, getterName, receiver);
|
|
859
|
+
context.setOriginal(getter, node);
|
|
860
|
+
context.setCommentRange(getter, commentPos, commentEnd);
|
|
861
|
+
context.setSourceMapRange(getter, sourceMapPos, sourceMapEnd);
|
|
862
|
+
// Fresh modifiers, so comments aren't duplicated.
|
|
863
|
+
const setterModifiers =
|
|
864
|
+
modifiers !== undefined ? factory.createModifiersFromFlags(modifiers.modifierFlags) : undefined;
|
|
865
|
+
const setter = this.createAccessorPropertySetRedirector(node, setterModifiers, setterName, receiver);
|
|
866
|
+
context.setOriginal(setter, node);
|
|
867
|
+
context.addEmitFlags(setter, EmitFlags.NoComments);
|
|
868
|
+
context.setSourceMapRange(setter, sourceMapPos, sourceMapEnd);
|
|
869
|
+
return factory.createSyntaxList(
|
|
870
|
+
this.accessorResultMode.visitArray([backingField as PropertyDeclaration, getter, setter]),
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
private transformPrivateFieldInitializer(node: PropertyDeclaration): Node | undefined {
|
|
875
|
+
const factory = this.factory;
|
|
876
|
+
if (this.shouldTransformClassElementToWeakMap(node)) {
|
|
877
|
+
// Fields become WeakMaps: the declaration goes.
|
|
878
|
+
const info = this.accessPrivateIdentifier(node.name);
|
|
879
|
+
if (info === undefined) throw new Error('Undeclared private name for property declaration.');
|
|
880
|
+
if (!info.isValid) return node;
|
|
881
|
+
// A static field of a class whose static blocks stay becomes a static block.
|
|
882
|
+
if (info.isStatic && !this.shouldTransformPrivateElementsOrClassStaticBlocks) {
|
|
883
|
+
const statement = this.transformPropertyOrClassStaticBlock(node, factory.createThisExpression());
|
|
884
|
+
if (statement !== undefined)
|
|
885
|
+
return factory.created(new ClassStaticBlockDeclaration(undefined, factory.createBlock([statement], true)));
|
|
886
|
+
}
|
|
887
|
+
return undefined;
|
|
888
|
+
}
|
|
889
|
+
if (
|
|
890
|
+
this.shouldTransformInitializersUsingSet &&
|
|
891
|
+
!hasStaticModifier(node) &&
|
|
892
|
+
(this.currentClassFacts() & ClassFacts.WillHoistInitializersToConstructor) !== 0
|
|
893
|
+
)
|
|
894
|
+
return factory.updatePropertyDeclaration(
|
|
895
|
+
node,
|
|
896
|
+
this.visitModifiers(node.modifiers),
|
|
897
|
+
node.name,
|
|
898
|
+
undefined,
|
|
899
|
+
undefined,
|
|
900
|
+
undefined,
|
|
901
|
+
);
|
|
902
|
+
const named = this.transformNamedEvaluationIfNeeded(node, '') as PropertyDeclaration;
|
|
903
|
+
return factory.updatePropertyDeclaration(
|
|
904
|
+
named,
|
|
905
|
+
this.modifierMode.visitModifiers(named.modifiers),
|
|
906
|
+
this.visitPropertyName(named.name),
|
|
907
|
+
undefined,
|
|
908
|
+
undefined,
|
|
909
|
+
this.visitNode(named.initializer),
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
private transformPublicFieldInitializer(node: PropertyDeclaration): Node | undefined {
|
|
914
|
+
const factory = this.factory;
|
|
915
|
+
if (this.shouldTransformInitializers && !isAutoAccessorPropertyDeclaration(node)) {
|
|
916
|
+
// The field goes; its initializer moves to the constructor. A computed name is still evaluated.
|
|
917
|
+
const expression = this.getPropertyNameExpressionIfNeeded(
|
|
918
|
+
node.name,
|
|
919
|
+
node.initializer !== undefined || this.useDefineForClassFields,
|
|
920
|
+
);
|
|
921
|
+
if (expression !== undefined) flattenCommaList(expression, this.pendingExpressions);
|
|
922
|
+
// With static blocks kept, a static initializer runs in a static block, where `this` is the class.
|
|
923
|
+
if (isStatic(node) && !this.shouldTransformPrivateElementsOrClassStaticBlocks) {
|
|
924
|
+
const statement = this.transformPropertyOrClassStaticBlock(node, factory.createThisExpression());
|
|
925
|
+
if (statement !== undefined) {
|
|
926
|
+
const block = factory.created(
|
|
927
|
+
new ClassStaticBlockDeclaration(undefined, factory.createBlock([statement], false)),
|
|
928
|
+
);
|
|
929
|
+
this.context.setOriginal(block, node);
|
|
930
|
+
this.context.setCommentRange(block, node.pos, node.end);
|
|
931
|
+
this.context.addEmitFlags(statement, EmitFlags.NoComments);
|
|
932
|
+
return block;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return undefined;
|
|
936
|
+
}
|
|
937
|
+
return factory.updatePropertyDeclaration(
|
|
938
|
+
node,
|
|
939
|
+
this.modifierMode.visitModifiers(node.modifiers),
|
|
940
|
+
this.visitPropertyName(node.name),
|
|
941
|
+
undefined,
|
|
942
|
+
undefined,
|
|
943
|
+
this.visitNode(node.initializer),
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
private transformFieldInitializer(node: PropertyDeclaration): Node | undefined {
|
|
948
|
+
if (isPrivateIdentifierClassElementDeclaration(node)) return this.transformPrivateFieldInitializer(node);
|
|
949
|
+
return this.transformPublicFieldInitializer(node);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
private shouldTransformAutoAccessorsInCurrentClass(): boolean {
|
|
953
|
+
if (this.shouldTransformAutoAccessors) return true;
|
|
954
|
+
// At ESNext with useDefineForClassFields: false, only when initializers move to the constructor.
|
|
955
|
+
return (this.currentClassFacts() & ClassFacts.WillHoistInitializersToConstructor) !== 0;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
private currentClassFacts(): ClassFacts {
|
|
959
|
+
const environment = this.lexicalEnvironment;
|
|
960
|
+
return environment !== undefined && environment.data !== undefined ? environment.data.facts : ClassFacts.None;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
private visitPropertyDeclaration(node: PropertyDeclaration): Node | undefined {
|
|
964
|
+
if (
|
|
965
|
+
isAutoAccessorPropertyDeclaration(node) &&
|
|
966
|
+
(this.shouldTransformAutoAccessorsInCurrentClass() || this.shouldAlwaysTransformPrivateStaticElements(node))
|
|
967
|
+
)
|
|
968
|
+
return this.transformAutoAccessor(node);
|
|
969
|
+
return this.transformFieldInitializer(node);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
private createPrivateIdentifierAccess(info: PrivateIdentifierInfo, receiver: Node): Node {
|
|
973
|
+
return this.createPrivateIdentifierAccessHelper(info, this.visitNode(receiver)!);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
private createPrivateIdentifierAccessHelper(info: PrivateIdentifierInfo, receiver: Node): Node {
|
|
977
|
+
this.context.setCommentRange(receiver, -1, receiver.end);
|
|
978
|
+
const state = info.brandCheckIdentifier!;
|
|
979
|
+
switch (info.kind) {
|
|
980
|
+
case PrivateKind.Accessor:
|
|
981
|
+
return this.factory.createClassPrivateFieldGetHelper(receiver, state, 'a', info.getterName);
|
|
982
|
+
case PrivateKind.Method:
|
|
983
|
+
return this.factory.createClassPrivateFieldGetHelper(receiver, state, 'm', info.methodName);
|
|
984
|
+
case PrivateKind.Field:
|
|
985
|
+
return this.factory.createClassPrivateFieldGetHelper(
|
|
986
|
+
receiver,
|
|
987
|
+
state,
|
|
988
|
+
'f',
|
|
989
|
+
info.isStatic ? info.variableName : undefined,
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
throw new Error('Access helpers should not be created for untransformed private elements');
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/** `super.x` in a static initializer, with the class and its base available. */
|
|
996
|
+
private staticSuperData(node: Node): ClassData | undefined {
|
|
997
|
+
const element = this.currentClassElement;
|
|
998
|
+
const environment = this.lexicalEnvironment;
|
|
999
|
+
if (
|
|
1000
|
+
!this.shouldTransformThisInStaticInitializers ||
|
|
1001
|
+
element === undefined ||
|
|
1002
|
+
!isSuperProperty(node) ||
|
|
1003
|
+
!isStaticPropertyDeclarationOrClassStaticBlock(element) ||
|
|
1004
|
+
environment === undefined
|
|
1005
|
+
)
|
|
1006
|
+
return undefined;
|
|
1007
|
+
return environment.data;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
private visitPropertyAccessExpression(node: PropertyAccessExpression): Node {
|
|
1011
|
+
const factory = this.factory;
|
|
1012
|
+
if (node.name instanceof PrivateIdentifier) {
|
|
1013
|
+
const info = this.accessPrivateIdentifier(node.name);
|
|
1014
|
+
if (info !== undefined) {
|
|
1015
|
+
const result = this.createPrivateIdentifierAccess(info, node.expression);
|
|
1016
|
+
this.context.setOriginal(result, node);
|
|
1017
|
+
result.pos = node.pos;
|
|
1018
|
+
result.end = node.end;
|
|
1019
|
+
return result;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
const data = node.name instanceof Identifier ? this.staticSuperData(node) : undefined;
|
|
1023
|
+
if (data !== undefined) {
|
|
1024
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0) return this.visitInvalidSuperProperty(node);
|
|
1025
|
+
if (data.classConstructor !== undefined && data.superClassReference !== undefined) {
|
|
1026
|
+
// `super.x` becomes `Reflect.get(_baseTemp, "x", _classTemp)`.
|
|
1027
|
+
const superProperty = factory.createReflectGetCall(
|
|
1028
|
+
data.superClassReference,
|
|
1029
|
+
factory.createStringLiteralFromNode(node.name),
|
|
1030
|
+
data.classConstructor,
|
|
1031
|
+
);
|
|
1032
|
+
this.context.setOriginal(superProperty, node.expression);
|
|
1033
|
+
superProperty.pos = node.expression.pos;
|
|
1034
|
+
superProperty.end = node.expression.end;
|
|
1035
|
+
return superProperty;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
// Property names are not references and are never substituted.
|
|
1039
|
+
if (node.name instanceof Identifier) return this.visitPropertyAccessExpressionForSubstitution(node);
|
|
1040
|
+
return this.visitEachChild(node);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
private visitPropertyAccessExpressionForSubstitution(node: PropertyAccessExpression): Node {
|
|
1044
|
+
const expression = this.visitNode(node.expression)!;
|
|
1045
|
+
if (expression === node.expression) return node;
|
|
1046
|
+
return this.factory.updatePropertyAccessExpression(node, expression, node.questionDotToken, node.name, node.flags);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
private visitElementAccessExpression(node: ElementAccessExpression): Node {
|
|
1050
|
+
const data = this.staticSuperData(node);
|
|
1051
|
+
if (data !== undefined) {
|
|
1052
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0) return this.visitInvalidSuperProperty(node);
|
|
1053
|
+
if (data.classConstructor !== undefined && data.superClassReference !== undefined) {
|
|
1054
|
+
// `super[x]` becomes `Reflect.get(_baseTemp, x, _classTemp)`.
|
|
1055
|
+
const superProperty = this.factory.createReflectGetCall(
|
|
1056
|
+
data.superClassReference,
|
|
1057
|
+
this.visitNode(node.argumentExpression)!,
|
|
1058
|
+
data.classConstructor,
|
|
1059
|
+
);
|
|
1060
|
+
this.context.setOriginal(superProperty, node.expression);
|
|
1061
|
+
superProperty.pos = node.expression.pos;
|
|
1062
|
+
superProperty.end = node.expression.end;
|
|
1063
|
+
return superProperty;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return this.visitEachChild(node);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
private visitPreOrPostfixUnaryExpression(node: Node, discarded: boolean): Node {
|
|
1070
|
+
const factory = this.factory;
|
|
1071
|
+
const context = this.context;
|
|
1072
|
+
const prefix = node instanceof PrefixUnaryExpression;
|
|
1073
|
+
const operator = prefix ? (node as PrefixUnaryExpression).operator : (node as PostfixUnaryExpression).operator;
|
|
1074
|
+
const operand = prefix ? (node as PrefixUnaryExpression).operand : (node as PostfixUnaryExpression).operand;
|
|
1075
|
+
if (operator !== SyntaxKind.PlusPlusToken && operator !== SyntaxKind.MinusMinusToken)
|
|
1076
|
+
return this.visitEachChild(node);
|
|
1077
|
+
const target = skipParentheses(operand);
|
|
1078
|
+
if (target instanceof PropertyAccessExpression && target.name instanceof PrivateIdentifier) {
|
|
1079
|
+
const info = this.accessPrivateIdentifier(target.name);
|
|
1080
|
+
if (info === undefined) return this.visitEachChild(node);
|
|
1081
|
+
const receiver = this.createCopiableReceiver(this.visitNode(target.expression)!);
|
|
1082
|
+
let expression = this.createPrivateIdentifierAccessHelper(info, receiver.read);
|
|
1083
|
+
let temp: Identifier | undefined = undefined;
|
|
1084
|
+
if (!prefix && !discarded) temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1085
|
+
expression = this.expandIncrementOrDecrement(node, operator, operand, expression, temp);
|
|
1086
|
+
expression = this.createPrivateIdentifierAssignment(
|
|
1087
|
+
info,
|
|
1088
|
+
receiver.initialize !== undefined ? receiver.initialize : receiver.read,
|
|
1089
|
+
expression,
|
|
1090
|
+
SyntaxKind.EqualsToken,
|
|
1091
|
+
);
|
|
1092
|
+
context.setOriginal(expression, node);
|
|
1093
|
+
expression.pos = node.pos;
|
|
1094
|
+
expression.end = node.end;
|
|
1095
|
+
if (temp !== undefined) expression = this.withRange(factory.createCommaExpression(expression, temp), node);
|
|
1096
|
+
return expression;
|
|
1097
|
+
}
|
|
1098
|
+
const data = this.staticSuperData(target);
|
|
1099
|
+
if (data === undefined) return this.visitEachChild(node);
|
|
1100
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0) {
|
|
1101
|
+
const visited = this.visitInvalidSuperProperty(target);
|
|
1102
|
+
if (prefix) return factory.updatePrefixUnaryExpression(node as PrefixUnaryExpression, operator, visited);
|
|
1103
|
+
return factory.updatePostfixUnaryExpression(node as PostfixUnaryExpression, visited, operator);
|
|
1104
|
+
}
|
|
1105
|
+
if (data.classConstructor === undefined || data.superClassReference === undefined) return this.visitEachChild(node);
|
|
1106
|
+
// `++super.a` becomes `(Reflect.set(_baseTemp, "a", (_a = Reflect.get(_baseTemp, "a", _classTemp), _b = ++_a), _classTemp), _b)`.
|
|
1107
|
+
let getterName: Node | undefined = undefined;
|
|
1108
|
+
let setterName: Node | undefined = undefined;
|
|
1109
|
+
if (target instanceof PropertyAccessExpression) {
|
|
1110
|
+
if (target.name instanceof Identifier) {
|
|
1111
|
+
getterName = factory.createStringLiteralFromNode(target.name);
|
|
1112
|
+
setterName = getterName;
|
|
1113
|
+
}
|
|
1114
|
+
} else if (target instanceof ElementAccessExpression) {
|
|
1115
|
+
if (isSimpleInlineableExpression(target.argumentExpression)) {
|
|
1116
|
+
getterName = target.argumentExpression;
|
|
1117
|
+
setterName = getterName;
|
|
1118
|
+
} else {
|
|
1119
|
+
const temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1120
|
+
getterName = temp;
|
|
1121
|
+
setterName = factory.createAssignment(temp, this.visitNode(target.argumentExpression)!);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
if (getterName === undefined || setterName === undefined) return this.visitEachChild(node);
|
|
1125
|
+
let expression: Node = this.withRange(
|
|
1126
|
+
factory.createReflectGetCall(data.superClassReference, getterName, data.classConstructor),
|
|
1127
|
+
target,
|
|
1128
|
+
);
|
|
1129
|
+
let temp: Identifier | undefined = undefined;
|
|
1130
|
+
if (!discarded) temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1131
|
+
expression = this.expandIncrementOrDecrement(node, operator, operand, expression, temp);
|
|
1132
|
+
expression = factory.createReflectSetCall(data.superClassReference, setterName, expression, data.classConstructor);
|
|
1133
|
+
context.setOriginal(expression, node);
|
|
1134
|
+
this.withRange(expression, node);
|
|
1135
|
+
if (temp !== undefined) expression = this.withRange(factory.createCommaExpression(expression, temp), node);
|
|
1136
|
+
return expression;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
private withRange<T extends Node>(node: T, range: Node): T {
|
|
1140
|
+
node.pos = range.pos;
|
|
1141
|
+
node.end = range.end;
|
|
1142
|
+
return node;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/** `(_a = expression, ++_a)`, or `(_a = expression, result = _a++, _a)` for postfix operators. */
|
|
1146
|
+
private expandIncrementOrDecrement(
|
|
1147
|
+
node: Node,
|
|
1148
|
+
operator: SyntaxKind,
|
|
1149
|
+
operand: Node,
|
|
1150
|
+
expression: Node,
|
|
1151
|
+
result: Identifier | undefined,
|
|
1152
|
+
): Node {
|
|
1153
|
+
const factory = this.factory;
|
|
1154
|
+
const temp = this.context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1155
|
+
let value: Node = this.withRange(factory.createAssignment(temp, expression), operand);
|
|
1156
|
+
let operation: Node =
|
|
1157
|
+
node instanceof PrefixUnaryExpression
|
|
1158
|
+
? factory.createPrefixUnaryExpression(operator, temp)
|
|
1159
|
+
: factory.created(new PostfixUnaryExpression(temp, operator));
|
|
1160
|
+
this.withRange(operation, node);
|
|
1161
|
+
if (result !== undefined) operation = this.withRange(factory.createAssignment(result, operation), node);
|
|
1162
|
+
value = this.withRange(factory.createCommaExpression(value, operation), node);
|
|
1163
|
+
if (node instanceof PostfixUnaryExpression)
|
|
1164
|
+
value = this.withRange(factory.createCommaExpression(value, temp), node);
|
|
1165
|
+
return value;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
private visitForStatement(node: ForStatement): Node {
|
|
1169
|
+
const initializer = this.discarded.visitNode(node.initializer);
|
|
1170
|
+
const condition = this.visitNode(node.condition);
|
|
1171
|
+
const incrementor = this.discarded.visitNode(node.incrementor);
|
|
1172
|
+
const saved = this.inIterationStatement;
|
|
1173
|
+
this.inIterationStatement = true;
|
|
1174
|
+
const body = this.visitIterationBody(node.statement)!;
|
|
1175
|
+
this.inIterationStatement = saved;
|
|
1176
|
+
return this.factory.updateForStatement(node, initializer, condition, incrementor, body);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
private visitExpressionStatement(node: ExpressionStatement): Node {
|
|
1180
|
+
// A private name as a statement (`#;`) stays so that it fails at runtime.
|
|
1181
|
+
if (node.expression instanceof PrivateIdentifier && this.shouldTransformPrivateElementsOrClassStaticBlocks)
|
|
1182
|
+
return node;
|
|
1183
|
+
return this.factory.updateExpressionStatement(node, this.discarded.visitNode(node.expression)!);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
private createCopiableReceiver(receiver: Node): CopiableReceiver {
|
|
1187
|
+
const clone = nodeIsSynthesized(receiver) ? receiver : this.shallowClone(receiver);
|
|
1188
|
+
if (isSimpleInlineableExpression(receiver)) return new CopiableReceiver(clone, undefined);
|
|
1189
|
+
const read = this.context.addVariableDeclaration(this.factory.createTempVariable(0));
|
|
1190
|
+
return new CopiableReceiver(read, this.factory.createAssignment(read, clone));
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/** A copy of `node` sharing its children, which keep generated names. */
|
|
1194
|
+
private shallowClone(node: Node): Node {
|
|
1195
|
+
const factory = this.factory;
|
|
1196
|
+
if (node instanceof Identifier) return factory.cloneIdentifier(node);
|
|
1197
|
+
if (node instanceof PropertyAccessExpression)
|
|
1198
|
+
return factory.cloneNode(
|
|
1199
|
+
node,
|
|
1200
|
+
new PropertyAccessExpression(node.expression, node.questionDotToken, node.name, node.flags),
|
|
1201
|
+
);
|
|
1202
|
+
if (node instanceof ElementAccessExpression)
|
|
1203
|
+
return factory.cloneNode(
|
|
1204
|
+
node,
|
|
1205
|
+
new ElementAccessExpression(node.expression, node.questionDotToken, node.argumentExpression, node.flags),
|
|
1206
|
+
);
|
|
1207
|
+
if (node instanceof ParenthesizedExpression)
|
|
1208
|
+
return factory.cloneNode(node, new ParenthesizedExpression(node.expression));
|
|
1209
|
+
if (node instanceof CallExpression)
|
|
1210
|
+
return factory.cloneNode(
|
|
1211
|
+
node,
|
|
1212
|
+
new CallExpression(node.expression, node.questionDotToken, node.typeArguments, node.arguments, node.flags),
|
|
1213
|
+
);
|
|
1214
|
+
return factory.cloneNode(node, node.deepClone());
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
private visitCallExpression(node: CallExpression): Node {
|
|
1218
|
+
const factory = this.factory;
|
|
1219
|
+
const callee = node.expression;
|
|
1220
|
+
if (
|
|
1221
|
+
callee instanceof PropertyAccessExpression &&
|
|
1222
|
+
callee.name instanceof PrivateIdentifier &&
|
|
1223
|
+
this.accessPrivateIdentifier(callee.name) !== undefined
|
|
1224
|
+
) {
|
|
1225
|
+
// `obj.#x()` binds `this`: `__classPrivateFieldGet(obj, _C_instances, "m", _C_x).call(obj)`.
|
|
1226
|
+
const binding = this.createCallBinding(callee);
|
|
1227
|
+
const target = this.visitNode(binding.target)!;
|
|
1228
|
+
const args: Node[] = [this.visitNode(binding.thisArg)!];
|
|
1229
|
+
const visitedArgs = this.visitNodes(node.arguments)!.nodes;
|
|
1230
|
+
for (let i = 0; i < visitedArgs.length; i++) args.push(visitedArgs[i]);
|
|
1231
|
+
const optional = (node.flags & NodeFlags.OptionalChain) !== 0;
|
|
1232
|
+
const call = factory.created(
|
|
1233
|
+
new PropertyAccessExpression(
|
|
1234
|
+
target,
|
|
1235
|
+
optional ? node.questionDotToken : undefined,
|
|
1236
|
+
factory.createIdentifier('call'),
|
|
1237
|
+
optional ? NodeFlags.OptionalChain : NodeFlags.None,
|
|
1238
|
+
),
|
|
1239
|
+
);
|
|
1240
|
+
return factory.updateCallExpression(node, call, undefined, undefined, factory.createNodeList(args), node.flags);
|
|
1241
|
+
}
|
|
1242
|
+
const data = this.staticSuperData(callee);
|
|
1243
|
+
if (data !== undefined && data.classConstructor !== undefined) {
|
|
1244
|
+
// `super.f(...)` becomes `Reflect.get(_baseTemp, "f", _classTemp).call(_classTemp, ...)`.
|
|
1245
|
+
const invocation = factory.createFunctionCallCall(
|
|
1246
|
+
this.visitNode(callee)!,
|
|
1247
|
+
data.classConstructor,
|
|
1248
|
+
this.visitNodes(node.arguments)!.nodes,
|
|
1249
|
+
);
|
|
1250
|
+
this.context.setOriginal(invocation, node);
|
|
1251
|
+
return this.withRange(invocation, node as CallExpression);
|
|
1252
|
+
}
|
|
1253
|
+
return this.visitEachChild(node);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
private visitTaggedTemplateExpression(node: TaggedTemplateExpression): Node {
|
|
1257
|
+
const factory = this.factory;
|
|
1258
|
+
const tag = node.tag;
|
|
1259
|
+
if (
|
|
1260
|
+
tag instanceof PropertyAccessExpression &&
|
|
1261
|
+
tag.name instanceof PrivateIdentifier &&
|
|
1262
|
+
this.accessPrivateIdentifier(tag.name) !== undefined
|
|
1263
|
+
) {
|
|
1264
|
+
// A private tag binds `this` with `.bind`.
|
|
1265
|
+
const binding = this.createCallBinding(tag);
|
|
1266
|
+
const bound = factory.createCallExpression(
|
|
1267
|
+
factory.createPropertyAccessExpression(this.visitNode(binding.target)!, factory.createIdentifier('bind')),
|
|
1268
|
+
[this.visitNode(binding.thisArg)!],
|
|
1269
|
+
);
|
|
1270
|
+
return factory.updateTaggedTemplateExpression(
|
|
1271
|
+
node,
|
|
1272
|
+
bound,
|
|
1273
|
+
undefined,
|
|
1274
|
+
undefined,
|
|
1275
|
+
this.visitNode(node.template)!,
|
|
1276
|
+
node.flags,
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1279
|
+
const data = this.staticSuperData(tag);
|
|
1280
|
+
if (data !== undefined && data.classConstructor !== undefined) {
|
|
1281
|
+
// `` super.f`x` `` becomes `` Reflect.get(_baseTemp, "f", _classTemp).bind(_classTemp)`x` ``.
|
|
1282
|
+
const invocation = factory.createFunctionBindCall(this.visitNode(tag)!, data.classConstructor, []);
|
|
1283
|
+
this.context.setOriginal(invocation, node);
|
|
1284
|
+
this.withRange(invocation, node as TaggedTemplateExpression);
|
|
1285
|
+
return factory.updateTaggedTemplateExpression(
|
|
1286
|
+
node,
|
|
1287
|
+
invocation,
|
|
1288
|
+
undefined,
|
|
1289
|
+
undefined,
|
|
1290
|
+
this.visitNode(node.template)!,
|
|
1291
|
+
node.flags,
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
return this.visitEachChild(node);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
/** A static block as an expression to evaluate after the class: an arrow function called in place. */
|
|
1298
|
+
private transformClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration): Node | undefined {
|
|
1299
|
+
if (!this.shouldTransformPrivateElementsOrClassStaticBlocks) return undefined;
|
|
1300
|
+
const context = this.context;
|
|
1301
|
+
const factory = this.factory;
|
|
1302
|
+
if (isClassThisAssignmentBlock(context, node)) {
|
|
1303
|
+
const result = this.visitNode((node.body.statements.nodes[0] as ExpressionStatement).expression)!;
|
|
1304
|
+
// `_classThis = _classThis` does nothing.
|
|
1305
|
+
if (result instanceof BinaryExpression && isAssignmentExpression(result, true) && result.left === result.right)
|
|
1306
|
+
return undefined;
|
|
1307
|
+
return result;
|
|
1308
|
+
}
|
|
1309
|
+
if (isClassNamedEvaluationHelperBlock(context, node))
|
|
1310
|
+
return this.visitNode((node.body.statements.nodes[0] as ExpressionStatement).expression);
|
|
1311
|
+
context.startVariableEnvironment();
|
|
1312
|
+
const saved = this.currentClassElement;
|
|
1313
|
+
this.currentClassElement = node;
|
|
1314
|
+
let statements = this.visitArray(node.body.statements.nodes);
|
|
1315
|
+
this.currentClassElement = saved;
|
|
1316
|
+
statements = context.mergeEnvironment(statements, context.endVariableEnvironment());
|
|
1317
|
+
const iife = factory.createImmediatelyInvokedArrowFunction(statements);
|
|
1318
|
+
const arrow = skipParentheses(iife.expression);
|
|
1319
|
+
context.setOriginal(arrow, node);
|
|
1320
|
+
context.addEmitFlags(arrow, EmitFlags.NoLexicalArguments);
|
|
1321
|
+
// Keep the statements' range for detached comments, as in `static { // do }`.
|
|
1322
|
+
if (arrow instanceof ArrowFunction && arrow.body instanceof Block) {
|
|
1323
|
+
arrow.body.statements.pos = node.body.statements.pos;
|
|
1324
|
+
arrow.body.statements.end = node.body.statements.end;
|
|
1325
|
+
}
|
|
1326
|
+
context.setOriginal(iife, node);
|
|
1327
|
+
context.assignSourceMapRange(iife, node);
|
|
1328
|
+
context.addEmitFlags(arrow, EmitFlags.NoLexicalThis);
|
|
1329
|
+
return iife;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
private visitBinaryExpression(node: BinaryExpression, discarded: boolean): Node {
|
|
1333
|
+
const factory = this.factory;
|
|
1334
|
+
const context = this.context;
|
|
1335
|
+
if (isDestructuringAssignment(node)) {
|
|
1336
|
+
// `({ x: obj.#x } = ...)`, `({ x: super.x } = ...)`
|
|
1337
|
+
const saved = this.pendingExpressions;
|
|
1338
|
+
this.pendingExpressions = [];
|
|
1339
|
+
const updated = factory.updateBinaryExpression(
|
|
1340
|
+
node,
|
|
1341
|
+
undefined,
|
|
1342
|
+
this.assignmentTargetMode.visitNode(node.left)!,
|
|
1343
|
+
undefined,
|
|
1344
|
+
node.operatorToken,
|
|
1345
|
+
this.visitNode(node.right)!,
|
|
1346
|
+
);
|
|
1347
|
+
const pending = this.pendingExpressions;
|
|
1348
|
+
this.pendingExpressions = saved;
|
|
1349
|
+
if (pending.length === 0) return updated;
|
|
1350
|
+
pending.push(updated as BinaryExpression);
|
|
1351
|
+
return factory.inlineExpressions(pending)!;
|
|
1352
|
+
}
|
|
1353
|
+
let current = node;
|
|
1354
|
+
if (isAssignmentExpression(node, false)) {
|
|
1355
|
+
const named = this.transformNamedEvaluationIfNeeded(node, '') as BinaryExpression;
|
|
1356
|
+
current = named;
|
|
1357
|
+
const left = skipOuterExpressions(
|
|
1358
|
+
named.left,
|
|
1359
|
+
OuterExpressionKinds.PartiallyEmittedExpressions | OuterExpressionKinds.Parentheses,
|
|
1360
|
+
);
|
|
1361
|
+
if (left instanceof PropertyAccessExpression && left.name instanceof PrivateIdentifier) {
|
|
1362
|
+
// `obj.#x = ...`
|
|
1363
|
+
const info = this.accessPrivateIdentifier(left.name);
|
|
1364
|
+
if (info !== undefined) {
|
|
1365
|
+
const result = this.createPrivateIdentifierAssignment(
|
|
1366
|
+
info,
|
|
1367
|
+
left.expression,
|
|
1368
|
+
named.right,
|
|
1369
|
+
named.operatorToken.kind,
|
|
1370
|
+
);
|
|
1371
|
+
context.setOriginal(result, named);
|
|
1372
|
+
return this.withRange(result, named);
|
|
1373
|
+
}
|
|
1374
|
+
} else {
|
|
1375
|
+
const data = this.staticSuperData(named.left);
|
|
1376
|
+
if (data !== undefined) {
|
|
1377
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0)
|
|
1378
|
+
return factory.updateBinaryExpression(
|
|
1379
|
+
named,
|
|
1380
|
+
undefined,
|
|
1381
|
+
this.visitInvalidSuperProperty(named.left),
|
|
1382
|
+
undefined,
|
|
1383
|
+
named.operatorToken,
|
|
1384
|
+
this.visitNode(named.right)!,
|
|
1385
|
+
);
|
|
1386
|
+
if (data.classConstructor !== undefined && data.superClassReference !== undefined) {
|
|
1387
|
+
const assigned = this.transformSuperPropertyAssignment(named, data, discarded);
|
|
1388
|
+
if (assigned !== undefined) return assigned;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
if (current.operatorToken.kind === SyntaxKind.InKeyword && current.left instanceof PrivateIdentifier)
|
|
1394
|
+
return this.transformPrivateIdentifierInInExpression(current);
|
|
1395
|
+
return this.visitEachChild(current);
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/** `super.x = 1` becomes `(Reflect.set(_baseTemp, "x", _a = 1, _classTemp), _a)`. */
|
|
1399
|
+
private transformSuperPropertyAssignment(
|
|
1400
|
+
node: BinaryExpression,
|
|
1401
|
+
data: ClassData,
|
|
1402
|
+
discarded: boolean,
|
|
1403
|
+
): Node | undefined {
|
|
1404
|
+
const factory = this.factory;
|
|
1405
|
+
const context = this.context;
|
|
1406
|
+
const left = node.left;
|
|
1407
|
+
let setterName: Node | undefined = undefined;
|
|
1408
|
+
if (left instanceof ElementAccessExpression) setterName = this.visitNode(left.argumentExpression)!;
|
|
1409
|
+
else if (left instanceof PropertyAccessExpression && left.name instanceof Identifier)
|
|
1410
|
+
setterName = factory.createStringLiteralFromNode(left.name);
|
|
1411
|
+
if (setterName === undefined) return undefined;
|
|
1412
|
+
const superClass = data.superClassReference!;
|
|
1413
|
+
const classConstructor = data.classConstructor!;
|
|
1414
|
+
let expression = this.visitNode(node.right)!;
|
|
1415
|
+
const operator = node.operatorToken.kind;
|
|
1416
|
+
if (isCompoundAssignment(operator)) {
|
|
1417
|
+
let getterName = setterName;
|
|
1418
|
+
if (!isSimpleInlineableExpression(setterName)) {
|
|
1419
|
+
const temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1420
|
+
getterName = temp;
|
|
1421
|
+
setterName = factory.createAssignment(temp, setterName);
|
|
1422
|
+
}
|
|
1423
|
+
const get = factory.createReflectGetCall(superClass, getterName, classConstructor);
|
|
1424
|
+
context.setOriginal(get, left);
|
|
1425
|
+
this.withRange(get, left);
|
|
1426
|
+
expression = this.withRange(
|
|
1427
|
+
factory.createBinaryExpression(get, nonAssignmentOperatorForCompoundAssignment(operator), expression),
|
|
1428
|
+
node as BinaryExpression,
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
let temp: Identifier | undefined = undefined;
|
|
1432
|
+
if (!discarded) {
|
|
1433
|
+
temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1434
|
+
expression = this.withRange(factory.createAssignment(temp, expression), node as BinaryExpression);
|
|
1435
|
+
}
|
|
1436
|
+
expression = factory.createReflectSetCall(superClass, setterName, expression, classConstructor);
|
|
1437
|
+
context.setOriginal(expression, node);
|
|
1438
|
+
this.withRange(expression, node as BinaryExpression);
|
|
1439
|
+
if (temp !== undefined)
|
|
1440
|
+
expression = this.withRange(factory.createCommaExpression(expression, temp), node as BinaryExpression);
|
|
1441
|
+
return expression;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
private createPrivateIdentifierAssignment(
|
|
1445
|
+
info: PrivateIdentifierInfo,
|
|
1446
|
+
receiverExpression: Node,
|
|
1447
|
+
rightExpression: Node,
|
|
1448
|
+
operator: SyntaxKind,
|
|
1449
|
+
): Node {
|
|
1450
|
+
const factory = this.factory;
|
|
1451
|
+
let receiver = this.visitNode(receiverExpression)!;
|
|
1452
|
+
let right = this.visitNode(rightExpression)!;
|
|
1453
|
+
if (isCompoundAssignment(operator)) {
|
|
1454
|
+
const copiable = this.createCopiableReceiver(receiver);
|
|
1455
|
+
receiver = copiable.initialize !== undefined ? copiable.initialize : copiable.read;
|
|
1456
|
+
right = factory.createBinaryExpression(
|
|
1457
|
+
this.createPrivateIdentifierAccessHelper(info, copiable.read),
|
|
1458
|
+
nonAssignmentOperatorForCompoundAssignment(operator),
|
|
1459
|
+
right,
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
this.context.setCommentRange(receiver, -1, receiver.end);
|
|
1463
|
+
const state = info.brandCheckIdentifier!;
|
|
1464
|
+
switch (info.kind) {
|
|
1465
|
+
case PrivateKind.Accessor:
|
|
1466
|
+
return factory.createClassPrivateFieldSetHelper(receiver, state, right, 'a', info.setterName);
|
|
1467
|
+
case PrivateKind.Method:
|
|
1468
|
+
return factory.createClassPrivateFieldSetHelper(receiver, state, right, 'm', undefined);
|
|
1469
|
+
case PrivateKind.Field:
|
|
1470
|
+
return factory.createClassPrivateFieldSetHelper(
|
|
1471
|
+
receiver,
|
|
1472
|
+
state,
|
|
1473
|
+
right,
|
|
1474
|
+
'f',
|
|
1475
|
+
info.isStatic ? info.variableName : undefined,
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1478
|
+
throw new Error('Access helpers should not be created for untransformed private elements');
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
/**
|
|
1482
|
+
* Whether the body or initializer of `member` refers to the class `classNode` by name, which then
|
|
1483
|
+
* needs an alias once the member's code moves out of the class.
|
|
1484
|
+
*/
|
|
1485
|
+
private memberContainsConstructorReference(member: Node, classNode: Node): boolean {
|
|
1486
|
+
const finder = new ConstructorReferenceFinder(
|
|
1487
|
+
this.resolver,
|
|
1488
|
+
this.context.mostOriginal(classNode),
|
|
1489
|
+
getNameOfDeclaration(classNode),
|
|
1490
|
+
);
|
|
1491
|
+
const body = member instanceof ClassStaticBlockDeclaration ? member.body : getBody(member);
|
|
1492
|
+
if (body !== undefined && finder.check(body)) return true;
|
|
1493
|
+
if (member instanceof PropertyDeclaration && member.initializer !== undefined && finder.check(member.initializer))
|
|
1494
|
+
return true;
|
|
1495
|
+
return false;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
private classContainsConstructorReference(node: Node): boolean {
|
|
1499
|
+
const members = membersOf(node);
|
|
1500
|
+
for (let i = 0; i < members.length; i++) if (this.memberContainsConstructorReference(members[i], node)) return true;
|
|
1501
|
+
return false;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
private getClassFacts(node: Node): ClassFacts {
|
|
1505
|
+
const context = this.context;
|
|
1506
|
+
let facts = ClassFacts.None;
|
|
1507
|
+
const original = context.mostOriginal(node);
|
|
1508
|
+
if (isClassLike(original) && classOrConstructorParameterIsDecorated(this.legacyDecorators, original))
|
|
1509
|
+
facts |= ClassFacts.ClassWasDecorated;
|
|
1510
|
+
const members = membersOf(node);
|
|
1511
|
+
if (
|
|
1512
|
+
this.shouldTransformPrivateElementsOrClassStaticBlocks &&
|
|
1513
|
+
(classHasClassThisAssignment(context, getClassMembers(node)) || classHasExplicitlyAssignedName(context, node))
|
|
1514
|
+
)
|
|
1515
|
+
facts |= ClassFacts.NeedsClassConstructorReference;
|
|
1516
|
+
let containsPublicInstanceFields = false;
|
|
1517
|
+
let containsInitializedPublicInstanceFields = false;
|
|
1518
|
+
let containsInstancePrivateElements = false;
|
|
1519
|
+
let containsInstanceAutoAccessors = false;
|
|
1520
|
+
for (let i = 0; i < members.length; i++) {
|
|
1521
|
+
const member = members[i];
|
|
1522
|
+
const name = getName(member);
|
|
1523
|
+
if (isStatic(member)) {
|
|
1524
|
+
if (
|
|
1525
|
+
name !== undefined &&
|
|
1526
|
+
(name.kind === SyntaxKind.PrivateIdentifier || isAutoAccessorPropertyDeclaration(member)) &&
|
|
1527
|
+
this.shouldTransformPrivateElementsOrClassStaticBlocks
|
|
1528
|
+
)
|
|
1529
|
+
facts |= ClassFacts.NeedsClassConstructorReference;
|
|
1530
|
+
else if (
|
|
1531
|
+
isAutoAccessorPropertyDeclaration(member) &&
|
|
1532
|
+
this.shouldTransformAutoAccessors &&
|
|
1533
|
+
getName(node) === undefined &&
|
|
1534
|
+
context.getClassThis(node) === undefined
|
|
1535
|
+
)
|
|
1536
|
+
facts |= ClassFacts.NeedsClassConstructorReference;
|
|
1537
|
+
if (member instanceof PropertyDeclaration || member instanceof ClassStaticBlockDeclaration) {
|
|
1538
|
+
if (
|
|
1539
|
+
this.shouldTransformThisInStaticInitializers &&
|
|
1540
|
+
this.facts.has(member, SubtreeFacts.ContainsLexicalThis)
|
|
1541
|
+
) {
|
|
1542
|
+
facts |= ClassFacts.NeedsSubstitutionForThisInClassStaticField;
|
|
1543
|
+
if ((facts & ClassFacts.ClassWasDecorated) === 0) facts |= ClassFacts.NeedsClassConstructorReference;
|
|
1544
|
+
}
|
|
1545
|
+
if (
|
|
1546
|
+
this.shouldTransformThisInStaticInitializers &&
|
|
1547
|
+
this.facts.has(member, SubtreeFacts.ContainsLexicalSuper) &&
|
|
1548
|
+
(facts & ClassFacts.ClassWasDecorated) === 0
|
|
1549
|
+
)
|
|
1550
|
+
facts |= ClassFacts.NeedsClassConstructorReference | ClassFacts.NeedsClassSuperReference;
|
|
1551
|
+
}
|
|
1552
|
+
} else if (!hasSyntacticModifier(context.mostOriginal(member), ModifierFlags.Abstract)) {
|
|
1553
|
+
if (isAutoAccessorPropertyDeclaration(member)) {
|
|
1554
|
+
containsInstanceAutoAccessors = true;
|
|
1555
|
+
if (isPrivateIdentifierClassElementDeclaration(member)) containsInstancePrivateElements = true;
|
|
1556
|
+
} else if (isPrivateIdentifierClassElementDeclaration(member)) {
|
|
1557
|
+
containsInstancePrivateElements = true;
|
|
1558
|
+
if (this.memberContainsConstructorReference(member, node)) facts |= ClassFacts.NeedsClassConstructorReference;
|
|
1559
|
+
} else if (member instanceof PropertyDeclaration) {
|
|
1560
|
+
containsPublicInstanceFields = true;
|
|
1561
|
+
if (member.initializer !== undefined) containsInitializedPublicInstanceFields = true;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
const transformPrivate = this.shouldTransformPrivateElementsOrClassStaticBlocks;
|
|
1566
|
+
if (
|
|
1567
|
+
(this.shouldTransformInitializersUsingDefine && containsPublicInstanceFields) ||
|
|
1568
|
+
(this.shouldTransformInitializersUsingSet && containsInitializedPublicInstanceFields) ||
|
|
1569
|
+
(transformPrivate && containsInstancePrivateElements) ||
|
|
1570
|
+
(transformPrivate && containsInstanceAutoAccessors && this.shouldTransformAutoAccessors)
|
|
1571
|
+
)
|
|
1572
|
+
facts |= ClassFacts.WillHoistInitializersToConstructor;
|
|
1573
|
+
return facts;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
private visitExpressionWithTypeArgumentsInHeritageClause(node: ExpressionWithTypeArguments): Node {
|
|
1577
|
+
if ((this.currentClassFacts() & ClassFacts.NeedsClassSuperReference) !== 0) {
|
|
1578
|
+
const factory = this.factory;
|
|
1579
|
+
const temp = this.context.addVariableDeclaration(
|
|
1580
|
+
factory.createTempVariable(GeneratedIdentifierFlags.ReservedInNestedScopes),
|
|
1581
|
+
);
|
|
1582
|
+
this.getClassData().superClassReference = temp;
|
|
1583
|
+
return factory.updateExpressionWithTypeArguments(
|
|
1584
|
+
node,
|
|
1585
|
+
factory.createAssignment(temp, this.visitNode(node.expression)!),
|
|
1586
|
+
undefined,
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
return this.heritageMode.visitEachChild(node);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/** Visits a class in a new class lexical environment. */
|
|
1593
|
+
private visitClassLike(node: Node): Node | undefined {
|
|
1594
|
+
const savedContainer = this.currentClassContainer;
|
|
1595
|
+
const savedPending = this.pendingExpressions;
|
|
1596
|
+
const savedEnvironment = this.lexicalEnvironment;
|
|
1597
|
+
this.currentClassContainer = node;
|
|
1598
|
+
this.pendingExpressions = [];
|
|
1599
|
+
this.lexicalEnvironment = new ClassEnvironment(savedEnvironment);
|
|
1600
|
+
const context = this.context;
|
|
1601
|
+
const original = context.mostOriginal(node);
|
|
1602
|
+
this.enclosingClassDeclarations.add(original);
|
|
1603
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks || this.hasTransformPrivateStaticElementsFlag(node)) {
|
|
1604
|
+
const name = getNameOfDeclaration(node);
|
|
1605
|
+
if (name instanceof Identifier) this.getPrivateEnvironment().className = name as Identifier;
|
|
1606
|
+
else {
|
|
1607
|
+
const assignedName = context.getAssignedName(node);
|
|
1608
|
+
if (assignedName instanceof StringLiteral) {
|
|
1609
|
+
const textSource = context.getTextSource(assignedName);
|
|
1610
|
+
if (textSource instanceof Identifier) this.getPrivateEnvironment().className = textSource as Identifier;
|
|
1611
|
+
else if (isIdentifierText(assignedName.text))
|
|
1612
|
+
this.getPrivateEnvironment().className = this.factory.createIdentifier(assignedName.text);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks) {
|
|
1617
|
+
const methods = privateInstanceMethodsAndAccessors(node);
|
|
1618
|
+
if (methods.length > 0)
|
|
1619
|
+
this.getPrivateEnvironment().weakSetName = this.createHoistedVariableForClass(
|
|
1620
|
+
'instances',
|
|
1621
|
+
getName(methods[0])!,
|
|
1622
|
+
'',
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
const facts = this.getClassFacts(node);
|
|
1626
|
+
if (facts !== ClassFacts.None) this.getClassData().facts = facts;
|
|
1627
|
+
const result =
|
|
1628
|
+
node instanceof ClassDeclaration
|
|
1629
|
+
? this.visitClassDeclarationInEnvironment(node as ClassDeclaration, facts)
|
|
1630
|
+
: this.visitClassExpressionInEnvironment(node as ClassExpression, facts);
|
|
1631
|
+
this.enclosingClassDeclarations.delete(original);
|
|
1632
|
+
this.currentClassContainer = savedContainer;
|
|
1633
|
+
this.pendingExpressions = savedPending;
|
|
1634
|
+
this.lexicalEnvironment = savedEnvironment;
|
|
1635
|
+
return result;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
private visitClassDeclarationInEnvironment(node: ClassDeclaration, facts: ClassFacts): Node {
|
|
1639
|
+
const factory = this.factory;
|
|
1640
|
+
const context = this.context;
|
|
1641
|
+
// Private statics and static `this` or `super` need a reference to the class.
|
|
1642
|
+
let pendingClassReferenceAssignment: Node | undefined = undefined;
|
|
1643
|
+
const classThis = classThisOf(context, node);
|
|
1644
|
+
if ((facts & ClassFacts.NeedsClassConstructorReference) !== 0) {
|
|
1645
|
+
// Reusing `_classThis` is only safe when static blocks are transformed too: the assignment
|
|
1646
|
+
// then runs before them, so it doesn't overwrite a replacement constructor from decorators.
|
|
1647
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks && classThis !== undefined) {
|
|
1648
|
+
this.getClassData().classConstructor = classThis;
|
|
1649
|
+
pendingClassReferenceAssignment = factory.createAssignment(
|
|
1650
|
+
classThis,
|
|
1651
|
+
factory.getLocalName(node, NameOptions.None),
|
|
1652
|
+
);
|
|
1653
|
+
} else {
|
|
1654
|
+
const temp = context.addVariableDeclaration(
|
|
1655
|
+
factory.createTempVariable(GeneratedIdentifierFlags.ReservedInNestedScopes),
|
|
1656
|
+
);
|
|
1657
|
+
this.getClassData().classConstructor = factory.cloneIdentifier(temp);
|
|
1658
|
+
pendingClassReferenceAssignment = factory.createAssignment(temp, factory.getLocalName(node, NameOptions.None));
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
if (classThis !== undefined) this.getClassData().classThis = classThis;
|
|
1662
|
+
// Aliases are registered before visiting members, which substitute eagerly.
|
|
1663
|
+
const alias = this.getClassData().classConstructor;
|
|
1664
|
+
if (alias !== undefined && this.classContainsConstructorReference(node))
|
|
1665
|
+
this.classAliases.set(context.mostOriginal(node), alias);
|
|
1666
|
+
let modifiers = this.modifierMode.visitModifiers(node.modifiers);
|
|
1667
|
+
const heritageClauses = this.heritageMode.visitNodes(node.heritageClauses);
|
|
1668
|
+
const transformed = this.transformClassMembers(node);
|
|
1669
|
+
const statements: Node[] = [];
|
|
1670
|
+
if (pendingClassReferenceAssignment !== undefined) this.pendingExpressions.unshift(pendingClassReferenceAssignment);
|
|
1671
|
+
// Expressions from elided or moved computed property names.
|
|
1672
|
+
if (this.pendingExpressions.length > 0)
|
|
1673
|
+
statements.push(factory.createExpressionStatement(factory.inlineExpressions(this.pendingExpressions)!));
|
|
1674
|
+
let name: Identifier | undefined = node.name;
|
|
1675
|
+
if (this.shouldTransformInitializersUsingSet || this.shouldTransformPrivateElementsOrClassStaticBlocks) {
|
|
1676
|
+
// Static initializers run after the class, which is safe because the declaration is lexical.
|
|
1677
|
+
const statics = staticPropertiesAndClassStaticBlocks(node);
|
|
1678
|
+
if (statics.length > 0) {
|
|
1679
|
+
if (name === undefined) name = factory.createGeneratedNameForNode(node, 0, '', '');
|
|
1680
|
+
this.addPropertyOrClassStaticBlockStatements(statements, statics, factory.getLocalName(node, NameOptions.None));
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
if (
|
|
1684
|
+
statements.length > 0 &&
|
|
1685
|
+
hasSyntacticModifier(node, ModifierFlags.Export) &&
|
|
1686
|
+
hasSyntacticModifier(node, ModifierFlags.Default)
|
|
1687
|
+
) {
|
|
1688
|
+
modifiers = this.extractModifiers(modifiers, ~(ModifierFlags.Export | ModifierFlags.Default));
|
|
1689
|
+
statements.push(
|
|
1690
|
+
factory.created(
|
|
1691
|
+
new ExportAssignment(undefined, false, undefined, factory.getLocalName(node, NameOptions.None)),
|
|
1692
|
+
),
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
const updated = factory.updateClassDeclaration(
|
|
1696
|
+
node,
|
|
1697
|
+
modifiers,
|
|
1698
|
+
name,
|
|
1699
|
+
undefined,
|
|
1700
|
+
heritageClauses,
|
|
1701
|
+
transformed.members,
|
|
1702
|
+
);
|
|
1703
|
+
const result: Node[] = [];
|
|
1704
|
+
if (transformed.prologue !== undefined) result.push(factory.createExpressionStatement(transformed.prologue));
|
|
1705
|
+
result.push(updated as ClassDeclaration);
|
|
1706
|
+
for (let i = 0; i < statements.length; i++) result.push(statements[i]);
|
|
1707
|
+
return factory.createSyntaxList(result);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
private createClassTemp(): Identifier {
|
|
1711
|
+
const temp = this.factory.createTempVariable(GeneratedIdentifierFlags.ReservedInNestedScopes);
|
|
1712
|
+
return temp;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
private visitClassExpressionInEnvironment(node: ClassExpression, facts: ClassFacts): Node {
|
|
1716
|
+
const factory = this.factory;
|
|
1717
|
+
const context = this.context;
|
|
1718
|
+
// A class expression from a decorated class declaration puts its statics in statements after
|
|
1719
|
+
// the variable statement, as the declaration would.
|
|
1720
|
+
const isDecoratedClassDeclaration = (facts & ClassFacts.ClassWasDecorated) !== 0;
|
|
1721
|
+
const classThis = classThisOf(context, node);
|
|
1722
|
+
if (classThis !== undefined) this.getClassData().classThis = classThis;
|
|
1723
|
+
let temp: Identifier | undefined = undefined;
|
|
1724
|
+
if ((facts & ClassFacts.NeedsClassConstructorReference) !== 0) {
|
|
1725
|
+
if (
|
|
1726
|
+
(this.shouldTransformPrivateElementsOrClassStaticBlocks || this.hasTransformPrivateStaticElementsFlag(node)) &&
|
|
1727
|
+
classThis !== undefined
|
|
1728
|
+
) {
|
|
1729
|
+
this.getClassData().classConstructor = classThis;
|
|
1730
|
+
temp = classThis;
|
|
1731
|
+
} else {
|
|
1732
|
+
temp = this.addHoisted(this.createClassTemp(), this.classExpressionNeedsBlockScopedTemp());
|
|
1733
|
+
this.getClassData().classConstructor = factory.cloneIdentifier(temp);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
const statics = staticPropertiesAndClassStaticBlocks(node);
|
|
1737
|
+
// Aliases must be known before visiting members, so predict whether a temporary will wrap the class.
|
|
1738
|
+
let isClassWithConstructorReference = false;
|
|
1739
|
+
let hasTransformableStatics = false;
|
|
1740
|
+
let deferTempDeclaration = false;
|
|
1741
|
+
if (!isDecoratedClassDeclaration) {
|
|
1742
|
+
isClassWithConstructorReference = this.classContainsConstructorReference(node);
|
|
1743
|
+
hasTransformableStatics = this.hasTransformableStatics(node, statics);
|
|
1744
|
+
let willHavePrivatePendingExpressions = false;
|
|
1745
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks) {
|
|
1746
|
+
const members = node.members.nodes;
|
|
1747
|
+
for (let i = 0; i < members.length; i++) {
|
|
1748
|
+
const member = members[i];
|
|
1749
|
+
if (
|
|
1750
|
+
isPrivateIdentifierClassElementDeclaration(member) &&
|
|
1751
|
+
!hasStaticModifier(member) &&
|
|
1752
|
+
this.shouldTransformClassElementToWeakMap(member)
|
|
1753
|
+
) {
|
|
1754
|
+
willHavePrivatePendingExpressions = true;
|
|
1755
|
+
break;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
const willNeedTempWrapper = hasTransformableStatics || willHavePrivatePendingExpressions;
|
|
1760
|
+
if (
|
|
1761
|
+
isClassWithConstructorReference &&
|
|
1762
|
+
willNeedTempWrapper &&
|
|
1763
|
+
this.getClassData().classConstructor === undefined
|
|
1764
|
+
) {
|
|
1765
|
+
// Declared after the members are visited, to keep tsc's declaration order.
|
|
1766
|
+
temp = this.createClassTemp();
|
|
1767
|
+
deferTempDeclaration = true;
|
|
1768
|
+
this.getClassData().classConstructor = factory.cloneIdentifier(temp);
|
|
1769
|
+
}
|
|
1770
|
+
const alias = this.getClassData().classConstructor;
|
|
1771
|
+
if (isClassWithConstructorReference && willNeedTempWrapper && alias !== undefined)
|
|
1772
|
+
this.classAliases.set(context.mostOriginal(node), alias);
|
|
1773
|
+
}
|
|
1774
|
+
const modifiers = this.modifierMode.visitModifiers(node.modifiers);
|
|
1775
|
+
const heritageClauses = this.heritageMode.visitNodes(node.heritageClauses);
|
|
1776
|
+
const transformed = this.transformClassMembers(node);
|
|
1777
|
+
if (deferTempDeclaration) this.addHoisted(temp!, this.classExpressionNeedsBlockScopedTemp());
|
|
1778
|
+
const classExpression = factory.updateClassExpression(
|
|
1779
|
+
node,
|
|
1780
|
+
modifiers,
|
|
1781
|
+
node.name,
|
|
1782
|
+
undefined,
|
|
1783
|
+
heritageClauses,
|
|
1784
|
+
transformed.members,
|
|
1785
|
+
);
|
|
1786
|
+
const expressions: Node[] = [];
|
|
1787
|
+
if (transformed.prologue !== undefined) expressions.push(transformed.prologue);
|
|
1788
|
+
if (!isDecoratedClassDeclaration) {
|
|
1789
|
+
if (hasTransformableStatics || this.pendingExpressions.length > 0) {
|
|
1790
|
+
if (temp === undefined) {
|
|
1791
|
+
temp = this.addHoisted(this.createClassTemp(), this.classExpressionNeedsBlockScopedTemp());
|
|
1792
|
+
const alias = factory.cloneIdentifier(temp);
|
|
1793
|
+
this.getClassData().classConstructor = alias;
|
|
1794
|
+
if (isClassWithConstructorReference) this.classAliases.set(context.mostOriginal(node), alias);
|
|
1795
|
+
}
|
|
1796
|
+
expressions.push(factory.createAssignment(temp, classExpression));
|
|
1797
|
+
// Expressions left from elided or moved computed property names.
|
|
1798
|
+
for (let i = 0; i < this.pendingExpressions.length; i++) expressions.push(this.pendingExpressions[i]);
|
|
1799
|
+
const initializers = this.generateInitializedPropertyExpressionsOrClassStaticBlock(statics, temp);
|
|
1800
|
+
for (let i = 0; i < initializers.length; i++) expressions.push(initializers[i]);
|
|
1801
|
+
expressions.push(factory.cloneIdentifier(temp));
|
|
1802
|
+
} else expressions.push(classExpression as Node);
|
|
1803
|
+
} else {
|
|
1804
|
+
for (let i = 0; i < this.pendingExpressions.length; i++)
|
|
1805
|
+
this.pendingStatements.push(factory.createExpressionStatement(this.pendingExpressions[i]));
|
|
1806
|
+
if (statics.length > 0) {
|
|
1807
|
+
const receiver = classThis !== undefined ? classThis : factory.getLocalName(node, NameOptions.None);
|
|
1808
|
+
this.addPropertyOrClassStaticBlockStatements(this.pendingStatements, statics, receiver);
|
|
1809
|
+
}
|
|
1810
|
+
if (temp !== undefined) expressions.push(factory.createAssignment(temp, classExpression));
|
|
1811
|
+
else if (this.shouldTransformPrivateElementsOrClassStaticBlocks && classThis !== undefined)
|
|
1812
|
+
expressions.push(factory.createAssignment(classThis, classExpression));
|
|
1813
|
+
else expressions.push(classExpression as Node);
|
|
1814
|
+
}
|
|
1815
|
+
if (expressions.length > 1) {
|
|
1816
|
+
context.addEmitFlags(classExpression, EmitFlags.Indented);
|
|
1817
|
+
for (let i = 0; i < expressions.length; i++) context.addEmitFlags(expressions[i], EmitFlags.StartOnNewLine);
|
|
1818
|
+
}
|
|
1819
|
+
return factory.inlineExpressions(expressions)!;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
/** `this` in a static initializer, or a computed name, of a class whose code moves out of its body. */
|
|
1823
|
+
private visitThisExpression(node: Node): Node {
|
|
1824
|
+
const environment = this.lexicalEnvironment;
|
|
1825
|
+
if (environment === undefined || environment.data === undefined || !this.shouldTransformThisInStaticInitializers)
|
|
1826
|
+
return node;
|
|
1827
|
+
const data = environment.data;
|
|
1828
|
+
// Computed names of ES-decorated classes are already in an arrow function seeing the outer `this`.
|
|
1829
|
+
if (
|
|
1830
|
+
this.insideComputedPropertyName &&
|
|
1831
|
+
((data.facts & ClassFacts.ClassWasDecorated) === 0 || this.legacyDecorators)
|
|
1832
|
+
) {
|
|
1833
|
+
const classThis = this.tryGetClassThisNoContainer();
|
|
1834
|
+
if (classThis !== undefined) return classThis;
|
|
1835
|
+
}
|
|
1836
|
+
const element = this.currentClassElement;
|
|
1837
|
+
if (element !== undefined && isStaticPropertyDeclarationOrClassStaticBlock(element)) {
|
|
1838
|
+
const classThis = this.tryGetClassThisNoContainer();
|
|
1839
|
+
if (classThis !== undefined) return classThis;
|
|
1840
|
+
// A legacy decorator may replace the class, so `this` can't name it.
|
|
1841
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0 && this.legacyDecorators)
|
|
1842
|
+
return this.factory.createParenthesizedExpression(this.factory.createVoidZero());
|
|
1843
|
+
}
|
|
1844
|
+
return node;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
private transformClassMembers(node: Node): ClassMembers {
|
|
1848
|
+
const factory = this.factory;
|
|
1849
|
+
const context = this.context;
|
|
1850
|
+
const memberList = getMembers(node)!;
|
|
1851
|
+
const memberNodes = memberList.nodes;
|
|
1852
|
+
const privateStaticsInClass = this.hasTransformPrivateStaticElementsFlag(node);
|
|
1853
|
+
// Declare private names.
|
|
1854
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks || this.shouldTransformPrivateStaticElementsInFile) {
|
|
1855
|
+
for (let i = 0; i < memberNodes.length; i++) {
|
|
1856
|
+
const member = memberNodes[i];
|
|
1857
|
+
if (!isPrivateIdentifierClassElementDeclaration(member)) continue;
|
|
1858
|
+
if (this.shouldTransformClassElementToWeakMap(member)) this.addPrivateIdentifierToEnvironment(member);
|
|
1859
|
+
else
|
|
1860
|
+
this.setPrivateIdentifier(
|
|
1861
|
+
this.getPrivateEnvironment(),
|
|
1862
|
+
getName(member)!,
|
|
1863
|
+
new PrivateIdentifierInfo(PrivateKind.Untransformed, undefined, false, false),
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
if (this.shouldTransformPrivateElementsOrClassStaticBlocks && privateInstanceMethodsAndAccessors(node).length > 0)
|
|
1867
|
+
this.createBrandCheckWeakSetForPrivateMethods(this.getPrivateEnvironment());
|
|
1868
|
+
if (this.shouldTransformAutoAccessorsInCurrentClass()) {
|
|
1869
|
+
for (let i = 0; i < memberNodes.length; i++) {
|
|
1870
|
+
const member = memberNodes[i];
|
|
1871
|
+
if (!isAutoAccessorPropertyDeclaration(member)) continue;
|
|
1872
|
+
const storageName = factory.createGeneratedPrivateNameForNode(getName(member)!, '', accessorStorageSuffix);
|
|
1873
|
+
if (
|
|
1874
|
+
this.shouldTransformPrivateElementsOrClassStaticBlocks ||
|
|
1875
|
+
(privateStaticsInClass && hasStaticModifier(member))
|
|
1876
|
+
)
|
|
1877
|
+
this.addPrivateIdentifierPropertyDeclarationToEnvironment(member, storageName);
|
|
1878
|
+
else {
|
|
1879
|
+
// Unless the first loop declared it, as for a private auto-accessor expanded by ES decorators.
|
|
1880
|
+
const environment = this.getPrivateEnvironment();
|
|
1881
|
+
if (this.getPrivateIdentifier(environment, storageName) === undefined)
|
|
1882
|
+
this.setPrivateIdentifier(
|
|
1883
|
+
environment,
|
|
1884
|
+
storageName,
|
|
1885
|
+
new PrivateIdentifierInfo(PrivateKind.Untransformed, undefined, false, false),
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
let members = this.classElementMode.visitNodes(memberList)!;
|
|
1892
|
+
let syntheticConstructor: Node | undefined = undefined;
|
|
1893
|
+
let hasConstructor = false;
|
|
1894
|
+
for (let i = 0; i < members.nodes.length; i++)
|
|
1895
|
+
if (members.nodes[i].kind === SyntaxKind.Constructor) hasConstructor = true;
|
|
1896
|
+
if (!hasConstructor) syntheticConstructor = this.transformConstructor(undefined, node);
|
|
1897
|
+
// Without static blocks transformed, computed name expressions are evaluated in a static block
|
|
1898
|
+
// at the top of the class, before other static initializers.
|
|
1899
|
+
let syntheticStaticBlock: Node | undefined = undefined;
|
|
1900
|
+
let prologue: Node | undefined = undefined;
|
|
1901
|
+
if (!this.shouldTransformPrivateElementsOrClassStaticBlocks && this.pendingExpressions.length > 0) {
|
|
1902
|
+
let statement: Node = factory.createExpressionStatement(factory.inlineExpressions(this.pendingExpressions)!);
|
|
1903
|
+
if (this.facts.has(statement, SubtreeFacts.ContainsLexicalThisOrSuper)) {
|
|
1904
|
+
// `this` and `super` in computed names refer to the outer scope: evaluate them in an arrow function.
|
|
1905
|
+
const temp = context.addVariableDeclaration(factory.createTempVariable(0));
|
|
1906
|
+
const arrow = factory.createArrowFunction([], factory.createBlock([statement], false));
|
|
1907
|
+
prologue = factory.createAssignment(temp, arrow);
|
|
1908
|
+
statement = factory.createExpressionStatement(factory.createCallExpression(temp, []));
|
|
1909
|
+
}
|
|
1910
|
+
syntheticStaticBlock = factory.created(
|
|
1911
|
+
new ClassStaticBlockDeclaration(undefined, factory.createBlock([statement], false)),
|
|
1912
|
+
);
|
|
1913
|
+
this.pendingExpressions = [];
|
|
1914
|
+
}
|
|
1915
|
+
if (syntheticConstructor !== undefined || syntheticStaticBlock !== undefined) {
|
|
1916
|
+
// The classThis and named evaluation blocks stay first.
|
|
1917
|
+
const nodes = members.nodes;
|
|
1918
|
+
let classThisIndex = -1;
|
|
1919
|
+
let namedEvaluationIndex = -1;
|
|
1920
|
+
for (let i = 0; i < nodes.length; i++)
|
|
1921
|
+
if (classThisIndex < 0 && isClassThisAssignmentBlock(context, nodes[i])) classThisIndex = i;
|
|
1922
|
+
for (let i = 0; i < nodes.length; i++)
|
|
1923
|
+
if (namedEvaluationIndex < 0 && isClassNamedEvaluationHelperBlock(context, nodes[i])) namedEvaluationIndex = i;
|
|
1924
|
+
const updated: Node[] = [];
|
|
1925
|
+
if (classThisIndex >= 0) updated.push(nodes[classThisIndex]);
|
|
1926
|
+
if (namedEvaluationIndex >= 0) updated.push(nodes[namedEvaluationIndex]);
|
|
1927
|
+
if (syntheticConstructor !== undefined) updated.push(syntheticConstructor);
|
|
1928
|
+
if (syntheticStaticBlock !== undefined) updated.push(syntheticStaticBlock);
|
|
1929
|
+
for (let i = 0; i < nodes.length; i++)
|
|
1930
|
+
if (i !== classThisIndex && i !== namedEvaluationIndex) updated.push(nodes[i]);
|
|
1931
|
+
members = new NodeList(memberList.pos, memberList.end, updated);
|
|
1932
|
+
}
|
|
1933
|
+
return new ClassMembers(members, prologue);
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
private createBrandCheckWeakSetForPrivateMethods(environment: PrivateEnvironment): boolean {
|
|
1937
|
+
const factory = this.factory;
|
|
1938
|
+
this.pendingExpressions.push(
|
|
1939
|
+
factory.createAssignment(
|
|
1940
|
+
environment.weakSetName!,
|
|
1941
|
+
factory.created(new NewExpression(factory.createIdentifier('WeakSet'), undefined, factory.createNodeList([]))),
|
|
1942
|
+
),
|
|
1943
|
+
);
|
|
1944
|
+
return true;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
private transformConstructor(constructor: ConstructorDeclaration | undefined, container: Node): Node | undefined {
|
|
1948
|
+
// Parameters and body are visited in the scopes of the new body, so hoisted variables come first.
|
|
1949
|
+
if ((this.currentClassFacts() & ClassFacts.WillHoistInitializersToConstructor) === 0)
|
|
1950
|
+
return constructor !== undefined ? this.visitEachChild(constructor) : undefined;
|
|
1951
|
+
const extendsElement = getClassExtendsHeritageElement(container);
|
|
1952
|
+
const isDerivedClass =
|
|
1953
|
+
extendsElement !== undefined &&
|
|
1954
|
+
skipOuterExpressions(extendsElement.expression, OuterExpressionKinds.All).kind !== SyntaxKind.NullKeyword;
|
|
1955
|
+
const parameters = constructor !== undefined ? this.visitNodes(constructor.parameters) : undefined;
|
|
1956
|
+
const body = this.transformConstructorBody(container, constructor, isDerivedClass);
|
|
1957
|
+
if (body === undefined) return constructor !== undefined ? this.visitEachChild(constructor) : undefined;
|
|
1958
|
+
const factory = this.factory;
|
|
1959
|
+
if (constructor !== undefined)
|
|
1960
|
+
return factory.updateConstructorDeclaration(
|
|
1961
|
+
constructor,
|
|
1962
|
+
undefined,
|
|
1963
|
+
undefined,
|
|
1964
|
+
parameters!,
|
|
1965
|
+
undefined,
|
|
1966
|
+
undefined,
|
|
1967
|
+
body,
|
|
1968
|
+
);
|
|
1969
|
+
const result = factory.created(
|
|
1970
|
+
new ConstructorDeclaration(undefined, undefined, factory.createNodeList([]), undefined, undefined, body),
|
|
1971
|
+
);
|
|
1972
|
+
return this.withRange(result, container);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
private transformConstructorBodyWorker(
|
|
1976
|
+
statementsOut: Node[],
|
|
1977
|
+
statementsIn: Node[],
|
|
1978
|
+
start: number,
|
|
1979
|
+
superPath: number[],
|
|
1980
|
+
depth: number,
|
|
1981
|
+
initializerStatements: Node[],
|
|
1982
|
+
constructor: ConstructorDeclaration,
|
|
1983
|
+
): Node[] {
|
|
1984
|
+
const superIndex = superPath[depth] | 0;
|
|
1985
|
+
const superStatement = statementsIn[superIndex];
|
|
1986
|
+
appendAll(statementsOut, this.visitArray(statementsIn.slice(start, superIndex)));
|
|
1987
|
+
let offset = superIndex + 1;
|
|
1988
|
+
if (superStatement instanceof TryStatement) {
|
|
1989
|
+
const tryBlock = superStatement.tryBlock;
|
|
1990
|
+
const inner = this.transformConstructorBodyWorker(
|
|
1991
|
+
[],
|
|
1992
|
+
tryBlock.statements.nodes,
|
|
1993
|
+
0,
|
|
1994
|
+
superPath,
|
|
1995
|
+
depth + 1,
|
|
1996
|
+
initializerStatements,
|
|
1997
|
+
constructor,
|
|
1998
|
+
);
|
|
1999
|
+
const list = new NodeList(tryBlock.statements.pos, tryBlock.statements.end, inner);
|
|
2000
|
+
const catchClause = this.visitNode(superStatement.catchClause);
|
|
2001
|
+
const finallyBlock = this.visitNode(superStatement.finallyBlock);
|
|
2002
|
+
statementsOut.push(
|
|
2003
|
+
this.factory.updateTryStatement(
|
|
2004
|
+
superStatement as TryStatement,
|
|
2005
|
+
this.factory.updateBlock(tryBlock, list, tryBlock.multiLine),
|
|
2006
|
+
catchClause instanceof CatchClause ? (catchClause as CatchClause) : undefined,
|
|
2007
|
+
finallyBlock instanceof Block ? (finallyBlock as Block) : undefined,
|
|
2008
|
+
)!,
|
|
2009
|
+
);
|
|
2010
|
+
} else {
|
|
2011
|
+
appendAll(statementsOut, this.visitArray([superStatement]));
|
|
2012
|
+
// Parameter property assignments directly follow `super()`; initializers go after them.
|
|
2013
|
+
offset = this.skipParameterPropertyAssignments(statementsIn, offset, constructor);
|
|
2014
|
+
appendAll(statementsOut, initializerStatements);
|
|
2015
|
+
}
|
|
2016
|
+
appendAll(statementsOut, this.visitArray(statementsIn.slice(offset)));
|
|
2017
|
+
return statementsOut;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
private skipParameterPropertyAssignments(
|
|
2021
|
+
statements: Node[],
|
|
2022
|
+
start: number,
|
|
2023
|
+
constructor: ConstructorDeclaration,
|
|
2024
|
+
): number {
|
|
2025
|
+
let offset = start;
|
|
2026
|
+
while (
|
|
2027
|
+
offset < statements.length &&
|
|
2028
|
+
isParameterPropertyDeclaration(this.context.mostOriginal(statements[offset]), constructor)
|
|
2029
|
+
)
|
|
2030
|
+
offset++;
|
|
2031
|
+
return offset;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
private transformConstructorBody(
|
|
2035
|
+
container: Node,
|
|
2036
|
+
constructor: ConstructorDeclaration | undefined,
|
|
2037
|
+
isDerivedClass: boolean,
|
|
2038
|
+
): Node | undefined {
|
|
2039
|
+
const factory = this.factory;
|
|
2040
|
+
const context = this.context;
|
|
2041
|
+
const instanceProperties = propertiesOf(container, false);
|
|
2042
|
+
let properties = instanceProperties;
|
|
2043
|
+
if (!this.useDefineForClassFields) properties = withInitializerOrPrivateName(properties);
|
|
2044
|
+
const privateMethodsAndAccessors = privateInstanceMethodsAndAccessors(container);
|
|
2045
|
+
const needsConstructorBody = properties.length > 0 || privateMethodsAndAccessors.length > 0;
|
|
2046
|
+
if (constructor === undefined && !needsConstructorBody) return this.visitFunctionBody(undefined);
|
|
2047
|
+
context.startVariableEnvironment();
|
|
2048
|
+
const needsSyntheticConstructor = constructor === undefined && isDerivedClass;
|
|
2049
|
+
let statements: Node[] = [];
|
|
2050
|
+
const initializerStatements: Node[] = [];
|
|
2051
|
+
const receiver = factory.createThisExpression();
|
|
2052
|
+
// Private methods can be called in initializers, so their brand comes first.
|
|
2053
|
+
this.addInstanceMethodStatements(initializerStatements, privateMethodsAndAccessors, receiver);
|
|
2054
|
+
if (constructor !== undefined) {
|
|
2055
|
+
const parameterProperties: Node[] = [];
|
|
2056
|
+
const others: Node[] = [];
|
|
2057
|
+
for (let i = 0; i < instanceProperties.length; i++)
|
|
2058
|
+
if (isParameterPropertyDeclaration(context.mostOriginal(instanceProperties[i]), constructor))
|
|
2059
|
+
parameterProperties.push(instanceProperties[i]);
|
|
2060
|
+
for (let i = 0; i < properties.length; i++)
|
|
2061
|
+
if (!isParameterPropertyDeclaration(context.mostOriginal(properties[i]), constructor))
|
|
2062
|
+
others.push(properties[i]);
|
|
2063
|
+
this.addPropertyOrClassStaticBlockStatements(initializerStatements, parameterProperties, receiver);
|
|
2064
|
+
this.addPropertyOrClassStaticBlockStatements(initializerStatements, others, receiver);
|
|
2065
|
+
} else this.addPropertyOrClassStaticBlockStatements(initializerStatements, properties, receiver);
|
|
2066
|
+
const constructorBody =
|
|
2067
|
+
constructor !== undefined && constructor.body instanceof Block ? (constructor.body as Block) : undefined;
|
|
2068
|
+
if (constructorBody !== undefined) {
|
|
2069
|
+
const nodes = constructorBody.statements.nodes;
|
|
2070
|
+
let offset = 0;
|
|
2071
|
+
while (offset < nodes.length && isPrologueDirective(nodes[offset])) statements.push(nodes[offset++]);
|
|
2072
|
+
const superPath = findSuperStatementIndexPath(nodes.slice(offset), 0);
|
|
2073
|
+
if (superPath.length > 0) {
|
|
2074
|
+
superPath[0] = (superPath[0] | 0) + offset;
|
|
2075
|
+
statements = this.transformConstructorBodyWorker(
|
|
2076
|
+
statements,
|
|
2077
|
+
nodes,
|
|
2078
|
+
offset,
|
|
2079
|
+
superPath,
|
|
2080
|
+
0,
|
|
2081
|
+
initializerStatements,
|
|
2082
|
+
constructor!,
|
|
2083
|
+
);
|
|
2084
|
+
} else {
|
|
2085
|
+
offset = this.skipParameterPropertyAssignments(nodes, offset, constructor!);
|
|
2086
|
+
appendAll(statements, initializerStatements);
|
|
2087
|
+
appendAll(statements, this.visitArray(nodes.slice(offset)));
|
|
2088
|
+
}
|
|
2089
|
+
} else {
|
|
2090
|
+
if (needsSyntheticConstructor)
|
|
2091
|
+
// `super(...arguments);`
|
|
2092
|
+
statements.push(
|
|
2093
|
+
factory.createExpressionStatement(
|
|
2094
|
+
factory.createCallExpression(factory.createKeywordExpression(SyntaxKind.SuperKeyword), [
|
|
2095
|
+
factory.created(new SpreadElement(factory.createIdentifier('arguments'))),
|
|
2096
|
+
]),
|
|
2097
|
+
),
|
|
2098
|
+
);
|
|
2099
|
+
appendAll(statements, initializerStatements);
|
|
2100
|
+
}
|
|
2101
|
+
statements = context.mergeEnvironment(statements, context.endVariableEnvironment());
|
|
2102
|
+
if (statements.length === 0 && constructor === undefined) return undefined;
|
|
2103
|
+
const multiLine =
|
|
2104
|
+
constructorBody !== undefined && constructorBody.statements.nodes.length >= statements.length
|
|
2105
|
+
? constructorBody.multiLine
|
|
2106
|
+
: statements.length > 0;
|
|
2107
|
+
const members = getMembers(container)!;
|
|
2108
|
+
const list =
|
|
2109
|
+
constructorBody !== undefined
|
|
2110
|
+
? new NodeList(constructorBody.statements.pos, constructorBody.statements.end, statements)
|
|
2111
|
+
: new NodeList(members.pos, members.end, statements);
|
|
2112
|
+
const block = factory.created(new Block(list, multiLine));
|
|
2113
|
+
if (constructorBody !== undefined) this.withRange(block, constructorBody);
|
|
2114
|
+
return block;
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
private addPropertyOrClassStaticBlockStatements(statements: Node[], properties: Node[], receiver: Node): boolean {
|
|
2118
|
+
for (let i = 0; i < properties.length; i++) {
|
|
2119
|
+
const property = properties[i];
|
|
2120
|
+
if (isStatic(property) && !this.shouldTransformPrivateElementsOrClassStaticBlocks) continue;
|
|
2121
|
+
const statement = this.transformPropertyOrClassStaticBlock(property, receiver);
|
|
2122
|
+
if (statement !== undefined) statements.push(statement);
|
|
2123
|
+
}
|
|
2124
|
+
return true;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
private transformStaticBlockInElement(property: ClassStaticBlockDeclaration): Node | undefined {
|
|
2128
|
+
const saved = this.currentClassElement;
|
|
2129
|
+
this.currentClassElement = property;
|
|
2130
|
+
const expression = this.transformClassStaticBlockDeclaration(property);
|
|
2131
|
+
this.currentClassElement = saved;
|
|
2132
|
+
return expression;
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
private transformPropertyOrClassStaticBlock(property: Node, receiver: Node): Node | undefined {
|
|
2136
|
+
const context = this.context;
|
|
2137
|
+
const expression =
|
|
2138
|
+
property instanceof ClassStaticBlockDeclaration
|
|
2139
|
+
? this.transformStaticBlockInElement(property as ClassStaticBlockDeclaration)
|
|
2140
|
+
: this.transformProperty(property as PropertyDeclaration, receiver);
|
|
2141
|
+
if (expression === undefined) return undefined;
|
|
2142
|
+
const statement = this.factory.createExpressionStatement(expression);
|
|
2143
|
+
context.setOriginal(statement, property);
|
|
2144
|
+
context.addEmitFlags(statement, context.getEmitFlags(property) & EmitFlags.NoComments);
|
|
2145
|
+
context.setCommentRange(statement, property.pos, property.end);
|
|
2146
|
+
const original = context.mostOriginal(property);
|
|
2147
|
+
if (original instanceof ParameterDeclaration) {
|
|
2148
|
+
context.setSourceMapRange(statement, original.pos, original.end);
|
|
2149
|
+
context.addEmitFlags(statement, EmitFlags.NoComments);
|
|
2150
|
+
} else context.setSourceMapRange(statement, posPastModifiers(property), property.end);
|
|
2151
|
+
// The statement got a copy of the synthesized comments; don't print them twice.
|
|
2152
|
+
context.setSyntheticLeadingComments(expression, undefined);
|
|
2153
|
+
context.setSyntheticTrailingComments(expression, undefined);
|
|
2154
|
+
// Comments of an auto-accessor go to its getter.
|
|
2155
|
+
if (hasSyntacticModifier(original, ModifierFlags.Accessor)) context.addEmitFlags(statement, EmitFlags.NoComments);
|
|
2156
|
+
return statement;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
private generateInitializedPropertyExpressionsOrClassStaticBlock(properties: Node[], receiver: Node): Node[] {
|
|
2160
|
+
const expressions: Node[] = [];
|
|
2161
|
+
for (let i = 0; i < properties.length; i++) {
|
|
2162
|
+
const property = properties[i];
|
|
2163
|
+
const expression =
|
|
2164
|
+
property instanceof ClassStaticBlockDeclaration
|
|
2165
|
+
? this.transformStaticBlockInElement(property as ClassStaticBlockDeclaration)
|
|
2166
|
+
: this.transformProperty(property as PropertyDeclaration, receiver);
|
|
2167
|
+
if (expression === undefined) continue;
|
|
2168
|
+
this.context.setOriginalEx(expression, property, true);
|
|
2169
|
+
this.context.assignCommentAndSourceMapRanges(expression, property);
|
|
2170
|
+
expressions.push(expression);
|
|
2171
|
+
}
|
|
2172
|
+
return expressions;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
private transformProperty(property: PropertyDeclaration, receiver: Node): Node | undefined {
|
|
2176
|
+
const saved = this.currentClassElement;
|
|
2177
|
+
const transformed = this.transformPropertyWorker(property, receiver);
|
|
2178
|
+
if (transformed !== undefined && hasStaticModifier(property)) {
|
|
2179
|
+
const context = this.context;
|
|
2180
|
+
context.addEmitFlags(transformed, EmitFlags.NoLexicalThis);
|
|
2181
|
+
if (this.currentClassFacts() !== ClassFacts.None) {
|
|
2182
|
+
context.setOriginal(transformed, property);
|
|
2183
|
+
context.setSourceMapRange(
|
|
2184
|
+
transformed,
|
|
2185
|
+
context.sourceMapPos(property.name),
|
|
2186
|
+
context.sourceMapEnd(property.name),
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
this.currentClassElement = saved;
|
|
2191
|
+
return transformed;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
private transformPropertyWorker(node: PropertyDeclaration, receiver: Node): Node | undefined {
|
|
2195
|
+
const factory = this.factory;
|
|
2196
|
+
const context = this.context;
|
|
2197
|
+
const emitAssignment = !this.useDefineForClassFields;
|
|
2198
|
+
const property = this.transformNamedEvaluationIfNeeded(node, '') as PropertyDeclaration;
|
|
2199
|
+
// The generated name reuses the value cached by the moved computed name expression.
|
|
2200
|
+
let propertyName: Node = property.name;
|
|
2201
|
+
if (hasSyntacticModifier(property, ModifierFlags.Accessor))
|
|
2202
|
+
propertyName = factory.createGeneratedPrivateNameForNode(property.name, '', accessorStorageSuffix);
|
|
2203
|
+
else if (propertyName instanceof ComputedPropertyName && !isSimpleInlineableExpression(propertyName.expression))
|
|
2204
|
+
propertyName = factory.updateComputedPropertyName(
|
|
2205
|
+
propertyName,
|
|
2206
|
+
factory.createGeneratedNameForNode(propertyName, 0, '', ''),
|
|
2207
|
+
);
|
|
2208
|
+
if (hasStaticModifier(property)) this.currentClassElement = property;
|
|
2209
|
+
if (propertyName instanceof PrivateIdentifier && this.shouldTransformClassElementToWeakMap(property)) {
|
|
2210
|
+
const info = this.accessPrivateIdentifier(propertyName);
|
|
2211
|
+
if (info === undefined) throw new Error('Undeclared private name for property declaration.');
|
|
2212
|
+
if (info.kind !== PrivateKind.Field) return undefined;
|
|
2213
|
+
const initializer = this.visitNode(property.initializer);
|
|
2214
|
+
const value = initializer !== undefined ? initializer : factory.createVoidZero();
|
|
2215
|
+
// `_C_x.set(this, value)`, or `_C_x = { value }` for statics.
|
|
2216
|
+
if (!info.isStatic) return factory.createMethodCall(info.brandCheckIdentifier!, 'set', [receiver, value]);
|
|
2217
|
+
return factory.createAssignment(
|
|
2218
|
+
info.variableName!,
|
|
2219
|
+
factory.createObjectLiteral(
|
|
2220
|
+
[factory.createPropertyAssignment(factory.createIdentifier('value'), value)],
|
|
2221
|
+
false,
|
|
2222
|
+
),
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
if (
|
|
2226
|
+
(propertyName instanceof PrivateIdentifier || hasStaticModifier(property)) &&
|
|
2227
|
+
property.initializer === undefined
|
|
2228
|
+
)
|
|
2229
|
+
return undefined;
|
|
2230
|
+
const original = context.mostOriginal(property);
|
|
2231
|
+
if (hasSyntacticModifier(original, ModifierFlags.Abstract)) return undefined;
|
|
2232
|
+
let initializer = this.visitNode(property.initializer);
|
|
2233
|
+
if (isParameterPropertyDeclaration(original, original.parent) && propertyName instanceof Identifier) {
|
|
2234
|
+
// A parameter property's value is its parameter; an initializer here only comes from decorators.
|
|
2235
|
+
const localName = factory.cloneIdentifier(propertyName);
|
|
2236
|
+
if (initializer !== undefined) {
|
|
2237
|
+
// Unwrap `(__runInitializers(this, _instanceExtraInitializers), void 0)`.
|
|
2238
|
+
if (initializer instanceof ParenthesizedExpression) {
|
|
2239
|
+
const inner = initializer.expression;
|
|
2240
|
+
if (
|
|
2241
|
+
inner instanceof BinaryExpression &&
|
|
2242
|
+
inner.operatorToken.kind === SyntaxKind.CommaToken &&
|
|
2243
|
+
context.isCallToHelper(inner.left, '__runInitializers') &&
|
|
2244
|
+
inner.right instanceof VoidExpression &&
|
|
2245
|
+
inner.right.expression.kind === SyntaxKind.NumericLiteral
|
|
2246
|
+
)
|
|
2247
|
+
initializer = inner.left;
|
|
2248
|
+
}
|
|
2249
|
+
initializer = factory.inlineExpressions([initializer, localName])!;
|
|
2250
|
+
} else initializer = localName;
|
|
2251
|
+
context.addEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap);
|
|
2252
|
+
const originalName = getName(original)!;
|
|
2253
|
+
context.setSourceMapRange(localName, originalName.pos, originalName.end);
|
|
2254
|
+
context.addEmitFlags(localName, EmitFlags.NoComments);
|
|
2255
|
+
} else if (initializer === undefined) initializer = factory.createVoidZero();
|
|
2256
|
+
if (emitAssignment || propertyName instanceof PrivateIdentifier) {
|
|
2257
|
+
const access = this.createMemberAccessForPropertyName(receiver, propertyName);
|
|
2258
|
+
context.addEmitFlags(access, EmitFlags.NoLeadingComments);
|
|
2259
|
+
return factory.createAssignment(access, initializer);
|
|
2260
|
+
}
|
|
2261
|
+
// useDefineForClassFields: `Object.defineProperty(this, "x", { ... })`
|
|
2262
|
+
let name: Node = propertyName;
|
|
2263
|
+
if (propertyName instanceof ComputedPropertyName) name = propertyName.expression;
|
|
2264
|
+
else if (propertyName instanceof Identifier) name = factory.createStringLiteral(propertyName.text, TokenFlags.None);
|
|
2265
|
+
const descriptor = factory.createObjectLiteral(
|
|
2266
|
+
[
|
|
2267
|
+
factory.createPropertyAssignment(factory.createIdentifier('enumerable'), factory.createTrue()),
|
|
2268
|
+
factory.createPropertyAssignment(factory.createIdentifier('configurable'), factory.createTrue()),
|
|
2269
|
+
factory.createPropertyAssignment(factory.createIdentifier('writable'), factory.createTrue()),
|
|
2270
|
+
factory.createPropertyAssignment(factory.createIdentifier('value'), initializer),
|
|
2271
|
+
],
|
|
2272
|
+
true,
|
|
2273
|
+
);
|
|
2274
|
+
return factory.createObjectDefinePropertyCall(receiver, name, descriptor);
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
private createMemberAccessForPropertyName(receiver: Node, name: Node): Node {
|
|
2278
|
+
const factory = this.factory;
|
|
2279
|
+
if (name instanceof ComputedPropertyName)
|
|
2280
|
+
return this.withRange(factory.createElementAccessExpression(receiver, name.expression), name);
|
|
2281
|
+
const access: Node =
|
|
2282
|
+
name instanceof Identifier || name instanceof PrivateIdentifier
|
|
2283
|
+
? factory.createPropertyAccessExpression(receiver, name)
|
|
2284
|
+
: factory.createElementAccessExpression(receiver, name);
|
|
2285
|
+
this.context.setCommentRange(access, name.pos, name.end);
|
|
2286
|
+
this.context.setSourceMapRange(access, name.pos, name.end);
|
|
2287
|
+
this.context.addEmitFlags(access, EmitFlags.NoNestedSourceMaps);
|
|
2288
|
+
return access;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
/** `_C_instances.add(this)` brands instances for private methods and accessors. */
|
|
2292
|
+
private addInstanceMethodStatements(statements: Node[], methods: Node[], receiver: Node): boolean {
|
|
2293
|
+
if (!this.shouldTransformPrivateElementsOrClassStaticBlocks || methods.length === 0) return false;
|
|
2294
|
+
const weakSetName = this.getPrivateEnvironment().weakSetName!;
|
|
2295
|
+
statements.push(
|
|
2296
|
+
this.factory.createExpressionStatement(this.factory.createMethodCall(weakSetName, 'add', [receiver])),
|
|
2297
|
+
);
|
|
2298
|
+
return true;
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
private visitInvalidSuperProperty(node: Node): Node {
|
|
2302
|
+
const factory = this.factory;
|
|
2303
|
+
if (node instanceof PropertyAccessExpression)
|
|
2304
|
+
return factory.updatePropertyAccessExpression(
|
|
2305
|
+
node as PropertyAccessExpression,
|
|
2306
|
+
factory.createVoidZero(),
|
|
2307
|
+
undefined,
|
|
2308
|
+
node.name,
|
|
2309
|
+
node.flags,
|
|
2310
|
+
);
|
|
2311
|
+
const access = node as ElementAccessExpression;
|
|
2312
|
+
return factory.updateElementAccessExpression(
|
|
2313
|
+
access,
|
|
2314
|
+
factory.createVoidZero(),
|
|
2315
|
+
undefined,
|
|
2316
|
+
this.visitNode(access.argumentExpression)!,
|
|
2317
|
+
access.flags,
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* A visited computed name: an assignment caching its value when it's needed again (`shouldHoist`),
|
|
2323
|
+
* the expression when it has effects, or undefined when it's unused or safe to repeat.
|
|
2324
|
+
*/
|
|
2325
|
+
private getPropertyNameExpressionIfNeeded(name: Node, shouldHoist: boolean): Node | undefined {
|
|
2326
|
+
if (!(name instanceof ComputedPropertyName)) return undefined;
|
|
2327
|
+
const cacheAssignment = findComputedPropertyNameCacheAssignment(name);
|
|
2328
|
+
const expression = this.visitInOuterEnvironment(name.expression);
|
|
2329
|
+
const inner = skipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions);
|
|
2330
|
+
const inlinable = isSimpleInlineableExpression(inner);
|
|
2331
|
+
const alreadyTransformed =
|
|
2332
|
+
cacheAssignment !== undefined ||
|
|
2333
|
+
(inner instanceof BinaryExpression &&
|
|
2334
|
+
isAssignmentExpression(inner, true) &&
|
|
2335
|
+
inner.left instanceof Identifier &&
|
|
2336
|
+
this.context.hasAutoGenerateInfo(inner.left));
|
|
2337
|
+
if (!alreadyTransformed && !inlinable && shouldHoist) {
|
|
2338
|
+
const generated = this.addHoisted(
|
|
2339
|
+
this.factory.createGeneratedNameForNode(name, 0, '', ''),
|
|
2340
|
+
this.requiresBlockScopedVar(),
|
|
2341
|
+
);
|
|
2342
|
+
return this.factory.createAssignment(generated, expression);
|
|
2343
|
+
}
|
|
2344
|
+
if (inlinable || inner instanceof Identifier) return undefined;
|
|
2345
|
+
return expression;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
private getClassData(): ClassData {
|
|
2349
|
+
const environment = this.lexicalEnvironment!;
|
|
2350
|
+
if (environment.data === undefined) environment.data = new ClassData();
|
|
2351
|
+
return environment.data;
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
private getPrivateEnvironment(): PrivateEnvironment {
|
|
2355
|
+
const environment = this.lexicalEnvironment!;
|
|
2356
|
+
if (environment.privateEnv === undefined) environment.privateEnv = new PrivateEnvironment();
|
|
2357
|
+
return environment.privateEnv;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
/** The brand check of a static member: the class, or its classThis. */
|
|
2361
|
+
private staticBrandCheck(): Identifier | undefined {
|
|
2362
|
+
const data = this.getClassData();
|
|
2363
|
+
return data.classThis !== undefined ? data.classThis : data.classConstructor;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
private addPrivateIdentifierPropertyDeclarationToEnvironment(node: Node, name: Node): boolean {
|
|
2367
|
+
const environment = this.getPrivateEnvironment();
|
|
2368
|
+
const isStaticMember = hasStaticModifier(node);
|
|
2369
|
+
const isValid = !this.isReservedPrivateName(name) && this.getPrivateIdentifier(environment, name) === undefined;
|
|
2370
|
+
if (isStaticMember) {
|
|
2371
|
+
const info = new PrivateIdentifierInfo(PrivateKind.Field, this.staticBrandCheck(), true, isValid);
|
|
2372
|
+
info.variableName = this.createHoistedVariableForPrivateName(name, '');
|
|
2373
|
+
this.setPrivateIdentifier(environment, name, info);
|
|
2374
|
+
return true;
|
|
2375
|
+
}
|
|
2376
|
+
const weakMapName = this.createHoistedVariableForPrivateName(name, '');
|
|
2377
|
+
this.setPrivateIdentifier(
|
|
2378
|
+
environment,
|
|
2379
|
+
name,
|
|
2380
|
+
new PrivateIdentifierInfo(PrivateKind.Field, weakMapName, false, isValid),
|
|
2381
|
+
);
|
|
2382
|
+
const factory = this.factory;
|
|
2383
|
+
this.pendingExpressions.push(
|
|
2384
|
+
factory.createAssignment(
|
|
2385
|
+
weakMapName,
|
|
2386
|
+
factory.created(new NewExpression(factory.createIdentifier('WeakMap'), undefined, factory.createNodeList([]))),
|
|
2387
|
+
),
|
|
2388
|
+
);
|
|
2389
|
+
return true;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
private addPrivateIdentifierToEnvironment(node: Node): boolean {
|
|
2393
|
+
const environment = this.getPrivateEnvironment();
|
|
2394
|
+
const name = getName(node)!;
|
|
2395
|
+
const isStaticMember = hasStaticModifier(node);
|
|
2396
|
+
const previous = this.getPrivateIdentifier(environment, name);
|
|
2397
|
+
const isValid = !this.isReservedPrivateName(name) && previous === undefined;
|
|
2398
|
+
if (node instanceof PropertyDeclaration && !isAutoAccessorPropertyDeclaration(node))
|
|
2399
|
+
return this.addPrivateIdentifierPropertyDeclarationToEnvironment(node, name);
|
|
2400
|
+
const brandCheck = isStaticMember ? this.staticBrandCheck() : environment.weakSetName;
|
|
2401
|
+
if (brandCheck === undefined)
|
|
2402
|
+
throw new Error(isStaticMember ? 'classConstructor should be set' : 'weakSetName should be set');
|
|
2403
|
+
if (node instanceof PropertyDeclaration) {
|
|
2404
|
+
const info = new PrivateIdentifierInfo(PrivateKind.Accessor, brandCheck, isStaticMember, isValid);
|
|
2405
|
+
info.getterName = this.createHoistedVariableForPrivateName(name, '_get');
|
|
2406
|
+
info.setterName = this.createHoistedVariableForPrivateName(name, '_set');
|
|
2407
|
+
this.setPrivateIdentifier(environment, name, info);
|
|
2408
|
+
} else if (node.kind === SyntaxKind.MethodDeclaration) {
|
|
2409
|
+
const methodName = this.createHoistedVariableForPrivateName(name, '');
|
|
2410
|
+
const info = new PrivateIdentifierInfo(PrivateKind.Method, brandCheck, isStaticMember, isValid);
|
|
2411
|
+
info.methodName = methodName;
|
|
2412
|
+
this.setPrivateIdentifier(environment, name, info);
|
|
2413
|
+
} else {
|
|
2414
|
+
const getter = node.kind === SyntaxKind.GetAccessor;
|
|
2415
|
+
const accessorName = this.createHoistedVariableForPrivateName(name, getter ? '_get' : '_set');
|
|
2416
|
+
// A get and set accessor pair shares one entry.
|
|
2417
|
+
if (
|
|
2418
|
+
previous !== undefined &&
|
|
2419
|
+
previous.kind === PrivateKind.Accessor &&
|
|
2420
|
+
previous.isStatic === isStaticMember &&
|
|
2421
|
+
(getter ? previous.getterName === undefined : previous.setterName === undefined)
|
|
2422
|
+
) {
|
|
2423
|
+
if (getter) previous.getterName = accessorName;
|
|
2424
|
+
else previous.setterName = accessorName;
|
|
2425
|
+
} else {
|
|
2426
|
+
const info = new PrivateIdentifierInfo(PrivateKind.Accessor, brandCheck, isStaticMember, isValid);
|
|
2427
|
+
if (getter) info.getterName = accessorName;
|
|
2428
|
+
else info.setterName = accessorName;
|
|
2429
|
+
this.setPrivateIdentifier(environment, name, info);
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
return true;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
private setPrivateIdentifier(environment: PrivateEnvironment, name: Node, info: PrivateIdentifierInfo): boolean {
|
|
2436
|
+
if (this.context.hasAutoGenerateInfo(name))
|
|
2437
|
+
environment.generated.set(this.context.getNodeForGeneratedName(name), info);
|
|
2438
|
+
else environment.members.set(privateNameText(name), info);
|
|
2439
|
+
return true;
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
private getPrivateIdentifier(environment: PrivateEnvironment, name: Node): PrivateIdentifierInfo | undefined {
|
|
2443
|
+
if (this.context.hasAutoGenerateInfo(name))
|
|
2444
|
+
return environment.generated.get(this.context.getNodeForGeneratedName(name));
|
|
2445
|
+
return environment.members.get(privateNameText(name));
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
/** A hoisted variable such as `_C_x`, prefixed with the class name when it has one. */
|
|
2449
|
+
private createHoistedVariableForClass(text: string, node: Node, suffix: string): Identifier {
|
|
2450
|
+
const className = this.getPrivateEnvironment().className;
|
|
2451
|
+
const prefix = className !== undefined ? '_' + className.text + '_' : '_';
|
|
2452
|
+
const identifier = this.factory.createUniqueNameWithSuffix(
|
|
2453
|
+
prefix + text,
|
|
2454
|
+
GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes,
|
|
2455
|
+
suffix,
|
|
2456
|
+
);
|
|
2457
|
+
return this.addHoisted(identifier, this.requiresBlockScopedVar());
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
private createHoistedVariableForPrivateName(name: Node, suffix: string): Identifier {
|
|
2461
|
+
// Generated names, as of auto-accessor storage, are named from their node when printed.
|
|
2462
|
+
if (this.context.hasAutoGenerateInfo(name)) {
|
|
2463
|
+
const className = this.getPrivateEnvironment().className;
|
|
2464
|
+
const prefix = className !== undefined ? '_' + className.text + '_' : '_';
|
|
2465
|
+
const identifier = this.factory.createGeneratedNameForNode(
|
|
2466
|
+
name,
|
|
2467
|
+
GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes,
|
|
2468
|
+
prefix,
|
|
2469
|
+
suffix,
|
|
2470
|
+
);
|
|
2471
|
+
return this.addHoisted(identifier, this.requiresBlockScopedVar());
|
|
2472
|
+
}
|
|
2473
|
+
let text = privateNameText(name);
|
|
2474
|
+
if (text.length > 0 && text.charCodeAt(0) === 0x23) text = text.slice(1);
|
|
2475
|
+
return this.createHoistedVariableForClass(text, name, suffix);
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
/** What a private name declared in this or an enclosing class transforms to. */
|
|
2479
|
+
private accessPrivateIdentifier(name: Node): PrivateIdentifierInfo | undefined {
|
|
2480
|
+
for (let environment = this.lexicalEnvironment; environment !== undefined; environment = environment.previous) {
|
|
2481
|
+
const privateEnv = environment.privateEnv;
|
|
2482
|
+
if (privateEnv === undefined) continue;
|
|
2483
|
+
const info = this.getPrivateIdentifier(privateEnv, name);
|
|
2484
|
+
if (info !== undefined) return info.kind === PrivateKind.Untransformed ? undefined : info;
|
|
2485
|
+
}
|
|
2486
|
+
return undefined;
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
private isReservedPrivateName(node: Node): boolean {
|
|
2490
|
+
if (node instanceof PrivateIdentifier && this.context.hasAutoGenerateInfo(node)) return false;
|
|
2491
|
+
return privateNameText(node) === '#constructor';
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
/** `obj.#x` as a destructuring target: `({ set value(_a) { __classPrivateFieldSet(obj, ...); } }).value`. */
|
|
2495
|
+
private wrapPrivateIdentifierForDestructuringTarget(node: PropertyAccessExpression): Node {
|
|
2496
|
+
const factory = this.factory;
|
|
2497
|
+
const parameter = factory.createGeneratedNameForNode(node, 0, '', '');
|
|
2498
|
+
const info = this.accessPrivateIdentifier(node.name);
|
|
2499
|
+
if (info === undefined) return this.visitEachChild(node);
|
|
2500
|
+
let receiver: Node = node.expression;
|
|
2501
|
+
// `this` and `super` would bind differently in the setter.
|
|
2502
|
+
const kind = node.expression.kind;
|
|
2503
|
+
if (kind === SyntaxKind.ThisKeyword || kind === SyntaxKind.SuperKeyword || !isSimpleCopiableExpression(receiver)) {
|
|
2504
|
+
const temp = this.context.addVariableDeclaration(
|
|
2505
|
+
factory.createTempVariable(GeneratedIdentifierFlags.ReservedInNestedScopes),
|
|
2506
|
+
);
|
|
2507
|
+
this.pendingExpressions.push(factory.createAssignment(temp, this.visitNode(node.expression)!));
|
|
2508
|
+
receiver = temp;
|
|
2509
|
+
}
|
|
2510
|
+
return factory.createAssignmentTargetWrapper(
|
|
2511
|
+
parameter,
|
|
2512
|
+
this.createPrivateIdentifierAssignment(info, receiver, parameter, SyntaxKind.EqualsToken),
|
|
2513
|
+
);
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
private visitDestructuringAssignmentTarget(node: Node): Node {
|
|
2517
|
+
if (node instanceof ObjectLiteralExpression || node instanceof ArrayLiteralExpression)
|
|
2518
|
+
return this.visitAssignmentPattern(node);
|
|
2519
|
+
if (node instanceof PropertyAccessExpression && node.name instanceof PrivateIdentifier)
|
|
2520
|
+
return this.wrapPrivateIdentifierForDestructuringTarget(node);
|
|
2521
|
+
const data = this.staticSuperData(node);
|
|
2522
|
+
if (data !== undefined) {
|
|
2523
|
+
if ((data.facts & ClassFacts.ClassWasDecorated) !== 0) return this.visitInvalidSuperProperty(node);
|
|
2524
|
+
if (data.classConstructor !== undefined && data.superClassReference !== undefined) {
|
|
2525
|
+
let name: Node | undefined = undefined;
|
|
2526
|
+
if (node instanceof ElementAccessExpression) name = this.visitNode(node.argumentExpression);
|
|
2527
|
+
else if (node instanceof PropertyAccessExpression && node.name instanceof Identifier)
|
|
2528
|
+
name = this.factory.createStringLiteralFromNode(node.name);
|
|
2529
|
+
if (name !== undefined) {
|
|
2530
|
+
const temp = this.factory.createTempVariable(0);
|
|
2531
|
+
return this.factory.createAssignmentTargetWrapper(
|
|
2532
|
+
temp,
|
|
2533
|
+
this.factory.createReflectSetCall(data.superClassReference, name, temp, data.classConstructor),
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
return this.visitEachChild(node);
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
private visitAssignmentElement(element: Node): Node {
|
|
2542
|
+
const node = this.transformNamedEvaluationIfNeeded(element, '');
|
|
2543
|
+
if (node instanceof BinaryExpression && isAssignmentExpression(node, true)) {
|
|
2544
|
+
const left = this.visitDestructuringAssignmentTarget(node.left);
|
|
2545
|
+
const right = this.visitNode(node.right)!;
|
|
2546
|
+
return this.factory.updateBinaryExpression(
|
|
2547
|
+
node as BinaryExpression,
|
|
2548
|
+
undefined,
|
|
2549
|
+
left,
|
|
2550
|
+
undefined,
|
|
2551
|
+
node.operatorToken,
|
|
2552
|
+
right,
|
|
2553
|
+
);
|
|
2554
|
+
}
|
|
2555
|
+
return this.visitDestructuringAssignmentTarget(node);
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
private visitArrayAssignmentElement(node: Node): Node | undefined {
|
|
2559
|
+
if (isArrayBindingOrAssignmentElement(node)) {
|
|
2560
|
+
if (node instanceof SpreadElement) {
|
|
2561
|
+
if (isLeftHandSideExpression(node.expression))
|
|
2562
|
+
return this.factory.updateSpreadElement(
|
|
2563
|
+
node as SpreadElement,
|
|
2564
|
+
this.visitDestructuringAssignmentTarget(node.expression),
|
|
2565
|
+
);
|
|
2566
|
+
return this.visitEachChild(node);
|
|
2567
|
+
}
|
|
2568
|
+
if (node.kind !== SyntaxKind.OmittedExpression) return this.visitAssignmentElement(node);
|
|
2569
|
+
}
|
|
2570
|
+
return this.visitEachChild(node);
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
private visitObjectAssignmentElement(node: Node): Node | undefined {
|
|
2574
|
+
const factory = this.factory;
|
|
2575
|
+
if (node instanceof SpreadAssignment) {
|
|
2576
|
+
if (isLeftHandSideExpression(node.expression))
|
|
2577
|
+
return factory.updateSpreadAssignment(
|
|
2578
|
+
node as SpreadAssignment,
|
|
2579
|
+
this.visitDestructuringAssignmentTarget(node.expression),
|
|
2580
|
+
);
|
|
2581
|
+
return this.visitEachChild(node);
|
|
2582
|
+
}
|
|
2583
|
+
if (node instanceof ShorthandPropertyAssignment)
|
|
2584
|
+
return this.visitEachChild(this.transformNamedEvaluationIfNeeded(node, ''));
|
|
2585
|
+
if (node instanceof PropertyAssignment) {
|
|
2586
|
+
const name = this.visitNode(node.name)!;
|
|
2587
|
+
const initializer = node.initializer;
|
|
2588
|
+
if (initializer instanceof BinaryExpression && isAssignmentExpression(initializer, true))
|
|
2589
|
+
return factory.updatePropertyAssignment(
|
|
2590
|
+
node as PropertyAssignment,
|
|
2591
|
+
undefined,
|
|
2592
|
+
name,
|
|
2593
|
+
undefined,
|
|
2594
|
+
undefined,
|
|
2595
|
+
this.visitAssignmentElement(initializer),
|
|
2596
|
+
);
|
|
2597
|
+
if (isLeftHandSideExpression(initializer))
|
|
2598
|
+
return factory.updatePropertyAssignment(
|
|
2599
|
+
node as PropertyAssignment,
|
|
2600
|
+
undefined,
|
|
2601
|
+
name,
|
|
2602
|
+
undefined,
|
|
2603
|
+
undefined,
|
|
2604
|
+
this.visitDestructuringAssignmentTarget(initializer),
|
|
2605
|
+
);
|
|
2606
|
+
return this.visitEachChild(node);
|
|
2607
|
+
}
|
|
2608
|
+
return this.visitEachChild(node);
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
/** Private names and static `super` in destructuring targets, as `[{ set value(x) { ... } }.value] = ...`. */
|
|
2612
|
+
private visitAssignmentPattern(node: Node): Node {
|
|
2613
|
+
if (node instanceof ArrayLiteralExpression)
|
|
2614
|
+
return this.factory.updateArrayLiteralExpression(
|
|
2615
|
+
node as ArrayLiteralExpression,
|
|
2616
|
+
this.arrayElementMode.visitNodes(node.elements)!,
|
|
2617
|
+
node.multiLine,
|
|
2618
|
+
);
|
|
2619
|
+
const object = node as ObjectLiteralExpression;
|
|
2620
|
+
return this.factory.updateObjectLiteralExpression(
|
|
2621
|
+
object,
|
|
2622
|
+
this.objectElementMode.visitNodes(object.properties)!,
|
|
2623
|
+
object.multiLine,
|
|
2624
|
+
);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
private createAccessorPropertyGetRedirector(
|
|
2628
|
+
node: PropertyDeclaration,
|
|
2629
|
+
modifiers: ModifierList | undefined,
|
|
2630
|
+
name: Node,
|
|
2631
|
+
receiver: Node,
|
|
2632
|
+
): Node {
|
|
2633
|
+
const factory = this.factory;
|
|
2634
|
+
const storage = factory.createGeneratedPrivateNameForNode(node.name, '', accessorStorageSuffix);
|
|
2635
|
+
const body = factory.createBlock(
|
|
2636
|
+
[factory.createReturnStatement(factory.createPropertyAccessExpression(receiver, storage))],
|
|
2637
|
+
false,
|
|
2638
|
+
);
|
|
2639
|
+
return factory.created(
|
|
2640
|
+
new GetAccessorDeclaration(modifiers, name, undefined, factory.createNodeList([]), undefined, undefined, body),
|
|
2641
|
+
);
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
private createAccessorPropertySetRedirector(
|
|
2645
|
+
node: PropertyDeclaration,
|
|
2646
|
+
modifiers: ModifierList | undefined,
|
|
2647
|
+
name: Node,
|
|
2648
|
+
receiver: Node,
|
|
2649
|
+
): Node {
|
|
2650
|
+
const factory = this.factory;
|
|
2651
|
+
const storage = factory.createGeneratedPrivateNameForNode(node.name, '', accessorStorageSuffix);
|
|
2652
|
+
const assignment = factory.createAssignment(
|
|
2653
|
+
factory.createPropertyAccessExpression(receiver, storage),
|
|
2654
|
+
factory.createIdentifier('value'),
|
|
2655
|
+
);
|
|
2656
|
+
const body = factory.createBlock([factory.createExpressionStatement(assignment)], false);
|
|
2657
|
+
const parameters = factory.createNodeList([factory.createParameter(factory.createIdentifier('value'))]);
|
|
2658
|
+
return factory.created(
|
|
2659
|
+
new SetAccessorDeclaration(modifiers, name, undefined, parameters, undefined, undefined, body),
|
|
2660
|
+
);
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
private createCallBinding(node: Node): CallBinding {
|
|
2664
|
+
const factory = this.factory;
|
|
2665
|
+
if (isSuperProperty(node)) return new CallBinding(factory.createThisExpression(), node);
|
|
2666
|
+
if (node instanceof PropertyAccessExpression) {
|
|
2667
|
+
if (!shouldBeCapturedInTempVariable(node.expression)) return new CallBinding(node.expression, node);
|
|
2668
|
+
const thisArg = this.context.addVariableDeclaration(factory.createTempVariable(0));
|
|
2669
|
+
const target = factory.createPropertyAccessExpression(
|
|
2670
|
+
factory.createParenthesizedExpression(factory.createAssignment(thisArg, node.expression)),
|
|
2671
|
+
node.name,
|
|
2672
|
+
);
|
|
2673
|
+
return new CallBinding(thisArg, target);
|
|
2674
|
+
}
|
|
2675
|
+
return new CallBinding(factory.createVoidZero(), node);
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
/** Finds identifiers in member code that resolve to a class, skipping property names. */
|
|
2680
|
+
class ConstructorReferenceFinder extends NodeVisitor {
|
|
2681
|
+
readonly resolver: EmitResolver;
|
|
2682
|
+
readonly classOriginal: Node;
|
|
2683
|
+
readonly className: Node | undefined;
|
|
2684
|
+
|
|
2685
|
+
constructor(resolver: EmitResolver, classOriginal: Node, className: Node | undefined) {
|
|
2686
|
+
super();
|
|
2687
|
+
this.resolver = resolver;
|
|
2688
|
+
this.classOriginal = classOriginal;
|
|
2689
|
+
this.className = className;
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
check(node: Node): boolean {
|
|
2693
|
+
if (node instanceof Identifier && !isSameNode(node, this.className)) {
|
|
2694
|
+
const declaration = this.resolver.getReferencedValueDeclaration(node as Identifier);
|
|
2695
|
+
if (declaration !== undefined && declaration === this.classOriginal) return true;
|
|
2696
|
+
}
|
|
2697
|
+
if (node instanceof PropertyAccessExpression) return this.check(node.expression);
|
|
2698
|
+
return node.forEachChild(this);
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
visitNode(node: Node): boolean {
|
|
2702
|
+
return this.check(node);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2706
|
+
function membersOf(node: Node): Node[] {
|
|
2707
|
+
const members = getMembers(node);
|
|
2708
|
+
return members === undefined ? [] : members.nodes;
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
function parametersOf(node: Node): NodeList {
|
|
2712
|
+
const parameters = getParameters(node);
|
|
2713
|
+
return parameters !== undefined ? parameters : new NodeList(-1, -1, []);
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
function appendAll(target: Node[], source: readonly Node[]): boolean {
|
|
2717
|
+
for (let i = 0; i < source.length; i++) target.push(source[i]);
|
|
2718
|
+
return true;
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
function classThisOf(context: EmitContext, node: Node): Identifier | undefined {
|
|
2722
|
+
const classThis = context.getClassThis(node);
|
|
2723
|
+
return classThis instanceof Identifier ? (classThis as Identifier) : undefined;
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
function privateNameText(node: Node): string {
|
|
2727
|
+
if (node instanceof PrivateIdentifier) return node.text;
|
|
2728
|
+
if (node instanceof Identifier) return node.text;
|
|
2729
|
+
return '';
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
function isInitializedProperty(node: Node): boolean {
|
|
2733
|
+
return node instanceof PropertyDeclaration && node.initializer !== undefined;
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
function isSuperProperty(node: Node): boolean {
|
|
2737
|
+
if (node instanceof PropertyAccessExpression) return node.expression.kind === SyntaxKind.SuperKeyword;
|
|
2738
|
+
if (node instanceof ElementAccessExpression) return node.expression.kind === SyntaxKind.SuperKeyword;
|
|
2739
|
+
return false;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
function isStaticPropertyDeclarationOrClassStaticBlock(node: Node): boolean {
|
|
2743
|
+
return (
|
|
2744
|
+
node.kind === SyntaxKind.ClassStaticBlockDeclaration ||
|
|
2745
|
+
(node.kind === SyntaxKind.PropertyDeclaration && hasStaticModifier(node))
|
|
2746
|
+
);
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
function isCompoundAssignment(kind: SyntaxKind): boolean {
|
|
2750
|
+
return kind >= SyntaxKind.FirstCompoundAssignment && kind <= SyntaxKind.LastCompoundAssignment;
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
function nonAssignmentOperatorForCompoundAssignment(kind: SyntaxKind): SyntaxKind {
|
|
2754
|
+
switch (kind) {
|
|
2755
|
+
case SyntaxKind.PlusEqualsToken:
|
|
2756
|
+
return SyntaxKind.PlusToken;
|
|
2757
|
+
case SyntaxKind.MinusEqualsToken:
|
|
2758
|
+
return SyntaxKind.MinusToken;
|
|
2759
|
+
case SyntaxKind.AsteriskEqualsToken:
|
|
2760
|
+
return SyntaxKind.AsteriskToken;
|
|
2761
|
+
case SyntaxKind.AsteriskAsteriskEqualsToken:
|
|
2762
|
+
return SyntaxKind.AsteriskAsteriskToken;
|
|
2763
|
+
case SyntaxKind.SlashEqualsToken:
|
|
2764
|
+
return SyntaxKind.SlashToken;
|
|
2765
|
+
case SyntaxKind.PercentEqualsToken:
|
|
2766
|
+
return SyntaxKind.PercentToken;
|
|
2767
|
+
case SyntaxKind.LessThanLessThanEqualsToken:
|
|
2768
|
+
return SyntaxKind.LessThanLessThanToken;
|
|
2769
|
+
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
|
2770
|
+
return SyntaxKind.GreaterThanGreaterThanToken;
|
|
2771
|
+
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
|
|
2772
|
+
return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
|
|
2773
|
+
case SyntaxKind.AmpersandEqualsToken:
|
|
2774
|
+
return SyntaxKind.AmpersandToken;
|
|
2775
|
+
case SyntaxKind.BarEqualsToken:
|
|
2776
|
+
return SyntaxKind.BarToken;
|
|
2777
|
+
case SyntaxKind.CaretEqualsToken:
|
|
2778
|
+
return SyntaxKind.CaretToken;
|
|
2779
|
+
case SyntaxKind.BarBarEqualsToken:
|
|
2780
|
+
return SyntaxKind.BarBarToken;
|
|
2781
|
+
case SyntaxKind.AmpersandAmpersandEqualsToken:
|
|
2782
|
+
return SyntaxKind.AmpersandAmpersandToken;
|
|
2783
|
+
case SyntaxKind.QuestionQuestionEqualsToken:
|
|
2784
|
+
return SyntaxKind.QuestionQuestionToken;
|
|
2785
|
+
}
|
|
2786
|
+
return SyntaxKind.Unknown;
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
function isSimpleCopiableExpression(node: Node): boolean {
|
|
2790
|
+
switch (node.kind) {
|
|
2791
|
+
case SyntaxKind.StringLiteral:
|
|
2792
|
+
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
2793
|
+
case SyntaxKind.NumericLiteral:
|
|
2794
|
+
case SyntaxKind.Identifier:
|
|
2795
|
+
return true;
|
|
2796
|
+
}
|
|
2797
|
+
return node.kind >= SyntaxKind.FirstKeyword && node.kind <= SyntaxKind.LastKeyword;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
/** A literal or keyword that can be repeated; identifiers may be reassigned in between. */
|
|
2801
|
+
function isSimpleInlineableExpression(node: Node): boolean {
|
|
2802
|
+
return node.kind !== SyntaxKind.Identifier && isSimpleCopiableExpression(node);
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
function shouldBeCapturedInTempVariable(node: Node): boolean {
|
|
2806
|
+
switch (skipParentheses(node).kind) {
|
|
2807
|
+
case SyntaxKind.Identifier:
|
|
2808
|
+
case SyntaxKind.ThisKeyword:
|
|
2809
|
+
case SyntaxKind.NumericLiteral:
|
|
2810
|
+
case SyntaxKind.BigIntLiteral:
|
|
2811
|
+
case SyntaxKind.StringLiteral:
|
|
2812
|
+
return false;
|
|
2813
|
+
}
|
|
2814
|
+
return true;
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
function isArrayBindingOrAssignmentElement(node: Node): boolean {
|
|
2818
|
+
switch (node.kind) {
|
|
2819
|
+
case SyntaxKind.BindingElement:
|
|
2820
|
+
case SyntaxKind.OmittedExpression:
|
|
2821
|
+
case SyntaxKind.SpreadElement:
|
|
2822
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
2823
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
2824
|
+
case SyntaxKind.Identifier:
|
|
2825
|
+
case SyntaxKind.PropertyAccessExpression:
|
|
2826
|
+
case SyntaxKind.ElementAccessExpression:
|
|
2827
|
+
return true;
|
|
2828
|
+
}
|
|
2829
|
+
return isAssignmentExpression(node, true);
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
function staticPropertiesAndClassStaticBlocks(node: Node): Node[] {
|
|
2833
|
+
const result: Node[] = [];
|
|
2834
|
+
const members = membersOf(node);
|
|
2835
|
+
for (let i = 0; i < members.length; i++) {
|
|
2836
|
+
const member = members[i];
|
|
2837
|
+
if (
|
|
2838
|
+
member.kind === SyntaxKind.ClassStaticBlockDeclaration ||
|
|
2839
|
+
(member.kind === SyntaxKind.PropertyDeclaration && hasStaticModifier(member))
|
|
2840
|
+
)
|
|
2841
|
+
result.push(member);
|
|
2842
|
+
}
|
|
2843
|
+
return result;
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
function propertiesOf(node: Node, isStaticProperty: boolean): Node[] {
|
|
2847
|
+
const result: Node[] = [];
|
|
2848
|
+
const members = membersOf(node);
|
|
2849
|
+
for (let i = 0; i < members.length; i++)
|
|
2850
|
+
if (members[i] instanceof PropertyDeclaration && hasStaticModifier(members[i]) === isStaticProperty)
|
|
2851
|
+
result.push(members[i]);
|
|
2852
|
+
return result;
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
function privateInstanceMethodsAndAccessors(node: Node): Node[] {
|
|
2856
|
+
const result: Node[] = [];
|
|
2857
|
+
const members = membersOf(node);
|
|
2858
|
+
for (let i = 0; i < members.length; i++) {
|
|
2859
|
+
const member = members[i];
|
|
2860
|
+
if (
|
|
2861
|
+
!isStatic(member) &&
|
|
2862
|
+
(isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member)) &&
|
|
2863
|
+
getName(member)!.kind === SyntaxKind.PrivateIdentifier
|
|
2864
|
+
)
|
|
2865
|
+
result.push(member);
|
|
2866
|
+
}
|
|
2867
|
+
return result;
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
function getClassExtendsHeritageElement(node: Node): ExpressionWithTypeArguments | undefined {
|
|
2871
|
+
let clauses: NodeList | undefined = undefined;
|
|
2872
|
+
if (node instanceof ClassDeclaration) clauses = node.heritageClauses;
|
|
2873
|
+
else if (node instanceof ClassExpression) clauses = node.heritageClauses;
|
|
2874
|
+
if (clauses === undefined) return undefined;
|
|
2875
|
+
for (let i = 0; i < clauses.nodes.length; i++) {
|
|
2876
|
+
const clause = clauses.nodes[i];
|
|
2877
|
+
if (clause instanceof HeritageClause && clause.token === SyntaxKind.ExtendsKeyword) {
|
|
2878
|
+
const first = clause.types.nodes[0];
|
|
2879
|
+
return first instanceof ExpressionWithTypeArguments ? (first as ExpressionWithTypeArguments) : undefined;
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
return undefined;
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
/** Whether a class or its constructor's parameters have decorators that apply. */
|
|
2886
|
+
function classOrConstructorParameterIsDecorated(legacy: boolean, node: Node): boolean {
|
|
2887
|
+
if (hasDecorators(node) && (node.kind === SyntaxKind.ClassDeclaration || !legacy)) return true;
|
|
2888
|
+
if (!legacy) return false;
|
|
2889
|
+
const members = membersOf(node);
|
|
2890
|
+
for (let i = 0; i < members.length; i++) {
|
|
2891
|
+
const member = members[i];
|
|
2892
|
+
if (!(member instanceof ConstructorDeclaration) || member.body === undefined) continue;
|
|
2893
|
+
const parameters = member.parameters.nodes;
|
|
2894
|
+
for (let j = 0; j < parameters.length; j++) if (hasDecorators(parameters[j])) return true;
|
|
2895
|
+
return false;
|
|
2896
|
+
}
|
|
2897
|
+
return false;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
/** The `_a = ...` assignment caching a computed name's value, at the end of its comma list. */
|
|
2901
|
+
function findComputedPropertyNameCacheAssignment(name: ComputedPropertyName): BinaryExpression | undefined {
|
|
2902
|
+
let node = name.expression;
|
|
2903
|
+
for (;;) {
|
|
2904
|
+
node = skipOuterExpressions(node, OuterExpressionKinds.None);
|
|
2905
|
+
if (node instanceof BinaryExpression && node.operatorToken.kind === SyntaxKind.CommaToken) {
|
|
2906
|
+
node = node.right;
|
|
2907
|
+
continue;
|
|
2908
|
+
}
|
|
2909
|
+
if (node instanceof BinaryExpression && isAssignmentExpression(node, true) && node.left instanceof Identifier)
|
|
2910
|
+
return node;
|
|
2911
|
+
return undefined;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/** The expressions of a comma list, appended to `out`. */
|
|
2916
|
+
function flattenCommaList(node: Node, out: Node[]): boolean {
|
|
2917
|
+
if (node instanceof ParenthesizedExpression && nodeIsSynthesized(node)) return flattenCommaList(node.expression, out);
|
|
2918
|
+
if (node instanceof BinaryExpression && node.operatorToken.kind === SyntaxKind.CommaToken) {
|
|
2919
|
+
flattenCommaList(node.left, out);
|
|
2920
|
+
return flattenCommaList(node.right, out);
|
|
2921
|
+
}
|
|
2922
|
+
out.push(node);
|
|
2923
|
+
return true;
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
/** The start of a member after its modifiers, or its decorators, for source maps. */
|
|
2927
|
+
function posPastModifiers(node: Node): number {
|
|
2928
|
+
if (node instanceof PropertyDeclaration) return node.name.pos;
|
|
2929
|
+
if (node instanceof MethodDeclaration) return node.name.pos;
|
|
2930
|
+
if (node.kind === SyntaxKind.ClassStaticBlockDeclaration) return node.pos;
|
|
2931
|
+
const modifiers = getModifiers(node);
|
|
2932
|
+
if (modifiers === undefined || modifiers.nodes.length === 0) return node.pos;
|
|
2933
|
+
const last = modifiers.nodes[modifiers.nodes.length - 1];
|
|
2934
|
+
if (last.end >= 0) return last.end;
|
|
2935
|
+
for (let i = modifiers.nodes.length - 1; i >= 0; i--)
|
|
2936
|
+
if (modifiers.nodes[i].kind === SyntaxKind.Decorator)
|
|
2937
|
+
return modifiers.nodes[i].end >= 0 ? modifiers.nodes[i].end : node.pos;
|
|
2938
|
+
return node.pos;
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2941
|
+
/** Properties assigned in the constructor with useDefineForClassFields: false. */
|
|
2942
|
+
function withInitializerOrPrivateName(properties: Node[]): Node[] {
|
|
2943
|
+
const result: Node[] = [];
|
|
2944
|
+
for (let i = 0; i < properties.length; i++) {
|
|
2945
|
+
const property = properties[i];
|
|
2946
|
+
if (
|
|
2947
|
+
getInitializer(property) !== undefined ||
|
|
2948
|
+
getName(property)!.kind === SyntaxKind.PrivateIdentifier ||
|
|
2949
|
+
hasSyntacticModifier(property, ModifierFlags.Accessor)
|
|
2950
|
+
)
|
|
2951
|
+
result.push(property);
|
|
2952
|
+
}
|
|
2953
|
+
return result;
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
class ClassesNeedingNames extends AnonymousFunctionFilter {
|
|
2957
|
+
readonly transformer: ClassFieldsTransformer;
|
|
2958
|
+
|
|
2959
|
+
constructor(transformer: ClassFieldsTransformer) {
|
|
2960
|
+
super();
|
|
2961
|
+
this.transformer = transformer;
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
accepts(node: Node): boolean {
|
|
2965
|
+
return this.transformer.isAnonymousClassNeedingAssignedName(node);
|
|
2966
|
+
}
|
|
2967
|
+
}
|