Merge branch 'transforms' into sourceMapUpdatesForClasses

This commit is contained in:
Ron Buckton
2016-04-14 11:28:23 -07:00
218 changed files with 1376 additions and 918 deletions
+26
View File
@@ -1910,6 +1910,17 @@ namespace ts {
// This is so that they can flow through PropertyName transforms unaffected.
// Instead, we mark the container as ES6, so that it can properly handle the transform.
transformFlags = TransformFlags.ContainsComputedPropertyName;
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
// A computed method name like `[this.getName()](x: string) { ... }` needs to
// distinguish itself from the normal case of a method body containing `this`:
// `this` inside a method doesn't need to be rewritten (the method provides `this`),
// whereas `this` inside a computed name *might* need to be rewritten if the class/object
// is inside an arrow function:
// `_this = this; () => class K { [_this.getName()]() { ... } }`
// To make this distinction, use ContainsLexicalThisInComputedPropertyName
// instead of ContainsLexicalThis for computed property names
transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName;
}
break;
case SyntaxKind.SpreadElementExpression:
@@ -1945,6 +1956,11 @@ namespace ts {
// is an ES6 node.
transformFlags = TransformFlags.AssertES6;
}
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}
break;
case SyntaxKind.CallExpression:
@@ -2256,6 +2272,11 @@ namespace ts {
|| hasModifier(node, ModifierFlags.Export)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
}
@@ -2272,6 +2293,11 @@ namespace ts {
| TransformFlags.ContainsDecorators)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
}
+90 -39
View File
@@ -1118,7 +1118,7 @@ namespace ts {
}
// Resolves a qualified name and any involved aliases
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean): Symbol {
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean, location?: Node): Symbol {
if (nodeIsMissing(name)) {
return undefined;
}
@@ -1127,7 +1127,7 @@ namespace ts {
if (name.kind === SyntaxKind.Identifier) {
const message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0;
symbol = resolveName(name, (<Identifier>name).text, meaning, ignoreErrors ? undefined : message, <Identifier>name);
symbol = resolveName(location || name, (<Identifier>name).text, meaning, ignoreErrors ? undefined : message, <Identifier>name);
if (!symbol) {
return undefined;
}
@@ -1136,7 +1136,7 @@ namespace ts {
const left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression>name).expression;
const right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, location);
if (!namespace || namespace === unknownSymbol || nodeIsMissing(right)) {
return undefined;
}
@@ -16042,7 +16042,14 @@ namespace ts {
// Emitter support
function isArgumentsLocalBinding(node: Identifier): boolean {
return getReferencedValueSymbol(node) === argumentsSymbol;
if (!isGeneratedIdentifier(node)) {
node = getSourceTreeNodeOfType(node, isIdentifier);
if (node) {
return getReferencedValueSymbol(node) === argumentsSymbol;
}
}
return false;
}
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
@@ -16077,37 +16084,49 @@ namespace ts {
// 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, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration {
let symbol = getReferencedValueSymbol(node);
if (symbol) {
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.
const exportSymbol = getMergedSymbol(symbol.exportSymbol);
if (exportSymbol.flags & SymbolFlags.ExportHasLocal && !prefixLocals) {
return undefined;
node = getSourceTreeNodeOfType(node, isIdentifier);
if (node) {
let symbol = getReferencedValueSymbol(node);
if (symbol) {
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.
const exportSymbol = getMergedSymbol(symbol.exportSymbol);
if (exportSymbol.flags & SymbolFlags.ExportHasLocal && !prefixLocals) {
return undefined;
}
symbol = exportSymbol;
}
symbol = exportSymbol;
}
const 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;
const 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;
}
}
}
}
}
return undefined;
}
// 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 {
const symbol = getReferencedValueSymbol(node);
return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined;
node = getSourceTreeNodeOfType(node, isIdentifier);
if (node) {
const symbol = getReferencedValueSymbol(node);
if (symbol && symbol.flags & SymbolFlags.Alias) {
return getDeclarationOfAliasSymbol(symbol);
}
}
return undefined;
}
function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean {
@@ -16157,35 +16176,57 @@ namespace ts {
// a name that either hides an existing name or might hide it when compiled downlevel,
// return the declaration of that entity. Otherwise, return undefined.
function getReferencedDeclarationWithCollidingName(node: Identifier): Declaration {
const symbol = getReferencedValueSymbol(node);
return symbol && isSymbolOfDeclarationWithCollidingName(symbol) ? symbol.valueDeclaration : undefined;
if (!isGeneratedIdentifier(node)) {
node = getSourceTreeNodeOfType(node, isIdentifier);
if (node) {
const symbol = getReferencedValueSymbol(node);
if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) {
return symbol.valueDeclaration;
}
}
}
return undefined;
}
// Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an
// existing name or might hide a name when compiled downlevel
function isDeclarationWithCollidingName(node: Declaration): boolean {
return isSymbolOfDeclarationWithCollidingName(getSymbolOfNode(node));
node = getSourceTreeNodeOfType(node, isDeclaration);
if (node) {
const symbol = getSymbolOfNode(node);
if (symbol) {
return isSymbolOfDeclarationWithCollidingName(symbol);
}
}
return false;
}
function isValueAliasDeclaration(node: Node): boolean {
node = getSourceTreeNode(node);
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return isAliasResolvedToValue(getSymbolOfNode(node));
return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol);
case SyntaxKind.ExportDeclaration:
const exportClause = (<ExportDeclaration>node).exportClause;
return exportClause && forEach(exportClause.elements, isValueAliasDeclaration);
case SyntaxKind.ExportAssignment:
return (<ExportAssignment>node).expression && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
return (<ExportAssignment>node).expression
&& (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier
? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol)
: true;
}
return false;
}
function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean {
if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
node = getSourceTreeNodeOfType(node, isImportEqualsDeclaration);
if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
// parent is not source file or it is not reference to internal module
return false;
}
@@ -16212,9 +16253,10 @@ namespace ts {
}
function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
node = getSourceTreeNode(node);
if (isAliasSymbolDeclaration(node)) {
const symbol = getSymbolOfNode(node);
if (getSymbolLinks(symbol).referenced) {
if (symbol && getSymbolLinks(symbol).referenced) {
return true;
}
}
@@ -16247,7 +16289,8 @@ namespace ts {
}
function getNodeCheckFlags(node: Node): NodeCheckFlags {
return getNodeLinks(node).flags;
node = getSourceTreeNode(node);
return node ? getNodeLinks(node).flags : undefined;
}
function getEnumMemberValue(node: EnumMember): number {
@@ -16275,16 +16318,16 @@ namespace ts {
return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0;
}
function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind {
function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true);
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, location);
const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
if (constructorType && isConstructorType(constructorType)) {
return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
}
// Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true);
const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, location);
// We might not be able to resolve type symbol so use unknown type in that case (eg error case)
if (!typeSymbol) {
return TypeReferenceSerializationKind.ObjectType;
@@ -16363,9 +16406,17 @@ namespace ts {
}
function getReferencedValueDeclaration(reference: Identifier): Declaration {
Debug.assert(!nodeIsSynthesized(reference));
const symbol = getReferencedValueSymbol(reference);
return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration;
if (!isGeneratedIdentifier(reference)) {
reference = getSourceTreeNodeOfType(reference, isIdentifier);
if (reference) {
const symbol = getReferencedValueSymbol(reference);
if (symbol) {
return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration;
}
}
}
return undefined;
}
function createResolver(): EmitResolver {
+5 -6
View File
@@ -333,11 +333,10 @@ namespace ts {
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
},
{
// this option will be removed when this is merged with master and exists solely
// to enable the tree transforming emitter side-by-side with the existing emitter.
name: "experimentalTransforms",
name: "useLegacyEmitter",
type: "boolean",
experimental: true
experimental: true,
description: Diagnostics.Use_the_legacy_emitter_instead_of_the_transforming_emitter
}
];
@@ -475,7 +474,7 @@ namespace ts {
}
function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) {
const key = (value || "").trim().toLowerCase();
const key = (value || "").toLowerCase();
const map = opt.type;
if (hasProperty(map, key)) {
return map[key];
@@ -486,7 +485,7 @@ namespace ts {
}
function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (string | number)[] {
const values = (value || "").trim().split(",");
const values = (value || "").split(",");
switch (opt.element.type) {
case "number":
return ts.map(values, parseInt);
+2 -2
View File
@@ -1105,11 +1105,11 @@ namespace ts {
return currentAssertionLevel;
}
const developmentMode = sys && /^development$/i.test(sys.getEnvironmentVariable("NODE_ENV"));
if (developmentMode === undefined) {
if (sys === undefined) {
return AssertionLevel.None;
}
const developmentMode = /^development$/i.test(getEnvironmentVariable("NODE_ENV"));
currentAssertionLevel = developmentMode
? AssertionLevel.Normal
: AssertionLevel.None;
+4
View File
@@ -2604,6 +2604,10 @@
"category": "Message",
"code": 6112
},
"Use the legacy emitter instead of the transforming emitter.": {
"category": "Message",
"code": 6113
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+19 -12
View File
@@ -2240,41 +2240,49 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
emit(node.right);
}
function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean) {
function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean, location?: Node) {
if (node.left.kind === SyntaxKind.Identifier) {
emitEntityNameAsExpression(node.left, useFallback);
emitEntityNameAsExpression(node.left, useFallback, location);
}
else if (useFallback) {
const temp = createAndRecordTempVariable(TempFlags.Auto);
write("(");
emitNodeWithoutSourceMap(temp);
write(" = ");
emitEntityNameAsExpression(node.left, /*useFallback*/ true);
emitEntityNameAsExpression(node.left, /*useFallback*/ true, location);
write(") && ");
emitNodeWithoutSourceMap(temp);
}
else {
emitEntityNameAsExpression(node.left, /*useFallback*/ false);
emitEntityNameAsExpression(node.left, /*useFallback*/ false, location);
}
write(".");
emit(node.right);
}
function emitEntityNameAsExpression(node: EntityName | Expression, useFallback: boolean) {
function emitEntityNameAsExpression(node: EntityName | Expression, useFallback: boolean, location?: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
let name = <Identifier>node;
if (location) {
// to resolve the expression to the correct container, create a shallow
// clone of `node` with a new parent.
name = clone(name);
name.parent = location;
}
if (useFallback) {
write("typeof ");
emitExpressionIdentifier(<Identifier>node);
emitExpressionIdentifier(name);
write(" !== 'undefined' && ");
}
emitExpressionIdentifier(<Identifier>node);
emitExpressionIdentifier(name);
break;
case SyntaxKind.QualifiedName:
emitQualifiedNameAsExpression(<QualifiedName>node, useFallback);
emitQualifiedNameAsExpression(<QualifiedName>node, useFallback, location);
break;
default:
@@ -5943,22 +5951,21 @@ const _super = (function (geti, seti) {
}
// Clone the type name and parent it to a location outside of the current declaration.
const typeName = cloneEntityName(node.typeName, location);
const result = resolver.getTypeReferenceSerializationKind(typeName);
const result = resolver.getTypeReferenceSerializationKind(node.typeName, location);
switch (result) {
case TypeReferenceSerializationKind.Unknown:
let temp = createAndRecordTempVariable(TempFlags.Auto);
write("(typeof (");
emitNodeWithoutSourceMap(temp);
write(" = ");
emitEntityNameAsExpression(typeName, /*useFallback*/ true);
emitEntityNameAsExpression(node.typeName, /*useFallback*/ true, location);
write(") === 'function' && ");
emitNodeWithoutSourceMap(temp);
write(") || Object");
break;
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
emitEntityNameAsExpression(typeName, /*useFallback*/ false);
emitEntityNameAsExpression(node.typeName, /*useFallback*/ false, location);
break;
case TypeReferenceSerializationKind.VoidType:
+89 -7
View File
@@ -1163,11 +1163,11 @@ namespace ts {
let thisArg: Expression;
let target: LeftHandSideExpression;
if (isSuperProperty(callee)) {
thisArg = createThis(/*location*/ callee.expression);
thisArg = createThis();
target = callee;
}
else if (callee.kind === SyntaxKind.SuperKeyword) {
thisArg = createThis(/*location*/ callee);
thisArg = createThis();
target = languageVersion < ScriptTarget.ES6 ? createIdentifier("_super", /*location*/ callee) : <PrimaryExpression>callee;
}
else {
@@ -1180,15 +1180,15 @@ namespace ts {
createAssignment(
thisArg,
(<PropertyAccessExpression>callee).expression,
/*location*/(<PropertyAccessExpression>callee).expression
/*location*/ (<PropertyAccessExpression>callee).expression
),
(<PropertyAccessExpression>callee).name,
/*location*/ callee
/*location*/ callee
);
}
else {
thisArg = (<PropertyAccessExpression>callee).expression;
target = <PropertyAccessExpression>callee;
target = <PropertyAccessExpression>callee;
}
break;
}
@@ -1201,10 +1201,10 @@ namespace ts {
createAssignment(
thisArg,
(<ElementAccessExpression>callee).expression,
/*location*/(<ElementAccessExpression>callee).expression
/*location*/ (<ElementAccessExpression>callee).expression
),
(<ElementAccessExpression>callee).argumentExpression,
/*location*/ callee
/*location*/ callee
);
}
else {
@@ -1252,7 +1252,18 @@ namespace ts {
return (node.expression as StringLiteral).text === "use strict";
}
/**
* Add any necessary prologue-directives into target statement-array.
* The function needs to be called during each transformation step.
* This function needs to be called whenever we transform the statement
* list of a source file, namespace, or function-like body.
*
* @param target: result statements array
* @param source: origin statements array
* @param ensureUseStrict: boolean determining whether the function need to add prologue-directives
*/
export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): number {
Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
let foundUseStrict = false;
for (let i = 0; i < source.length; i++) {
if (isPrologueDirective(source[i])) {
@@ -1707,4 +1718,75 @@ namespace ts {
nodes.hasTrailingComma = hasTrailingComma;
return nodes;
}
/**
* Get the name of that target module from an import or export declaration
*/
export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name));
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
return undefined;
}
/**
* Get the name of a target module from an import/export declaration as should be written in the emitted output.
* The emitted output name can be different from the input if:
* 1. The module has a /// <amd-module name="<new name>" />
* 2. --out or --outFile is used, making the name relative to the rootDir
* 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System).
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions)
|| tryRenameExternalModule(<StringLiteral>moduleName, sourceFile)
|| getSynthesizedClone(<StringLiteral>moduleName);
}
return undefined;
}
/**
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression, sourceFile: SourceFile) {
if (sourceFile.renamedDependencies && hasProperty(sourceFile.renamedDependencies, moduleName.text)) {
return createLiteral(sourceFile.renamedDependencies[moduleName.text]);
}
return undefined;
}
/**
* Get the name of a module as should be written in the emitted output.
* The emitted output name can be different from the input if:
* 1. The module has a /// <amd-module name="<new name>" />
* 2. --out or --outFile is used, making the name relative to the rootDir
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function tryGetModuleNameFromFile(file: SourceFile, host: EmitHost, options: CompilerOptions): StringLiteral {
if (!file) {
return undefined;
}
if (file.moduleName) {
return createLiteral(file.moduleName);
}
if (!isDeclarationFile(file) && (options.out || options.outFile)) {
return createLiteral(getExternalModuleNameFromPath(host, file.fileName));
}
return undefined;
}
function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions);
}
}
+7 -3
View File
@@ -1642,8 +1642,10 @@ const _super = (function (geti, seti) {
function emitImportDeclaration(node: ImportDeclaration) {
emitModifiers(node, node.modifiers);
write("import ");
emit(node.importClause);
write(" from ");
if (node.importClause) {
emit(node.importClause);
write(" from ");
}
emitExpression(node.moduleSpecifier);
write(";");
}
@@ -2605,8 +2607,10 @@ const _super = (function (geti, seti) {
function getSourceNodeForGeneratedName(name: Identifier) {
let node: Node = name;
while (node.original !== undefined) {
const nodeId = node.id;
node = node.original;
if (isIdentifier(node) && node.autoGenerateKind === GeneratedIdentifierKind.Node) {
// If "node" is not the exact clone of "original" identifier, use "original" identifier to generate the name
if (isIdentifier(node) && node.autoGenerateKind === GeneratedIdentifierKind.Node && node.id !== nodeId) {
break;
}
}
+6 -4
View File
@@ -644,7 +644,8 @@ namespace ts {
fileExists: fileName => sys.fileExists(fileName),
readFile: fileName => sys.readFile(fileName),
trace: (s: string) => sys.write(s + newLine),
directoryExists: directoryName => sys.directoryExists(directoryName)
directoryExists: directoryName => sys.directoryExists(directoryName),
getEnvironmentVariable: name => getEnvironmentVariable(name, /*host*/ undefined)
};
}
@@ -995,11 +996,12 @@ namespace ts {
const start = new Date().getTime();
// TODO(rbuckton): remove USE_TRANSFORMS condition when we switch to transforms permanently.
if (/^(y(es)?|t(rue|ransforms?)?|1|\+)$/i.test(sys.getEnvironmentVariable("USE_TRANSFORMS"))) {
options.experimentalTransforms = true;
let useLegacyEmitter = options.useLegacyEmitter;
if (/^(no?|f(alse)?|0|-)$/i.test(getEnvironmentVariable("USE_TRANSFORMS", host))) {
useLegacyEmitter = true;
}
const fileEmitter = options.experimentalTransforms ? printFiles : emitFiles;
const fileEmitter = useLegacyEmitter ? emitFiles : printFiles;
const emitResult = fileEmitter(
emitResolver,
getEmitHost(writeFileCallback),
+2 -3
View File
@@ -74,6 +74,7 @@ namespace ts {
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
getEnvironmentVariable?(name: string): string;
};
export var sys: System = (function () {
@@ -632,9 +633,7 @@ namespace ts {
createDirectory: ChakraHost.createDirectory,
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
getEnvironmentVariable(name: string) {
return "";
},
getEnvironmentVariable: ChakraHost.getEnvironmentVariable || ((name: string) => ""),
readDirectory: ChakraHost.readDirectory,
exit: ChakraHost.quit,
};
+1
View File
@@ -68,6 +68,7 @@ namespace ts {
const context: TransformationContext = {
getCompilerOptions: () => host.getCompilerOptions(),
getEmitResolver: () => resolver,
getEmitHost: () => host,
getNodeEmitFlags,
setNodeEmitFlags,
hoistVariableDeclaration,
+9 -3
View File
@@ -17,10 +17,16 @@ namespace ts {
node: BinaryExpression,
needsValue: boolean,
recordTempVariable: (node: Identifier) => void,
visitor?: (node: Node) => VisitResult<Node>) {
visitor?: (node: Node) => VisitResult<Node>): Expression {
if (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
return node.right;
const right = node.right;
if (isDestructuringAssignment(right)) {
return flattenDestructuringAssignment(context, right, needsValue, recordTempVariable, visitor);
}
else {
return node.right;
}
}
let location: TextRange = node;
@@ -401,4 +407,4 @@ namespace ts {
return emitTempVariableAssignment(value, location);
}
}
}
}
+48 -23
View File
@@ -467,7 +467,7 @@ namespace ts {
if (isGeneratedIdentifier(node)) {
return node;
}
if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(<Identifier>getOriginalNode(node))) {
if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(node)) {
return node;
}
return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments"));
@@ -549,7 +549,7 @@ namespace ts {
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getDeclarationName(node),
getDeclarationName(node, /*allowComments*/ true),
transformClassLikeDeclarationToExpression(node)
)
]),
@@ -739,7 +739,14 @@ namespace ts {
}
addRange(statements, endLexicalEnvironment());
return createBlock(statements, /*location*/ constructor && constructor.body, /*multiLine*/ true);
return createBlock(
createNodeArray(
statements,
/*location*/ constructor ? constructor.body.statements : undefined
),
/*location*/ constructor ? constructor.body : undefined,
/*multiLine*/ true
);
}
function transformConstructorBodyWithSynthesizedSuper(node: ConstructorDeclaration) {
@@ -928,7 +935,7 @@ namespace ts {
* synthesized call to `super`
*/
function shouldAddRestParameter(node: ParameterDeclaration, inConstructorWithSynthesizedSuper: boolean) {
return node && node.dotDotDotToken && !inConstructorWithSynthesizedSuper;
return node && node.dotDotDotToken && node.name.kind === SyntaxKind.Identifier && !inConstructorWithSynthesizedSuper;
}
/**
@@ -1208,7 +1215,15 @@ namespace ts {
let statementsLocation: TextRange;
const statements: Statement[] = [];
const body = node.body;
let statementOffset: number;
startLexicalEnvironment();
if (isBlock(body)) {
// ensureUseStrict is false because no new prologue-directive should be added.
// addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array
statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false);
}
addCaptureThisForNodeIfNeeded(statements, node);
addDefaultValueAssignmentsIfNeeded(statements, node);
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
@@ -1218,10 +1233,9 @@ namespace ts {
multiLine = true;
}
const body = node.body;
if (isBlock(body)) {
statementsLocation = body.statements;
addRange(statements, visitNodes(body.statements, visitor, isStatement));
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
// If the original body was a multi-line block, this must be a multi-line block.
if (!multiLine && body.multiLine) {
@@ -1423,10 +1437,7 @@ namespace ts {
// * Why loop initializer is excluded?
// - Since we've introduced a fresh name it already will be undefined.
const original = getOriginalNode(node);
Debug.assert(isVariableDeclaration(original));
const flags = resolver.getNodeCheckFlags(original);
const flags = resolver.getNodeCheckFlags(node);
const isCapturedInFunction = flags & NodeCheckFlags.CapturedBlockScopedBinding;
const isDeclaredInLoop = flags & NodeCheckFlags.BlockScopedBindingInLoop;
const emittedAsTopLevel =
@@ -1440,7 +1451,7 @@ namespace ts {
!emittedAsTopLevel
&& enclosingBlockScopeContainer.kind !== SyntaxKind.ForInStatement
&& enclosingBlockScopeContainer.kind !== SyntaxKind.ForOfStatement
&& (!resolver.isDeclarationWithCollidingName(<Declaration>original)
&& (!resolver.isDeclarationWithCollidingName(node)
|| (isDeclaredInLoop
&& !isCapturedInFunction
&& !isIterationStatement(enclosingBlockScopeContainer, /*lookInLabeledStatements*/ false)));
@@ -1718,7 +1729,7 @@ namespace ts {
}
function shouldConvertIterationStatementBody(node: IterationStatement): boolean {
return (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0;
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0;
}
/**
@@ -2611,8 +2622,8 @@ namespace ts {
// Only substitute the identifier if we have enabled substitutions for block-scoped
// bindings.
if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) {
const original = getOriginalNode(node);
if (isIdentifier(original) && !nodeIsSynthesized(original) && original.parent && isNameOfDeclarationWithCollidingName(original)) {
const original = getSourceTreeNodeOfType(node, isIdentifier);
if (original && isNameOfDeclarationWithCollidingName(original)) {
return getGeneratedNameForNode(original);
}
}
@@ -2665,12 +2676,9 @@ namespace ts {
*/
function substituteExpressionIdentifier(node: Identifier): Identifier {
if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) {
const original = getOriginalNode(node);
if (isIdentifier(original)) {
const declaration = resolver.getReferencedDeclarationWithCollidingName(original);
if (declaration) {
return getGeneratedNameForNode(declaration.name);
}
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
if (declaration) {
return getGeneratedNameForNode(declaration.name);
}
}
@@ -2690,8 +2698,25 @@ namespace ts {
return node;
}
function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) {
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
/**
* Gets the name of a declaration, without source map or comments.
*
* @param node The declaration.
* @param allowComments Allow comments for the name.
*/
function getDeclarationName(node: DeclarationStatement | ClassExpression, allowComments?: boolean) {
if (node.name) {
const name = getMutableClone(node.name);
let flags = NodeEmitFlags.NoSourceMap;
if (!allowComments) {
flags |= NodeEmitFlags.NoComments;
}
setNodeEmitFlags(name, flags | getNodeEmitFlags(name));
return name;
}
return getGeneratedNameForNode(node);
}
function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) {
@@ -2733,4 +2758,4 @@ namespace ts {
return isIdentifier(expression) && expression === parameter.name;
}
}
}
}
+50
View File
@@ -23,6 +23,8 @@ namespace ts {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return visitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ImportClause:
return visitImportClause(<ImportClause>node);
case SyntaxKind.NamedImports:
@@ -30,11 +32,59 @@ namespace ts {
return visitNamedBindings(<NamedImportBindings>node);
case SyntaxKind.ImportSpecifier:
return visitImportSpecifier(<ImportSpecifier>node);
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
case SyntaxKind.ExportDeclaration:
return visitExportDeclaration(<ExportDeclaration>node);
case SyntaxKind.NamedExports:
return visitNamedExports(<NamedExports>node);
case SyntaxKind.ExportSpecifier:
return visitExportSpecifier(<ExportSpecifier>node);
}
return node;
}
function visitExportAssignment(node: ExportAssignment): ExportAssignment {
if (node.isExportEquals) {
return undefined; // do not emit export equals for ES6
}
const original = getOriginalNode(node);
return nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original) ? node: undefined;
}
function visitExportDeclaration(node: ExportDeclaration): ExportDeclaration {
if (!node.exportClause) {
return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined;
}
if (!resolver.isValueAliasDeclaration(node)) {
return undefined;
}
const newExportClause = visitNode(node.exportClause, visitor, isNamedExports, /*optional*/ true);
if (node.exportClause === newExportClause) {
return node;
}
return newExportClause
? createExportDeclaration(newExportClause, node.moduleSpecifier)
: undefined;
}
function visitNamedExports(node: NamedExports): NamedExports {
const newExports = visitNodes(node.elements, visitor, isExportSpecifier);
if (node.elements === newExports) {
return node;
}
return newExports.length ? createNamedExports(newExports) : undefined;
}
function visitExportSpecifier(node: ExportSpecifier): ExportSpecifier {
return resolver.isValueAliasDeclaration(node) ? node : undefined;
}
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): ImportEqualsDeclaration {
return !isExternalModuleImportEqualsDeclaration(node) || resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
function visitImportDeclaration(node: ImportDeclaration) {
if (node.importClause) {
const newImportClause = visitNode(node.importClause, visitor, isImportClause);
+65 -80
View File
@@ -21,6 +21,7 @@ namespace ts {
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
const host = context.getEmitHost();
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const previousExpressionSubstitution = context.expressionSubstitution;
@@ -31,7 +32,7 @@ namespace ts {
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let hasExportStars: boolean;
let hasExportStarsToExportValues: boolean;
return transformSourceFile;
@@ -45,7 +46,7 @@ namespace ts {
currentSourceFile = node;
// Collect information about the external module.
({ externalImports, exportSpecifiers, exportEquals, hasExportStars } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
// Perform the transformation.
const updated = transformModuleDelegates[moduleKind](node);
@@ -55,7 +56,7 @@ namespace ts {
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = false;
hasExportStarsToExportValues = false;
return updated;
}
@@ -77,7 +78,7 @@ namespace ts {
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
const updated = updateSourceFile(node, statements);
if (hasExportStars) {
if (hasExportStarsToExportValues) {
setNodeEmitFlags(updated, NodeEmitFlags.EmitExportStar | getNodeEmitFlags(node));
}
@@ -91,7 +92,7 @@ namespace ts {
*/
function transformAMDModule(node: SourceFile) {
const define = createIdentifier("define");
const moduleName = node.moduleName ? createLiteral(node.moduleName) : undefined;
const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions);
return transformAsynchronousModule(node, define, moduleName, /*includeNonAmdDependencies*/ true);
}
@@ -200,7 +201,7 @@ namespace ts {
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
if (hasExportStars) {
if (hasExportStarsToExportValues) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
setNodeEmitFlags(body, NodeEmitFlags.EmitExportStar);
@@ -357,6 +358,9 @@ namespace ts {
return undefined;
}
// Set emitFlags on the name of the importEqualsDeclaration
// This is so the printer will not substitute the identifier
setNodeEmitFlags(node.name, NodeEmitFlags.NoSubstitution);
const statements: Statement[] = [];
if (moduleKind !== ModuleKind.AMD) {
if (hasModifier(node, ModifierFlags.Export)) {
@@ -442,7 +446,7 @@ namespace ts {
return singleOrMany(statements);
}
else {
else if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) {
// export * from "mod";
return createStatement(
createCall(
@@ -460,8 +464,7 @@ namespace ts {
function visitExportAssignment(node: ExportAssignment): VisitResult<Statement> {
if (!node.isExportEquals) {
const original = getOriginalNode(node);
if (nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original)) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
@@ -553,7 +556,7 @@ namespace ts {
}
else {
statements.push(
createExportStatement(node.name, node.name, /*location*/ node)
createExportStatement(node.name, setNodeEmitFlags(getSynthesizedClone(node.name), NodeEmitFlags.LocalName), /*location*/ node)
);
}
}
@@ -639,6 +642,9 @@ namespace ts {
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
const statements: Statement[] = [];
const name = node.name || getGeneratedNameForNode(node);
// Set emitFlags on the name of the classDeclaration
// This is so that when printer will not substitute the identifier
setNodeEmitFlags(name, NodeEmitFlags.NoSubstitution);
if (hasModifier(node, ModifierFlags.Export)) {
statements.push(
createClassDeclaration(
@@ -713,40 +719,50 @@ namespace ts {
}
function substituteExpressionIdentifier(node: Identifier): Expression {
const original = getOriginalNode(node);
if (isIdentifier(original)) {
const container = resolver.getReferencedExportContainer(original, (getNodeEmitFlags(node) & NodeEmitFlags.PrefixExportedLocal) !== 0);
if (container) {
if (container.kind === SyntaxKind.SourceFile) {
return createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(node),
/*location*/ node
);
}
if (getNodeEmitFlags(node) & NodeEmitFlags.LocalName) {
return node;
}
const container = resolver.getReferencedExportContainer(node, (getNodeEmitFlags(node) & NodeEmitFlags.ExportName) !== 0);
if (container) {
if (container.kind === SyntaxKind.SourceFile) {
return createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(node),
/*location*/ node
);
}
else {
const declaration = resolver.getReferencedImportDeclaration(node.parent ? node : original);
if (declaration) {
if (declaration.kind === SyntaxKind.ImportClause) {
if (languageVersion >= ScriptTarget.ES5) {
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent),
createIdentifier("default"),
/*location*/ node
);
}
else {
return createElementAccess(
getGeneratedNameForNode(declaration.parent),
createLiteral("default"),
/*location*/ node
);
}
}
else {
const declaration = resolver.getReferencedImportDeclaration(node);
if (declaration) {
if (declaration.kind === SyntaxKind.ImportClause) {
if (languageVersion >= ScriptTarget.ES5) {
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent),
createIdentifier("default"),
/*location*/ node
);
}
else if (declaration.kind === SyntaxKind.ImportSpecifier) {
const name = (<ImportSpecifier>declaration).propertyName
|| (<ImportSpecifier>declaration).name;
else {
return createElementAccess(
getGeneratedNameForNode(declaration.parent),
createLiteral("default"),
/*location*/ node
);
}
}
else if (declaration.kind === SyntaxKind.ImportSpecifier) {
const name = (<ImportSpecifier>declaration).propertyName
|| (<ImportSpecifier>declaration).name;
if (name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion <= ScriptTarget.ES3) {
return createElementAccess(
getGeneratedNameForNode(declaration.parent.parent.parent),
createLiteral(name.text),
/*location*/ node
);
}
else {
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent.parent.parent),
getSynthesizedClone(name),
@@ -768,42 +784,8 @@ namespace ts {
);
}
function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<StringLiteral>moduleName)
|| createLiteral(<StringLiteral>moduleName);
}
return undefined;
}
/**
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression) {
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
return createLiteral(currentSourceFile.renamedDependencies[moduleName.text]);
}
return undefined;
}
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): Identifier {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return createIdentifier(getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name));
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
}
function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
const moduleName = getExternalModuleNameLiteral(importNode);
const moduleName = getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions);
const args: Expression[] = [];
if (isDefined(moduleName)) {
args.push(moduleName);
@@ -818,7 +800,7 @@ namespace ts {
function createExportAssignment(name: Identifier, value: Expression) {
return createAssignment(
name.originalKeywordKind && languageVersion === ScriptTarget.ES3
name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion === ScriptTarget.ES3
? createElementAccess(
createIdentifier("exports"),
createLiteral(name.text)
@@ -862,11 +844,14 @@ namespace ts {
for (const importNode of externalImports) {
// Find the name of the external module
const externalModuleName = getExternalModuleNameLiteral(importNode);
const externalModuleName = getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions);
// Find the name of the module alias, if there is one
const importAliasName = getLocalNameForExternalImport(importNode);
const importAliasName = getLocalNameForExternalImport(importNode, currentSourceFile);
if (includeNonAmdDependencies && importAliasName) {
// Set emitFlags on the name of the classDeclaration
// This is so that when printer will not substitute the identifier
setNodeEmitFlags(importAliasName, NodeEmitFlags.NoSubstitution);
aliasedModuleNames.push(externalModuleName);
importAliasNames.push(createParameter(importAliasName));
}
+22 -53
View File
@@ -10,6 +10,7 @@ namespace ts {
}
const {
getNodeEmitFlags,
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
@@ -19,6 +20,7 @@ namespace ts {
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
const host = context.getEmitHost();
const languageVersion = getEmitScriptTarget(compilerOptions);
const previousExpressionSubstitution = context.expressionSubstitution;
context.enableExpressionSubstitution(SyntaxKind.Identifier);
@@ -37,7 +39,7 @@ namespace ts {
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let hasExportStars: boolean;
let hasExportStarsToExportValues: boolean;
let exportFunctionForFile: Identifier;
let contextObjectForFile: Identifier;
let exportedLocalNames: Identifier[];
@@ -62,7 +64,7 @@ namespace ts {
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = false;
hasExportStarsToExportValues = false;
exportFunctionForFile = undefined;
contextObjectForFile = undefined;
exportedLocalNames = undefined;
@@ -89,7 +91,7 @@ namespace ts {
Debug.assert(!exportFunctionForFile);
// Collect information about the external module and dependency groups.
({ externalImports, exportSpecifiers, exportEquals, hasExportStars } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
@@ -105,6 +107,7 @@ namespace ts {
// Add the body of the module.
addSystemModuleBody(statements, node, dependencyGroups);
const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions);
const dependencies = createArrayLiteral(map(dependencyGroups, getNameOfDependencyGroup));
const body = createFunctionExpression(
/*asteriskToken*/ undefined,
@@ -120,16 +123,18 @@ namespace ts {
);
// Write the call to `System.register`
// Clear the emit-helpers flag for later passes since we'll have already used it in the module body
// So the helper will be emit at the correct position instead of at the top of the source-file
return updateSourceFile(node, [
createStatement(
createCall(
createPropertyAccess(createIdentifier("System"), "register"),
node.moduleName
? [createLiteral(node.moduleName), dependencies, body]
moduleName
? [moduleName, dependencies, body]
: [dependencies, body]
)
)
]);
], /*nodeEmitFlags*/ ~NodeEmitFlags.EmitEmitHelpers & getNodeEmitFlags(node));
}
/**
@@ -188,7 +193,7 @@ namespace ts {
startLexicalEnvironment();
// Add any prologue directives.
const statementOffset = addPrologueDirectives(statements, node.statements, !compilerOptions.noImplicitUseStrict);
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
// var __moduleName = context_1 && context_1.id;
addNode(statements,
@@ -253,7 +258,7 @@ namespace ts {
}
function addExportStarIfNeeded(statements: Statement[]) {
if (!hasExportStars) {
if (!hasExportStarsToExportValues) {
return;
}
// when resolving exports local exported entries/indirect exported entries in the module
@@ -338,11 +343,11 @@ namespace ts {
const setters: Expression[] = [];
for (const group of dependencyGroups) {
// derive a unique name for parameter from the first named entry in the group
const localName = forEach(group.externalImports, getLocalNameForExternalImport);
const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(i, currentSourceFile));
const parameterName = localName ? getGeneratedNameForNode(localName) : createUniqueName("");
const statements: Statement[] = [];
for (const entry of group.externalImports) {
const importVariableName = getLocalNameForExternalImport(entry);
const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile);
switch (entry.kind) {
case SyntaxKind.ImportDeclaration:
if (!(<ImportDeclaration>entry).importClause) {
@@ -531,7 +536,7 @@ namespace ts {
function visitImportDeclaration(node: ImportDeclaration): Node {
if (node.importClause && contains(externalImports, node)) {
hoistVariableDeclaration(getLocalNameForExternalImport(node));
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile));
}
return undefined;
@@ -539,7 +544,7 @@ namespace ts {
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): Node {
if (contains(externalImports, node)) {
hoistVariableDeclaration(getLocalNameForExternalImport(node));
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile));
}
// NOTE(rbuckton): Do we support export import = require('') in System?
@@ -570,8 +575,7 @@ namespace ts {
function visitExportAssignment(node: ExportAssignment): Statement {
if (!node.isExportEquals) {
const original = getOriginalNode(node);
if (nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original)) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
return createExportStatement(
createLiteral("default"),
node.expression
@@ -1012,8 +1016,7 @@ namespace ts {
const left = node.left;
switch (left.kind) {
case SyntaxKind.Identifier:
const originalNode = getOriginalNode(left);
const exportDeclaration = resolver.getReferencedExportContainer(<Identifier>originalNode);
const exportDeclaration = resolver.getReferencedExportContainer(<Identifier>left);
if (exportDeclaration) {
return createExportExpression(<Identifier>left, node);
}
@@ -1149,41 +1152,6 @@ namespace ts {
return node;
}
function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<StringLiteral>moduleName)
|| getSynthesizedClone(<StringLiteral>moduleName);
}
return undefined;
}
/**
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression) {
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
return createLiteral(currentSourceFile.renamedDependencies[moduleName.text]);
}
return undefined;
}
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): Identifier {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return createIdentifier(getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name));
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
}
/**
* Gets a name to use for a DeclarationStatement.
* @param node The declaration statement.
@@ -1313,7 +1281,7 @@ namespace ts {
const dependencyGroups: DependencyGroup[] = [];
for (let i = 0; i < externalImports.length; i++) {
const externalImport = externalImports[i];
const externalModuleName = getExternalModuleNameLiteral(externalImport);
const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions);
const text = externalModuleName.text;
if (hasProperty(groupIndices, text)) {
// deduplicate/group entries in dependency list by the dependency name
@@ -1374,9 +1342,10 @@ namespace ts {
hoistBindingElement(node, /*isExported*/ false);
}
function updateSourceFile(node: SourceFile, statements: Statement[]) {
function updateSourceFile(node: SourceFile, statements: Statement[], nodeEmitFlags: NodeEmitFlags) {
const updated = getMutableClone(node);
updated.statements = createNodeArray(statements, node.statements);
setNodeEmitFlags(updated, nodeEmitFlags);
return updated;
}
}
+92 -66
View File
@@ -157,7 +157,15 @@ namespace ts {
* @param node The node to visit.
*/
function namespaceElementVisitorWorker(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) {
if (node.kind === SyntaxKind.ExportDeclaration ||
node.kind === SyntaxKind.ImportDeclaration ||
node.kind === SyntaxKind.ImportClause ||
(node.kind === SyntaxKind.ImportEqualsDeclaration &&
(<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference)) {
// do not emit ES6 imports and exports since they are illegal inside a namespace
return undefined;
}
else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) {
// This node is explicitly marked as TypeScript, or is exported at the namespace
// level, so we should transform the node.
return visitTypeScript(node);
@@ -596,7 +604,7 @@ namespace ts {
// Record an alias to avoid class double-binding.
let decoratedClassAlias: Identifier;
if (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.DecoratedClassWithSelfReference) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.DecoratedClassWithSelfReference) {
enableExpressionSubstitutionForDecoratedClasses();
decoratedClassAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default");
decoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAlias;
@@ -829,7 +837,13 @@ namespace ts {
// End the lexical environment.
addNodes(statements, endLexicalEnvironment());
return setMultiLine(
createBlock(statements, constructor ? constructor.body : undefined),
createBlock(
createNodeArray(
statements,
/*location*/ constructor ? constructor.body.statements : undefined
),
/*location*/ constructor ? constructor.body : undefined
),
true
);
}
@@ -1262,7 +1276,7 @@ namespace ts {
//
const prefix = getClassMemberPrefix(node, member);
const memberName = getExpressionForPropertyName(member);
const memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ true);
const descriptor = languageVersion > ScriptTarget.ES3
? member.kind === SyntaxKind.PropertyDeclaration
// We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it
@@ -1374,7 +1388,6 @@ namespace ts {
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
if (compilerOptions.emitDecoratorMetadata) {
let properties: ObjectLiteralElement[];
if (shouldAddTypeMetadata(node)) {
decoratorExpressions.push(createMetadataHelper("design:type", serializeTypeOfNode(node)));
}
@@ -1608,11 +1621,9 @@ namespace ts {
* @param node The type reference node.
*/
function serializeTypeReferenceNode(node: TypeReferenceNode) {
// Clone the type name and parent it to a location outside of the current declaration.
const typeName = cloneEntityName(node.typeName, currentScope);
switch (resolver.getTypeReferenceSerializationKind(typeName)) {
switch (resolver.getTypeReferenceSerializationKind(node.typeName, currentScope)) {
case TypeReferenceSerializationKind.Unknown:
const serialized = serializeEntityNameAsExpression(typeName, /*useFallback*/ true);
const serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true);
const temp = createTempVariable(hoistVariableDeclaration);
return createLogicalOr(
createLogicalAnd(
@@ -1628,7 +1639,7 @@ namespace ts {
);
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
return serializeEntityNameAsExpression(typeName, /*useFallback*/ false);
return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false);
case TypeReferenceSerializationKind.VoidType:
return createVoidZero();
@@ -1669,17 +1680,20 @@ namespace ts {
function serializeEntityNameAsExpression(node: EntityName, useFallback: boolean): Expression {
switch (node.kind) {
case SyntaxKind.Identifier:
const name = getMutableClone(<Identifier>node);
name.original = undefined;
name.parent = currentScope;
if (useFallback) {
return createLogicalAnd(
createStrictInequality(
createTypeOf(<Identifier>node),
createTypeOf(name),
createLiteral("undefined")
),
<Identifier>node
name
);
}
return <Identifier>node;
return name;
case SyntaxKind.QualifiedName:
return serializeQualifiedNameAsExpression(<QualifiedName>node, useFallback);
@@ -1736,10 +1750,12 @@ namespace ts {
*
* @param member The member whose name should be converted into an expression.
*/
function getExpressionForPropertyName(member: ClassElement | EnumMember): Expression {
function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression {
const name = member.name;
if (isComputedPropertyName(name)) {
return getGeneratedNameForNode(name);
return generateNameForComputedPropertyName
? getGeneratedNameForNode(name)
: (<ComputedPropertyName>name).expression;
}
else if (isIdentifier(name)) {
return createLiteral(name.text);
@@ -2207,24 +2223,6 @@ namespace ts {
|| (isES6ExportedDeclaration(node) && isFirstDeclarationOfKind(node, node.kind));
}
/**
* Adds a leading VariableStatement for an enum or module declaration.
*/
function addVarForEnumDeclaration(statements: Statement[], node: EnumDeclaration) {
// Emit a variable statement for the enum.
statements.push(
createVariableStatement(
isES6ExportedDeclaration(node)
? visitNodes(node.modifiers, visitor, isModifier)
: undefined,
[createVariableDeclaration(
getDeclarationName(node)
)],
/*location*/ node
)
);
}
/**
* Adds a trailing VariableStatement for an enum or module declaration.
*/
@@ -2255,7 +2253,7 @@ namespace ts {
const statements: Statement[] = [];
if (shouldEmitVarForEnumDeclaration(node)) {
addVarForEnumDeclaration(statements, node);
addVarForEnumOrModuleDeclaration(statements, node);
}
const localName = getGeneratedNameForNode(node);
@@ -2323,7 +2321,10 @@ namespace ts {
* @param member The enum member node.
*/
function transformEnumMember(member: EnumMember): Statement {
const name = getExpressionForPropertyName(member);
// enums don't support computed properties
// we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes
// old emitter always generate 'expression' part of the name as-is.
const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false);
return createStatement(
createAssignment(
createElementAccess(
@@ -2389,9 +2390,9 @@ namespace ts {
}
/**
* Adds a leading VariableStatement for a module declaration.
* Adds a leading VariableStatement for a enum or module declaration.
*/
function addVarForModuleDeclaration(statements: Statement[], node: ModuleDeclaration) {
function addVarForEnumOrModuleDeclaration(statements: Statement[], node: ModuleDeclaration | EnumDeclaration) {
// Emit a variable statement for the module.
statements.push(
setOriginalNode(
@@ -2402,7 +2403,21 @@ namespace ts {
[createVariableDeclaration(
getDeclarationName(node)
)],
/*location*/ node
// Trailing comments for module declaration should be emitted with function closure instead of variable statement
// So do not set the end position for the variable statement node
// /** Module comment*/
// module m1 {
// function foo4Export() {
// }
// } // trailing comment module
// Should emit
// /** Module comment*/
// var m1;
// (function (m1) {
// function foo4Export() {
// }
// })(m1 || (m1 = {})); // trailing comment module
/*location*/ { pos: node.pos, end: -1 }
),
node
)
@@ -2427,7 +2442,7 @@ namespace ts {
const statements: Statement[] = [];
if (shouldEmitVarForModuleDeclaration(node)) {
addVarForModuleDeclaration(statements, node);
addVarForEnumOrModuleDeclaration(statements, node);
}
const localName = getGeneratedNameForNode(node);
@@ -2638,9 +2653,9 @@ namespace ts {
return getNamespaceMemberName(name);
}
else {
// We set the "PrefixExportedLocal" flag to indicate to any module transformer
// We set the "ExportName" flag to indicate to any module transformer
// downstream that any `exports.` prefix should be added.
setNodeEmitFlags(name, getNodeEmitFlags(name) | NodeEmitFlags.PrefixExportedLocal);
setNodeEmitFlags(name, getNodeEmitFlags(name) | NodeEmitFlags.ExportName);
return name;
}
}
@@ -2732,41 +2747,52 @@ namespace ts {
}
function substituteExpressionIdentifier(node: Identifier): Expression {
return trySubstituteDecoratedClassName(node)
|| trySubstituteNamespaceExportedName(node)
|| node;
}
function trySubstituteDecoratedClassName(node: Identifier): Expression {
if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses) {
const original = getOriginalNode(node);
if (isIdentifier(original)) {
if (resolver.getNodeCheckFlags(original) & NodeCheckFlags.SelfReferenceInDecoratedClass) {
// 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.
const declaration = resolver.getReferencedValueDeclaration(original);
if (declaration) {
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
if (classAlias) {
return getRelocatedClone(classAlias, /*location*/ node);
}
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.SelfReferenceInDecoratedClass) {
// 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.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
if (classAlias) {
return getRelocatedClone(classAlias, /*location*/ node);
}
}
}
}
return undefined;
}
function trySubstituteNamespaceExportedName(node: Identifier): Expression {
if (enabledSubstitutions & applicableSubstitutions) {
// If this is explicitly a local name, do not substitute.
if (getNodeEmitFlags(node) & NodeEmitFlags.LocalName) {
return node;
}
// If we are nested within a namespace declaration, we may need to qualifiy
// an identifier that is exported from a merged namespace.
const original = getOriginalNode(node);
if (isIdentifier(original) && original.parent) {
const container = resolver.getReferencedExportContainer(original);
if (container) {
const substitute =
(applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) ||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration);
if (substitute) {
return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node);
}
const original = getSourceTreeNodeOfType(node, isIdentifier);
const container = resolver.getReferencedExportContainer(original, /*prefixLocals*/ false);
if (container && original !== container.name) {
const substitute =
(applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) ||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration);
if (substitute) {
return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node);
}
}
}
return node;
return undefined;
}
function substituteCallExpression(node: CallExpression): Expression {
@@ -2894,7 +2920,7 @@ namespace ts {
function getSuperContainerAsyncMethodFlags() {
return currentSuperContainer !== undefined
&& resolver.getNodeCheckFlags(getOriginalNode(currentSuperContainer)) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
}
}
}
}
+15 -11
View File
@@ -1963,7 +1963,7 @@ namespace ts {
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
getReferencedValueDeclaration(reference: Identifier): Declaration;
getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind;
getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind;
isOptionalParameter(node: ParameterDeclaration): boolean;
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
isArgumentsLocalBinding(node: Identifier): boolean;
@@ -2498,7 +2498,7 @@ namespace ts {
noImplicitUseStrict?: boolean;
lib?: string[];
/* @internal */ stripInternal?: boolean;
/* @internal */ experimentalTransforms?: boolean;
/* @internal */ useLegacyEmitter?: boolean;
// Skip checking lib.d.ts to help speed up tests.
/* @internal */ skipDefaultLibCheck?: boolean;
@@ -2805,6 +2805,7 @@ namespace ts {
* 'throw new Error("NotImplemented")'
*/
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
getEnvironmentVariable?(name: string): string;
}
/* @internal */
@@ -2829,11 +2830,12 @@ namespace ts {
ContainsPropertyInitializer = 1 << 10,
ContainsLexicalThis = 1 << 11,
ContainsCapturedLexicalThis = 1 << 12,
ContainsDefaultValueAssignments = 1 << 13,
ContainsParameterPropertyAssignments = 1 << 14,
ContainsSpreadElementExpression = 1 << 15,
ContainsComputedPropertyName = 1 << 16,
ContainsBlockScopedBinding = 1 << 17,
ContainsLexicalThisInComputedPropertyName = 1 << 13,
ContainsDefaultValueAssignments = 1 << 14,
ContainsParameterPropertyAssignments = 1 << 15,
ContainsSpreadElementExpression = 1 << 16,
ContainsComputedPropertyName = 1 << 17,
ContainsBlockScopedBinding = 1 << 18,
HasComputedFlags = 1 << 31, // Transform flags have been computed.
@@ -2852,10 +2854,10 @@ namespace ts {
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments,
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
TypeExcludes = ~ContainsTypeScript,
ObjectLiteralExcludes = ContainsDecorators | ContainsComputedPropertyName,
ObjectLiteralExcludes = ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
ArrayLiteralOrCallOrNewExcludes = ContainsSpreadElementExpression,
}
@@ -2874,8 +2876,9 @@ namespace ts {
NoSourceMap = 1 << 10, // Do not emit a source map location for this node.
NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node.
NoComments = 1 << 12, // Do not emit comments for this node.
PrefixExportedLocal = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
Indented = 1 << 14, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
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).
}
/** Additional context provided to `visitEachChild` */
@@ -2891,6 +2894,7 @@ namespace ts {
export interface TransformationContext extends LexicalEnvironment {
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getEmitHost(): EmitHost;
getNodeEmitFlags(node: Node): NodeEmitFlags;
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
hoistFunctionDeclaration(node: FunctionDeclaration): void;
+44 -26
View File
@@ -169,6 +169,18 @@ namespace ts {
return `${ file.fileName }(${ loc.line + 1 },${ loc.character + 1 })`;
}
export function getEnvironmentVariable(name: string, host?: CompilerHost) {
if (host && host.getEnvironmentVariable) {
return host.getEnvironmentVariable(name);
}
if (sys && sys.getEnvironmentVariable) {
return sys.getEnvironmentVariable(name);
}
return "";
}
export function getStartPosOfNode(node: Node): number {
return node.pos;
}
@@ -1699,24 +1711,6 @@ namespace ts {
|| kind === SyntaxKind.SourceFile;
}
/**
* Creates a deep clone of an EntityName, with new parent pointers.
* @param node The EntityName to clone.
* @param parent The parent for the cloned node.
*/
export function cloneEntityName(node: EntityName, parent?: Node): EntityName {
const clone = getMutableClone(node);
clone.parent = parent;
if (isQualifiedName(clone)) {
const { left, right } = clone;
clone.left = cloneEntityName(left, clone);
clone.right = getMutableClone(right);
clone.right.parent = clone;
}
return clone;
}
export function nodeIsSynthesized(node: TextRange): boolean {
return positionIsSynthesized(node.pos)
|| positionIsSynthesized(node.end);
@@ -1729,13 +1723,31 @@ namespace ts {
}
export function getOriginalNode(node: Node): Node {
while (node.original !== undefined) {
node = node.original;
if (node) {
while (node.original !== undefined) {
node = node.original;
}
}
return node;
}
export function getSourceTreeNode(node: Node): Node {
node = getOriginalNode(node);
if (node) {
if (node.parent || node.kind === SyntaxKind.SourceFile) {
return node;
}
}
return undefined;
}
export function getSourceTreeNodeOfType<T extends Node>(node: T, nodeTest: (node: Node) => node is T): T {
const source = getSourceTreeNode(node);
return source && nodeTest(source) ? source : undefined;
}
export function getOriginalNodeId(node: Node) {
node = getOriginalNode(node);
return node ? getNodeId(node) : 0;
@@ -2972,7 +2984,7 @@ namespace ts {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers: Map<ExportSpecifier[]> = {};
let exportEquals: ExportAssignment = undefined;
let hasExportStars = false;
let hasExportStarsToExportValues = false;
for (const node of sourceFile.statements) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
@@ -2987,7 +2999,7 @@ namespace ts {
break;
case SyntaxKind.ImportEqualsDeclaration:
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(getOriginalNode(node))) {
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) {
// import x = require("mod") where x is referenced
externalImports.push(<ImportEqualsDeclaration>node);
}
@@ -2997,10 +3009,12 @@ namespace ts {
if ((<ExportDeclaration>node).moduleSpecifier) {
if (!(<ExportDeclaration>node).exportClause) {
// export * from "mod"
externalImports.push(<ExportDeclaration>node);
hasExportStars = true;
if (resolver.moduleExportsSomeValue((<ExportDeclaration>node).moduleSpecifier)) {
externalImports.push(<ExportDeclaration>node);
hasExportStarsToExportValues = true;
}
}
else if (resolver.isValueAliasDeclaration(getOriginalNode(node))) {
else if (resolver.isValueAliasDeclaration(node)) {
// export { x, y } from "mod" where at least one export is a value symbol
externalImports.push(<ExportDeclaration>node);
}
@@ -3028,7 +3042,7 @@ namespace ts {
}
}
return { externalImports, exportSpecifiers, exportEquals, hasExportStars };
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues };
}
export function getInitializedVariables(node: VariableDeclarationList) {
@@ -3402,6 +3416,10 @@ namespace ts {
|| kind === SyntaxKind.ModuleDeclaration;
}
export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
return node.kind === SyntaxKind.ImportEqualsDeclaration;
}
export function isImportClause(node: Node): node is ImportClause {
return node.kind === SyntaxKind.ImportClause;
}
+23 -4
View File
@@ -424,7 +424,7 @@ namespace Utils {
filtered.push(line);
}
(<any>error).stack = filtered.join(ts.sys.newLine);
(<any>error).stack = filtered.join(Harness.IO.newLine());
}
return error;
@@ -480,6 +480,8 @@ namespace Harness {
getExecutingFilePath(): string;
exit(exitCode?: number): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
tryEnableSourceMapsForHost?(): void;
getEnvironmentVariable?(name: string): string;
}
export var IO: IO;
@@ -518,6 +520,7 @@ namespace Harness {
export const fileExists: typeof IO.fileExists = fso.FileExists;
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name);
export function createDirectory(path: string) {
if (directoryExists(path)) {
@@ -587,6 +590,13 @@ namespace Harness {
export const log: typeof IO.log = s => console.log(s);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name);
export function tryEnableSourceMapsForHost() {
if (ts.sys.tryEnableSourceMapsForHost) {
ts.sys.tryEnableSourceMapsForHost();
}
}
export function createDirectory(path: string) {
if (!directoryExists(path)) {
@@ -741,7 +751,16 @@ namespace Harness {
return dirPath;
}
export let directoryName: typeof IO.directoryName = Utils.memoize(directoryNameImpl);
export const resolvePath = (path: string) => directoryName(path);
export function resolvePath(path: string) {
const response = Http.getFileFromServerSync(serverRoot + path + "?resolve=true");
if (response.status === 200) {
return response.responseText;
}
else {
return null;
}
}
export function fileExists(path: string): boolean {
const response = Http.getFileFromServerSync(serverRoot + path);
@@ -1681,8 +1700,8 @@ namespace Harness {
if (Error) (<any>Error).stackTraceLimit = 1;
}
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
ts.sys.tryEnableSourceMapsForHost();
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable("NODE_ENV"))) {
Harness.IO.tryEnableSourceMapsForHost();
}
// TODO: not sure why Utils.evalFile isn't working with this, eventually will concat it like old compiler instead of eval
+26 -19
View File
@@ -463,32 +463,39 @@ class ProjectRunner extends RunnerBase {
}
});
it("Baseline of emitted result (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
if (testCase.baselineCheck) {
var lastError: any = undefined;
ts.forEach(compilerResult.outputFiles, outputFile => {
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
try {
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
}
catch (e) {
lastError = e;
}
});
if (lastError) {
throw lastError;
}
}
});
it("SourceMapRecord for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
if (compilerResult.sourceMapData) {
Harness.Baseline.runBaseline("SourceMapRecord for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
return Harness.SourceMapRecorder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
});
}
});
// it("SourceMapRecord for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
// if (compilerResult.sourceMapData) {
// Harness.Baseline.runBaseline("SourceMapRecord for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
// return Harness.SourceMapRecorder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
// ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
// });
// }
// });
// Verify that all the generated .d.ts files compile
+10 -4
View File
@@ -40,8 +40,14 @@ let testConfigFile =
Harness.IO.fileExists(mytestconfig) ? Harness.IO.readFile(mytestconfig) :
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : "");
type TestConfig = {
tests?: string[];
stackTraceLimit?: number | "full";
light?: boolean;
};
if (testConfigFile !== "") {
const testConfig = JSON.parse(testConfigFile);
const testConfig = <TestConfig>JSON.parse(testConfigFile);
if (testConfig.light) {
Harness.lightMode = true;
}
@@ -49,12 +55,12 @@ if (testConfigFile !== "") {
if (testConfig.stackTraceLimit === "full") {
(<any>Error).stackTraceLimit = Infinity;
}
else if ((testConfig.stackTraceLimit | 0) > 0) {
else if ((+testConfig.stackTraceLimit | 0) > 0) {
(<any>Error).stackTraceLimit = testConfig.stackTraceLimit;
}
if (testConfig.test && testConfig.test.length > 0) {
for (const option of testConfig.test) {
if (testConfig.tests && testConfig.tests.length > 0) {
for (const option of testConfig.tests) {
if (!option) {
continue;
}