Fix class name emit in ES5

This commit is contained in:
Ron Buckton
2017-04-25 12:44:02 -07:00
committed by Mohamed Hegazy
parent f3737dd97a
commit c1103424b8
6 changed files with 44 additions and 20 deletions

View File

@@ -2937,6 +2937,28 @@ namespace ts {
);
}
/**
* Gets the internal name of a declaration. This is primarily used for declarations that can be
* referred to by name in the body of an ES5 class function body. An internal name will *never*
* be prefixed with an module or namespace export modifier like "exports." when emitted as an
* expression. An internal name will also *never* be renamed due to a collision with a block
* scoped variable.
*
* @param node The declaration.
* @param allowComments A value indicating whether comments may be emitted for the name.
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
*/
export function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName);
}
/**
* Gets whether an identifier should only be referred to by its internal name.
*/
export function isInternalName(node: Identifier) {
return (getEmitFlags(node) & EmitFlags.InternalName) !== 0;
}
/**
* Gets the local name of a declaration. This is primarily used for declarations that can be
* referred to by name in the declaration's immediate scope (classes, enums, namespaces). A

View File

@@ -813,7 +813,7 @@ namespace ts {
// Create a synthetic text range for the return statement.
const closingBraceLocation = createTokenRange(skipTrivia(currentText, node.members.end), SyntaxKind.CloseBraceToken);
const localName = getLocalName(node);
const localName = getInternalName(node);
// The following partially-emitted expression exists purely to align our sourcemap
// emit with the original emitter.
@@ -870,7 +870,7 @@ namespace ts {
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
getDeclarationName(node),
getInternalName(node),
/*typeParameters*/ undefined,
transformConstructorParameters(constructor, hasSynthesizedSuper),
/*type*/ undefined,
@@ -3725,7 +3725,7 @@ namespace ts {
function substituteIdentifier(node: Identifier) {
// Only substitute the identifier if we have enabled substitutions for block-scoped
// bindings.
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) {
const original = getParseTreeNode(node, isIdentifier);
if (original && isNameOfDeclarationWithCollidingName(original)) {
return setTextRange(getGeneratedNameForNode(original), node);
@@ -3778,7 +3778,7 @@ namespace ts {
* @param node An Identifier node.
*/
function substituteExpressionIdentifier(node: Identifier): Identifier {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) {
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
if (declaration) {
return setTextRange(getGeneratedNameForNode(declaration.name), node);
@@ -3802,8 +3802,9 @@ namespace ts {
}
function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) {
const expression = getLocalName(node);
return hasModifier(member, ModifierFlags.Static) ? expression : createPropertyAccess(expression, "prototype");
return hasModifier(member, ModifierFlags.Static)
? getLocalName(node)
: createPropertyAccess(getInternalName(node), "prototype");
}
function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration, hasExtendsClause: boolean) {

View File

@@ -3940,14 +3940,15 @@ namespace ts {
HelperName = 1 << 12,
ExportName = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
LocalName = 1 << 14, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
Indented = 1 << 15, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
NoIndentation = 1 << 16, // Do not indent the node.
AsyncFunctionBody = 1 << 17,
ReuseTempVariableScope = 1 << 18, // Reuse the existing temp variable scope during emit.
CustomPrologue = 1 << 19, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
NoHoisting = 1 << 20, // Do not hoist this declaration in --module system
HasEndOfDeclarationMarker = 1 << 21, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
Iterator = 1 << 22, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
InternalName = 1 << 15, // The name is internal to an ES5 class body function.
Indented = 1 << 16, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
NoIndentation = 1 << 17, // Do not indent the node.
AsyncFunctionBody = 1 << 18,
ReuseTempVariableScope = 1 << 19, // Reuse the existing temp variable scope during emit.
CustomPrologue = 1 << 20, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
NoHoisting = 1 << 21, // Do not hoist this declaration in --module system
HasEndOfDeclarationMarker = 1 << 22, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
}
export interface EmitHelper {