diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5af58a11678..90ec1c793a3 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -50,7 +50,7 @@ namespace ts { } else { const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); - const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); + const sourceMapFilePath = isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); // For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error const isJs = isSourceFileJavaScript(sourceFile); const declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6374dbb5179..d7c94261fa9 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -717,6 +717,7 @@ namespace ts { initializeState(sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); // Set source file so that errors will be reported with this file name sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false); + sourceFile.flags = contextFlags; // Prime the scanner. nextToken(); diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index a274404f320..9229e2daa0e 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -125,7 +125,7 @@ namespace ts { * @param sourceFileOrBundle The input source file or bundle for the program. */ function initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle, outputSourceMapDataList?: SourceMapData[]) { - if (disabled) { + if (disabled || fileExtensionIs(filePath, Extension.Json)) { return; } @@ -270,7 +270,7 @@ namespace ts { * @param pos The position. */ function emitPos(pos: number) { - if (disabled || positionIsSynthesized(pos)) { + if (disabled || positionIsSynthesized(pos) || isJsonSourceMapSource(currentSource)) { return; } @@ -328,7 +328,7 @@ namespace ts { * @param emitCallback The callback used to emit the node. */ function emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { - if (disabled) { + if (disabled || isInJsonFile(node)) { return emitCallback(hint, node); } @@ -381,7 +381,7 @@ namespace ts { * @param emitCallback The callback used to emit the token. */ function emitTokenWithSourceMap(node: Node, token: SyntaxKind, writer: (s: string) => void, tokenPos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number) { - if (disabled) { + if (disabled || isInJsonFile(node)) { return emitCallback(token, writer, tokenPos); } @@ -404,6 +404,10 @@ namespace ts { return tokenPos; } + function isJsonSourceMapSource(sourceFile: SourceMapSource) { + return fileExtensionIs(sourceFile.fileName, Extension.Json); + } + /** * Set the current source file. * @@ -417,6 +421,10 @@ namespace ts { currentSource = sourceFile; currentSourceText = currentSource.text; + if (isJsonSourceMapSource(sourceFile)) { + return; + } + // Add the file to tsFilePaths // If sourceroot option: Use the relative path corresponding to the common directory path // otherwise source locations relative to map file location @@ -446,7 +454,7 @@ namespace ts { * Gets the text for the source map. */ function getText() { - if (disabled) { + if (disabled || isJsonSourceMapSource(currentSource)) { return undefined!; // TODO: GH#18217 } @@ -467,7 +475,7 @@ namespace ts { * Gets the SourceMappingURL for the source map. */ function getSourceMappingURL() { - if (disabled) { + if (disabled || isJsonSourceMapSource(currentSource)) { return undefined!; // TODO: GH#18217 } @@ -519,4 +527,4 @@ namespace ts { return encodedStr; } -} \ No newline at end of file +} diff --git a/src/harness/compiler.ts b/src/harness/compiler.ts index 95a7d85fe58..1290bbb4be8 100644 --- a/src/harness/compiler.ts +++ b/src/harness/compiler.ts @@ -183,7 +183,7 @@ namespace compiler { public getSourceMapRecord(): string | undefined { if (this.result!.sourceMaps && this.result!.sourceMaps!.length > 0) { - return Harness.SourceMapRecorder.getSourceMapRecord(this.result!.sourceMaps!, this.program!, Array.from(this.js.values()), Array.from(this.dts.values())); + return Harness.SourceMapRecorder.getSourceMapRecord(this.result!.sourceMaps!, this.program!, Array.from(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), Array.from(this.dts.values())); } } @@ -216,6 +216,16 @@ namespace compiler { } return vpath.changeExtension(path, ext); } + + public getNumberOfJsFiles() { + let count = this.js.size; + this.js.forEach(document => { + if (ts.fileExtensionIs(document.file, ts.Extension.Json)) { + count--; + } + }); + return count; + } } export function compileFiles(host: fakes.CompilerHost, rootFiles: string[] | undefined, compilerOptions: ts.CompilerOptions): CompilationResult { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d57de0cb910..d325883fc11 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1270,7 +1270,7 @@ namespace Harness { throw new Error("Only declaration files should be generated when emitDeclarationOnly:true"); } } - else if (result.dts.size !== result.js.size) { + else if (result.dts.size !== result.getNumberOfJsFiles()) { throw new Error("There were no errors and declFiles generated did not match number of js files generated"); } } @@ -1645,7 +1645,7 @@ namespace Harness { return; } else if (options.sourceMap || declMaps) { - if (result.maps.size !== (result.js.size * (declMaps && options.sourceMap ? 2 : 1))) { + if (result.maps.size !== (result.getNumberOfJsFiles() * (declMaps && options.sourceMap ? 2 : 1))) { throw new Error("Number of sourcemap files should be same as js files."); } diff --git a/tests/baselines/reference/requireOfJsonFileWithDeclaration.js b/tests/baselines/reference/requireOfJsonFileWithDeclaration.js new file mode 100644 index 00000000000..2cb5085ffb7 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithDeclaration.js @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/requireOfJsonFileWithDeclaration.ts] //// + +//// [file1.ts] +import b1 = require('./b.json'); +let x = b1.a; +import b2 = require('./b.json'); +if (x) { + let b = b2.b; + x = (b1.b === b); +} + +//// [b.json] +{ + "a": true, + "b": "hello" +} + +//// [out/b.json] +{ + "a": true, + "b": "hello" +} +//// [out/file1.js] +"use strict"; +exports.__esModule = true; +var b1 = require("./b.json"); +var x = b1.a; +var b2 = require("./b.json"); +if (x) { + var b = b2.b; + x = (b1.b === b); +} + + +//// [out/file1.d.ts] +export {}; diff --git a/tests/baselines/reference/requireOfJsonFileWithDeclaration.symbols b/tests/baselines/reference/requireOfJsonFileWithDeclaration.symbols new file mode 100644 index 00000000000..a8f82b6b145 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithDeclaration.symbols @@ -0,0 +1,38 @@ +=== tests/cases/compiler/file1.ts === +import b1 = require('./b.json'); +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) + +let x = b1.a; +>x : Symbol(x, Decl(file1.ts, 1, 3)) +>b1.a : Symbol("a", Decl(b.json, 0, 1)) +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) +>a : Symbol("a", Decl(b.json, 0, 1)) + +import b2 = require('./b.json'); +>b2 : Symbol(b2, Decl(file1.ts, 1, 13)) + +if (x) { +>x : Symbol(x, Decl(file1.ts, 1, 3)) + + let b = b2.b; +>b : Symbol(b, Decl(file1.ts, 4, 7)) +>b2.b : Symbol("b", Decl(b.json, 1, 14)) +>b2 : Symbol(b2, Decl(file1.ts, 1, 13)) +>b : Symbol("b", Decl(b.json, 1, 14)) + + x = (b1.b === b); +>x : Symbol(x, Decl(file1.ts, 1, 3)) +>b1.b : Symbol("b", Decl(b.json, 1, 14)) +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) +>b : Symbol("b", Decl(b.json, 1, 14)) +>b : Symbol(b, Decl(file1.ts, 4, 7)) +} + +=== tests/cases/compiler/b.json === +{ + "a": true, +>"a" : Symbol("a", Decl(b.json, 0, 1)) + + "b": "hello" +>"b" : Symbol("b", Decl(b.json, 1, 14)) +} diff --git a/tests/baselines/reference/requireOfJsonFileWithDeclaration.types b/tests/baselines/reference/requireOfJsonFileWithDeclaration.types new file mode 100644 index 00000000000..c718c429408 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithDeclaration.types @@ -0,0 +1,45 @@ +=== tests/cases/compiler/file1.ts === +import b1 = require('./b.json'); +>b1 : { "a": boolean; "b": string; } + +let x = b1.a; +>x : boolean +>b1.a : boolean +>b1 : { "a": boolean; "b": string; } +>a : boolean + +import b2 = require('./b.json'); +>b2 : { "a": boolean; "b": string; } + +if (x) { +>x : boolean + + let b = b2.b; +>b : string +>b2.b : string +>b2 : { "a": boolean; "b": string; } +>b : string + + x = (b1.b === b); +>x = (b1.b === b) : boolean +>x : boolean +>(b1.b === b) : boolean +>b1.b === b : boolean +>b1.b : string +>b1 : { "a": boolean; "b": string; } +>b : string +>b : string +} + +=== tests/cases/compiler/b.json === +{ +>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; } + + "a": true, +>"a" : boolean +>true : true + + "b": "hello" +>"b" : string +>"hello" : "hello" +} diff --git a/tests/baselines/reference/requireOfJsonFileWithSourceMap.js b/tests/baselines/reference/requireOfJsonFileWithSourceMap.js new file mode 100644 index 00000000000..2a6b929f662 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithSourceMap.js @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/requireOfJsonFileWithSourceMap.ts] //// + +//// [file1.ts] +import b1 = require('./b.json'); +let x = b1.a; +import b2 = require('./b.json'); +if (x) { + let b = b2.b; + x = (b1.b === b); +} + +//// [b.json] +{ + "a": true, + "b": "hello" +} + +//// [out/b.json] +{ + "a": true, + "b": "hello" +} +//// [out/file1.js] +"use strict"; +exports.__esModule = true; +var b1 = require("./b.json"); +var x = b1.a; +var b2 = require("./b.json"); +if (x) { + var b = b2.b; + x = (b1.b === b); +} +//# sourceMappingURL=file1.js.map \ No newline at end of file diff --git a/tests/baselines/reference/requireOfJsonFileWithSourceMap.js.map b/tests/baselines/reference/requireOfJsonFileWithSourceMap.js.map new file mode 100644 index 00000000000..d0848a65469 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithSourceMap.js.map @@ -0,0 +1,2 @@ +//// [out/file1.js.map] +{"version":3,"file":"file1.js","sourceRoot":"","sources":["../tests/cases/compiler/file1.ts"],"names":[],"mappings":";;AAAA,6BAAgC;AAChC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACb,6BAAgC;AAChC,IAAI,CAAC,EAAE;IACH,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACb,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;CACpB"} \ No newline at end of file diff --git a/tests/baselines/reference/requireOfJsonFileWithSourceMap.sourcemap.txt b/tests/baselines/reference/requireOfJsonFileWithSourceMap.sourcemap.txt new file mode 100644 index 00000000000..ac39c3d7464 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithSourceMap.sourcemap.txt @@ -0,0 +1,145 @@ +=================================================================== +JsFile: file1.js +mapUrl: file1.js.map +sourceRoot: +sources: ../tests/cases/compiler/file1.ts +=================================================================== +------------------------------------------------------------------- +emittedFile:out/file1.js +sourceFile:../tests/cases/compiler/file1.ts +------------------------------------------------------------------- +>>>"use strict"; +>>>exports.__esModule = true; +>>>var b1 = require("./b.json"); +1 > +2 >^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1 > +2 >import b1 = require('./b.json'); +1 >Emitted(3, 1) Source(1, 1) + SourceIndex(0) +2 >Emitted(3, 30) Source(1, 33) + SourceIndex(0) +--- +>>>var x = b1.a; +1 > +2 >^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^ +8 > ^ +9 > ^^^^^^^^^^^^^^^^^-> +1 > + > +2 >let +3 > x +4 > = +5 > b1 +6 > . +7 > a +8 > ; +1 >Emitted(4, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(4, 5) Source(2, 5) + SourceIndex(0) +3 >Emitted(4, 6) Source(2, 6) + SourceIndex(0) +4 >Emitted(4, 9) Source(2, 9) + SourceIndex(0) +5 >Emitted(4, 11) Source(2, 11) + SourceIndex(0) +6 >Emitted(4, 12) Source(2, 12) + SourceIndex(0) +7 >Emitted(4, 13) Source(2, 13) + SourceIndex(0) +8 >Emitted(4, 14) Source(2, 14) + SourceIndex(0) +--- +>>>var b2 = require("./b.json"); +1-> +2 >^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1-> + > +2 >import b2 = require('./b.json'); +1->Emitted(5, 1) Source(3, 1) + SourceIndex(0) +2 >Emitted(5, 30) Source(3, 33) + SourceIndex(0) +--- +>>>if (x) { +1 > +2 >^^^^ +3 > ^ +4 > ^^ +5 > ^^^^^^^^^^^-> +1 > + > +2 >if ( +3 > x +4 > ) +1 >Emitted(6, 1) Source(4, 1) + SourceIndex(0) +2 >Emitted(6, 5) Source(4, 5) + SourceIndex(0) +3 >Emitted(6, 6) Source(4, 6) + SourceIndex(0) +4 >Emitted(6, 8) Source(4, 8) + SourceIndex(0) +--- +>>> var b = b2.b; +1->^^^^ +2 > ^^^^ +3 > ^ +4 > ^^^ +5 > ^^ +6 > ^ +7 > ^ +8 > ^ +9 > ^^^^^-> +1->{ + > +2 > let +3 > b +4 > = +5 > b2 +6 > . +7 > b +8 > ; +1->Emitted(7, 5) Source(5, 5) + SourceIndex(0) +2 >Emitted(7, 9) Source(5, 9) + SourceIndex(0) +3 >Emitted(7, 10) Source(5, 10) + SourceIndex(0) +4 >Emitted(7, 13) Source(5, 13) + SourceIndex(0) +5 >Emitted(7, 15) Source(5, 15) + SourceIndex(0) +6 >Emitted(7, 16) Source(5, 16) + SourceIndex(0) +7 >Emitted(7, 17) Source(5, 17) + SourceIndex(0) +8 >Emitted(7, 18) Source(5, 18) + SourceIndex(0) +--- +>>> x = (b1.b === b); +1->^^^^ +2 > ^ +3 > ^^^ +4 > ^ +5 > ^^ +6 > ^ +7 > ^ +8 > ^^^^^ +9 > ^ +10> ^ +11> ^ +1-> + > +2 > x +3 > = +4 > ( +5 > b1 +6 > . +7 > b +8 > === +9 > b +10> ) +11> ; +1->Emitted(8, 5) Source(6, 5) + SourceIndex(0) +2 >Emitted(8, 6) Source(6, 6) + SourceIndex(0) +3 >Emitted(8, 9) Source(6, 9) + SourceIndex(0) +4 >Emitted(8, 10) Source(6, 10) + SourceIndex(0) +5 >Emitted(8, 12) Source(6, 12) + SourceIndex(0) +6 >Emitted(8, 13) Source(6, 13) + SourceIndex(0) +7 >Emitted(8, 14) Source(6, 14) + SourceIndex(0) +8 >Emitted(8, 19) Source(6, 19) + SourceIndex(0) +9 >Emitted(8, 20) Source(6, 20) + SourceIndex(0) +10>Emitted(8, 21) Source(6, 21) + SourceIndex(0) +11>Emitted(8, 22) Source(6, 22) + SourceIndex(0) +--- +>>>} +1 >^ +2 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +1 > + >} +1 >Emitted(9, 2) Source(7, 2) + SourceIndex(0) +--- +>>>//# sourceMappingURL=file1.js.map \ No newline at end of file diff --git a/tests/baselines/reference/requireOfJsonFileWithSourceMap.symbols b/tests/baselines/reference/requireOfJsonFileWithSourceMap.symbols new file mode 100644 index 00000000000..a8f82b6b145 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithSourceMap.symbols @@ -0,0 +1,38 @@ +=== tests/cases/compiler/file1.ts === +import b1 = require('./b.json'); +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) + +let x = b1.a; +>x : Symbol(x, Decl(file1.ts, 1, 3)) +>b1.a : Symbol("a", Decl(b.json, 0, 1)) +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) +>a : Symbol("a", Decl(b.json, 0, 1)) + +import b2 = require('./b.json'); +>b2 : Symbol(b2, Decl(file1.ts, 1, 13)) + +if (x) { +>x : Symbol(x, Decl(file1.ts, 1, 3)) + + let b = b2.b; +>b : Symbol(b, Decl(file1.ts, 4, 7)) +>b2.b : Symbol("b", Decl(b.json, 1, 14)) +>b2 : Symbol(b2, Decl(file1.ts, 1, 13)) +>b : Symbol("b", Decl(b.json, 1, 14)) + + x = (b1.b === b); +>x : Symbol(x, Decl(file1.ts, 1, 3)) +>b1.b : Symbol("b", Decl(b.json, 1, 14)) +>b1 : Symbol(b1, Decl(file1.ts, 0, 0)) +>b : Symbol("b", Decl(b.json, 1, 14)) +>b : Symbol(b, Decl(file1.ts, 4, 7)) +} + +=== tests/cases/compiler/b.json === +{ + "a": true, +>"a" : Symbol("a", Decl(b.json, 0, 1)) + + "b": "hello" +>"b" : Symbol("b", Decl(b.json, 1, 14)) +} diff --git a/tests/baselines/reference/requireOfJsonFileWithSourceMap.types b/tests/baselines/reference/requireOfJsonFileWithSourceMap.types new file mode 100644 index 00000000000..c718c429408 --- /dev/null +++ b/tests/baselines/reference/requireOfJsonFileWithSourceMap.types @@ -0,0 +1,45 @@ +=== tests/cases/compiler/file1.ts === +import b1 = require('./b.json'); +>b1 : { "a": boolean; "b": string; } + +let x = b1.a; +>x : boolean +>b1.a : boolean +>b1 : { "a": boolean; "b": string; } +>a : boolean + +import b2 = require('./b.json'); +>b2 : { "a": boolean; "b": string; } + +if (x) { +>x : boolean + + let b = b2.b; +>b : string +>b2.b : string +>b2 : { "a": boolean; "b": string; } +>b : string + + x = (b1.b === b); +>x = (b1.b === b) : boolean +>x : boolean +>(b1.b === b) : boolean +>b1.b === b : boolean +>b1.b : string +>b1 : { "a": boolean; "b": string; } +>b : string +>b : string +} + +=== tests/cases/compiler/b.json === +{ +>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; } + + "a": true, +>"a" : boolean +>true : true + + "b": "hello" +>"b" : string +>"hello" : "hello" +} diff --git a/tests/cases/compiler/requireOfJsonFileWithDeclaration.ts b/tests/cases/compiler/requireOfJsonFileWithDeclaration.ts new file mode 100644 index 00000000000..5a288ce76ca --- /dev/null +++ b/tests/cases/compiler/requireOfJsonFileWithDeclaration.ts @@ -0,0 +1,20 @@ +// @module: commonjs +// @outdir: out/ +// @fullEmitPaths: true +// @resolveJsonModule: true +// @declaration: true + +// @Filename: file1.ts +import b1 = require('./b.json'); +let x = b1.a; +import b2 = require('./b.json'); +if (x) { + let b = b2.b; + x = (b1.b === b); +} + +// @Filename: b.json +{ + "a": true, + "b": "hello" +} \ No newline at end of file diff --git a/tests/cases/compiler/requireOfJsonFileWithSourceMap.ts b/tests/cases/compiler/requireOfJsonFileWithSourceMap.ts new file mode 100644 index 00000000000..d83fbda47a0 --- /dev/null +++ b/tests/cases/compiler/requireOfJsonFileWithSourceMap.ts @@ -0,0 +1,21 @@ +// @module: commonjs +// @outdir: out/ +// @allowJs: true +// @fullEmitPaths: true +// @resolveJsonModule: true +// @sourceMap: true + +// @Filename: file1.ts +import b1 = require('./b.json'); +let x = b1.a; +import b2 = require('./b.json'); +if (x) { + let b = b2.b; + x = (b1.b === b); +} + +// @Filename: b.json +{ + "a": true, + "b": "hello" +} \ No newline at end of file