From 148bfb1cf03b86590ed6ec3c4a44ef15d8904942 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Wed, 13 May 2020 18:07:03 -0400 Subject: [PATCH 1/2] fix wrapping classes when targeting ESNext --- src/compiler/transformers/ts.ts | 7 ++++++- .../reference/thisInClassBodyStaticESNext.js | 17 +++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 7f848685aec36..45f49c5a905e0 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -23,10 +23,10 @@ namespace ts { IsNamedExternalExport = 1 << 4, IsDefaultExternalExport = 1 << 5, IsDerivedClass = 1 << 6, + UseImmediatelyInvokedFunctionExpression = 1 << 7, HasAnyDecorators = HasConstructorDecorators | HasMemberDecorators, NeedsName = HasStaticInitializedProperties | HasMemberDecorators, - UseImmediatelyInvokedFunctionExpression = HasAnyDecorators | HasStaticInitializedProperties, IsExported = IsExportOfNamespace | IsDefaultExternalExport | IsNamedExternalExport, } @@ -595,6 +595,11 @@ namespace ts { if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace; else if (isDefaultExternalModuleExport(node)) facts |= ClassFacts.IsDefaultExternalExport; else if (isNamedExternalModuleExport(node)) facts |= ClassFacts.IsNamedExternalExport; + if (facts & ClassFacts.HasAnyDecorators) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; + if (facts & ClassFacts.HasStaticInitializedProperties) { + if (languageVersion < ScriptTarget.ESNext) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; + else if (languageVersion === ScriptTarget.ESNext && !compilerOptions.useDefineForClassFields) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; + } return facts; } diff --git a/tests/baselines/reference/thisInClassBodyStaticESNext.js b/tests/baselines/reference/thisInClassBodyStaticESNext.js index 6ad51b36a7385..7f061b12a4149 100644 --- a/tests/baselines/reference/thisInClassBodyStaticESNext.js +++ b/tests/baselines/reference/thisInClassBodyStaticESNext.js @@ -11,13 +11,10 @@ class Foo { //// [thisInClassBodyStaticESNext.js] // all are allowed with es-compliant class field emit -let Foo = /** @class */ (() => { - class Foo { - x = this; - static t = this; - static at = () => this; - static ft = function () { return this; }; - static mt() { return this; } - } - return Foo; -})(); +class Foo { + x = this; + static t = this; + static at = () => this; + static ft = function () { return this; }; + static mt() { return this; } +} From cef1fcdfc6130d25e9d50bcfb89c95ff117dfcc6 Mon Sep 17 00:00:00 2001 From: Ryan Delaney Date: Fri, 15 May 2020 18:04:07 +0000 Subject: [PATCH 2/2] Add addOptimizationHints compiler option --- src/compiler/commandLineParser.ts | 7 ++++ src/compiler/diagnosticMessages.json | 4 ++ src/compiler/transformers/ts.ts | 17 +++++--- src/compiler/types.ts | 1 + .../reference/addOptimizationHints.errors.txt | 23 +++++++++++ .../reference/addOptimizationHints.js | 40 +++++++++++++++++++ .../reference/addOptimizationHints.symbols | 32 +++++++++++++++ .../reference/addOptimizationHints.types | 35 ++++++++++++++++ .../addOptimizationHintsFalse.errors.txt | 23 +++++++++++ .../reference/addOptimizationHintsFalse.js | 34 ++++++++++++++++ .../addOptimizationHintsFalse.symbols | 32 +++++++++++++++ .../reference/addOptimizationHintsFalse.types | 35 ++++++++++++++++ .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + .../addOptimizationHints/tsconfig.json | 5 +++ tests/cases/compiler/addOptimizationHints.ts | 20 ++++++++++ .../compiler/addOptimizationHintsFalse.ts | 20 ++++++++++ 17 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/addOptimizationHints.errors.txt create mode 100644 tests/baselines/reference/addOptimizationHints.js create mode 100644 tests/baselines/reference/addOptimizationHints.symbols create mode 100644 tests/baselines/reference/addOptimizationHints.types create mode 100644 tests/baselines/reference/addOptimizationHintsFalse.errors.txt create mode 100644 tests/baselines/reference/addOptimizationHintsFalse.js create mode 100644 tests/baselines/reference/addOptimizationHintsFalse.symbols create mode 100644 tests/baselines/reference/addOptimizationHintsFalse.types create mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/addOptimizationHints/tsconfig.json create mode 100644 tests/cases/compiler/addOptimizationHints.ts create mode 100644 tests/cases/compiler/addOptimizationHintsFalse.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 8d4f332032d6f..d1dc91494eff2 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -986,6 +986,13 @@ namespace ts { category: Diagnostics.Advanced_Options, description: Diagnostics.Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols, }, + { + name: "addOptimizationHints", + type: "boolean", + affectsEmit: true, + category: Diagnostics.Advanced_Options, + description: Diagnostics.Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols, + }, { // A list of plugins to load in the language service name: "plugins", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2dfabe540adf7..845081e7a57a7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4400,6 +4400,10 @@ "category": "Error", "code": 6233 }, + "Emit code hints for optimizers and minifiers.": { + "category": "Message", + "code": 6234 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 45f49c5a905e0..a6bc7dcf898ac 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -585,6 +585,17 @@ namespace ts { return parameter.decorators !== undefined && parameter.decorators.length > 0; } + function shouldWrapClassWithIIFE(facts: ClassFacts) { + if (compilerOptions.addOptimizationHints === false) return false; + if (facts & ClassFacts.HasAnyDecorators) return true; + if (facts & ClassFacts.HasStaticInitializedProperties) { + if (languageVersion < ScriptTarget.ESNext) return true; + else if (languageVersion === ScriptTarget.ESNext && !compilerOptions.useDefineForClassFields) return true; + } + + return false; + } + function getClassFacts(node: ClassDeclaration, staticProperties: readonly PropertyDeclaration[]) { let facts = ClassFacts.None; if (some(staticProperties)) facts |= ClassFacts.HasStaticInitializedProperties; @@ -595,11 +606,7 @@ namespace ts { if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace; else if (isDefaultExternalModuleExport(node)) facts |= ClassFacts.IsDefaultExternalExport; else if (isNamedExternalModuleExport(node)) facts |= ClassFacts.IsNamedExternalExport; - if (facts & ClassFacts.HasAnyDecorators) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; - if (facts & ClassFacts.HasStaticInitializedProperties) { - if (languageVersion < ScriptTarget.ESNext) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; - else if (languageVersion === ScriptTarget.ESNext && !compilerOptions.useDefineForClassFields) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; - } + if (shouldWrapClassWithIIFE(facts)) facts |= ClassFacts.UseImmediatelyInvokedFunctionExpression; return facts; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 54d889b2ff4fc..415ee85a83a62 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5133,6 +5133,7 @@ namespace ts { export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; export interface CompilerOptions { + addOptimizationHints?: boolean; /*@internal*/ all?: boolean; allowJs?: boolean; /*@internal*/ allowNonTsExtensions?: boolean; diff --git a/tests/baselines/reference/addOptimizationHints.errors.txt b/tests/baselines/reference/addOptimizationHints.errors.txt new file mode 100644 index 0000000000000..ac09a4a787f1e --- /dev/null +++ b/tests/baselines/reference/addOptimizationHints.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/addOptimizationHints.ts(13,2): error TS2304: Cannot find name 'decorate'. + + +==== tests/cases/compiler/addOptimizationHints.ts (1 errors) ==== + class HasNoStatics { + value: unknown; + method() {} + } + + class HasStatic { + static value = 0; + static someMethod() {} + + method() {} + } + + @decorate + ~~~~~~~~ +!!! error TS2304: Cannot find name 'decorate'. + class HasDecorator { + method() {} + } + \ No newline at end of file diff --git a/tests/baselines/reference/addOptimizationHints.js b/tests/baselines/reference/addOptimizationHints.js new file mode 100644 index 0000000000000..7b1a2cc46a8dd --- /dev/null +++ b/tests/baselines/reference/addOptimizationHints.js @@ -0,0 +1,40 @@ +//// [addOptimizationHints.ts] +class HasNoStatics { + value: unknown; + method() {} +} + +class HasStatic { + static value = 0; + static someMethod() {} + + method() {} +} + +@decorate +class HasDecorator { + method() {} +} + + +//// [addOptimizationHints.js] +class HasNoStatics { + method() { } +} +let HasStatic = /** @class */ (() => { + class HasStatic { + static someMethod() { } + method() { } + } + HasStatic.value = 0; + return HasStatic; +})(); +let HasDecorator = /** @class */ (() => { + let HasDecorator = class HasDecorator { + method() { } + }; + HasDecorator = __decorate([ + decorate + ], HasDecorator); + return HasDecorator; +})(); diff --git a/tests/baselines/reference/addOptimizationHints.symbols b/tests/baselines/reference/addOptimizationHints.symbols new file mode 100644 index 0000000000000..d5eabf8eb4477 --- /dev/null +++ b/tests/baselines/reference/addOptimizationHints.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/addOptimizationHints.ts === +class HasNoStatics { +>HasNoStatics : Symbol(HasNoStatics, Decl(addOptimizationHints.ts, 0, 0)) + + value: unknown; +>value : Symbol(HasNoStatics.value, Decl(addOptimizationHints.ts, 0, 20)) + + method() {} +>method : Symbol(HasNoStatics.method, Decl(addOptimizationHints.ts, 1, 17)) +} + +class HasStatic { +>HasStatic : Symbol(HasStatic, Decl(addOptimizationHints.ts, 3, 1)) + + static value = 0; +>value : Symbol(HasStatic.value, Decl(addOptimizationHints.ts, 5, 17)) + + static someMethod() {} +>someMethod : Symbol(HasStatic.someMethod, Decl(addOptimizationHints.ts, 6, 19)) + + method() {} +>method : Symbol(HasStatic.method, Decl(addOptimizationHints.ts, 7, 24)) +} + +@decorate +class HasDecorator { +>HasDecorator : Symbol(HasDecorator, Decl(addOptimizationHints.ts, 10, 1)) + + method() {} +>method : Symbol(HasDecorator.method, Decl(addOptimizationHints.ts, 13, 20)) +} + diff --git a/tests/baselines/reference/addOptimizationHints.types b/tests/baselines/reference/addOptimizationHints.types new file mode 100644 index 0000000000000..6eb0802817977 --- /dev/null +++ b/tests/baselines/reference/addOptimizationHints.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/addOptimizationHints.ts === +class HasNoStatics { +>HasNoStatics : HasNoStatics + + value: unknown; +>value : unknown + + method() {} +>method : () => void +} + +class HasStatic { +>HasStatic : HasStatic + + static value = 0; +>value : number +>0 : 0 + + static someMethod() {} +>someMethod : () => void + + method() {} +>method : () => void +} + +@decorate +>decorate : any + +class HasDecorator { +>HasDecorator : HasDecorator + + method() {} +>method : () => void +} + diff --git a/tests/baselines/reference/addOptimizationHintsFalse.errors.txt b/tests/baselines/reference/addOptimizationHintsFalse.errors.txt new file mode 100644 index 0000000000000..bccd89840cd95 --- /dev/null +++ b/tests/baselines/reference/addOptimizationHintsFalse.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/addOptimizationHintsFalse.ts(13,2): error TS2304: Cannot find name 'decorate'. + + +==== tests/cases/compiler/addOptimizationHintsFalse.ts (1 errors) ==== + class HasNoStatics { + value: unknown; + method() {} + } + + class HasStatic { + static value = 0; + static someMethod() {} + + method() {} + } + + @decorate + ~~~~~~~~ +!!! error TS2304: Cannot find name 'decorate'. + class HasDecorator { + method() {} + } + \ No newline at end of file diff --git a/tests/baselines/reference/addOptimizationHintsFalse.js b/tests/baselines/reference/addOptimizationHintsFalse.js new file mode 100644 index 0000000000000..2a495445ff1c3 --- /dev/null +++ b/tests/baselines/reference/addOptimizationHintsFalse.js @@ -0,0 +1,34 @@ +//// [addOptimizationHintsFalse.ts] +class HasNoStatics { + value: unknown; + method() {} +} + +class HasStatic { + static value = 0; + static someMethod() {} + + method() {} +} + +@decorate +class HasDecorator { + method() {} +} + + +//// [addOptimizationHintsFalse.js] +class HasNoStatics { + method() { } +} +class HasStatic { + static someMethod() { } + method() { } +} +HasStatic.value = 0; +let HasDecorator = class HasDecorator { + method() { } +}; +HasDecorator = __decorate([ + decorate +], HasDecorator); diff --git a/tests/baselines/reference/addOptimizationHintsFalse.symbols b/tests/baselines/reference/addOptimizationHintsFalse.symbols new file mode 100644 index 0000000000000..9d0750fd0c9bd --- /dev/null +++ b/tests/baselines/reference/addOptimizationHintsFalse.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/addOptimizationHintsFalse.ts === +class HasNoStatics { +>HasNoStatics : Symbol(HasNoStatics, Decl(addOptimizationHintsFalse.ts, 0, 0)) + + value: unknown; +>value : Symbol(HasNoStatics.value, Decl(addOptimizationHintsFalse.ts, 0, 20)) + + method() {} +>method : Symbol(HasNoStatics.method, Decl(addOptimizationHintsFalse.ts, 1, 17)) +} + +class HasStatic { +>HasStatic : Symbol(HasStatic, Decl(addOptimizationHintsFalse.ts, 3, 1)) + + static value = 0; +>value : Symbol(HasStatic.value, Decl(addOptimizationHintsFalse.ts, 5, 17)) + + static someMethod() {} +>someMethod : Symbol(HasStatic.someMethod, Decl(addOptimizationHintsFalse.ts, 6, 19)) + + method() {} +>method : Symbol(HasStatic.method, Decl(addOptimizationHintsFalse.ts, 7, 24)) +} + +@decorate +class HasDecorator { +>HasDecorator : Symbol(HasDecorator, Decl(addOptimizationHintsFalse.ts, 10, 1)) + + method() {} +>method : Symbol(HasDecorator.method, Decl(addOptimizationHintsFalse.ts, 13, 20)) +} + diff --git a/tests/baselines/reference/addOptimizationHintsFalse.types b/tests/baselines/reference/addOptimizationHintsFalse.types new file mode 100644 index 0000000000000..5e73d696d3516 --- /dev/null +++ b/tests/baselines/reference/addOptimizationHintsFalse.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/addOptimizationHintsFalse.ts === +class HasNoStatics { +>HasNoStatics : HasNoStatics + + value: unknown; +>value : unknown + + method() {} +>method : () => void +} + +class HasStatic { +>HasStatic : HasStatic + + static value = 0; +>value : number +>0 : 0 + + static someMethod() {} +>someMethod : () => void + + method() {} +>method : () => void +} + +@decorate +>decorate : any + +class HasDecorator { +>HasDecorator : HasDecorator + + method() {} +>method : () => void +} + diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2c7742fb88b97..bfa9e68a3f7ed 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2651,6 +2651,7 @@ declare namespace ts { } export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; export interface CompilerOptions { + addOptimizationHints?: boolean; allowJs?: boolean; allowSyntheticDefaultImports?: boolean; allowUmdGlobalAccess?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c901f86e38499..3ff058b7e8948 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2651,6 +2651,7 @@ declare namespace ts { } export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; export interface CompilerOptions { + addOptimizationHints?: boolean; allowJs?: boolean; allowSyntheticDefaultImports?: boolean; allowUmdGlobalAccess?: boolean; diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/addOptimizationHints/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/addOptimizationHints/tsconfig.json new file mode 100644 index 0000000000000..20b45590dbe5e --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/addOptimizationHints/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "addOptimizationHints": true + } +} diff --git a/tests/cases/compiler/addOptimizationHints.ts b/tests/cases/compiler/addOptimizationHints.ts new file mode 100644 index 0000000000000..b6bbcd2322cde --- /dev/null +++ b/tests/cases/compiler/addOptimizationHints.ts @@ -0,0 +1,20 @@ +// @target: ES2015 +// @experimentalDecorators: true +// @noemithelpers: true +// @addOptimizationHints: true +class HasNoStatics { + value: unknown; + method() {} +} + +class HasStatic { + static value = 0; + static someMethod() {} + + method() {} +} + +@decorate +class HasDecorator { + method() {} +} diff --git a/tests/cases/compiler/addOptimizationHintsFalse.ts b/tests/cases/compiler/addOptimizationHintsFalse.ts new file mode 100644 index 0000000000000..f609662c82ca0 --- /dev/null +++ b/tests/cases/compiler/addOptimizationHintsFalse.ts @@ -0,0 +1,20 @@ +// @target: ES2015 +// @experimentalDecorators: true +// @noemithelpers: true +// @addOptimizationHints: false +class HasNoStatics { + value: unknown; + method() {} +} + +class HasStatic { + static value = 0; + static someMethod() {} + + method() {} +} + +@decorate +class HasDecorator { + method() {} +}