diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 60864e411fc..df2687768fc 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -448,7 +448,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
/** If removeComments is true, no leading-comments needed to be emitted **/
let emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos: number) { } : emitLeadingCommentsOfPositionWorker;
- let moduleEmitDelegates: Map<(node: SourceFile, startIndex: number) => void> = {
+ let moduleEmitDelegates: Map<(node: SourceFile, startIndex: number, resolvePath?: boolean) => void> = {
[ModuleKind.ES6]: emitES6Module,
[ModuleKind.AMD]: emitAMDModule,
[ModuleKind.System]: emitSystemModule,
@@ -456,6 +456,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
[ModuleKind.CommonJS]: emitCommonJSModule,
};
+ let bundleEmitDelegates: Map<(node: SourceFile, startIndex: number, resolvePath?: boolean) => void> = {
+ [ModuleKind.ES6]: () => {},
+ [ModuleKind.AMD]: emitAMDModule,
+ [ModuleKind.System]: emitSystemModule,
+ [ModuleKind.UMD]: emitUMDModule,
+ [ModuleKind.CommonJS]: () => {},
+ };
+
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
initializeEmitterWithSourceMaps();
}
@@ -465,6 +473,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitSourceFile(root);
}
else {
+ forEach(host.getSourceFiles(), emitEmitHelpers);
forEach(host.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
emitSourceFile(sourceFile);
@@ -488,7 +497,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitConcatenatedModule(sourceFile: SourceFile): void {
currentSourceFile = sourceFile;
exportFunctionForFile = undefined;
- moduleEmitDelegates[modulekind](sourceFile, 0);
+ let canonicalName = resolveToSemiabsolutePath(sourceFile.fileName);
+ sourceFile.moduleName = sourceFile.moduleName || canonicalName;
+ bundleEmitDelegates[modulekind](sourceFile, 0, /*resolvePath*/true);
+ }
+
+ function resolveToSemiabsolutePath(path: string): string {
+ let dir = host.getCurrentDirectory();
+ return removeFileExtension(
+ getRelativePathToDirectoryOrUrl(dir, path, dir, f => host.getCanonicalFileName(f), /*isAbsolutePathAnUrl*/false)
+ );
}
function isUniqueName(name: string): boolean {
@@ -6620,7 +6638,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write("}"); // execute
}
- function emitSystemModule(node: SourceFile, startIndex: number): void {
+ function emitSystemModule(node: SourceFile, startIndex: number, resolvePath?: boolean): void {
collectExternalModuleInfo(node);
// System modules has the following shape
// System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */})
@@ -6660,6 +6678,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(", ");
}
+ if (resolvePath) {
+ text = makeModulePathSemiabsolute(text);
+ }
write(text);
}
write(`], function(${exportFunctionForFile}) {`);
@@ -6679,7 +6700,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
importAliasNames: string[];
}
- function getAMDDependencyNames(node: SourceFile, includeNonAmdDependencies: boolean): AMDDependencyNames {
+ function makeModulePathSemiabsolute(externalModuleName: string): string {
+ let quotemark = externalModuleName.charAt(0);
+ let unquotedModuleName = externalModuleName.substring(1, externalModuleName.length - 1);
+ let resolvedFileName = host.resolveModuleName(unquotedModuleName, currentSourceFile.fileName);
+ if (resolvedFileName) {
+ let semiabsoluteName = resolveToSemiabsolutePath(resolvedFileName);
+ externalModuleName = quoteString(semiabsoluteName, quotemark);
+ }
+ return externalModuleName;
+ }
+
+ function getAMDDependencyNames(node: SourceFile, includeNonAmdDependencies: boolean, resolvePath?: boolean): AMDDependencyNames {
// names of modules with corresponding parameter in the factory function
let aliasedModuleNames: string[] = [];
// names of modules with no corresponding parameters in factory function
@@ -6703,6 +6735,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Find the name of the external module
let externalModuleName = getExternalModuleNameText(importNode);
+ if (resolvePath) {
+ externalModuleName = makeModulePathSemiabsolute(externalModuleName);
+ }
+
// Find the name of the module alias, if there is one
let importAliasName = getLocalNameForExternalImport(importNode);
if (includeNonAmdDependencies && importAliasName) {
@@ -6717,7 +6753,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return { aliasedModuleNames, unaliasedModuleNames, importAliasNames };
}
- function emitAMDDependencies(node: SourceFile, includeNonAmdDependencies: boolean) {
+ function emitAMDDependencies(node: SourceFile, includeNonAmdDependencies: boolean, resolvePath?: boolean) {
// An AMD define function has the following shape:
// define(id?, dependencies?, factory);
//
@@ -6730,7 +6766,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// `import "module"` or ``
// we need to add modules without alias names to the end of the dependencies list
- let dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies);
+ let dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, resolvePath);
emitAMDDependencyList(dependencyNames);
write(", ");
emitAMDFactoryHeader(dependencyNames);
@@ -6758,7 +6794,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(") {");
}
- function emitAMDModule(node: SourceFile, startIndex: number) {
+ function emitAMDModule(node: SourceFile, startIndex: number, resolvePath?: boolean) {
emitEmitHelpers(node);
collectExternalModuleInfo(node);
@@ -6767,7 +6803,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (node.moduleName) {
write("\"" + node.moduleName + "\", ");
}
- emitAMDDependencies(node, /*includeNonAmdDependencies*/ true);
+ emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, resolvePath);
increaseIndent();
emitExportStarHelper();
emitCaptureThisForNodeIfNecessary(node);
@@ -6789,11 +6825,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitExportEquals(/*emitAsReturn*/ false);
}
- function emitUMDModule(node: SourceFile, startIndex: number) {
+ function emitUMDModule(node: SourceFile, startIndex: number, resolvePath?: boolean) {
emitEmitHelpers(node);
collectExternalModuleInfo(node);
- let dependencyNames = getAMDDependencyNames(node, /*includeNonAmdDependencies*/ false);
+ let dependencyNames = getAMDDependencyNames(node, /*includeNonAmdDependencies*/ false, resolvePath);
// Module is detected first to support Browserify users that load into a browser with an AMD loader
writeLines(`(function (factory) {
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index c6d3a245a8d..b595d48dc57 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -522,6 +522,12 @@ namespace ts {
getSourceFiles: program.getSourceFiles,
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)),
+ resolveModuleName: (name: string, containingFile?: string) => {
+ let resolvedModule = resolveModuleNamesWorker([name], containingFile || "dummy.ts")[0];
+ if (!resolvedModule)
+ return;
+ return resolvedModule.resolvedFileName;
+ },
};
}
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 452f59f0f03..9ae65af046e 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -40,6 +40,7 @@ namespace ts {
getNewLine(): string;
writeFile: WriteFileCallback;
+ resolveModuleName(path: string, containingFile?: string): string;
}
// Pool writers to avoid needing to allocate them for every symbol we write.
@@ -1619,21 +1620,48 @@ namespace ts {
"\u0085": "\\u0085" // nextLine
};
+ let singleQuoteEscapedCharsRegExp = /[\\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
+ let singleQuoteEscapedCharsMap: Map = {
+ "\0": "\\0",
+ "\t": "\\t",
+ "\v": "\\v",
+ "\f": "\\f",
+ "\b": "\\b",
+ "\r": "\\r",
+ "\n": "\\n",
+ "\\": "\\\\",
+ "\'": "\\\'",
+ "\u2028": "\\u2028", // lineSeparator
+ "\u2029": "\\u2029", // paragraphSeparator
+ "\u0085": "\\u0085" // nextLine
+ };
+
/**
* Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
* but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine)
* Note that this doesn't actually wrap the input in double quotes.
*/
export function escapeString(s: string): string {
- s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
+ return escapeStringByQuote(s, "\"");
+ }
+
+ export function escapeStringByQuote(s: string, quotemark: string): string {
+ let regex = quotemark === "'" ? singleQuoteEscapedCharsRegExp : escapedCharsRegExp;
+ let replacementMap = quotemark === "'" ? singleQuoteEscapedCharsMap : escapedCharsMap;
+
+ s = regex.test(s) ? s.replace(regex, getReplacement) : s;
return s;
function getReplacement(c: string) {
- return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
+ return replacementMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
}
}
+ export function quoteString(s: string, quotemark: string): string {
+ return quotemark + escapeStringByQuote(s, quotemark) + quotemark;
+ }
+
export function isIntrinsicJsxName(name: string) {
let ch = name.substr(0, 1);
return ch.toLowerCase() === ch;