1namespace ts.tscWatch { 2 describe("unittests:: tsc:: builder cancellationToken", () => { 3 verifyCancellation(/*useBuildInfo*/ true, "when emitting buildInfo"); 4 verifyCancellation(/*useBuildInfo*/ false, "when using state"); 5 function verifyCancellation(useBuildInfo: boolean, scenario: string) { 6 it(scenario, () => { 7 const aFile: File = { 8 path: `${projectRoot}/a.ts`, 9 content: Utils.dedent` 10 import {B} from './b'; 11 declare var console: any; 12 let b = new B(); 13 console.log(b.c.d);` 14 }; 15 const bFile: File = { 16 path: `${projectRoot}/b.ts`, 17 content: Utils.dedent` 18 import {C} from './c'; 19 export class B { 20 c = new C(); 21 }` 22 }; 23 const cFile: File = { 24 path: `${projectRoot}/c.ts`, 25 content: Utils.dedent` 26 export class C { 27 d = 1; 28 }` 29 }; 30 const dFile: File = { 31 path: `${projectRoot}/d.ts`, 32 content: "export class D { }" 33 }; 34 const config: File = { 35 path: `${projectRoot}/tsconfig.json`, 36 content: JSON.stringify({ compilerOptions: { incremental: true, declaration: true } }) 37 }; 38 const { sys, baseline, oldSnap: originalSnap } = createBaseline(createWatchedSystem( 39 [aFile, bFile, cFile, dFile, config, libFile], 40 { currentDirectory: projectRoot } 41 )); 42 sys.exit = exitCode => sys.exitCode = exitCode; 43 const reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true); 44 const parsedConfig = parseConfigFileWithSystem( 45 "tsconfig.json", 46 {}, 47 /*extendedConfigCache*/ undefined, 48 /*watchOptionsToExtend*/ undefined, 49 sys, 50 reportDiagnostic 51 )!; 52 const host = createIncrementalCompilerHost(parsedConfig.options, sys); 53 let programs: CommandLineProgram[] = emptyArray; 54 let oldPrograms: CommandLineProgram[] = emptyArray; 55 let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram = undefined!; 56 let oldSnap = originalSnap; 57 let cancel = false; 58 const cancellationToken: CancellationToken = { 59 isCancellationRequested: () => cancel, 60 throwIfCancellationRequested: () => { 61 if (cancel) { 62 sys.write(`Cancelled!!\r\n`); 63 throw new OperationCanceledException(); 64 } 65 }, 66 }; 67 68 // Initial build 69 baselineBuild(); 70 71 // Cancel on first semantic operation 72 // Change 73 oldSnap = applyChange( 74 sys, 75 baseline, 76 sys => sys.appendFile(cFile.path, "export function foo() {}"), 77 "Add change that affects d.ts" 78 ); 79 createIncrementalProgram(); 80 81 // Cancel during semantic diagnostics 82 cancel = true; 83 try { 84 builderProgram.getSemanticDiagnosticsOfNextAffectedFile(cancellationToken); 85 } 86 catch (e) { 87 sys.write(`Operation ws cancelled:: ${e instanceof OperationCanceledException}\r\n`); 88 } 89 cancel = false; 90 builderProgram.emitBuildInfo(); 91 baselineBuildInfo(builderProgram.getCompilerOptions(), sys); 92 watchBaseline({ 93 baseline, 94 getPrograms: () => programs, 95 oldPrograms, 96 sys, 97 oldSnap, 98 }); 99 100 // Normal emit again 101 noChange("Normal build"); 102 baselineBuild(); 103 104 // Do clean build:: all the emitted files should be same 105 noChange("Clean build"); 106 baselineCleanBuild(); 107 108 Harness.Baseline.runBaseline(`tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, baseline.join("\r\n")); 109 110 function noChange(caption: string) { 111 oldSnap = applyChange(sys, baseline, noop, caption); 112 } 113 114 function updatePrograms() { 115 oldPrograms = programs; 116 programs = [[builderProgram.getProgram(), builderProgram]]; 117 } 118 119 function createIncrementalProgram() { 120 builderProgram = useBuildInfo ? 121 ts.createIncrementalProgram({ 122 rootNames: parsedConfig.fileNames, 123 options: parsedConfig.options, 124 host, 125 }) : 126 builderProgram = builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram( 127 parsedConfig.fileNames, 128 parsedConfig.options, 129 host, 130 builderProgram, 131 /* configFileParsingDiagnostics*/ undefined, 132 /*projectReferences*/ undefined, 133 ); 134 updatePrograms(); 135 } 136 137 function emitAndBaseline() { 138 emitFilesAndReportErrorsAndGetExitStatus(builderProgram, reportDiagnostic); 139 baselineBuildInfo(builderProgram.getCompilerOptions(), sys); 140 watchBaseline({ 141 baseline, 142 getPrograms: () => programs, 143 oldPrograms, 144 sys, 145 oldSnap, 146 }); 147 } 148 149 function baselineBuild() { 150 createIncrementalProgram(); 151 emitAndBaseline(); 152 } 153 154 function baselineCleanBuild() { 155 builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram( 156 parsedConfig.fileNames, 157 parsedConfig.options, 158 host, 159 /*oldProgram*/ undefined, 160 /* configFileParsingDiagnostics*/ undefined, 161 /*projectReferences*/ undefined, 162 ); 163 updatePrograms(); 164 emitAndBaseline(); 165 } 166 }); 167 } 168 }); 169}