mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Merge pull request #19046 from Microsoft/fix15395
Fix emit for classes with both fields and 'extends null'
This commit is contained in:
commit
d08770bdff
@ -26,7 +26,7 @@ namespace ts {
|
||||
IsExportOfNamespace = 1 << 3,
|
||||
IsNamedExternalExport = 1 << 4,
|
||||
IsDefaultExternalExport = 1 << 5,
|
||||
HasExtendsClause = 1 << 6,
|
||||
IsDerivedClass = 1 << 6,
|
||||
UseImmediatelyInvokedFunctionExpression = 1 << 7,
|
||||
|
||||
HasAnyDecorators = HasConstructorDecorators | HasMemberDecorators,
|
||||
@ -553,7 +553,8 @@ namespace ts {
|
||||
function getClassFacts(node: ClassDeclaration, staticProperties: ReadonlyArray<PropertyDeclaration>) {
|
||||
let facts = ClassFacts.None;
|
||||
if (some(staticProperties)) facts |= ClassFacts.HasStaticInitializedProperties;
|
||||
if (getClassExtendsHeritageClauseElement(node)) facts |= ClassFacts.HasExtendsClause;
|
||||
const extendsClauseElement = getClassExtendsHeritageClauseElement(node);
|
||||
if (extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword) facts |= ClassFacts.IsDerivedClass;
|
||||
if (shouldEmitDecorateCallForClass(node)) facts |= ClassFacts.HasConstructorDecorators;
|
||||
if (childIsDecorated(node)) facts |= ClassFacts.HasMemberDecorators;
|
||||
if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace;
|
||||
@ -699,7 +700,7 @@ namespace ts {
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, visitor, isHeritageClause),
|
||||
transformClassMembers(node, (facts & ClassFacts.HasExtendsClause) !== 0)
|
||||
transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0)
|
||||
);
|
||||
|
||||
// To better align with the old emitter, we should not emit a trailing source map
|
||||
@ -814,7 +815,7 @@ namespace ts {
|
||||
// ${members}
|
||||
// }
|
||||
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
|
||||
const members = transformClassMembers(node, (facts & ClassFacts.HasExtendsClause) !== 0);
|
||||
const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0);
|
||||
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members);
|
||||
setOriginalNode(classExpression, node);
|
||||
setTextRange(classExpression, location);
|
||||
@ -887,11 +888,11 @@ namespace ts {
|
||||
* Transforms the members of a class.
|
||||
*
|
||||
* @param node The current class.
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
|
||||
*/
|
||||
function transformClassMembers(node: ClassDeclaration | ClassExpression, hasExtendsClause: boolean) {
|
||||
function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
|
||||
const members: ClassElement[] = [];
|
||||
const constructor = transformConstructor(node, hasExtendsClause);
|
||||
const constructor = transformConstructor(node, isDerivedClass);
|
||||
if (constructor) {
|
||||
members.push(constructor);
|
||||
}
|
||||
@ -904,9 +905,9 @@ namespace ts {
|
||||
* Transforms (or creates) a constructor for a class.
|
||||
*
|
||||
* @param node The current class.
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
|
||||
*/
|
||||
function transformConstructor(node: ClassDeclaration | ClassExpression, hasExtendsClause: boolean) {
|
||||
function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
|
||||
// Check if we have property assignment inside class declaration.
|
||||
// If there is a property assignment, we need to emit constructor whether users define it or not
|
||||
// If there is no property assignment, we can omit constructor if users do not define it
|
||||
@ -921,7 +922,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const parameters = transformConstructorParameters(constructor);
|
||||
const body = transformConstructorBody(node, constructor, hasExtendsClause);
|
||||
const body = transformConstructorBody(node, constructor, isDerivedClass);
|
||||
|
||||
// constructor(${parameters}) {
|
||||
// ${body}
|
||||
@ -947,7 +948,6 @@ namespace ts {
|
||||
* parameter property assignments or instance property initializers.
|
||||
*
|
||||
* @param constructor The constructor declaration.
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
*/
|
||||
function transformConstructorParameters(constructor: ConstructorDeclaration) {
|
||||
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
|
||||
@ -975,9 +975,9 @@ namespace ts {
|
||||
*
|
||||
* @param node The current class.
|
||||
* @param constructor The current class constructor.
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
|
||||
*/
|
||||
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
|
||||
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, isDerivedClass: boolean) {
|
||||
let statements: Statement[] = [];
|
||||
let indexOfFirstStatement = 0;
|
||||
|
||||
@ -1001,7 +1001,7 @@ namespace ts {
|
||||
const propertyAssignments = getParametersWithPropertyAssignments(constructor);
|
||||
addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment));
|
||||
}
|
||||
else if (hasExtendsClause) {
|
||||
else if (isDerivedClass) {
|
||||
// Add a synthetic `super` call:
|
||||
//
|
||||
// super(...arguments);
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
//// [classExtendingNull.ts]
|
||||
class C1 extends null { }
|
||||
class C2 extends (null) { }
|
||||
|
||||
class C3 extends null { x = 1; }
|
||||
class C4 extends (null) { x = 1; }
|
||||
|
||||
//// [classExtendingNull.js]
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
@ -26,3 +27,17 @@ var C2 = /** @class */ (function (_super) {
|
||||
}
|
||||
return C2;
|
||||
}((null)));
|
||||
var C3 = /** @class */ (function (_super) {
|
||||
__extends(C3, _super);
|
||||
function C3() {
|
||||
this.x = 1;
|
||||
}
|
||||
return C3;
|
||||
}(null));
|
||||
var C4 = /** @class */ (function (_super) {
|
||||
__extends(C4, _super);
|
||||
function C4() {
|
||||
this.x = 1;
|
||||
}
|
||||
return C4;
|
||||
}((null)));
|
||||
|
||||
@ -5,3 +5,11 @@ class C1 extends null { }
|
||||
class C2 extends (null) { }
|
||||
>C2 : Symbol(C2, Decl(classExtendingNull.ts, 0, 25))
|
||||
|
||||
class C3 extends null { x = 1; }
|
||||
>C3 : Symbol(C3, Decl(classExtendingNull.ts, 1, 27))
|
||||
>x : Symbol(C3.x, Decl(classExtendingNull.ts, 2, 23))
|
||||
|
||||
class C4 extends (null) { x = 1; }
|
||||
>C4 : Symbol(C4, Decl(classExtendingNull.ts, 2, 32))
|
||||
>x : Symbol(C4.x, Decl(classExtendingNull.ts, 3, 25))
|
||||
|
||||
|
||||
@ -8,3 +8,16 @@ class C2 extends (null) { }
|
||||
>(null) : null
|
||||
>null : null
|
||||
|
||||
class C3 extends null { x = 1; }
|
||||
>C3 : C3
|
||||
>null : null
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
class C4 extends (null) { x = 1; }
|
||||
>C4 : C4
|
||||
>(null) : null
|
||||
>null : null
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
class C1 extends null { }
|
||||
class C2 extends (null) { }
|
||||
class C3 extends null { x = 1; }
|
||||
class C4 extends (null) { x = 1; }
|
||||
Loading…
x
Reference in New Issue
Block a user