diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f2d11ef227c..695b999e7bf 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -114,10 +114,11 @@ namespace ts { // Literals + export function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange): StringLiteral; export function createLiteral(value: string, location?: TextRange): StringLiteral; export function createLiteral(value: number, location?: TextRange): LiteralExpression; export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression; - export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression { + export function createLiteral(value: string | number | boolean | StringLiteral | Identifier, location?: TextRange): PrimaryExpression { if (typeof value === "number") { const node = createNode(SyntaxKind.NumericLiteral, location); node.text = value.toString(); @@ -126,9 +127,15 @@ namespace ts { else if (typeof value === "boolean") { return createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location); } + else if (typeof value === "string") { + const node = createNode(SyntaxKind.StringLiteral, location); + node.text = value; + return node; + } else { const node = createNode(SyntaxKind.StringLiteral, location); - node.text = String(value); + node.textSourceNode = value; + node.text = value.text; return node; } } diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index e2bef72f15a..194d668686c 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -668,7 +668,7 @@ const _super = (function (geti, seti) { // SyntaxKind.TemplateMiddle // SyntaxKind.TemplateTail function emitLiteral(node: LiteralLikeNode) { - const text = getLiteralText(node, currentSourceFile, languageVersion); + const text = getLiteralTextOfNode(node); if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { writer.writeLiteral(text); @@ -980,7 +980,7 @@ const _super = (function (geti, seti) { function needsDotDotForPropertyAccess(expression: Expression) { if (expression.kind === SyntaxKind.NumericLiteral) { // check if numeric literal was originally written with a dot - const text = getLiteralText(expression, currentSourceFile, languageVersion); + const text = getLiteralTextOfNode(expression); return text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; } else { @@ -2350,6 +2350,9 @@ const _super = (function (geti, seti) { else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { return unescapeIdentifier(node.text); } + else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + return getTextOfNode((node).textSourceNode, includeTrivia); + } else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { return node.text; } @@ -2357,6 +2360,20 @@ const _super = (function (geti, seti) { return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); } + function getLiteralTextOfNode(node: LiteralLikeNode): string { + if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + const textSourceNode = (node).textSourceNode; + if (isIdentifier(textSourceNode)) { + return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; + } + else { + return getLiteralTextOfNode(textSourceNode); + } + } + + return getLiteralText(node, currentSourceFile, languageVersion); + } + function tryGetConstEnumValue(node: Node): number { if (compilerOptions.isolatedModules) { return undefined; diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 8aec7598aa4..3166b77c293 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -720,7 +720,7 @@ namespace ts { const moduleName = getExternalModuleName(importNode); if (moduleName.kind === SyntaxKind.StringLiteral) { return tryRenameExternalModule(moduleName) - || getSynthesizedClone(moduleName); + || createLiteral(moduleName); } return undefined; diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 55fd8a1ab17..cc35ec22bf1 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -5,7 +5,7 @@ namespace ts { export function transformSystemModule(context: TransformationContext) { interface DependencyGroup { - name: Identifier; + name: StringLiteral; externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; } @@ -640,7 +640,7 @@ namespace ts { return [ node, createExportStatement(name, name) - ] + ]; } return node; } @@ -1101,7 +1101,7 @@ namespace ts { else { return operator === SyntaxKind.PlusPlusToken ? createSubtract(call, createLiteral(1)) - : createAdd(call, createLiteral(1)) + : createAdd(call, createLiteral(1)); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 475d96b87f7..09e60035ff3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -804,6 +804,8 @@ namespace ts { // @kind(SyntaxKind.StringLiteral) export interface StringLiteral extends LiteralExpression { _stringLiteralBrand: any; + /* @internal */ + textSourceNode?: Identifier | StringLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). } // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5f3899f4e24..18a95bc5ff0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2982,7 +2982,7 @@ namespace ts { break; case SyntaxKind.ImportEqualsDeclaration: - if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) { + if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(getOriginalNode(node))) { // import x = require("mod") where x is referenced externalImports.push(node); } @@ -2995,7 +2995,7 @@ namespace ts { externalImports.push(node); hasExportStars = true; } - else if (resolver.isValueAliasDeclaration(node)) { + else if (resolver.isValueAliasDeclaration(getOriginalNode(node))) { // export { x, y } from "mod" where at least one export is a value symbol externalImports.push(node); } diff --git a/tests/baselines/reference/ambientDeclarationsExternal.js b/tests/baselines/reference/ambientDeclarationsExternal.js index b92993128ab..42375bc1d09 100644 --- a/tests/baselines/reference/ambientDeclarationsExternal.js +++ b/tests/baselines/reference/ambientDeclarationsExternal.js @@ -29,6 +29,6 @@ var n: number; //// [consumer.js] "use strict"; // Ambient external module members are always exported with or without export keyword when module lacks export assignment -var imp3 = require("equ2"); +var imp3 = require('equ2'); var n = imp3.x; var n; diff --git a/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js b/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js index c91adaff864..77d8e2d830d 100644 --- a/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js +++ b/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js @@ -20,7 +20,7 @@ var c = new A(); //// [ambientExternalModuleWithInternalImportDeclaration_0.js] //// [ambientExternalModuleWithInternalImportDeclaration_1.js] -define(["require", "exports", "M"], function (require, exports, A) { +define(["require", "exports", 'M'], function (require, exports, A) { "use strict"; var c = new A(); }); diff --git a/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js b/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js index 4c70a338bc3..158992234a2 100644 --- a/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js +++ b/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js @@ -19,7 +19,7 @@ var c = new A(); //// [ambientExternalModuleWithoutInternalImportDeclaration_0.js] //// [ambientExternalModuleWithoutInternalImportDeclaration_1.js] -define(["require", "exports", "M"], function (require, exports, A) { +define(["require", "exports", 'M'], function (require, exports, A) { "use strict"; var c = new A(); }); diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index 10afa784ebb..356cbff33d9 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -10,7 +10,7 @@ export {n2} export {n2 as n3} //// [systemModule10.js] -System.register(["file1", "file2"], function (exports_1, context_1) { +System.register(['file1', 'file2'], function (exports_1, context_1) { "use strict"; var __moduleName = context_1 && context_1.id; var file1_1, n2; diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index 830c611bd38..068613968af 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -10,7 +10,7 @@ export {n2} export {n2 as n3} //// [systemModule10_ES5.js] -System.register(["file1", "file2"], function (exports_1, context_1) { +System.register(['file1', 'file2'], function (exports_1, context_1) { "use strict"; var __moduleName = context_1 && context_1.id; var file1_1, n2;