Skip to content
Next Next commit
If target:esnext,then useDefineForClassFields: true will now be the d…
…efault.
  • Loading branch information
dragomirtitian committed Apr 5, 2021
commit dc5d50e3d37b37a2ff848205b8e9af655ed0d6e3
15 changes: 8 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ namespace ts {
const compilerOptions = host.getCompilerOptions();
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const useDefineForClassFields = getUseDefineForClassFields(compilerOptions);
const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions);
const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
Expand Down Expand Up @@ -1501,7 +1502,7 @@ namespace ts {
}
else if (isParameterPropertyDeclaration(declaration, declaration.parent)) {
// foo = this.bar is illegal in esnext+useDefineForClassFields when bar is a parameter property
return !(compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields
return !(compilerOptions.target === ScriptTarget.ESNext && useDefineForClassFields
&& getContainingClass(declaration) === getContainingClass(usage)
&& isUsedInFunctionOrInstanceProperty(usage, declaration));
}
Expand Down Expand Up @@ -1532,7 +1533,7 @@ namespace ts {
return true;
}
if (isUsedInFunctionOrInstanceProperty(usage, declaration)) {
if (compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields
if (compilerOptions.target === ScriptTarget.ESNext && useDefineForClassFields
&& getContainingClass(declaration)
&& (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) {
return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true);
Expand Down Expand Up @@ -1680,7 +1681,7 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
// static properties in classes introduce temporary variables
if (hasStaticModifier(node)) {
return target < ScriptTarget.ESNext || !compilerOptions.useDefineForClassFields;
return target < ScriptTarget.ESNext || !useDefineForClassFields;
}
return requiresScopeChangeWorker((node as PropertyDeclaration).name);
default:
Expand Down Expand Up @@ -2098,7 +2099,7 @@ namespace ts {

// Perform extra checks only if error reporting was requested
if (nameNotFoundMessage) {
if (propertyWithInvalidInitializer && !(compilerOptions.target === ScriptTarget.ESNext && compilerOptions.useDefineForClassFields)) {
if (propertyWithInvalidInitializer && !(compilerOptions.target === ScriptTarget.ESNext && useDefineForClassFields)) {
// We have a match, but the reference occurred within a property initializer and the identifier also binds
// to a local variable in the constructor where the code will be emitted. Note that this is actually allowed
// with ESNext+useDefineForClassFields because the scope semantics are different.
Expand Down Expand Up @@ -24183,7 +24184,7 @@ namespace ts {
break;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
if (hasSyntacticModifier(container, ModifierFlags.Static) && !(compilerOptions.target === ScriptTarget.ESNext && compilerOptions.useDefineForClassFields)) {
if (hasSyntacticModifier(container, ModifierFlags.Static) && !(compilerOptions.target === ScriptTarget.ESNext && useDefineForClassFields)) {
error(node, Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
// do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
}
Expand Down Expand Up @@ -33054,7 +33055,7 @@ namespace ts {
// - The constructor declares parameter properties
// or the containing class declares instance member variables with initializers.
const superCallShouldBeFirst =
(compilerOptions.target !== ScriptTarget.ESNext || !compilerOptions.useDefineForClassFields) &&
(compilerOptions.target !== ScriptTarget.ESNext || !useDefineForClassFields) &&
(some((<ClassDeclaration>node.parent).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) ||
some(node.parameters, p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier)));

Expand Down Expand Up @@ -37059,7 +37060,7 @@ namespace ts {
Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor;
error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type));
}
else if (compilerOptions.useDefineForClassFields) {
else if (useDefineForClassFields) {
const uninitialized = derived.declarations?.find(d => d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer);
if (uninitialized
&& !(derived.flags & SymbolFlags.Transient)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ namespace ts {
const memberFunction = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined, container);
const propertyName = visitNode(member.name, visitor, isPropertyName);
let e: Expression;
if (!isPrivateIdentifier(propertyName) && context.getCompilerOptions().useDefineForClassFields) {
if (!isPrivateIdentifier(propertyName) && getUseDefineForClassFields(context.getCompilerOptions())) {
const name = isComputedPropertyName(propertyName) ? propertyName.expression
: isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText))
: propertyName;
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6071,6 +6071,10 @@ namespace ts {
return compilerOptions.allowJs === undefined ? !!compilerOptions.checkJs : compilerOptions.allowJs;
}

export function getUseDefineForClassFields(compilerOptions: CompilerOptions): boolean {
return compilerOptions.useDefineForClassFields === undefined ? compilerOptions.target === ScriptTarget.ESNext : compilerOptions.useDefineForClassFields;
}

export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean {
return oldOptions !== newOptions &&
semanticDiagnosticsOptionDeclarations.some(option => !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @target: esnext,es2015,es5
// @noTypesAndSymbols: true
// @noEmit: true
// @useDefineForClassFields: false

// https://github.com/microsoft/TypeScript/issues/36295
class C {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @target: esnext,es2015,es5
// @noTypesAndSymbols: true
// @noEmit: true
// @useDefineForClassFields: false

// https://github.com/microsoft/TypeScript/issues/36295
class C {}
Expand Down