Merge pull request #19046 from Microsoft/fix15395

Fix emit for classes with both fields and 'extends null'
This commit is contained in:
Ron Buckton
2017-10-11 11:49:22 -07:00
committed by GitHub
5 changed files with 53 additions and 15 deletions

View File

@@ -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);