Merge pull request #3380 from Microsoft/emitterNameRewriting

Emitter name rewriting
This commit is contained in:
Anders Hejlsberg 2015-06-09 07:04:47 -07:00
commit ce2d914e4a
12 changed files with 312 additions and 346 deletions

View file

@ -12052,80 +12052,80 @@ module ts {
// Emitter support
function isExternalModuleSymbol(symbol: Symbol): boolean {
return symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length === 1 && symbol.declarations[0].kind === SyntaxKind.SourceFile;
}
function getAliasNameSubstitution(symbol: Symbol, getGeneratedNameForNode: (node: Node) => string): string {
// If this is es6 or higher, just use the name of the export
// no need to qualify it.
if (languageVersion >= ScriptTarget.ES6) {
return undefined;
}
let node = getDeclarationOfAliasSymbol(symbol);
if (node) {
if (node.kind === SyntaxKind.ImportClause) {
let defaultKeyword: string;
if (languageVersion === ScriptTarget.ES3) {
defaultKeyword = "[\"default\"]";
} else {
defaultKeyword = ".default";
}
return getGeneratedNameForNode(<ImportDeclaration>node.parent) + defaultKeyword;
}
if (node.kind === SyntaxKind.ImportSpecifier) {
let moduleName = getGeneratedNameForNode(<ImportDeclaration>node.parent.parent.parent);
let propertyName = (<ImportSpecifier>node).propertyName || (<ImportSpecifier>node).name;
return moduleName + "." + unescapeIdentifier(propertyName.text);
}
}
}
function getExportNameSubstitution(symbol: Symbol, location: Node, getGeneratedNameForNode: (Node: Node) => string): string {
if (isExternalModuleSymbol(symbol.parent)) {
// 1. If this is es6 or higher, just use the name of the export
// no need to qualify it.
// 2. export mechanism for System modules is different from CJS\AMD
// and it does not need qualifications for exports
if (languageVersion >= ScriptTarget.ES6 || compilerOptions.module === ModuleKind.System) {
return undefined;
}
return "exports." + unescapeIdentifier(symbol.name);
}
let node = location;
let containerSymbol = getParentOfSymbol(symbol);
while (node) {
if ((node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(node) === containerSymbol) {
return getGeneratedNameForNode(<ModuleDeclaration | EnumDeclaration>node) + "." + unescapeIdentifier(symbol.name);
}
node = node.parent;
}
}
function getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (Node: Node) => string): string {
let symbol = getNodeLinks(node).resolvedSymbol || (isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined);
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
// node of the exported entity's container. Otherwise, return undefined.
function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration {
let symbol = getReferencedValueSymbol(node);
if (symbol) {
// Whan an identifier resolves to a parented symbol, it references an exported entity from
// another declaration of the same internal module.
if (symbol.parent) {
return getExportNameSubstitution(symbol, node.parent, getGeneratedNameForNode);
if (symbol.flags & SymbolFlags.ExportValue) {
// If we reference an exported entity within the same module declaration, then whether
// we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
// kinds that we do NOT prefix.
let exportSymbol = getMergedSymbol(symbol.exportSymbol);
if (exportSymbol.flags & SymbolFlags.ExportHasLocal) {
return undefined;
}
symbol = exportSymbol;
}
// If we reference an exported entity within the same module declaration, then whether
// we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
// kinds that we do NOT prefix.
let exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
if (symbol !== exportSymbol && !(exportSymbol.flags & SymbolFlags.ExportHasLocal)) {
return getExportNameSubstitution(exportSymbol, node.parent, getGeneratedNameForNode);
}
// Named imports from ES6 import declarations are rewritten
if (symbol.flags & SymbolFlags.Alias) {
return getAliasNameSubstitution(symbol, getGeneratedNameForNode);
let parentSymbol = getParentOfSymbol(symbol);
if (parentSymbol) {
if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) {
return <SourceFile>parentSymbol.valueDeclaration;
}
for (let n = node.parent; n; n = n.parent) {
if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) {
return <ModuleDeclaration | EnumDeclaration>n;
}
}
}
}
}
// When resolved as an expression identifier, if the given node references an import, return the declaration of
// that import. Otherwise, return undefined.
function getReferencedImportDeclaration(node: Identifier): Declaration {
let symbol = getReferencedValueSymbol(node);
return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined;
}
function isStatementWithLocals(node: Node) {
switch (node.kind) {
case SyntaxKind.Block:
case SyntaxKind.CaseBlock:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
return true;
}
return false;
}
function isNestedRedeclarationSymbol(symbol: Symbol): boolean {
if (symbol.flags & SymbolFlags.BlockScoped) {
let links = getSymbolLinks(symbol);
if (links.isNestedRedeclaration === undefined) {
let container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
links.isNestedRedeclaration = isStatementWithLocals(container) &&
!!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
}
return links.isNestedRedeclaration;
}
return false;
}
// When resolved as an expression identifier, if the given node references a nested block scoped entity with
// a name that hides an existing name, return the declaration of that entity. Otherwise, return undefined.
function getReferencedNestedRedeclaration(node: Identifier): Declaration {
let symbol = getReferencedValueSymbol(node);
return symbol && isNestedRedeclarationSymbol(symbol) ? symbol.valueDeclaration : undefined;
}
// Return true if the given node is a declaration of a nested block scoped entity with a name that hides an
// existing name.
function isNestedRedeclaration(node: Declaration): boolean {
return isNestedRedeclarationSymbol(getSymbolOfNode(node));
}
function isValueAliasDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
@ -12227,10 +12227,13 @@ module ts {
}
/** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string {
function serializeEntityName(node: EntityName, fallbackPath?: string[]): string {
if (node.kind === SyntaxKind.Identifier) {
var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
var text = substitution || (<Identifier>node).text;
// TODO(ron.buckton): The getExpressionNameSubstitution function has been removed, but calling it
// here has no effect anyway as an identifier in a type name is not an expression.
// var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
// var text = substitution || (<Identifier>node).text;
var text = (<Identifier>node).text;
if (fallbackPath) {
fallbackPath.push(text);
}
@ -12239,8 +12242,8 @@ module ts {
}
}
else {
var left = serializeEntityName((<QualifiedName>node).left, getGeneratedNameForNode, fallbackPath);
var right = serializeEntityName((<QualifiedName>node).right, getGeneratedNameForNode, fallbackPath);
var left = serializeEntityName((<QualifiedName>node).left, fallbackPath);
var right = serializeEntityName((<QualifiedName>node).right, fallbackPath);
if (!fallbackPath) {
return left + "." + right;
}
@ -12248,7 +12251,7 @@ module ts {
}
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
function serializeTypeReferenceNode(node: TypeReferenceNode, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
function serializeTypeReferenceNode(node: TypeReferenceNode): string | string[] {
// serialization of a TypeReferenceNode uses the following rules:
//
// * The serialized type of a TypeReference that is `void` is "void 0".
@ -12281,11 +12284,11 @@ module ts {
}
else if (type === unknownType) {
var fallbackPath: string[] = [];
serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath);
serializeEntityName(node.typeName, fallbackPath);
return fallbackPath;
}
else if (type.symbol && type.symbol.valueDeclaration) {
return serializeEntityName(node.typeName, getGeneratedNameForNode);
return serializeEntityName(node.typeName);
}
else if (typeHasCallOrConstructSignatures(type)) {
return "Function";
@ -12295,7 +12298,7 @@ module ts {
}
/** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
function serializeTypeNode(node: TypeNode | LiteralExpression, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
function serializeTypeNode(node: TypeNode | LiteralExpression): string | string[] {
// serialization of a TypeNode uses the following rules:
//
// * The serialized type of `void` is "void 0" (undefined).
@ -12311,7 +12314,7 @@ module ts {
case SyntaxKind.VoidKeyword:
return "void 0";
case SyntaxKind.ParenthesizedType:
return serializeTypeNode((<ParenthesizedTypeNode>node).type, getGeneratedNameForNode);
return serializeTypeNode((<ParenthesizedTypeNode>node).type);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
return "Function";
@ -12326,7 +12329,7 @@ module ts {
case SyntaxKind.NumberKeyword:
return "Number";
case SyntaxKind.TypeReference:
return serializeTypeReferenceNode(<TypeReferenceNode>node, getGeneratedNameForNode);
return serializeTypeReferenceNode(<TypeReferenceNode>node);
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeLiteral:
case SyntaxKind.UnionType:
@ -12342,7 +12345,7 @@ module ts {
}
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
function serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
function serializeTypeOfNode(node: Node): string | string[] {
// serialization of the type of a declaration uses the following rules:
//
// * The serialized type of a ClassDeclaration is "Function"
@ -12355,10 +12358,10 @@ module ts {
// For rules on serializing type annotations, see `serializeTypeNode`.
switch (node.kind) {
case SyntaxKind.ClassDeclaration: return "Function";
case SyntaxKind.PropertyDeclaration: return serializeTypeNode((<PropertyDeclaration>node).type, getGeneratedNameForNode);
case SyntaxKind.Parameter: return serializeTypeNode((<ParameterDeclaration>node).type, getGeneratedNameForNode);
case SyntaxKind.GetAccessor: return serializeTypeNode((<AccessorDeclaration>node).type, getGeneratedNameForNode);
case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node), getGeneratedNameForNode);
case SyntaxKind.PropertyDeclaration: return serializeTypeNode((<PropertyDeclaration>node).type);
case SyntaxKind.Parameter: return serializeTypeNode((<ParameterDeclaration>node).type);
case SyntaxKind.GetAccessor: return serializeTypeNode((<AccessorDeclaration>node).type);
case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
}
if (isFunctionLike(node)) {
return "Function";
@ -12367,7 +12370,7 @@ module ts {
}
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
function serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[] {
function serializeParameterTypesOfNode(node: Node): (string | string[])[] {
// serialization of parameter types uses the following rules:
//
// * If the declaration is a class, the parameters of the first constructor with a body are used.
@ -12400,10 +12403,10 @@ module ts {
else {
parameterType = undefined;
}
result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode);
result[i] = serializeTypeNode(parameterType);
}
else {
result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode);
result[i] = serializeTypeOfNode(parameters[i]);
}
}
return result;
@ -12414,9 +12417,9 @@ module ts {
}
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
function serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
function serializeReturnTypeOfNode(node: Node): string | string[] {
if (node && isFunctionLike(node)) {
return serializeTypeNode((<FunctionLikeDeclaration>node).type, getGeneratedNameForNode);
return serializeTypeNode((<FunctionLikeDeclaration>node).type);
}
return "void 0";
}
@ -12445,17 +12448,15 @@ module ts {
return hasProperty(globals, name);
}
function resolvesToSomeValue(location: Node, name: string): boolean {
Debug.assert(!nodeIsSynthesized(location), "resolvesToSomeValue called with a synthesized location");
return !!resolveName(location, name, SymbolFlags.Value, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
function getReferencedValueSymbol(reference: Identifier): Symbol {
return getNodeLinks(reference).resolvedSymbol ||
resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias,
/*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
}
function getReferencedValueDeclaration(reference: Identifier): Declaration {
Debug.assert(!nodeIsSynthesized(reference));
let symbol =
getNodeLinks(reference).resolvedSymbol ||
resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
let symbol = getReferencedValueSymbol(reference);
return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration;
}
@ -12500,7 +12501,10 @@ module ts {
function createResolver(): EmitResolver {
return {
getExpressionNameSubstitution,
getReferencedExportContainer,
getReferencedImportDeclaration,
getReferencedNestedRedeclaration,
isNestedRedeclaration,
isValueAliasDeclaration,
hasGlobalName,
isReferencedAliasDeclaration,
@ -12514,7 +12518,6 @@ module ts {
isSymbolAccessible,
isEntityNameVisible,
getConstantValue,
resolvesToSomeValue,
collectLinkedAliases,
getBlockScopedVariableId,
getReferencedValueDeclaration,

View file

@ -125,7 +125,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let generatedNameSet: Map<string> = {};
let nodeToGeneratedName: string[] = [];
let blockScopedVariableToGeneratedName: string[];
let computedPropertyNamesToGeneratedNames: string[];
let extendsEmitted = false;
@ -249,81 +248,44 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function assignGeneratedName(node: Node, name: string) {
nodeToGeneratedName[getNodeId(node)] = unescapeIdentifier(name);
}
function generateNameForFunctionOrClassDeclaration(node: Declaration) {
if (!node.name) {
assignGeneratedName(node, makeUniqueName("default"));
}
}
function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
if (node.name.kind === SyntaxKind.Identifier) {
let name = node.name.text;
// Use module/enum name itself if it is unique, otherwise make a unique variation
assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name));
}
let name = node.name.text;
// Use module/enum name itself if it is unique, otherwise make a unique variation
return isUniqueLocalName(name, node) ? name : makeUniqueName(name);
}
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
let expr = getExternalModuleName(node);
let baseName = expr.kind === SyntaxKind.StringLiteral ?
escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
assignGeneratedName(node, makeUniqueName(baseName));
return makeUniqueName(baseName);
}
function generateNameForImportDeclaration(node: ImportDeclaration) {
if (node.importClause) {
generateNameForImportOrExportDeclaration(node);
}
}
function generateNameForExportDeclaration(node: ExportDeclaration) {
if (node.moduleSpecifier) {
generateNameForImportOrExportDeclaration(node);
}
}
function generateNameForExportAssignment(node: ExportAssignment) {
if (node.expression && node.expression.kind !== SyntaxKind.Identifier) {
assignGeneratedName(node, makeUniqueName("default"));
}
function generateNameForExportDefault() {
return makeUniqueName("default");
}
function generateNameForNode(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
return makeUniqueName((<Identifier>node).text);
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
return generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
return generateNameForImportOrExportDeclaration(<ImportDeclaration | ExportDeclaration>node);
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
generateNameForFunctionOrClassDeclaration(<Declaration>node);
break;
case SyntaxKind.ModuleDeclaration:
generateNameForModuleOrEnum(<ModuleDeclaration>node);
generateNameForNode((<ModuleDeclaration>node).body);
break;
case SyntaxKind.EnumDeclaration:
generateNameForModuleOrEnum(<EnumDeclaration>node);
break;
case SyntaxKind.ImportDeclaration:
generateNameForImportDeclaration(<ImportDeclaration>node);
break;
case SyntaxKind.ExportDeclaration:
generateNameForExportDeclaration(<ExportDeclaration>node);
break;
case SyntaxKind.ExportAssignment:
generateNameForExportAssignment(<ExportAssignment>node);
break;
return generateNameForExportDefault();
}
}
function getGeneratedNameForNode(node: Node) {
let nodeId = getNodeId(node);
if (!nodeToGeneratedName[nodeId]) {
generateNameForNode(node);
}
return nodeToGeneratedName[nodeId];
let id = getNodeId(node);
return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node)));
}
function initializeEmitterWithSourceMaps() {
@ -687,19 +649,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
}
function emitNodeWithSourceMap(node: Node, allowGeneratedIdentifiers?: boolean) {
function emitNodeWithSourceMap(node: Node) {
if (node) {
if (nodeIsSynthesized(node)) {
return emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
return emitNodeWithoutSourceMap(node);
}
if (node.kind != SyntaxKind.SourceFile) {
recordEmitNodeStartSpan(node);
emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
emitNodeWithoutSourceMap(node);
recordEmitNodeEndSpan(node);
}
else {
recordNewSourceFileStart(<SourceFile>node);
emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
emitNodeWithoutSourceMap(node);
}
}
}
@ -1201,80 +1163,129 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function isNotExpressionIdentifier(node: Identifier) {
function isExpressionIdentifier(node: Node): boolean {
let parent = node.parent;
switch (parent.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
return (<Declaration>parent).name === node;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return (<ImportOrExportSpecifier>parent).name === node || (<ImportOrExportSpecifier>parent).propertyName === node;
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.CaseClause:
case SyntaxKind.ComputedPropertyName:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.Decorator:
case SyntaxKind.DeleteExpression:
case SyntaxKind.DoStatement:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.ExportAssignment:
return false;
case SyntaxKind.LabeledStatement:
return (<LabeledStatement>node.parent).label === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.NewExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.SpreadElementExpression:
case SyntaxKind.SwitchStatement:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TemplateSpan:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.YieldExpression:
return true;
case SyntaxKind.BindingElement:
case SyntaxKind.EnumMember:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.VariableDeclaration:
return (<BindingElement | EnumMember | ParameterDeclaration | PropertyAssignment | PropertyDeclaration | VariableDeclaration>parent).initializer === node;
case SyntaxKind.PropertyAccessExpression:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionExpression:
return (<FunctionLikeDeclaration>parent).body === node;
case SyntaxKind.ImportEqualsDeclaration:
return (<ImportEqualsDeclaration>parent).moduleReference === node;
case SyntaxKind.QualifiedName:
return (<QualifiedName>parent).left === node;
}
return false;
}
function emitExpressionIdentifier(node: Identifier) {
let substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode);
if (substitution) {
write(substitution);
let container = resolver.getReferencedExportContainer(node);
if (container) {
if (container.kind === SyntaxKind.SourceFile) {
// Identifier references module export
if (languageVersion < ScriptTarget.ES6 && compilerOptions.module !== ModuleKind.System) {
write("exports.");
}
}
else {
// Identifier references namespace export
write(getGeneratedNameForNode(container));
write(".");
}
}
else {
writeTextOfNode(currentSourceFile, node);
}
}
function getGeneratedNameForIdentifier(node: Identifier): string {
if (nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) {
return undefined;
}
var variableId = resolver.getBlockScopedVariableId(node)
if (variableId === undefined) {
return undefined;
}
return blockScopedVariableToGeneratedName[variableId];
}
function emitIdentifier(node: Identifier, allowGeneratedIdentifiers: boolean) {
if (allowGeneratedIdentifiers) {
let generatedName = getGeneratedNameForIdentifier(node);
if (generatedName) {
write(generatedName);
else if (languageVersion < ScriptTarget.ES6) {
let declaration = resolver.getReferencedImportDeclaration(node);
if (declaration) {
if (declaration.kind === SyntaxKind.ImportClause) {
// Identifier references default import
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent));
write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default");
return;
}
else if (declaration.kind === SyntaxKind.ImportSpecifier) {
// Identifier references named import
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent.parent.parent));
write(".");
writeTextOfNode(currentSourceFile, (<ImportSpecifier>declaration).propertyName || (<ImportSpecifier>declaration).name);
return;
}
}
declaration = resolver.getReferencedNestedRedeclaration(node);
if (declaration) {
write(getGeneratedNameForNode(declaration.name));
return;
}
}
writeTextOfNode(currentSourceFile, node);
}
function isNameOfNestedRedeclaration(node: Identifier) {
if (languageVersion < ScriptTarget.ES6) {
let parent = node.parent;
switch (parent.kind) {
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.VariableDeclaration:
return (<Declaration>parent).name === node && resolver.isNestedRedeclaration(<Declaration>parent);
}
}
return false;
}
function emitIdentifier(node: Identifier) {
if (!node.parent) {
write(node.text);
}
else if (!isNotExpressionIdentifier(node)) {
else if (isExpressionIdentifier(node)) {
emitExpressionIdentifier(node);
}
else if (isNameOfNestedRedeclaration(node)) {
write(getGeneratedNameForNode(node));
}
else {
writeTextOfNode(currentSourceFile, node);
}
@ -1320,7 +1331,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
function emitBindingElement(node: BindingElement) {
if (node.propertyName) {
emit(node.propertyName, /*allowGeneratedIdentifiers*/ false);
emit(node.propertyName);
write(": ");
}
if (node.dotDotDotToken) {
@ -1682,7 +1693,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
write("*");
}
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
if (languageVersion < ScriptTarget.ES6) {
write(": function ");
}
@ -1690,40 +1701,34 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function emitPropertyAssignment(node: PropertyDeclaration) {
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
write(": ");
emit(node.initializer);
}
// Return true if identifier resolves to an exported member of a namespace
function isNamespaceExportReference(node: Identifier) {
let container = resolver.getReferencedExportContainer(node);
return container && container.kind !== SyntaxKind.SourceFile;
}
function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
emit(node.name, /*allowGeneratedIdentifiers*/ false);
// If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example:
// module m {
// export let y;
// }
// module m {
// export let obj = { y };
// }
// The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
if (languageVersion < ScriptTarget.ES6) {
// The name property of a short-hand property assignment is considered an expression position, so here
// we manually emit the identifier to avoid rewriting.
writeTextOfNode(currentSourceFile, node.name);
// If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier,
// we emit a normal property assignment. For example:
// module m {
// export let y;
// }
// module m {
// let obj = { y };
// }
// Here we need to emit obj = { y : m.y } regardless of the output target.
if (languageVersion < ScriptTarget.ES6 || isNamespaceExportReference(node.name)) {
// Emit identifier as an identifier
write(": ");
var generatedName = getGeneratedNameForIdentifier(node.name);
if (generatedName) {
write(generatedName);
}
else {
// Even though this is stored as identifier treat it as an expression
// Short-hand, { x }, is equivalent of normal form { x: x }
emitExpressionIdentifier(node.name);
}
}
else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) {
// Emit identifier as an identifier
write(": ");
// Even though this is stored as identifier treat it as an expression
// Short-hand, { x }, is equivalent of normal form { x: x }
emitExpressionIdentifier(node.name);
emit(node.name);
}
}
@ -1776,7 +1781,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
write(".");
let indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
}
@ -2781,8 +2786,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
write(", ");
}
renameNonTopLevelLetAndConst(name);
const isVariableDeclarationOrBindingElement =
name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement);
@ -2850,11 +2853,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression {
if (propName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression(object, propName);
// We create a synthetic copy of the identifier in order to avoid the rewriting that might
// otherwise occur when the identifier is emitted.
let syntheticName = <Identifier | LiteralExpression>createSynthesizedNode(propName.kind);
syntheticName.text = propName.text;
if (syntheticName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression(object, syntheticName);
}
return createPropertyAccessExpression(object, propName);
return createPropertyAccessExpression(object, syntheticName);
}
function createSliceCall(value: Expression, sliceIndex: number): CallExpression {
@ -2876,8 +2882,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
for (let p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
// TODO(andersh): Computed property support
let propName = <Identifier | LiteralExpression>((<PropertyAssignment>p).name);
let propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
}
}
@ -2991,8 +2996,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
else {
renameNonTopLevelLetAndConst(<Identifier>node.name);
let initializer = node.initializer;
if (!initializer && languageVersion < ScriptTarget.ES6) {
@ -3052,54 +3055,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
return getCombinedNodeFlags(node.parent);
}
function renameNonTopLevelLetAndConst(node: Node): void {
// do not rename if
// - language version is ES6+
// - node is synthesized
// - node is not identifier (can happen when tree is malformed)
// - node is definitely not name of variable declaration.
// it still can be part of parameter declaration, this check will be done next
if (languageVersion >= ScriptTarget.ES6 ||
nodeIsSynthesized(node) ||
node.kind !== SyntaxKind.Identifier ||
(node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) {
return;
}
let combinedFlags = getCombinedFlagsForIdentifier(<Identifier>node);
if (((combinedFlags & NodeFlags.BlockScoped) === 0) || combinedFlags & NodeFlags.Export) {
// do not rename exported or non-block scoped variables
return;
}
// here it is known that node is a block scoped variable
let list = getAncestor(node, SyntaxKind.VariableDeclarationList);
if (list.parent.kind === SyntaxKind.VariableStatement) {
let isSourceFileLevelBinding = list.parent.parent.kind === SyntaxKind.SourceFile;
let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleBlock;
let isFunctionLevelBinding =
list.parent.parent.kind === SyntaxKind.Block && isFunctionLike(list.parent.parent.parent);
if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) {
return;
}
}
let blockScopeContainer = getEnclosingBlockScopeContainer(node);
let parent = blockScopeContainer.kind === SyntaxKind.SourceFile
? blockScopeContainer
: blockScopeContainer.parent;
if (resolver.resolvesToSomeValue(parent, (<Identifier>node).text)) {
let variableId = resolver.getBlockScopedVariableId(<Identifier>node);
if (!blockScopedVariableToGeneratedName) {
blockScopedVariableToGeneratedName = [];
}
let generatedName = makeUniqueName((<Identifier>node).text);
blockScopedVariableToGeneratedName[variableId] = generatedName;
}
}
function isES6ExportedDeclaration(node: Node) {
return !!(node.flags & NodeFlags.Export) &&
languageVersion >= ScriptTarget.ES6 &&
@ -3263,7 +3218,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
function emitAccessor(node: AccessorDeclaration) {
write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
emitSignatureAndBody(node);
}
@ -4366,7 +4321,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let argumentsWritten = 0;
if (compilerOptions.emitDecoratorMetadata) {
if (shouldEmitTypeMetadata(node)) {
var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
var serializedType = resolver.serializeTypeOfNode(node);
if (serializedType) {
if (writeComma) {
write(", ");
@ -4379,7 +4334,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
if (shouldEmitParamTypesMetadata(node)) {
var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
var serializedTypes = resolver.serializeParameterTypesOfNode(node);
if (serializedTypes) {
if (writeComma || argumentsWritten) {
write(", ");
@ -4397,7 +4352,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
if (shouldEmitReturnTypeMetadata(node)) {
var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
var serializedType = resolver.serializeReturnTypeOfNode(node);
if (serializedType) {
if (writeComma || argumentsWritten) {
write(", ");
@ -4995,13 +4950,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function getLocalNameForExternalImport(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
let namespaceDeclaration = getNamespaceDeclarationNode(importNode);
if (namespaceDeclaration && !isDefaultImport(importNode)) {
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
let namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
}
else {
return getGeneratedNameForNode(<ImportDeclaration | ExportDeclaration>importNode);
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
}
@ -5790,7 +5748,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitLeadingComments(node.endOfFileToken);
}
function emitNodeWithoutSourceMap(node: Node, allowGeneratedIdentifiers?: boolean): void {
function emitNodeWithoutSourceMap(node: Node): void {
if (!node) {
return;
}
@ -5804,7 +5762,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitLeadingComments(node);
}
emitJavaScriptWorker(node, allowGeneratedIdentifiers);
emitJavaScriptWorker(node);
if (emitComments) {
emitTrailingComments(node);
@ -5854,11 +5812,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
return true;
}
function emitJavaScriptWorker(node: Node, allowGeneratedIdentifiers: boolean = true) {
function emitJavaScriptWorker(node: Node) {
// Check if the node can be emitted regardless of the ScriptTarget
switch (node.kind) {
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node, allowGeneratedIdentifiers);
return emitIdentifier(<Identifier>node);
case SyntaxKind.Parameter:
return emitParameter(<ParameterDeclaration>node);
case SyntaxKind.MethodDeclaration:

View file

@ -1420,7 +1420,10 @@ module ts {
/* @internal */
export interface EmitResolver {
hasGlobalName(name: string): boolean;
getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration;
getReferencedImportDeclaration(node: Identifier): Declaration;
getReferencedNestedRedeclaration(node: Identifier): Declaration;
isNestedRedeclaration(node: Declaration): boolean;
isValueAliasDeclaration(node: Node): boolean;
isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean;
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
@ -1435,12 +1438,11 @@ module ts {
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
resolvesToSomeValue(location: Node, name: string): boolean;
getBlockScopedVariableId(node: Identifier): number;
getReferencedValueDeclaration(reference: Identifier): Declaration;
serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[];
serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
serializeTypeOfNode(node: Node): string | string[];
serializeParameterTypesOfNode(node: Node): (string | string[])[];
serializeReturnTypeOfNode(node: Node): string | string[];
}
export const enum SymbolFlags {
@ -1517,6 +1519,8 @@ module ts {
HasExports = Class | Enum | Module,
HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
BlockScoped = BlockScopedVariable | Class | Enum,
PropertyOrAccessor = Property | Accessor,
Export = ExportNamespace | ExportType | ExportValue,
}
@ -1548,6 +1552,7 @@ module ts {
unionType?: UnionType; // Containing union type for union property
resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
}
/* @internal */

View file

@ -11,7 +11,7 @@ for (let v of []) {
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var v = _a[_i];
v;
for (var _b = 0, _c = [v]; _b < _c.length; _b++) {
for (var _b = 0, _c = [v_1]; _b < _c.length; _b++) {
var v_1 = _c[_b];
var x = v_1;
v_1++;

View file

@ -10,7 +10,7 @@ for (let v of []) {
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var v = _a[_i];
var v_1;
for (var _b = 0, _c = [v]; _b < _c.length; _b++) {
for (var _b = 0, _c = [v_2]; _b < _c.length; _b++) {
var v_2 = _c[_b];
var v_3;
}

View file

@ -14,9 +14,9 @@ var C = (function () {
return C;
})();
{
var C = (function () {
function C() {
var C_1 = (function () {
function C_1() {
}
return C;
return C_1;
})();
}

View file

@ -18,12 +18,12 @@ function f() {
})();
var c1 = C;
{
var C = (function () {
function C() {
var C_1 = (function () {
function C_1() {
}
return C;
return C_1;
})();
var c2 = C;
var c2 = C_1;
}
return C === c1;
}

View file

@ -40,25 +40,25 @@ define(["require", "exports"], function (require, exports) {
exports.v1 = exports.v;
function f() { }
exports.f = f;
exports.f1 = exports.f;
exports.f1 = f;
var C = (function () {
function C() {
}
return C;
})();
exports.C = C;
exports.C1 = exports.C;
exports.C1 = C;
(function (E) {
E[E["A"] = 0] = "A";
E[E["B"] = 1] = "B";
E[E["C"] = 2] = "C";
})(exports.E || (exports.E = {}));
var E = exports.E;
exports.E1 = exports.E;
exports.E1 = E;
var M;
(function (M) {
})(M = exports.M || (exports.M = {}));
exports.M1 = exports.M;
exports.M1 = M;
exports.a = M.x;
exports.a1 = exports.a;
});

View file

@ -39,25 +39,25 @@ exports.v = 1;
exports.v1 = exports.v;
function f() { }
exports.f = f;
exports.f1 = exports.f;
exports.f1 = f;
var C = (function () {
function C() {
}
return C;
})();
exports.C = C;
exports.C1 = exports.C;
exports.C1 = C;
(function (E) {
E[E["A"] = 0] = "A";
E[E["B"] = 1] = "B";
E[E["C"] = 2] = "C";
})(exports.E || (exports.E = {}));
var E = exports.E;
exports.E1 = exports.E;
exports.E1 = E;
var M;
(function (M) {
})(M = exports.M || (exports.M = {}));
exports.M1 = exports.M;
exports.M1 = M;
exports.a = M.x;
exports.a1 = exports.a;
//// [t2.js]

View file

@ -202,12 +202,12 @@ function f3(b) {
return a;
}
else {
var A = (function () {
function A() {
var A_1 = (function () {
function A_1() {
}
return A;
return A_1;
})();
var c = [new A()];
var c = [new A_1()];
c[0].x = E.B;
return c;
}

View file

@ -18,7 +18,7 @@ var m2;
_super.apply(this, arguments);
}
return class1;
})(mExported.me.class1);
})(m2.mExported.me.class1);
m2.class1 = class1;
var c2 = new m2.mExported.me.class1;
function f2() {
@ -31,7 +31,7 @@ var m2;
_super.apply(this, arguments);
}
return class2;
})(mExported.me.class1);
})(m2.mExported.me.class1);
m2.c3 = new mNonExported.mne.class1;
function f3() {
return new mNonExported.mne.class1();

View file

@ -18,7 +18,7 @@ var m2;
_super.apply(this, arguments);
}
return class1;
})(mExported.me.class1);
})(m2.mExported.me.class1);
m2.class1 = class1;
var c2 = new m2.mExported.me.class1;
function f2() {
@ -31,7 +31,7 @@ var m2;
_super.apply(this, arguments);
}
return class2;
})(mExported.me.class1);
})(m2.mExported.me.class1);
m2.c3 = new mNonExported.mne.class1;
function f3() {
return new mNonExported.mne.class1();