Merge branch 'master' into wideningInAccessExpressions

This commit is contained in:
Anders Hejlsberg
2019-06-07 11:52:24 -07:00
11 changed files with 449 additions and 822 deletions

View File

@@ -3229,7 +3229,8 @@ namespace ts {
// A ClassDeclaration is ES6 syntax.
transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// A class with a parameter property assignment or decorator is TypeScript syntax.
// A class with a parameter property assignment, property initializer, computed property name, or decorator is
// TypeScript syntax.
// An exported declaration may be TypeScript syntax, but is handled by the visitor
// for a namespace declaration.
if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax)
@@ -3246,7 +3247,8 @@ namespace ts {
// A ClassExpression is ES6 syntax.
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// A class with a parameter property assignment or decorator is TypeScript syntax.
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
@@ -3336,6 +3338,7 @@ namespace ts {
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.typeParameters
|| node.type
|| (node.name && isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly
|| !node.body) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@@ -3366,6 +3369,7 @@ namespace ts {
if (node.decorators
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.type
|| (node.name && isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly
|| !node.body) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@@ -3380,15 +3384,12 @@ namespace ts {
}
function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags | TransformFlags.ContainsClassFields;
// A PropertyDeclaration is TypeScript syntax.
let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript;
// Decorators, TypeScript-specific modifiers, and type annotations are TypeScript syntax.
if (some(node.decorators) || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// Hoisted variables related to class properties should live within the TypeScript class wrapper.
if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) {
// If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor
// so that it handle the transformation.
if (node.initializer || isComputedPropertyName(node.name)) {
transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
}

View File

@@ -44,7 +44,6 @@ namespace ts {
addRange(transformers, customTransformers && map(customTransformers.before, wrapScriptTransformerFactory));
transformers.push(transformTypeScript);
transformers.push(transformClassFields);
if (jsx === JsxEmit.React) {
transformers.push(transformJsx);

View File

@@ -1,491 +0,0 @@
/*@internal*/
namespace ts {
const enum ClassPropertySubstitutionFlags {
/**
* Enables substitutions for class expressions with static fields
* which have initializers that reference the class name.
*/
ClassAliases = 1 << 0,
}
/**
* Transforms ECMAScript Class Syntax.
* TypeScript parameter property syntax is transformed in the TypeScript transformer.
* For now, this transforms public field declarations using TypeScript class semantics
* (where the declarations get elided and initializers are transformed as assignments in the constructor).
* Eventually, this transform will change to the ECMAScript semantics (with Object.defineProperty).
*/
export function transformClassFields(context: TransformationContext) {
const {
hoistVariableDeclaration,
endLexicalEnvironment,
resumeLexicalEnvironment
} = context;
const resolver = context.getEmitResolver();
const previousOnSubstituteNode = context.onSubstituteNode;
context.onSubstituteNode = onSubstituteNode;
let enabledSubstitutions: ClassPropertySubstitutionFlags;
let classAliases: Identifier[];
/**
* Tracks what computed name expressions originating from elided names must be inlined
* at the next execution site, in document order
*/
let pendingExpressions: Expression[] | undefined;
/**
* Tracks what computed name expression statements and static property initializers must be
* emitted at the next execution site, in document order (for decorated classes).
*/
let pendingStatements: Statement[] | undefined;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
return node;
}
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
return visited;
}
function visitor(node: Node): VisitResult<Node> {
if (!(node.transformFlags & TransformFlags.ContainsClassFields)) return node;
switch (node.kind) {
case SyntaxKind.ClassExpression:
return visitClassExpression(node as ClassExpression);
case SyntaxKind.ClassDeclaration:
return visitClassDeclaration(node as ClassDeclaration);
case SyntaxKind.VariableStatement:
return visitVariableStatement(node as VariableStatement);
}
return visitEachChild(node, visitor, context);
}
/**
* Visits the members of a class that has fields.
*
* @param node The node to visit.
*/
function classElementVisitor(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.Constructor:
// Constructors for classes using class fields are transformed in
// `visitClassDeclaration` or `visitClassExpression`.
return undefined;
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration:
// Visit the name of the member (if it's a computed property name).
return visitEachChild(node, classElementVisitor, context);
case SyntaxKind.PropertyDeclaration:
return visitPropertyDeclaration(node as PropertyDeclaration);
case SyntaxKind.ComputedPropertyName:
return visitComputedPropertyName(node as ComputedPropertyName);
default:
return node;
}
}
function visitVariableStatement(node: VariableStatement) {
const savedPendingStatements = pendingStatements;
pendingStatements = [];
const visitedNode = visitEachChild(node, visitor, context);
const statement = some(pendingStatements) ?
[visitedNode, ...pendingStatements] :
visitedNode;
pendingStatements = savedPendingStatements;
return statement;
}
function visitComputedPropertyName(name: ComputedPropertyName) {
let node = visitEachChild(name, visitor, context);
if (some(pendingExpressions)) {
const expressions = pendingExpressions;
expressions.push(name.expression);
pendingExpressions = [];
node = updateComputedPropertyName(
node,
inlineExpressions(expressions)
);
}
return node;
}
function visitPropertyDeclaration(node: PropertyDeclaration) {
Debug.assert(!some(node.decorators));
// Create a temporary variable to store a computed property name (if necessary).
// If it's not inlineable, then we emit an expression after the class which assigns
// the property name to the temporary variable.
const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer);
if (expr && !isSimpleInlineableExpression(expr)) {
(pendingExpressions || (pendingExpressions = [])).push(expr);
}
return undefined;
}
function visitClassDeclaration(node: ClassDeclaration) {
if (!forEach(node.members, isPropertyDeclaration)) {
return visitEachChild(node, visitor, context);
}
const savedPendingExpressions = pendingExpressions;
pendingExpressions = undefined;
const extendsClauseElement = getEffectiveBaseTypeNode(node);
const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword);
const statements: Statement[] = [
updateClassDeclaration(
node,
node.decorators,
node.modifiers,
node.name,
node.typeParameters,
node.heritageClauses,
transformClassMembers(node, isDerivedClass)
)
];
// Write any pending expressions from elided or moved computed property names
if (some(pendingExpressions)) {
statements.push(createExpressionStatement(inlineExpressions(pendingExpressions!)));
}
pendingExpressions = savedPendingExpressions;
// Emit static property assignment. Because classDeclaration is lexically evaluated,
// it is safe to emit static property assignment after classDeclaration
// From ES6 specification:
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
if (some(staticProperties)) {
addInitializedPropertyStatements(statements, staticProperties, getInternalName(node));
}
return statements;
}
function visitClassExpression(node: ClassExpression): Expression {
if (!forEach(node.members, isPropertyDeclaration)) {
return visitEachChild(node, visitor, context);
}
const savedPendingExpressions = pendingExpressions;
pendingExpressions = undefined;
// If this class expression is a transformation of a decorated class declaration,
// then we want to output the pendingExpressions as statements, not as inlined
// expressions with the class statement.
//
// In this case, we use pendingStatements to produce the same output as the
// class declaration transformation. The VariableStatement visitor will insert
// these statements after the class expression variable statement.
const isDecoratedClassDeclaration = isClassDeclaration(getOriginalNode(node));
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const extendsClauseElement = getEffectiveBaseTypeNode(node);
const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword);
const classExpression = updateClassExpression(
node,
node.modifiers,
node.name,
node.typeParameters,
visitNodes(node.heritageClauses, visitor, isHeritageClause),
transformClassMembers(node, isDerivedClass)
);
if (some(staticProperties) || some(pendingExpressions)) {
if (isDecoratedClassDeclaration) {
Debug.assertDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration.");
// Write any pending expressions from elided or moved computed property names
if (pendingStatements && pendingExpressions && some(pendingExpressions)) {
pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions)));
}
pendingExpressions = savedPendingExpressions;
if (pendingStatements && some(staticProperties)) {
addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node));
}
return classExpression;
}
else {
const expressions: Expression[] = [];
const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference;
const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference);
if (isClassWithConstructorReference) {
// record an alias as the class name is not in scope for statics.
enableSubstitutionForClassAliases();
const alias = getSynthesizedClone(temp);
alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes;
classAliases[getOriginalNodeId(node)] = alias;
}
// To preserve the behavior of the old emitter, we explicitly indent
// the body of a class with static initializers.
setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression));
expressions.push(startOnNewLine(createAssignment(temp, classExpression)));
// Add any pending expressions leftover from elided or relocated computed property names
addRange(expressions, map(pendingExpressions, startOnNewLine));
addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp));
expressions.push(startOnNewLine(temp));
pendingExpressions = savedPendingExpressions;
return inlineExpressions(expressions);
}
}
pendingExpressions = savedPendingExpressions;
return classExpression;
}
function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
const members: ClassElement[] = [];
const constructor = transformConstructor(node, isDerivedClass);
if (constructor) {
members.push(constructor);
}
addRange(members, visitNodes(node.members, classElementVisitor, isClassElement));
return setTextRange(createNodeArray(members), /*location*/ node.members);
}
function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration);
const containsPropertyInitializer = forEach(node.members, isInitializedProperty);
if (!containsPropertyInitializer) {
return constructor;
}
const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context);
const body = transformConstructorBody(node, constructor, isDerivedClass);
if (!body) {
return undefined;
}
return startOnNewLine(
setOriginalNode(
setTextRange(
createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
body
),
constructor || node
),
constructor
)
);
}
function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) {
const properties = getInitializedProperties(node, /*isStatic*/ false);
// Only generate synthetic constructor when there are property initializers to move.
if (!constructor && !some(properties)) {
return visitFunctionBody(/*node*/ undefined, visitor, context);
}
resumeLexicalEnvironment();
let indexOfFirstStatement = 0;
let statements: Statement[] = [];
if (!constructor && isDerivedClass) {
// Add a synthetic `super` call:
//
// super(...arguments);
//
statements.push(
createExpressionStatement(
createCall(
createSuper(),
/*typeArguments*/ undefined,
[createSpread(createIdentifier("arguments"))]
)
)
);
}
if (constructor) {
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor);
}
// Add the property initializers. Transforms this:
//
// public x = 1;
//
// Into this:
//
// constructor() {
// this.x = 1;
// }
//
addInitializedPropertyStatements(statements, properties, createThis());
// Add existing statements, skipping the initial super call.
if (constructor) {
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement));
}
statements = mergeLexicalEnvironment(statements, endLexicalEnvironment());
return setTextRange(
createBlock(
setTextRange(
createNodeArray(statements),
/*location*/ constructor ? constructor.body!.statements : node.members
),
/*multiLine*/ true
),
/*location*/ constructor ? constructor.body : undefined
);
}
/**
* Generates assignment statements for property initializers.
*
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
for (const property of properties) {
const statement = createExpressionStatement(transformInitializedProperty(property, receiver));
setSourceMapRange(statement, moveRangePastModifiers(property));
setCommentRange(statement, property);
setOriginalNode(statement, property);
statements.push(statement);
}
}
/**
* Generates assignment expressions for property initializers.
*
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function generateInitializedPropertyExpressions(properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
const expressions: Expression[] = [];
for (const property of properties) {
const expression = transformInitializedProperty(property, receiver);
startOnNewLine(expression);
setSourceMapRange(expression, moveRangePastModifiers(property));
setCommentRange(expression, property);
setOriginalNode(expression, property);
expressions.push(expression);
}
return expressions;
}
/**
* Transforms a property initializer into an assignment statement.
*
* @param property The property declaration.
* @param receiver The object receiving the property assignment.
*/
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
: property.name;
const initializer = visitNode(property.initializer!, visitor, isExpression);
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
}
function enableSubstitutionForClassAliases() {
if ((enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) === 0) {
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
// We need to enable substitutions for identifiers. This allows us to
// substitute class names inside of a class declaration.
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = [];
}
}
/**
* Hooks node substitutions.
*
* @param hint The context for the emitter.
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression) {
return substituteExpression(node as Expression);
}
return node;
}
function substituteExpression(node: Expression) {
switch (node.kind) {
case SyntaxKind.Identifier:
return substituteExpressionIdentifier(node as Identifier);
}
return node;
}
function substituteExpressionIdentifier(node: Identifier): Expression {
return trySubstituteClassAlias(node) || node;
}
function trySubstituteClassAlias(node: Identifier): Expression | undefined {
if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) {
// Due to the emit for class decorators, any reference to the class from inside of the class body
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
// behavior of class names in ES6.
// Also, when emitting statics for class expressions, we must substitute a class alias for
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
if (classAlias) {
const clone = getSynthesizedClone(classAlias);
setSourceMapRange(clone, node);
setCommentRange(clone, node);
return clone;
}
}
}
}
return undefined;
}
/**
* If the name is a computed property, this function transforms it, then either returns an expression which caches the
* value of the result or the expression itself if the value is either unused or safe to inline into multiple locations
* @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator)
*/
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined {
if (isComputedPropertyName(name)) {
const expression = visitNode(name.expression, visitor, isExpression);
const innerExpression = skipPartiallyEmittedExpressions(expression);
const inlinable = isSimpleInlineableExpression(innerExpression);
const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left);
if (!alreadyTransformed && !inlinable && shouldHoist) {
const generatedName = getGeneratedNameForNode(name);
hoistVariableDeclaration(generatedName);
return createAssignment(generatedName, expression);
}
return (inlinable || isIdentifier(innerExpression)) ? undefined : expression;
}
}
}
}

View File

@@ -64,7 +64,6 @@ namespace ts {
let currentLexicalScope: SourceFile | Block | ModuleBlock | CaseBlock;
let currentNameScope: ClassDeclaration | undefined;
let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap<Node> | undefined;
let currentClassHasParameterProperties: boolean | undefined;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
@@ -84,6 +83,12 @@ namespace ts {
*/
let applicableSubstitutions: TypeScriptSubstitutionFlags;
/**
* Tracks what computed name expressions originating from elided names must be inlined
* at the next execution site, in document order
*/
let pendingExpressions: Expression[] | undefined;
return transformSourceFileOrBundle;
function transformSourceFileOrBundle(node: SourceFile | Bundle) {
@@ -131,7 +136,6 @@ namespace ts {
const savedCurrentScope = currentLexicalScope;
const savedCurrentNameScope = currentNameScope;
const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName;
const savedCurrentClassHasParameterProperties = currentClassHasParameterProperties;
// Handle state changes before visiting a node.
onBeforeVisitNode(node);
@@ -145,7 +149,6 @@ namespace ts {
currentLexicalScope = savedCurrentScope;
currentNameScope = savedCurrentNameScope;
currentClassHasParameterProperties = savedCurrentClassHasParameterProperties;
return visited;
}
@@ -318,9 +321,6 @@ namespace ts {
return undefined;
case SyntaxKind.PropertyDeclaration:
// Property declarations are not TypeScript syntax, but they must be visited
// for the decorator transformation.
return visitPropertyDeclaration(node as PropertyDeclaration);
case SyntaxKind.IndexSignature:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
@@ -437,6 +437,7 @@ namespace ts {
// - decorators
// - optional `implements` heritage clause
// - parameter property assignments in the constructor
// - property declarations
// - index signatures
// - method overload signatures
return visitClassDeclaration(<ClassDeclaration>node);
@@ -448,6 +449,7 @@ namespace ts {
// - decorators
// - optional `implements` heritage clause
// - parameter property assignments in the constructor
// - property declarations
// - index signatures
// - method overload signatures
return visitClassExpression(<ClassExpression>node);
@@ -609,6 +611,10 @@ namespace ts {
if (!isClassLikeDeclarationWithTypeScriptSyntax(node) && !(currentNamespace && hasModifier(node, ModifierFlags.Export))) {
return visitEachChild(node, visitor, context);
}
const savedPendingExpressions = pendingExpressions;
pendingExpressions = undefined;
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const facts = getClassFacts(node, staticProperties);
@@ -618,11 +624,25 @@ namespace ts {
const name = node.name || (facts & ClassFacts.NeedsName ? getGeneratedNameForNode(node) : undefined);
const classStatement = facts & ClassFacts.HasConstructorDecorators
? createClassDeclarationHeadWithDecorators(node, name)
? createClassDeclarationHeadWithDecorators(node, name, facts)
: createClassDeclarationHeadWithoutDecorators(node, name, facts);
let statements: Statement[] = [classStatement];
// Write any pending expressions from elided or moved computed property names
if (some(pendingExpressions)) {
statements.push(createExpressionStatement(inlineExpressions(pendingExpressions!)));
}
pendingExpressions = savedPendingExpressions;
// Emit static property assignment. Because classDeclaration is lexically evaluated,
// it is safe to emit static property assignment after classDeclaration
// From ES6 specification:
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
if (facts & ClassFacts.HasStaticInitializedProperties) {
addInitializedPropertyStatements(statements, staticProperties, facts & ClassFacts.UseImmediatelyInvokedFunctionExpression ? getInternalName(node) : getLocalName(node));
}
// Write any decorators of the node.
addClassElementDecorationStatements(statements, node, /*isStatic*/ false);
@@ -725,7 +745,7 @@ namespace ts {
name,
/*typeParameters*/ undefined,
visitNodes(node.heritageClauses, visitor, isHeritageClause),
transformClassMembers(node)
transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0)
);
// To better align with the old emitter, we should not emit a trailing source map
@@ -745,7 +765,7 @@ namespace ts {
* Transforms a decorated class declaration and appends the resulting statements. If
* the class requires an alias to avoid issues with double-binding, the alias is returned.
*/
function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined) {
function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) {
// When we emit an ES6 class that has a class decorator, we must tailor the
// emit to certain specific cases.
//
@@ -840,7 +860,7 @@ namespace ts {
// ${members}
// }
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
const members = transformClassMembers(node);
const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0);
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members);
setOriginalNode(classExpression, node);
setTextRange(classExpression, location);
@@ -868,19 +888,49 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
const members = transformClassMembers(node);
const savedPendingExpressions = pendingExpressions;
pendingExpressions = undefined;
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword));
const classExpression = createClassExpression(
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
node.heritageClauses,
heritageClauses,
members
);
setOriginalNode(classExpression, node);
setTextRange(classExpression, node);
if (some(staticProperties) || some(pendingExpressions)) {
const expressions: Expression[] = [];
const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference;
const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference);
if (isClassWithConstructorReference) {
// record an alias as the class name is not in scope for statics.
enableSubstitutionForClassAliases();
const alias = getSynthesizedClone(temp);
alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes;
classAliases[getOriginalNodeId(node)] = alias;
}
// To preserve the behavior of the old emitter, we explicitly indent
// the body of a class with static initializers.
setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression));
expressions.push(startOnNewLine(createAssignment(temp, classExpression)));
// Add any pending expressions leftover from elided or relocated computed property names
addRange(expressions, map(pendingExpressions, startOnNewLine));
pendingExpressions = savedPendingExpressions;
addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp));
expressions.push(startOnNewLine(temp));
return inlineExpressions(expressions);
}
pendingExpressions = savedPendingExpressions;
return classExpression;
}
@@ -888,90 +938,70 @@ namespace ts {
* Transforms the members of a class.
*
* @param node The current class.
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
*/
function transformClassMembers(node: ClassDeclaration | ClassExpression) {
function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
const members: ClassElement[] = [];
const existingMembers = visitNodes(node.members, classElementVisitor, isClassElement);
const constructor = getFirstConstructorWithBody(node);
const parametersWithPropertyAssignments =
constructor && hasTypeScriptClassSyntax(constructor)
? filter(constructor.parameters, isParameterPropertyDeclaration)
: undefined;
if (some(parametersWithPropertyAssignments) && constructor) {
currentClassHasParameterProperties = true;
// Create property declarations for constructor parameter properties.
addRange(
members,
parametersWithPropertyAssignments.map(param =>
createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
param.name,
/*questionOrExclamationToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined
)
)
);
const parameters = transformConstructorParameters(constructor);
const body = transformConstructorBody(node.members, constructor, parametersWithPropertyAssignments);
members.push(startOnNewLine(
setOriginalNode(
setTextRange(
createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
body
),
constructor
),
constructor
)
));
addRange(
members,
visitNodes(
existingMembers,
member => {
if (isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) {
const updated = updateProperty(
member,
member.decorators,
member.modifiers,
member.name,
member.questionToken,
member.type,
/*initializer*/ undefined
);
setCommentRange(updated, node);
setSourceMapRange(updated, node);
return updated;
}
return member;
},
isClassElement
)
);
}
else {
if (constructor) {
members.push(visitEachChild(constructor, visitor, context));
}
addRange(members, existingMembers);
const constructor = transformConstructor(node, isDerivedClass);
if (constructor) {
members.push(constructor);
}
addRange(members, visitNodes(node.members, classElementVisitor, isClassElement));
return setTextRange(createNodeArray(members), /*location*/ node.members);
}
/**
* Transforms (or creates) a constructor for a class.
*
* @param node The current class.
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
*/
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
const constructor = getFirstConstructorWithBody(node);
const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty);
const hasParameterPropertyAssignments = constructor &&
constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax &&
forEach(constructor.parameters, isParameterWithPropertyAssignment);
// If the class does not contain nodes that require a synthesized constructor,
// accept the current constructor if it exists.
if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) {
return visitEachChild(constructor, visitor, context);
}
const parameters = transformConstructorParameters(constructor);
const body = transformConstructorBody(node, constructor, isDerivedClass);
// constructor(${parameters}) {
// ${body}
// }
return startOnNewLine(
setOriginalNode(
setTextRange(
createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
body
),
constructor || node
),
constructor
)
);
}
/**
* Transforms (or creates) the parameters for the constructor of a class with
* parameter property assignments or instance property initializers.
*
* @param constructor The constructor declaration.
*/
function transformConstructorParameters(constructor: ConstructorDeclaration) {
function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) {
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
// If constructor is empty, then
// If ClassHeritag_eopt is present and protoParent is not null, then
@@ -992,54 +1022,70 @@ namespace ts {
}
/**
* Transforms (or creates) a constructor body for a class with parameter property assignments.
* Transforms (or creates) a constructor body for a class with parameter property
* assignments or instance property initializers.
*
* @param node The current class.
* @param constructor The current class constructor.
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
*/
function transformConstructorBody(members: NodeArray<ClassElement>, constructor: ConstructorDeclaration, propertyAssignments: ReadonlyArray<ParameterPropertyDeclaration>) {
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) {
let statements: Statement[] = [];
let indexOfFirstStatement = 0;
resumeLexicalEnvironment();
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor);
if (constructor) {
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements);
// Add parameters with property assignments. Transforms this:
// Add parameters with property assignments. Transforms this:
//
// constructor (public x, public y) {
// }
//
// Into this:
//
// constructor (x, y) {
// this.x = x;
// this.y = y;
// }
//
const propertyAssignments = getParametersWithPropertyAssignments(constructor);
addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment));
}
else if (isDerivedClass) {
// Add a synthetic `super` call:
//
// super(...arguments);
//
statements.push(
createExpressionStatement(
createCall(
createSuper(),
/*typeArguments*/ undefined,
[createSpread(createIdentifier("arguments"))]
)
)
);
}
// Add the property initializers. Transforms this:
//
// constructor (public x, public y) {
// }
// public x = 1;
//
// Into this:
//
// constructor (x, y) {
// this.x = x;
// this.y = y;
// constructor() {
// this.x = 1;
// }
//
addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment));
const properties = getInitializedProperties(node, /*isStatic*/ false);
addInitializedPropertyStatements(statements, properties, createThis());
// Get property initializers.
const classBodyProperties = members.filter(member => isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) as PropertyDeclaration[];
addRange(statements, classBodyProperties.map(
prop => {
const name = prop.name;
const lhs = (!isComputedPropertyName(name) || isSimpleInlineableExpression(name.expression)) ?
createMemberAccessForPropertyName(createThis(), name, prop) :
createElementAccess(createThis(), getGeneratedNameForNode(name));
const initializerNode = createExpressionStatement(
createAssignment(lhs, prop.initializer!)
);
setOriginalNode(initializerNode, prop);
setTextRange(initializerNode, prop);
setCommentRange(initializerNode, prop);
setSourceMapRange(initializerNode, prop);
return initializerNode;
}
));
// Add the existing statements, skipping the initial super call.
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement));
if (constructor) {
// The class already had a constructor, so we should add the existing statements, skipping the initial super call.
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement));
}
// End the lexical environment.
statements = mergeLexicalEnvironment(statements, endLexicalEnvironment());
@@ -1047,7 +1093,7 @@ namespace ts {
createBlock(
setTextRange(
createNodeArray(statements),
/*location*/ constructor ? constructor.body!.statements : members
/*location*/ constructor ? constructor.body!.statements : node.members
),
/*multiLine*/ true
),
@@ -1055,16 +1101,61 @@ namespace ts {
);
}
/**
* Adds super call and preceding prologue directives into the list of statements.
*
* @param ctor The constructor node.
* @returns index of the statement that follows super call
*/
function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[]): number {
if (ctor.body) {
const statements = ctor.body.statements;
// add prologue directives to the list (if any)
const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor);
if (index === statements.length) {
// list contains nothing but prologue directives (or empty) - exit
return index;
}
const statement = statements[index];
if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((<ExpressionStatement>statement).expression)) {
result.push(visitNode(statement, visitor, isStatement));
return index + 1;
}
return index;
}
return 0;
}
/**
* Gets all parameters of a constructor that should be transformed into property assignments.
*
* @param node The constructor node.
*/
function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray<ParameterDeclaration> {
return filter(node.parameters, isParameterWithPropertyAssignment);
}
/**
* Determines whether a parameter should be transformed into a property assignment.
*
* @param parameter The parameter node.
*/
function isParameterWithPropertyAssignment(parameter: ParameterDeclaration) {
return hasModifier(parameter, ModifierFlags.ParameterPropertyModifier)
&& isIdentifier(parameter.name);
}
/**
* Transforms a parameter into a property assignment statement.
*
* @param node The parameter declaration.
*/
function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) {
const name = node.name;
if (!isIdentifier(name)) {
return undefined;
}
function transformParameterWithPropertyAssignment(node: ParameterDeclaration) {
Debug.assert(isIdentifier(node.name));
const name = node.name as Identifier;
const propertyName = getMutableClone(name);
setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap);
@@ -1093,6 +1184,99 @@ namespace ts {
);
}
/**
* Gets all property declarations with initializers on either the static or instance side of a class.
*
* @param node The class node.
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
*/
function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<PropertyDeclaration> {
return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty);
}
/**
* Gets a value indicating whether a class element is a static property declaration with an initializer.
*
* @param member The class element node.
*/
function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration {
return isInitializedProperty(member, /*isStatic*/ true);
}
/**
* Gets a value indicating whether a class element is an instance property declaration with an initializer.
*
* @param member The class element node.
*/
function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration {
return isInitializedProperty(member, /*isStatic*/ false);
}
/**
* Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer.
*
* @param member The class element node.
* @param isStatic A value indicating whether the member should be a static or instance member.
*/
function isInitializedProperty(member: ClassElement, isStatic: boolean) {
return member.kind === SyntaxKind.PropertyDeclaration
&& isStatic === hasModifier(member, ModifierFlags.Static)
&& (<PropertyDeclaration>member).initializer !== undefined;
}
/**
* Generates assignment statements for property initializers.
*
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
for (const property of properties) {
const statement = createExpressionStatement(transformInitializedProperty(property, receiver));
setSourceMapRange(statement, moveRangePastModifiers(property));
setCommentRange(statement, property);
setOriginalNode(statement, property);
statements.push(statement);
}
}
/**
* Generates assignment expressions for property initializers.
*
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function generateInitializedPropertyExpressions(properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
const expressions: Expression[] = [];
for (const property of properties) {
const expression = transformInitializedProperty(property, receiver);
startOnNewLine(expression);
setSourceMapRange(expression, moveRangePastModifiers(property));
setCommentRange(expression, property);
setOriginalNode(expression, property);
expressions.push(expression);
}
return expressions;
}
/**
* Transforms a property initializer into an assignment statement.
*
* @param property The property declaration.
* @param receiver The object receiving the property assignment.
*/
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
: property.name;
const initializer = visitNode(property.initializer!, visitor, isExpression);
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
}
/**
* Gets either the static or instance members of a class that are decorated, or have
* parameters that are decorated.
@@ -1960,6 +2144,16 @@ namespace ts {
: createIdentifier("BigInt");
}
/**
* A simple inlinable expression is an expression which can be copied into multiple locations
* without risk of repeating any sideeffects and whose value could not possibly change between
* any such locations
*/
function isSimpleInlineableExpression(expression: Expression) {
return !isIdentifier(expression) && isSimpleCopiableExpression(expression) ||
isWellKnownSymbolSyntactically(expression);
}
/**
* Gets an expression that represents a property name. For a computed property, a
* name is generated for the node.
@@ -1981,6 +2175,26 @@ namespace ts {
}
}
/**
* If the name is a computed property, this function transforms it, then either returns an expression which caches the
* value of the result or the expression itself if the value is either unused or safe to inline into multiple locations
* @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator)
* @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal)
*/
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined {
if (isComputedPropertyName(name)) {
const expression = visitNode(name.expression, visitor, isExpression);
const innerExpression = skipPartiallyEmittedExpressions(expression);
const inlinable = isSimpleInlineableExpression(innerExpression);
if (!inlinable && shouldHoist) {
const generatedName = getGeneratedNameForNode(name);
hoistVariableDeclaration(generatedName);
return createAssignment(generatedName, expression);
}
return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression;
}
}
/**
* Visits the property name of a class element, for use when emitting property
* initializers. For a computed property on a node with decorators, a temporary
@@ -1990,20 +2204,18 @@ namespace ts {
*/
function visitPropertyNameOfClassElement(member: ClassElement): PropertyName {
const name = member.name!;
// Computed property names need to be transformed into a hoisted variable when they are used more than once.
// The names are used more than once when:
// - the property is non-static and its initializer is moved to the constructor (when there are parameter property assignments).
// - the property has a decorator.
if (isComputedPropertyName(name) && ((!hasStaticModifier(member) && currentClassHasParameterProperties) || some(member.decorators))) {
const expression = visitNode(name.expression, visitor, isExpression);
const innerExpression = skipPartiallyEmittedExpressions(expression);
if (!isSimpleInlineableExpression(innerExpression)) {
const generatedName = getGeneratedNameForNode(name);
hoistVariableDeclaration(generatedName);
return updateComputedPropertyName(name, createAssignment(generatedName, expression));
let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false);
if (expr) { // expr only exists if `name` is a computed property name
// Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order
if (some(pendingExpressions)) {
expr = inlineExpressions([...pendingExpressions, expr]);
pendingExpressions.length = 0;
}
return updateComputedPropertyName(name as ComputedPropertyName, expr);
}
else {
return name;
}
return visitNode(name, visitor, isPropertyName);
}
/**
@@ -2049,23 +2261,12 @@ namespace ts {
return !nodeIsMissing(node.body);
}
function visitPropertyDeclaration(node: PropertyDeclaration) {
const updated = updateProperty(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
visitPropertyNameOfClassElement(node),
/*questionOrExclamationToken*/ undefined,
/*type*/ undefined,
visitNode(node.initializer, visitor)
);
if (updated !== node) {
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(updated, node);
setSourceMapRange(updated, moveRangePastDecorators(node));
function visitPropertyDeclaration(node: PropertyDeclaration): undefined {
const expr = getPropertyNameExpressionIfNeeded(node.name, some(node.decorators) || !!node.initializer, /*omitSimple*/ true);
if (expr && !isSimpleInlineableExpression(expr)) {
(pendingExpressions || (pendingExpressions = [])).push(expr);
}
return updated;
return undefined;
}
function visitConstructor(node: ConstructorDeclaration) {

View File

@@ -240,47 +240,6 @@ namespace ts {
isIdentifier(expression);
}
/**
* A simple inlinable expression is an expression which can be copied into multiple locations
* without risk of repeating any sideeffects and whose value could not possibly change between
* any such locations
*/
export function isSimpleInlineableExpression(expression: Expression) {
return !isIdentifier(expression) && isSimpleCopiableExpression(expression) ||
isWellKnownSymbolSyntactically(expression);
}
/**
* Adds super call and preceding prologue directives into the list of statements.
*
* @param ctor The constructor node.
* @param result The list of statements.
* @param visitor The visitor to apply to each node added to the result array.
* @returns index of the statement that follows super call
*/
export function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number {
if (ctor.body) {
const statements = ctor.body.statements;
// add prologue directives to the list (if any)
const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor);
if (index === statements.length) {
// list contains nothing but prologue directives (or empty) - exit
return index;
}
const statement = statements[index];
if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((<ExpressionStatement>statement).expression)) {
result.push(visitNode(statement, visitor, isStatement));
return index + 1;
}
return index;
}
return 0;
}
/**
* @param input Template string input strings
* @param args Names which need to be made file-level unique
@@ -296,43 +255,4 @@ namespace ts {
return result;
};
}
/**
* Gets all property declarations with initializers on either the static or instance side of a class.
*
* @param node The class node.
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
*/
export function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<PropertyDeclaration> {
return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty);
}
/**
* Gets a value indicating whether a class element is a static property declaration with an initializer.
*
* @param member The class element node.
*/
export function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return isInitializedProperty(member) && hasStaticModifier(member);
}
/**
* Gets a value indicating whether a class element is an instance property declaration with an initializer.
*
* @param member The class element node.
*/
export function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return isInitializedProperty(member) && !hasStaticModifier(member);
}
/**
* Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer.
*
* @param member The class element node.
* @param isStatic A value indicating whether the member should be a static or instance member.
*/
export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return member.kind === SyntaxKind.PropertyDeclaration
&& (<PropertyDeclaration>member).initializer !== undefined;
}
}

View File

@@ -30,7 +30,6 @@
"transformers/utilities.ts",
"transformers/destructuring.ts",
"transformers/ts.ts",
"transformers/classFields.ts",
"transformers/es2017.ts",
"transformers/es2018.ts",
"transformers/es2019.ts",

View File

@@ -5197,7 +5197,6 @@ namespace ts {
ContainsYield = 1 << 17,
ContainsHoistedDeclarationOrCompletion = 1 << 18,
ContainsDynamicImport = 1 << 19,
ContainsClassFields = 1 << 20,
// Please leave this as 1 << 29.
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.

View File

@@ -34,8 +34,8 @@ var C = /** @class */ (function () {
}
return C;
}());
exports.C = C;
_a = a_1.x;
exports.C = C;
//// [c.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
@@ -64,8 +64,8 @@ var D = /** @class */ (function (_super) {
}
return D;
}(b_1.C));
exports.D = D;
_a = a_1.x;
exports.D = D;
//// [a.d.ts]

View File

@@ -196,8 +196,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var _a, _b, _c, _d;
var _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21;
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21;
function x(o, k) { }
let i = 0;
function foo() { return ++i + ""; }
@@ -210,11 +209,11 @@ class A {
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_f] = null;
this[_h] = null;
this[_b] = null;
this[_d] = null;
}
}
foo(), _e = foo(), _f = foo(), _g = fieldNameB, _h = fieldNameC;
foo(), _a = foo(), _b = foo(), _c = fieldNameB, _d = fieldNameC;
__decorate([
x
], A.prototype, "property", void 0);
@@ -229,42 +228,42 @@ __decorate([
], A.prototype, Symbol.iterator, void 0);
__decorate([
x
], A.prototype, _e, void 0);
], A.prototype, _a, void 0);
__decorate([
x
], A.prototype, _f, void 0);
], A.prototype, _b, void 0);
__decorate([
x
], A.prototype, _g, void 0);
], A.prototype, _c, void 0);
__decorate([
x
], A.prototype, _h, void 0);
void (_a = class B {
], A.prototype, _d, void 0);
void (_j = class B {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_k] = null;
this[_m] = null;
this[_f] = null;
this[_h] = null;
}
},
foo(),
_j = foo(),
_k = foo(),
_l = fieldNameB,
_m = fieldNameC,
_a);
_e = foo(),
_f = foo(),
_g = fieldNameB,
_h = fieldNameC,
_j);
class C {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_p] = null;
this[_r] = null;
this[_l] = null;
this[_o] = null;
}
[(foo(), _o = foo(), _p = foo(), _q = fieldNameB, _r = fieldNameC, "some" + "method")]() { }
[(foo(), _k = foo(), _l = foo(), _m = fieldNameB, _o = fieldNameC, "some" + "method")]() { }
}
__decorate([
x
@@ -278,28 +277,28 @@ __decorate([
__decorate([
x
], C.prototype, Symbol.iterator, void 0);
__decorate([
x
], C.prototype, _k, void 0);
__decorate([
x
], C.prototype, _l, void 0);
__decorate([
x
], C.prototype, _m, void 0);
__decorate([
x
], C.prototype, _o, void 0);
__decorate([
x
], C.prototype, _p, void 0);
__decorate([
x
], C.prototype, _q, void 0);
__decorate([
x
], C.prototype, _r, void 0);
void class D {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_t] = null;
this[_v] = null;
this[_q] = null;
this[_s] = null;
}
[(foo(), _s = foo(), _t = foo(), _u = fieldNameB, _v = fieldNameC, "some" + "method")]() { }
[(foo(), _p = foo(), _q = foo(), _r = fieldNameB, _s = fieldNameC, "some" + "method")]() { }
};
class E {
constructor() {
@@ -307,12 +306,12 @@ class E {
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_x] = null;
this[_z] = null;
this[_u] = null;
this[_w] = null;
}
[(foo(), _w = foo(), _x = foo(), "some" + "method")]() { }
[(foo(), _t = foo(), _u = foo(), "some" + "method")]() { }
}
_y = fieldNameB, _z = fieldNameC;
_v = fieldNameB, _w = fieldNameC;
__decorate([
x
], E.prototype, "property", void 0);
@@ -325,45 +324,45 @@ __decorate([
__decorate([
x
], E.prototype, Symbol.iterator, void 0);
__decorate([
x
], E.prototype, _t, void 0);
__decorate([
x
], E.prototype, _u, void 0);
__decorate([
x
], E.prototype, _v, void 0);
__decorate([
x
], E.prototype, _w, void 0);
__decorate([
x
], E.prototype, _x, void 0);
__decorate([
x
], E.prototype, _y, void 0);
__decorate([
x
], E.prototype, _z, void 0);
void (_b = class F {
void (_1 = class F {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_1] = null;
this[_3] = null;
this[_y] = null;
this[_0] = null;
}
[(foo(), _0 = foo(), _1 = foo(), "some" + "method")]() { }
[(foo(), _x = foo(), _y = foo(), "some" + "method")]() { }
},
_2 = fieldNameB,
_3 = fieldNameC,
_b);
_z = fieldNameB,
_0 = fieldNameC,
_1);
class G {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_3] = null;
this[_5] = null;
this[_7] = null;
}
[(foo(), _4 = foo(), _5 = foo(), "some" + "method")]() { }
[(_6 = fieldNameB, "some" + "method2")]() { }
[(foo(), _2 = foo(), _3 = foo(), "some" + "method")]() { }
[(_4 = fieldNameB, "some" + "method2")]() { }
}
_7 = fieldNameC;
_5 = fieldNameC;
__decorate([
x
], G.prototype, "property", void 0);
@@ -376,45 +375,45 @@ __decorate([
__decorate([
x
], G.prototype, Symbol.iterator, void 0);
__decorate([
x
], G.prototype, _2, void 0);
__decorate([
x
], G.prototype, _3, void 0);
__decorate([
x
], G.prototype, _4, void 0);
__decorate([
x
], G.prototype, _5, void 0);
__decorate([
x
], G.prototype, _6, void 0);
__decorate([
x
], G.prototype, _7, void 0);
void (_c = class H {
void (_10 = class H {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_7] = null;
this[_9] = null;
this[_11] = null;
}
[(foo(), _8 = foo(), _9 = foo(), "some" + "method")]() { }
[(_10 = fieldNameB, "some" + "method2")]() { }
[(foo(), _6 = foo(), _7 = foo(), "some" + "method")]() { }
[(_8 = fieldNameB, "some" + "method2")]() { }
},
_11 = fieldNameC,
_c);
_9 = fieldNameC,
_10);
class I {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_13] = null;
this[_16] = null;
this[_12] = null;
this[_15] = null;
}
[(foo(), _12 = foo(), _13 = foo(), _14 = "some" + "method")]() { }
[(_15 = fieldNameB, "some" + "method2")]() { }
[(foo(), _11 = foo(), _12 = foo(), _13 = "some" + "method")]() { }
[(_14 = fieldNameB, "some" + "method2")]() { }
}
_16 = fieldNameC;
_15 = fieldNameC;
__decorate([
x
], I.prototype, "property", void 0);
@@ -427,32 +426,32 @@ __decorate([
__decorate([
x
], I.prototype, Symbol.iterator, void 0);
__decorate([
x
], I.prototype, _11, void 0);
__decorate([
x
], I.prototype, _12, void 0);
__decorate([
x
], I.prototype, _13, void 0);
], I.prototype, _13, null);
__decorate([
x
], I.prototype, _14, null);
], I.prototype, _14, void 0);
__decorate([
x
], I.prototype, _15, void 0);
__decorate([
x
], I.prototype, _16, void 0);
void (_d = class J {
void (_21 = class J {
constructor() {
this["property2"] = 2;
this[Symbol.iterator] = null;
this["property4"] = 2;
this[Symbol.match] = null;
this[_18] = null;
this[_21] = null;
this[_17] = null;
this[_20] = null;
}
[(foo(), _17 = foo(), _18 = foo(), _19 = "some" + "method")]() { }
[(_20 = fieldNameB, "some" + "method2")]() { }
[(foo(), _16 = foo(), _17 = foo(), _18 = "some" + "method")]() { }
[(_19 = fieldNameB, "some" + "method2")]() { }
},
_21 = fieldNameC,
_d);
_20 = fieldNameC,
_21);

View File

@@ -35,8 +35,8 @@ System.register([], function (exports_1, context_1) {
MyClass2 = class MyClass2 {
static getInstance() { return MyClass2.value; }
};
exports_1("MyClass2", MyClass2);
MyClass2.value = 42;
exports_1("MyClass2", MyClass2);
}
};
});

View File

@@ -16,8 +16,8 @@ var Foo = /** @class */ (function () {
}
return Foo;
}());
exports.Foo = Foo;
_a = key;
exports.Foo = Foo;
//// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.d.ts]