• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    describe("unittests:: tsbuild:: outFile::", () => {
3        let outFileFs: vfs.FileSystem;
4        let outFileWithBuildFs: vfs.FileSystem;
5        before(() => {
6            outFileFs = loadProjectFromDisk("tests/projects/outfile-concat");
7        });
8        after(() => {
9            outFileFs = undefined!;
10            outFileWithBuildFs = undefined!;
11        });
12
13        interface VerifyOutFileScenarioInput {
14            subScenario: string;
15            modifyFs?: (fs: vfs.FileSystem) => void;
16            modifyAgainFs?: (fs: vfs.FileSystem) => void;
17            ignoreDtsChanged?: true;
18            ignoreDtsUnchanged?: true;
19            baselineOnly?: true;
20            additionalCommandLineArgs?: string[];
21        }
22
23        function verifyOutFileScenario({
24            subScenario,
25            modifyFs,
26            modifyAgainFs,
27            ignoreDtsChanged,
28            ignoreDtsUnchanged,
29            baselineOnly,
30            additionalCommandLineArgs,
31        }: VerifyOutFileScenarioInput) {
32            const edits: TestTscEdit[] = [];
33            if (!ignoreDtsChanged) {
34                edits.push({
35                    subScenario: "incremental-declaration-changes",
36                    modifyFs: fs => replaceText(fs, "/src/first/first_PART1.ts", "Hello", "Hola"),
37                });
38            }
39            if (!ignoreDtsUnchanged) {
40                edits.push({
41                    subScenario: "incremental-declaration-doesnt-change",
42                    modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
43                });
44            }
45            if (modifyAgainFs) {
46                edits.push({
47                    subScenario: "incremental-headers-change-without-dts-changes",
48                    modifyFs: modifyAgainFs
49                });
50            }
51            const input: VerifyTscWithEditsInput = {
52                subScenario,
53                fs: () => outFileFs,
54                scenario: "outfile-concat",
55                commandLineArgs: ["--b", "/src/third", "--verbose", ...(additionalCommandLineArgs || [])],
56                baselineSourceMap: true,
57                modifyFs,
58                baselineReadFileCalls: !baselineOnly,
59                edits,
60            };
61            return edits.length ?
62                verifyTscWithEdits(input) :
63                verifyTsc(input);
64        }
65
66        // Verify initial + incremental edits
67        verifyOutFileScenario({
68            subScenario: "baseline sectioned sourcemaps",
69        });
70
71        verifyOutFileScenario({
72            subScenario: "explainFiles",
73            additionalCommandLineArgs: ["--explainFiles"],
74            baselineOnly: true
75        });
76
77        // Verify baseline with build info + dts unChanged
78        verifyOutFileScenario({
79            subScenario: "when final project is not composite but uses project references",
80            modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
81            ignoreDtsChanged: true,
82            baselineOnly: true
83        });
84
85        // Verify baseline with build info
86        verifyOutFileScenario({
87            subScenario: "when final project is not composite but incremental",
88            modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"incremental": true,`),
89            ignoreDtsChanged: true,
90            ignoreDtsUnchanged: true,
91            baselineOnly: true
92        });
93
94        // Verify baseline with build info
95        verifyOutFileScenario({
96            subScenario: "when final project specifies tsBuildInfoFile",
97            modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true,
98        "tsBuildInfoFile": "./thirdjs/output/third.tsbuildinfo",`),
99            ignoreDtsChanged: true,
100            ignoreDtsUnchanged: true,
101            baselineOnly: true
102        });
103
104        function getOutFileFsAfterBuild() {
105            if (outFileWithBuildFs) return outFileWithBuildFs;
106            const fs = outFileFs.shadow();
107            const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" });
108            const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem);
109            const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true });
110            builder.build();
111            fs.makeReadonly();
112            return outFileWithBuildFs = fs;
113        }
114
115        verifyTscWithEdits({
116            scenario: "outFile",
117            subScenario: "clean projects",
118            fs: getOutFileFsAfterBuild,
119            commandLineArgs: ["--b", "/src/third", "--clean"],
120            edits: noChangeOnlyRuns
121        });
122
123        verifyTsc({
124            scenario: "outFile",
125            subScenario: "verify buildInfo absence results in new build",
126            fs: getOutFileFsAfterBuild,
127            commandLineArgs: ["--b", "/src/third", "--verbose"],
128            modifyFs: fs => fs.unlinkSync("/src/first/bin/first-output.tsbuildinfo"),
129        });
130
131        verifyTsc({
132            scenario: "outFile",
133            subScenario: "tsbuildinfo is not generated when incremental is set to false",
134            fs: () => outFileFs,
135            commandLineArgs: ["--b", "/src/third", "--verbose"],
136            modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
137        });
138
139        verifyTscCompileLike(testTscCompileLike, {
140            scenario: "outFile",
141            subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
142            fs: getOutFileFsAfterBuild,
143            commandLineArgs: ["--b", "/src/third", "--verbose"],
144            compile: sys => {
145                // Buildinfo will have version which does not match with current ts version
146                const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion");
147                const builder = createSolutionBuilder(buildHost, ["/src/third"], { verbose: true });
148                sys.exit(builder.build());
149            }
150        });
151
152        verifyTscWithEdits({
153            scenario: "outFile",
154            subScenario: "rebuilds completely when command line incremental flag changes between non dts changes",
155            fs: () => outFileFs,
156            // Make non composite third project
157            modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
158            // Build with command line incremental
159            commandLineArgs: ["--b", "/src/third", "--i", "--verbose"],
160            edits: [
161                {
162                    subScenario: "Make non incremental build with change in file that doesnt affect dts",
163                    modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
164                    commandLineArgs: ["--b", "/src/third", "--verbose"],
165                },
166                {
167                    subScenario: "Make incremental build with change in file that doesnt affect dts",
168                    modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
169                    commandLineArgs: ["--b", "/src/third", "--verbose", "--incremental"],
170                }
171            ]
172        });
173
174        verifyTscWithEdits({
175            scenario: "outFile",
176            subScenario: "when input file text does not change but its modified time changes",
177            fs: () => outFileFs,
178            commandLineArgs: ["--b", "/src/third", "--verbose"],
179            edits: [
180                {
181                    subScenario: "upstream project changes without changing file text",
182                    modifyFs: fs => {
183                        const time = new Date(fs.time());
184                        fs.utimesSync("/src/first/first_PART1.ts", time, time);
185                    },
186                },
187            ]
188        });
189
190        verifyTscCompileLike(testTscCompileLike, {
191            scenario: "outFile",
192            subScenario: "builds till project specified",
193            fs: () => outFileFs,
194            commandLineArgs: ["--build", "/src/second/tsconfig.json"],
195            compile: sys => {
196                const buildHost = createSolutionBuilderHostForBaseline(sys);
197                const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
198                sys.exit(builder.build("/src/second/tsconfig.json"));
199            }
200        });
201
202        verifyTscCompileLike(testTscCompileLike, {
203            scenario: "outFile",
204            subScenario: "cleans till project specified",
205            fs: getOutFileFsAfterBuild,
206            commandLineArgs: ["--build", "--clean", "/src/second/tsconfig.json"],
207            compile: sys => {
208                const buildHost = createSolutionBuilderHostForBaseline(sys);
209                const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true });
210                sys.exit(builder.clean("/src/second/tsconfig.json"));
211            }
212        });
213
214        describe("Prepend output with .tsbuildinfo", () => {
215            // Prologues
216            describe("Prologues", () => {
217                // Verify initial + incremental edits
218                verifyOutFileScenario({
219                    subScenario: "strict in all projects",
220                    modifyFs: fs => {
221                        enableStrict(fs, "/src/first/tsconfig.json");
222                        enableStrict(fs, "/src/second/tsconfig.json");
223                        enableStrict(fs, "/src/third/tsconfig.json");
224                    },
225                    modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`)
226                });
227
228                // Verify ignore dtsChanged
229                verifyOutFileScenario({
230                    subScenario: "strict in one dependency",
231                    modifyFs: fs => enableStrict(fs, "/src/second/tsconfig.json"),
232                    modifyAgainFs: fs => addTestPrologue(fs, "src/first/first_PART1.ts", `"myPrologue"`),
233                    ignoreDtsChanged: true,
234                    baselineOnly: true
235                });
236
237                // Verify initial + incremental edits - sourcemap verification
238                verifyOutFileScenario({
239                    subScenario: "multiple prologues in all projects",
240                    modifyFs: fs => {
241                        enableStrict(fs, "/src/first/tsconfig.json");
242                        addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`);
243                        enableStrict(fs, "/src/second/tsconfig.json");
244                        addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`);
245                        addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`);
246                        enableStrict(fs, "/src/third/tsconfig.json");
247                        addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue";`);
248                        addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue3";`);
249                    },
250                    modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`)
251                });
252
253                // Verify ignore dtsChanged
254                verifyOutFileScenario({
255                    subScenario: "multiple prologues in different projects",
256                    modifyFs: fs => {
257                        enableStrict(fs, "/src/first/tsconfig.json");
258                        addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`);
259                        addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`);
260                        enableStrict(fs, "/src/third/tsconfig.json");
261                    },
262                    modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`),
263                    ignoreDtsChanged: true,
264                    baselineOnly: true
265                });
266            });
267
268            // Shebang
269            describe("Shebang", () => {
270                // changes declaration because its emitted in .d.ts file
271                // Verify initial + incremental edits
272                verifyOutFileScenario({
273                    subScenario: "shebang in all projects",
274                    modifyFs: fs => {
275                        addShebang(fs, "first", "first_PART1");
276                        addShebang(fs, "first", "first_part2");
277                        addShebang(fs, "second", "second_part1");
278                        addShebang(fs, "third", "third_part1");
279                    },
280                });
281
282                // Verify ignore dtsChanged
283                verifyOutFileScenario({
284                    subScenario: "shebang in only one dependency project",
285                    modifyFs: fs => addShebang(fs, "second", "second_part1"),
286                    ignoreDtsChanged: true,
287                    baselineOnly: true
288                });
289            });
290
291            // emitHelpers
292            describe("emitHelpers", () => {
293                // Verify initial + incremental edits
294                verifyOutFileScenario({
295                    subScenario: "emitHelpers in all projects",
296                    modifyFs: fs => {
297                        addRest(fs, "first", "first_PART1");
298                        addRest(fs, "second", "second_part1");
299                        addRest(fs, "third", "third_part1");
300                    },
301                    modifyAgainFs: fs => removeRest(fs, "first", "first_PART1")
302                });
303
304                // Verify ignore dtsChanged
305                verifyOutFileScenario({
306                    subScenario: "emitHelpers in only one dependency project",
307                    modifyFs: fs => {
308                        addStubFoo(fs, "first", "first_PART1");
309                        addRest(fs, "second", "second_part1");
310                    },
311                    modifyAgainFs: fs => changeStubToRest(fs, "first", "first_PART1"),
312                    ignoreDtsChanged: true,
313                    baselineOnly: true
314                });
315
316                // Verify ignore dtsChanged
317                verifyOutFileScenario({
318                    subScenario: "multiple emitHelpers in all projects",
319                    modifyFs: fs => {
320                        addRest(fs, "first", "first_PART1");
321                        addSpread(fs, "first", "first_part3");
322                        addRest(fs, "second", "second_part1");
323                        addSpread(fs, "second", "second_part2");
324                        addRest(fs, "third", "third_part1");
325                        addSpread(fs, "third", "third_part1");
326                    },
327                    modifyAgainFs: fs => removeRest(fs, "first", "first_PART1"),
328                    ignoreDtsChanged: true,
329                    baselineOnly: true
330                });
331
332                // Verify ignore dtsChanged
333                verifyOutFileScenario({
334                    subScenario: "multiple emitHelpers in different projects",
335                    modifyFs: fs => {
336                        addRest(fs, "first", "first_PART1");
337                        addSpread(fs, "second", "second_part1");
338                        addRest(fs, "third", "third_part1");
339                    },
340                    modifyAgainFs: fs => removeRest(fs, "first", "first_PART1"),
341                    ignoreDtsChanged: true,
342                    baselineOnly: true
343                });
344            });
345
346            // triple slash refs
347            describe("triple slash refs", () => {
348                // changes declaration because its emitted in .d.ts file
349                // Verify initial + incremental edits
350                verifyOutFileScenario({
351                    subScenario: "triple slash refs in all projects",
352                    modifyFs: fs => {
353                        addTripleSlashRef(fs, "first", "first_part2");
354                        addTripleSlashRef(fs, "second", "second_part1");
355                        addTripleSlashRef(fs, "third", "third_part1");
356                    }
357                });
358
359                // Verify ignore dtsChanged
360                verifyOutFileScenario({
361                    subScenario: "triple slash refs in one project",
362                    modifyFs: fs => addTripleSlashRef(fs, "second", "second_part1"),
363                    ignoreDtsChanged: true,
364                    baselineOnly: true
365                });
366            });
367
368            describe("stripInternal", () => {
369                function disableRemoveComments(fs: vfs.FileSystem, file: string) {
370                    replaceText(fs, file, `"removeComments": true`, `"removeComments": false`);
371                }
372
373                function diableRemoveCommentsInAll(fs: vfs.FileSystem) {
374                    disableRemoveComments(fs, "/src/first/tsconfig.json");
375                    disableRemoveComments(fs, "/src/second/tsconfig.json");
376                    disableRemoveComments(fs, "/src/third/tsconfig.json");
377                }
378
379                function stripInternalOfThird(fs: vfs.FileSystem) {
380                    replaceText(fs, "/src/third/tsconfig.json", `"declaration": true,`, `"declaration": true,
381    "stripInternal": true,`);
382                }
383
384                function stripInternalScenario(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) {
385                    const internal: string = jsDocStyle ? `/**@internal*/` : `/*@internal*/`;
386                    if (removeCommentsDisabled) {
387                        diableRemoveCommentsInAll(fs);
388                    }
389                    stripInternalOfThird(fs);
390                    replaceText(fs, "/src/first/first_PART1.ts", "interface", `${internal} interface`);
391                    appendText(fs, "/src/second/second_part1.ts", `
392class normalC {
393    ${internal} constructor() { }
394    ${internal} prop: string;
395    ${internal} method() { }
396    ${internal} get c() { return 10; }
397    ${internal} set c(val: number) { }
398}
399namespace normalN {
400    ${internal} export class C { }
401    ${internal} export function foo() {}
402    ${internal} export namespace someNamespace { export class C {} }
403    ${internal} export namespace someOther.something { export class someClass {} }
404    ${internal} export import someImport = someNamespace.C;
405    ${internal} export type internalType = internalC;
406    ${internal} export const internalConst = 10;
407    ${internal} export enum internalEnum { a, b, c }
408}
409${internal} class internalC {}
410${internal} function internalfoo() {}
411${internal} namespace internalNamespace { export class someClass {} }
412${internal} namespace internalOther.something { export class someClass {} }
413${internal} import internalImport = internalNamespace.someClass;
414${internal} type internalType = internalC;
415${internal} const internalConst = 10;
416${internal} enum internalEnum { a, b, c }`);
417                }
418
419                // Verify initial + incremental edits
420                verifyOutFileScenario({
421                    subScenario: "stripInternal",
422                    modifyFs: stripInternalScenario,
423                    modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
424                });
425
426                // Verify ignore dtsChanged
427                verifyOutFileScenario({
428                    subScenario: "stripInternal with comments emit enabled",
429                    modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ true),
430                    modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
431                    ignoreDtsChanged: true,
432                    baselineOnly: true
433                });
434
435                // Verify ignore dtsChanged
436                verifyOutFileScenario({
437                    subScenario: "stripInternal jsdoc style comment",
438                    modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true),
439                    modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"),
440                    ignoreDtsChanged: true,
441                    baselineOnly: true
442                });
443
444                // Verify ignore dtsChanged
445                verifyOutFileScenario({
446                    subScenario: "stripInternal jsdoc style with comments emit enabled",
447                    modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ true, /*jsDocStyle*/ true),
448                    ignoreDtsChanged: true,
449                    baselineOnly: true
450                });
451
452                describe("with three levels of project dependency", () => {
453                    function makeOneTwoThreeDependOrder(fs: vfs.FileSystem) {
454                        replaceText(fs, "/src/second/tsconfig.json", "[", `[
455    { "path": "../first", "prepend": true }`);
456                        replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true },`, "");
457                    }
458
459                    function stripInternalWithDependentOrder(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) {
460                        stripInternalScenario(fs, removeCommentsDisabled, jsDocStyle);
461                        makeOneTwoThreeDependOrder(fs);
462                    }
463
464                    // Verify initial + incremental edits
465                    verifyOutFileScenario({
466                        subScenario: "stripInternal when one-two-three are prepended in order",
467                        modifyFs: stripInternalWithDependentOrder,
468                        modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
469                    });
470
471                    // Verify ignore dtsChanged
472                    verifyOutFileScenario({
473                        subScenario: "stripInternal with comments emit enabled when one-two-three are prepended in order",
474                        modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true),
475                        modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
476                        ignoreDtsChanged: true,
477                        baselineOnly: true
478                    });
479
480                    // Verify ignore dtsChanged
481                    verifyOutFileScenario({
482                        subScenario: "stripInternal jsdoc style comment when one-two-three are prepended in order",
483                        modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true),
484                        modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"),
485                        ignoreDtsChanged: true,
486                        baselineOnly: true
487                    });
488
489                    // Verify ignore dtsChanged
490                    verifyOutFileScenario({
491                        subScenario: "stripInternal jsdoc style with comments emit enabled when one-two-three are prepended in order",
492                        modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true, /*jsDocStyle*/ true),
493                        ignoreDtsChanged: true,
494                        baselineOnly: true
495                    });
496                });
497
498                // only baseline
499                verifyOutFileScenario({
500                    subScenario: "stripInternal baseline when internal is inside another internal",
501                    modifyFs: fs => {
502                        stripInternalOfThird(fs);
503                        prependText(fs, "/src/first/first_PART1.ts", `namespace ts {
504    /* @internal */
505    /**
506     * Subset of properties from SourceFile that are used in multiple utility functions
507     */
508    export interface SourceFileLike {
509        readonly text: string;
510        lineMap?: ReadonlyArray<number>;
511        /* @internal */
512        getPositionOfLineAndCharacter?(line: number, character: number, allowEdits?: true): number;
513    }
514
515    /* @internal */
516    export interface RedirectInfo {
517        /** Source file this redirects to. */
518        readonly redirectTarget: SourceFile;
519        /**
520         * Source file for the duplicate package. This will not be used by the Program,
521         * but we need to keep this around so we can watch for changes in underlying.
522         */
523        readonly unredirected: SourceFile;
524    }
525
526    // Source files are declarations when they are external modules.
527    export interface SourceFile {
528        someProp: string;
529    }
530}`);
531                    },
532                    ignoreDtsChanged: true,
533                    ignoreDtsUnchanged: true,
534                    baselineOnly: true
535                });
536
537                // only baseline
538                verifyOutFileScenario({
539                    subScenario: "stripInternal when few members of enum are internal",
540                    modifyFs: fs => {
541                        stripInternalOfThird(fs);
542                        prependText(fs, "/src/first/first_PART1.ts", `enum TokenFlags {
543    None = 0,
544    /* @internal */
545    PrecedingLineBreak = 1 << 0,
546    /* @internal */
547    PrecedingJSDocComment = 1 << 1,
548    /* @internal */
549    Unterminated = 1 << 2,
550    /* @internal */
551    ExtendedUnicodeEscape = 1 << 3,
552    Scientific = 1 << 4,
553    Octal = 1 << 5,
554    HexSpecifier = 1 << 6,
555    BinarySpecifier = 1 << 7,
556    OctalSpecifier = 1 << 8,
557    /* @internal */
558    ContainsSeparator = 1 << 9,
559    /* @internal */
560    BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
561    /* @internal */
562    NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
563}
564`);
565                    },
566                    ignoreDtsChanged: true,
567                    ignoreDtsUnchanged: true,
568                    baselineOnly: true
569                });
570
571                verifyOutFileScenario({
572                    subScenario: "stripInternal when prepend is completely internal",
573                    baselineOnly: true,
574                    ignoreDtsChanged: true,
575                    ignoreDtsUnchanged: true,
576                    modifyFs: fs => {
577                        fs.writeFileSync("/src/first/first_PART1.ts", "/* @internal */ const A = 1;");
578                        fs.writeFileSync("/src/third/third_part1.ts", "const B = 2;");
579                        fs.writeFileSync("/src/first/tsconfig.json", JSON.stringify({
580                            compilerOptions: {
581                                composite: true,
582                                declaration: true,
583                                declarationMap: true,
584                                skipDefaultLibCheck: true,
585                                sourceMap: true,
586                                outFile: "./bin/first-output.js"
587                            },
588                            files: ["/src/first/first_PART1.ts"]
589                        }));
590                        fs.writeFileSync("/src/third/tsconfig.json", JSON.stringify({
591                            compilerOptions: {
592                                composite: true,
593                                declaration: true,
594                                declarationMap: false,
595                                stripInternal: true,
596                                sourceMap: true,
597                                outFile: "./thirdjs/output/third-output.js",
598                            },
599                            references: [{ path: "../first", prepend: true }],
600                            files: ["/src/third/third_part1.ts"]
601                        }));
602                    }
603                });
604            });
605
606            describe("empty source files", () => {
607                function makeThirdEmptySourceFile(fs: vfs.FileSystem) {
608                    fs.writeFileSync("/src/third/third_part1.ts", "", "utf8");
609                }
610
611                // Verify ignore dtsChanged
612                verifyOutFileScenario({
613                    subScenario: "when source files are empty in the own file",
614                    modifyFs: makeThirdEmptySourceFile,
615                    ignoreDtsChanged: true,
616                    baselineOnly: true
617                });
618
619                // only baseline
620                verifyOutFileScenario({
621                    subScenario: "declarationMap and sourceMap disabled",
622                    modifyFs: fs => {
623                        makeThirdEmptySourceFile(fs);
624                        replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, "");
625                        replaceText(fs, "/src/third/tsconfig.json", `"sourceMap": true,`, "");
626                        replaceText(fs, "/src/third/tsconfig.json", `"declarationMap": true,`, "");
627                    },
628                    ignoreDtsChanged: true,
629                    ignoreDtsUnchanged: true,
630                    baselineOnly: true
631                });
632            });
633        });
634
635        verifyTsc({
636            scenario: "outFile",
637            subScenario: "non module projects without prepend",
638            fs: () => outFileFs,
639            commandLineArgs: ["--b", "/src/third", "--verbose"],
640            modifyFs: fs => {
641                // No prepend
642                replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`);
643                replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`);
644
645                // Non Modules
646                replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
647                replaceText(fs, "/src/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
648                replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
649
650                // Own file emit
651                replaceText(fs, "/src/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, "");
652                replaceText(fs, "/src/second/tsconfig.json", `"outFile": "../2/second-output.js",`, "");
653                replaceText(fs, "/src/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, "");
654            },
655        });
656    });
657}
658