mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
Merge branch 'master' into wideningInAccessExpressions
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -16,8 +16,8 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
_a = key;
|
||||
exports.Foo = Foo;
|
||||
|
||||
|
||||
//// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.d.ts]
|
||||
|
||||
Reference in New Issue
Block a user