Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ namespace ts {
return result;
}

export function some<T>(array: T[], predicate?: (value: T) => boolean): boolean {
if (array) {
for (const v of array) {
if (!predicate || predicate(v)) {
return true;
}
}
}
return false;
}

export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!array2 || !array2.length) return array1;
if (!array1 || !array1.length) return array2;
Expand Down Expand Up @@ -1177,7 +1188,7 @@ namespace ts {

/**
* Returns the path except for its basename. Eg:
*
*
* /path/to/file.ext -> /path/to
*/
export function getDirectoryPath(path: Path): Path;
Expand Down
26 changes: 15 additions & 11 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2206,7 +2206,7 @@ namespace ts {
* @param visitor: Optional callback used to visit any custom prologue directives.
*/
export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult<Node>): number {
Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array");
let foundUseStrict = false;
let statementOffset = 0;
const numStatements = source.length;
Expand All @@ -2219,16 +2219,20 @@ namespace ts {
target.push(statement);
}
else {
if (ensureUseStrict && !foundUseStrict) {
target.push(startOnNewLine(createStatement(createLiteral("use strict"))));
foundUseStrict = true;
}
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
}
else {
break;
}
break;
}
statementOffset++;
}
if (ensureUseStrict && !foundUseStrict) {
target.push(startOnNewLine(createStatement(createLiteral("use strict"))));
}
while (statementOffset < numStatements) {
const statement = source[statementOffset];
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
}
else {
break;
}
statementOffset++;
}
Expand Down
115 changes: 7 additions & 108 deletions src/compiler/transformers/module/es6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
namespace ts {
export function transformES6Module(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();

let currentSourceFile: SourceFile;

return transformSourceFile;

function transformSourceFile(node: SourceFile) {
Expand All @@ -17,128 +13,31 @@ namespace ts {
}

if (isExternalModule(node) || compilerOptions.isolatedModules) {
currentSourceFile = node;
return visitEachChild(node, visitor, context);
}

return node;
}

function visitor(node: Node): VisitResult<Node> {
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:
case SyntaxKind.NamespaceImport:
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(
/*decorators*/ undefined,
/*modifiers*/ undefined,
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);
if (!newImportClause.name && !newImportClause.namedBindings) {
return undefined;
}
else if (newImportClause !== node.importClause) {
return createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
newImportClause,
node.moduleSpecifier);
}
}
return node;
}

function visitImportClause(node: ImportClause): ImportClause {
let newDefaultImport = node.name;
if (!resolver.isReferencedAliasDeclaration(node)) {
newDefaultImport = undefined;
}
const newNamedBindings = visitNode(node.namedBindings, visitor, isNamedImportBindings, /*optional*/ true);
return newDefaultImport !== node.name || newNamedBindings !== node.namedBindings
? createImportClause(newDefaultImport, newNamedBindings)
: node;
}

function visitNamedBindings(node: NamedImportBindings): VisitResult<NamedImportBindings> {
if (node.kind === SyntaxKind.NamespaceImport) {
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
else {
const newNamedImportElements = visitNodes((<NamedImports>node).elements, visitor, isImportSpecifier);
if (!newNamedImportElements || newNamedImportElements.length == 0) {
return undefined;
}
if (newNamedImportElements === (<NamedImports>node).elements) {
return node;
}
return createNamedImports(newNamedImportElements);
}
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult<ImportEqualsDeclaration> {
// Elide `import=` as it is not legal with --module ES6
return undefined;
}

function visitImportSpecifier(node: ImportSpecifier) {
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
function visitExportAssignment(node: ExportAssignment): VisitResult<ExportAssignment> {
// Elide `export=` as it is not legal with --module ES6
return node.isExportEquals ? undefined : node;
}
}
}
43 changes: 20 additions & 23 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace ts {
currentSourceFile = node;

// Collect information about the external module.
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node));

// Perform the transformation.
const transformModule = transformModuleDelegates[moduleKind] || transformModuleDelegates[ModuleKind.None];
Expand Down Expand Up @@ -228,7 +228,7 @@ namespace ts {
}

function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
if (exportEquals) {
if (emitAsReturn) {
const statement = createReturn(
exportEquals.expression,
Expand Down Expand Up @@ -461,23 +461,21 @@ namespace ts {
);
}
for (const specifier of node.exportClause.elements) {
if (resolver.isValueAliasDeclaration(specifier)) {
const exportedValue = createPropertyAccess(
generatedName,
specifier.propertyName || specifier.name
);
statements.push(
createStatement(
createExportAssignment(specifier.name, exportedValue),
/*location*/ specifier
)
);
}
const exportedValue = createPropertyAccess(
generatedName,
specifier.propertyName || specifier.name
);
statements.push(
createStatement(
createExportAssignment(specifier.name, exportedValue),
/*location*/ specifier
)
);
}

return singleOrMany(statements);
}
else if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) {
else {
// export * from "mod";
return createStatement(
createCall(
Expand All @@ -495,15 +493,14 @@ namespace ts {
}

function visitExportAssignment(node: ExportAssignment): VisitResult<Statement> {
if (!node.isExportEquals) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
}
if (node.isExportEquals) {
// Elide as `export=` is handled in addExportEqualsIfNeeded
return undefined;
}

return undefined;
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
}

function addExportDefault(statements: Statement[], expression: Expression, location: TextRange): void {
Expand Down Expand Up @@ -568,7 +565,7 @@ namespace ts {
}

function collectExportMembers(names: Identifier[], node: Node): Identifier[] {
if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node) && isDeclaration(node)) {
if (isAliasSymbolDeclaration(node) && isDeclaration(node)) {
const name = node.name;
if (isIdentifier(name)) {
names.push(name);
Expand Down
31 changes: 13 additions & 18 deletions src/compiler/transformers/module/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ namespace ts {
Debug.assert(!exportFunctionForFile);

// Collect information about the external module and dependency groups.
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node));

// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
Expand Down Expand Up @@ -573,28 +573,23 @@ namespace ts {
}

function visitExportSpecifier(specifier: ExportSpecifier): Statement {
if (resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name)
|| resolver.isValueAliasDeclaration(specifier)) {
recordExportName(specifier.name);
return createExportStatement(
specifier.name,
specifier.propertyName || specifier.name
);
}
return undefined;
recordExportName(specifier.name);
return createExportStatement(
specifier.name,
specifier.propertyName || specifier.name
);
}

function visitExportAssignment(node: ExportAssignment): Statement {
if (!node.isExportEquals) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
return createExportStatement(
createLiteral("default"),
node.expression
);
}
if (node.isExportEquals) {
// Elide `export=` as it is illegal in a SystemJS module.
return undefined;
}

return undefined;
return createExportStatement(
createLiteral("default"),
node.expression
);
}

/**
Expand Down
Loading