@rushstack/heft-typescript-plugin 0.1.0-rc.5 → 0.2.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,25 +28,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
28
28
  exports.TypeScriptBuilder = void 0;
29
29
  const crypto = __importStar(require("crypto"));
30
30
  const path = __importStar(require("path"));
31
+ const worker_threads_1 = require("worker_threads");
31
32
  const semver = __importStar(require("semver"));
32
33
  const node_core_library_1 = require("@rushstack/node-core-library");
33
- const TypeScriptCachedFileSystem_1 = require("./fileSystem/TypeScriptCachedFileSystem");
34
+ const configureProgramForMultiEmit_1 = require("./configureProgramForMultiEmit");
34
35
  const OLDEST_SUPPORTED_TS_MAJOR_VERSION = 2;
35
36
  const OLDEST_SUPPORTED_TS_MINOR_VERSION = 9;
36
37
  const NEWEST_SUPPORTED_TS_MAJOR_VERSION = 5;
37
38
  const NEWEST_SUPPORTED_TS_MINOR_VERSION = 0;
38
- // symbols for attaching hidden metadata to ts.Program instances.
39
- const INNER_GET_COMPILER_OPTIONS_SYMBOL = Symbol('getCompilerOptions');
40
- const INNER_EMIT_SYMBOL = Symbol('emit');
41
39
  class TypeScriptBuilder {
42
- constructor(configuration) {
43
- this._suppressedDiagnosticCodes = new Set();
44
- this._cachedFileSystem = new TypeScriptCachedFileSystem_1.TypeScriptCachedFileSystem();
45
- this._tool = undefined;
46
- this._configuration = configuration;
47
- this._typescriptLogger = configuration.scopedLogger;
48
- this._typescriptTerminal = configuration.scopedLogger.terminal;
49
- }
50
40
  get _tsCacheFilePath() {
51
41
  if (!this.__tsCacheFilePath) {
52
42
  // TypeScript internally handles if the tsconfig options have changed from when the tsbuildinfo file was created.
@@ -66,6 +56,14 @@ class TypeScriptBuilder {
66
56
  }
67
57
  return this.__tsCacheFilePath;
68
58
  }
59
+ constructor(configuration) {
60
+ this._suppressedDiagnosticCodes = new Set();
61
+ this._tool = undefined;
62
+ this._nextRequestId = 0;
63
+ this._configuration = configuration;
64
+ this._typescriptLogger = configuration.scopedLogger;
65
+ this._typescriptTerminal = configuration.scopedLogger.terminal;
66
+ }
69
67
  async invokeAsync(onChangeDetected) {
70
68
  var _a, _b;
71
69
  if (!this._tool) {
@@ -133,23 +131,12 @@ class TypeScriptBuilder {
133
131
  ts.performance.measure(measurementName, beforeName, afterName);
134
132
  return Object.assign(Object.assign({}, result), { duration: ts.performance.getDuration(measurementName), count: ts.performance.getCount(beforeName) });
135
133
  };
136
- const measureTsPerformanceAsync = async (measurementName, fn) => {
137
- const beforeName = `before${measurementName}`;
138
- ts.performance.mark(beforeName);
139
- const resultPromise = fn();
140
- const result = await resultPromise;
141
- const afterName = `after${measurementName}`;
142
- ts.performance.mark(afterName);
143
- ts.performance.measure(measurementName, beforeName, afterName);
144
- return Object.assign(Object.assign({}, result), { duration: ts.performance.getDuration(measurementName) });
145
- };
146
134
  this._typescriptTerminal.writeLine(`Using TypeScript version ${ts.version}`);
147
135
  const rawDiagnostics = [];
148
136
  const pendingOperations = new Set();
149
137
  this._tool = {
150
138
  ts,
151
139
  measureSync: measureTsPerformance,
152
- measureAsync: measureTsPerformanceAsync,
153
140
  sourceFileCache: new Map(),
154
141
  watchProgram: undefined,
155
142
  solutionBuilder: undefined,
@@ -171,7 +158,10 @@ class TypeScriptBuilder {
171
158
  onChangeDetected();
172
159
  }
173
160
  return timeout;
174
- }
161
+ },
162
+ worker: undefined,
163
+ pendingTranspilePromises: new Map(),
164
+ pendingTranspileSignals: new Map()
175
165
  };
176
166
  }
177
167
  const { performance } = this._tool.ts;
@@ -179,88 +169,17 @@ class TypeScriptBuilder {
179
169
  performance.disable();
180
170
  performance.enable();
181
171
  if (onChangeDetected !== undefined) {
182
- this._runWatch(this._tool);
172
+ await this._runWatchAsync(this._tool);
183
173
  }
184
174
  else if (this._useSolutionBuilder) {
185
- this._runSolutionBuild(this._tool);
175
+ await this._runSolutionBuildAsync(this._tool);
186
176
  }
187
177
  else {
188
178
  await this._runBuildAsync(this._tool);
189
179
  }
190
180
  }
191
- _configureProgramForMultiEmit(innerProgram, ts) {
192
- const program = innerProgram;
193
- // Check to see if this Program has already been modified.
194
- let { [INNER_EMIT_SYMBOL]: innerEmit, [INNER_GET_COMPILER_OPTIONS_SYMBOL]: innerGetCompilerOptions } = program;
195
- if (!innerGetCompilerOptions) {
196
- program[INNER_GET_COMPILER_OPTIONS_SYMBOL] = innerGetCompilerOptions = program.getCompilerOptions;
197
- }
198
- if (!innerEmit) {
199
- program[INNER_EMIT_SYMBOL] = innerEmit = program.emit;
200
- }
201
- let foundPrimary = false;
202
- let defaultModuleKind;
203
- const multiEmitMap = new Map();
204
- for (const moduleKindToEmit of this._moduleKindsToEmit) {
205
- const kindCompilerOptions = moduleKindToEmit.isPrimary
206
- ? Object.assign({}, innerGetCompilerOptions()) : Object.assign(Object.assign({}, innerGetCompilerOptions()), { module: moduleKindToEmit.moduleKind, outDir: moduleKindToEmit.outFolderPath,
207
- // Don't emit declarations for secondary module kinds
208
- declaration: false, declarationMap: false });
209
- if (!kindCompilerOptions.outDir) {
210
- throw new node_core_library_1.InternalError('Expected compilerOptions.outDir to be assigned');
211
- }
212
- multiEmitMap.set(moduleKindToEmit, kindCompilerOptions);
213
- if (moduleKindToEmit.isPrimary) {
214
- if (foundPrimary) {
215
- throw new Error('Multiple primary module emit kinds encountered.');
216
- }
217
- else {
218
- foundPrimary = true;
219
- }
220
- defaultModuleKind = moduleKindToEmit.moduleKind;
221
- }
222
- }
223
- const changedFiles = new Set();
224
- program.emit = (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => {
225
- if (emitOnlyDtsFiles) {
226
- return program[INNER_EMIT_SYMBOL](targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
227
- }
228
- if (targetSourceFile && changedFiles) {
229
- changedFiles.add(targetSourceFile);
230
- }
231
- const originalCompilerOptions = program[INNER_GET_COMPILER_OPTIONS_SYMBOL]();
232
- let defaultModuleKindResult;
233
- const diagnostics = [];
234
- let emitSkipped = false;
235
- try {
236
- for (const [moduleKindToEmit, kindCompilerOptions] of multiEmitMap) {
237
- program.getCompilerOptions = () => kindCompilerOptions;
238
- // Need to mutate the compiler options for the `module` field specifically, because emitWorker() captures
239
- // options in the closure and passes it to `ts.getTransformers()`
240
- originalCompilerOptions.module = moduleKindToEmit.moduleKind;
241
- const flavorResult = program[INNER_EMIT_SYMBOL](targetSourceFile, writeFile && wrapWriteFile(writeFile, moduleKindToEmit.jsExtensionOverride), cancellationToken, emitOnlyDtsFiles, customTransformers);
242
- emitSkipped = emitSkipped || flavorResult.emitSkipped;
243
- // Need to aggregate diagnostics because some are impacted by the target module type
244
- for (const diagnostic of flavorResult.diagnostics) {
245
- diagnostics.push(diagnostic);
246
- }
247
- if (moduleKindToEmit.moduleKind === defaultModuleKind) {
248
- defaultModuleKindResult = flavorResult;
249
- }
250
- }
251
- const mergedDiagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics);
252
- return Object.assign(Object.assign({}, defaultModuleKindResult), { changedSourceFiles: changedFiles, diagnostics: mergedDiagnostics, emitSkipped });
253
- }
254
- finally {
255
- // Restore the original compiler options and module kind for future calls
256
- program.getCompilerOptions = program[INNER_GET_COMPILER_OPTIONS_SYMBOL];
257
- originalCompilerOptions.module = defaultModuleKind;
258
- }
259
- };
260
- return { changedFiles };
261
- }
262
- _runWatch(tool) {
263
- const { ts, measureSync: measureTsPerformance, pendingOperations, rawDiagnostics } = tool;
181
+ async _runWatchAsync(tool) {
182
+ const { ts, measureSync: measureTsPerformance, pendingOperations, rawDiagnostics, pendingTranspilePromises } = tool;
264
183
  if (!tool.solutionBuilder && !tool.watchProgram) {
265
184
  //#region CONFIGURE
266
185
  const { duration: configureDurationMs, tsconfig } = measureTsPerformance('Configure', () => {
@@ -290,12 +209,21 @@ class TypeScriptBuilder {
290
209
  pendingOperations.delete(operation);
291
210
  operation();
292
211
  }
212
+ if (pendingTranspilePromises.size) {
213
+ const emitResults = await Promise.all(pendingTranspilePromises.values());
214
+ for (const { diagnostics } of emitResults) {
215
+ for (const diagnostic of diagnostics) {
216
+ rawDiagnostics.push(diagnostic);
217
+ }
218
+ }
219
+ }
220
+ // eslint-disable-next-line require-atomic-updates
293
221
  tool.executing = false;
294
222
  }
295
223
  this._logDiagnostics(ts, rawDiagnostics);
296
224
  }
297
225
  async _runBuildAsync(tool) {
298
- const { ts, measureSync: measureTsPerformance, measureAsync: measureTsPerformanceAsync } = tool;
226
+ const { ts, measureSync: measureTsPerformance, pendingTranspilePromises } = tool;
299
227
  //#region CONFIGURE
300
228
  const { duration: configureDurationMs, tsconfig, compilerHost } = measureTsPerformance('Configure', () => {
301
229
  const _tsconfig = this._loadTsconfig(ts);
@@ -312,8 +240,15 @@ class TypeScriptBuilder {
312
240
  // There will be only one program here; emit will get a bit abused if we produce multiple outputs
313
241
  let builderProgram = undefined;
314
242
  let innerProgram;
243
+ const isolatedModules = !!this._configuration.useTranspilerWorker && !!tsconfig.options.isolatedModules;
244
+ const mode = isolatedModules ? 'declaration' : 'both';
245
+ let filesToTranspile;
315
246
  if (tsconfig.options.incremental) {
316
- builderProgram = this._getCreateBuilderProgram(ts)(tsconfig.fileNames, tsconfig.options, compilerHost, ts.readBuilderProgram(tsconfig.options, compilerHost), ts.getConfigFileParsingDiagnostics(tsconfig), tsconfig.projectReferences);
247
+ // Use ts.createEmitAndSemanticDiagnositcsBuilderProgram directly because the customizations performed by
248
+ // _getCreateBuilderProgram duplicate those performed in this function for non-incremental build.
249
+ const oldProgram = ts.readBuilderProgram(tsconfig.options, compilerHost);
250
+ builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(tsconfig.fileNames, tsconfig.options, compilerHost, oldProgram, ts.getConfigFileParsingDiagnostics(tsconfig), tsconfig.projectReferences);
251
+ filesToTranspile = getFilesToTranspileFromBuilderProgram(builderProgram);
317
252
  innerProgram = builderProgram.getProgram();
318
253
  }
319
254
  else {
@@ -325,11 +260,16 @@ class TypeScriptBuilder {
325
260
  oldProgram: undefined,
326
261
  configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(tsconfig)
327
262
  });
263
+ filesToTranspile = getFilesToTranspileFromProgram(innerProgram);
328
264
  }
329
265
  // Prefer the builder program, since it is what gives us incremental builds
330
266
  const genericProgram = builderProgram || innerProgram;
331
267
  this._logReadPerformance(ts);
332
268
  //#endregion
269
+ if (isolatedModules) {
270
+ // Kick the transpilation worker.
271
+ this._queueTranspileInWorker(tool, genericProgram.getCompilerOptions(), filesToTranspile);
272
+ }
333
273
  //#region ANALYSIS
334
274
  const { duration: diagnosticsDurationMs, diagnostics: preDiagnostics } = measureTsPerformance('Analyze', () => {
335
275
  const rawDiagnostics = [
@@ -344,34 +284,34 @@ class TypeScriptBuilder {
344
284
  this._typescriptTerminal.writeVerboseLine(`Analyze: ${diagnosticsDurationMs}ms`);
345
285
  //#endregion
346
286
  //#region EMIT
347
- const filesToWrite = [];
348
- const writeFileCallback = (filePath, data) => {
349
- filesToWrite.push({ filePath, data });
350
- };
351
- const { changedFiles } = this._configureProgramForMultiEmit(innerProgram, ts);
352
- const emitResult = genericProgram.emit(undefined, writeFileCallback);
287
+ const { changedFiles } = (0, configureProgramForMultiEmit_1.configureProgramForMultiEmit)(innerProgram, ts, this._moduleKindsToEmit, mode);
288
+ const emitResult = genericProgram.emit(undefined,
289
+ // The writeFile callback must be provided for the multi-emit redirector
290
+ ts.sys.writeFile, undefined, undefined, undefined);
291
+ this._cleanupWorker();
353
292
  //#endregion
354
293
  this._logEmitPerformance(ts);
355
294
  //#region FINAL_ANALYSIS
356
295
  // Need to ensure that we include emit diagnostics, since they might not be part of the other sets
357
296
  const rawDiagnostics = [...preDiagnostics, ...emitResult.diagnostics];
358
297
  //#endregion
359
- //#region WRITE
360
- // Using async file system I/O for theoretically better peak performance
361
- // Also allows to run concurrently with linting
362
- const writePromise = measureTsPerformanceAsync('Write', () => node_core_library_1.Async.forEachAsync(filesToWrite, async ({ filePath, data }) => this._cachedFileSystem.writeFile(filePath, data, { ensureFolderExists: true }), { concurrency: this._configuration.maxWriteParallelism }));
363
- //#endregion
364
- const { duration: writeDuration } = await writePromise;
365
- this._typescriptTerminal.writeVerboseLine(`I/O Write: ${writeDuration}ms (${filesToWrite.length} files)`);
298
+ this._configuration.emitChangedFilesCallback(innerProgram, changedFiles);
299
+ if (pendingTranspilePromises.size) {
300
+ const emitResults = await Promise.all(pendingTranspilePromises.values());
301
+ for (const { diagnostics } of emitResults) {
302
+ for (const diagnostic of diagnostics) {
303
+ rawDiagnostics.push(diagnostic);
304
+ }
305
+ }
306
+ }
366
307
  this._logDiagnostics(ts, rawDiagnostics);
367
308
  // Reset performance counters in case any are used in the callback
368
309
  ts.performance.disable();
369
310
  ts.performance.enable();
370
- this._configuration.emitChangedFilesCallback(innerProgram, changedFiles);
371
311
  }
372
- _runSolutionBuild(tool) {
312
+ async _runSolutionBuildAsync(tool) {
373
313
  this._typescriptTerminal.writeVerboseLine(`Using solution mode`);
374
- const { ts, measureSync, rawDiagnostics } = tool;
314
+ const { ts, measureSync, rawDiagnostics, pendingTranspilePromises } = tool;
375
315
  rawDiagnostics.length = 0;
376
316
  if (!tool.solutionBuilder) {
377
317
  //#region CONFIGURE
@@ -396,7 +336,16 @@ class TypeScriptBuilder {
396
336
  //#region EMIT
397
337
  // Ignoring the exit status because we only care about presence of diagnostics
398
338
  tool.solutionBuilder.build();
339
+ this._cleanupWorker();
399
340
  //#endregion
341
+ if (pendingTranspilePromises.size) {
342
+ const emitResults = await Promise.all(pendingTranspilePromises.values());
343
+ for (const { diagnostics } of emitResults) {
344
+ for (const diagnostic of diagnostics) {
345
+ rawDiagnostics.push(diagnostic);
346
+ }
347
+ }
348
+ }
400
349
  this._logDiagnostics(ts, rawDiagnostics);
401
350
  }
402
351
  _logDiagnostics(ts, rawDiagnostics) {
@@ -417,6 +366,7 @@ class TypeScriptBuilder {
417
366
  this._typescriptTerminal.writeVerboseLine(`Print: ${ts.performance.getDuration('printTime')}ms ` +
418
367
  `(${ts.performance.getCount('beforePrint')} files) (Includes Transform)`);
419
368
  this._typescriptTerminal.writeVerboseLine(`Emit: ${ts.performance.getDuration('Emit')}ms (Includes Print)`);
369
+ this._typescriptTerminal.writeVerboseLine(`I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount('beforeIOWrite')} files)`);
420
370
  }
421
371
  _logReadPerformance(ts) {
422
372
  this._typescriptTerminal.writeVerboseLine(`I/O Read: ${ts.performance.getDuration('I/O Read')}ms (${ts.performance.getCount('beforeIORead')} files)`);
@@ -605,13 +555,12 @@ class TypeScriptBuilder {
605
555
  return `${outFolderName}:${jsExtensionOverride || '.js'}`;
606
556
  }
607
557
  _loadTsconfig(ts) {
608
- const parsedConfigFile = ts.readConfigFile(this._configuration.tsconfigPath, this._cachedFileSystem.readFile);
558
+ const parsedConfigFile = ts.readConfigFile(this._configuration.tsconfigPath, ts.sys.readFile);
609
559
  const currentFolder = path.dirname(this._configuration.tsconfigPath);
610
560
  const tsconfig = ts.parseJsonConfigFileContent(parsedConfigFile.config, {
611
- fileExists: this._cachedFileSystem.exists,
612
- readFile: this._cachedFileSystem.readFile,
613
- readDirectory: (folderPath, extensions, excludes, includes, depth) => ts.matchFiles(folderPath, extensions, excludes, includes,
614
- /* useCaseSensitiveFileNames */ true, currentFolder, depth, this._cachedFileSystem.readFolderFilesAndDirectories.bind(this._cachedFileSystem), this._cachedFileSystem.getRealPath.bind(this._cachedFileSystem), this._cachedFileSystem.directoryExists.bind(this._cachedFileSystem)),
561
+ fileExists: ts.sys.fileExists,
562
+ readFile: ts.sys.readFile,
563
+ readDirectory: ts.sys.readDirectory,
615
564
  useCaseSensitiveFileNames: true
616
565
  }, currentFolder,
617
566
  /*existingOptions:*/ undefined, this._configuration.tsconfigPath);
@@ -629,11 +578,18 @@ class TypeScriptBuilder {
629
578
  this._typescriptTerminal.writeVerboseLine(`Reading program "${compilerOptions.configFilePath}"`);
630
579
  const newProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences);
631
580
  this._logReadPerformance(ts);
581
+ const isolatedModules = !!this._configuration.useTranspilerWorker && !!compilerOptions.isolatedModules;
582
+ const mode = isolatedModules ? 'declaration' : 'both';
583
+ if (isolatedModules) {
584
+ // Kick the transpilation worker.
585
+ const filesToTranspile = getFilesToTranspileFromBuilderProgram(newProgram);
586
+ this._queueTranspileInWorker(this._tool, compilerOptions, filesToTranspile);
587
+ }
632
588
  const { emit: originalEmit } = newProgram;
633
589
  const emit = (outerTargetSourceFile, outerWriteFile, outerCancellationToken, outerEmitOnlyDtsFiles, outerCustomTransformers) => {
634
590
  const innerProgram = newProgram.getProgram();
635
591
  const innerCompilerOptions = innerProgram.getCompilerOptions();
636
- const { changedFiles } = this._configureProgramForMultiEmit(innerProgram, ts);
592
+ const { changedFiles } = (0, configureProgramForMultiEmit_1.configureProgramForMultiEmit)(innerProgram, ts, this._moduleKindsToEmit, mode);
637
593
  const result = originalEmit.call(newProgram, outerTargetSourceFile, outerWriteFile, outerCancellationToken, outerEmitOnlyDtsFiles, outerCustomTransformers);
638
594
  result.changedSourceFiles = changedFiles;
639
595
  this._typescriptTerminal.writeVerboseLine(`Emitting program "${innerCompilerOptions.configFilePath}"`);
@@ -679,7 +635,7 @@ class TypeScriptBuilder {
679
635
  const reportWatchStatus = (diagnostic) => {
680
636
  this._printDiagnosticMessage(ts, diagnostic);
681
637
  };
682
- const compilerHost = ts.createWatchCompilerHost(tsconfig.fileNames, tsconfig.options, ts.sys, this._getCreateBuilderProgram(ts), tool.reportDiagnostic, reportWatchStatus, tsconfig.projectReferences);
638
+ const compilerHost = ts.createWatchCompilerHost(tsconfig.fileNames, tsconfig.options, ts.sys, this._getCreateBuilderProgram(ts), tool.reportDiagnostic, reportWatchStatus, tsconfig.projectReferences, tsconfig.watchOptions);
683
639
  compilerHost.clearTimeout = tool.clearTimeout;
684
640
  compilerHost.setTimeout = tool.setTimeout;
685
641
  return compilerHost;
@@ -735,16 +691,100 @@ class TypeScriptBuilder {
735
691
  throw new Error(`"${moduleKindName}" is not a valid module kind name.`);
736
692
  }
737
693
  }
694
+ _queueTranspileInWorker(tool, compilerOptions, filesToTranspile) {
695
+ const { pendingTranspilePromises, pendingTranspileSignals } = tool;
696
+ let maybeWorker = tool.worker;
697
+ if (!maybeWorker) {
698
+ const workerData = {
699
+ typeScriptToolPath: this._configuration.typeScriptToolPath
700
+ };
701
+ tool.worker = maybeWorker = new worker_threads_1.Worker(require.resolve('./TranspilerWorker.js'), {
702
+ workerData: workerData
703
+ });
704
+ maybeWorker.on('message', (response) => {
705
+ const { requestId: resolvingRequestId, type, result } = response;
706
+ const signal = pendingTranspileSignals.get(resolvingRequestId);
707
+ if (type === 'error') {
708
+ const error = Object.assign(new Error(result.message), result);
709
+ if (signal) {
710
+ signal.reject(error);
711
+ }
712
+ else {
713
+ this._typescriptTerminal.writeErrorLine(`Unexpected worker rejection for request with id ${resolvingRequestId}: ${error}`);
714
+ }
715
+ }
716
+ else if (signal) {
717
+ signal.resolve(result);
718
+ }
719
+ else {
720
+ this._typescriptTerminal.writeErrorLine(`Unexpected worker resolution for request with id ${resolvingRequestId}`);
721
+ }
722
+ pendingTranspileSignals.delete(resolvingRequestId);
723
+ pendingTranspilePromises.delete(resolvingRequestId);
724
+ });
725
+ maybeWorker.once('exit', (exitCode) => {
726
+ if (pendingTranspileSignals.size) {
727
+ const error = new Error(`Worker exited unexpectedly with code ${exitCode}.`);
728
+ for (const { reject: rejectTranspile } of pendingTranspileSignals.values()) {
729
+ rejectTranspile(error);
730
+ }
731
+ pendingTranspileSignals.clear();
732
+ }
733
+ });
734
+ maybeWorker.once('error', (err) => {
735
+ for (const { reject: rejectTranspile } of pendingTranspileSignals.values()) {
736
+ rejectTranspile(err);
737
+ }
738
+ pendingTranspileSignals.clear();
739
+ });
740
+ }
741
+ // make linter happy
742
+ const worker = maybeWorker;
743
+ const requestId = ++this._nextRequestId;
744
+ const transpilePromise = new Promise((resolve, reject) => {
745
+ pendingTranspileSignals.set(requestId, { resolve, reject });
746
+ this._typescriptTerminal.writeLine(`Asynchronously transpiling ${compilerOptions.configFilePath}`);
747
+ const request = {
748
+ compilerOptions,
749
+ filesToTranspile,
750
+ moduleKindsToEmit: this._moduleKindsToEmit,
751
+ requestId
752
+ };
753
+ worker.postMessage(request);
754
+ });
755
+ pendingTranspilePromises.set(requestId, transpilePromise);
756
+ }
757
+ _cleanupWorker() {
758
+ const tool = this._tool;
759
+ if (!tool) {
760
+ return;
761
+ }
762
+ const { worker } = tool;
763
+ if (worker) {
764
+ worker.postMessage(false);
765
+ tool.worker = undefined;
766
+ }
767
+ }
738
768
  }
739
769
  exports.TypeScriptBuilder = TypeScriptBuilder;
740
- const JS_EXTENSION_REGEX = /\.js(\.map)?$/;
741
- function wrapWriteFile(baseWriteFile, jsExtensionOverride) {
742
- if (!jsExtensionOverride) {
743
- return baseWriteFile;
770
+ function getFilesToTranspileFromBuilderProgram(builderProgram) {
771
+ const changedFilesSet = builderProgram.getState().changedFilesSet;
772
+ const filesToTranspile = new Map();
773
+ for (const fileName of changedFilesSet) {
774
+ const sourceFile = builderProgram.getSourceFile(fileName);
775
+ if (sourceFile && !sourceFile.isDeclarationFile) {
776
+ filesToTranspile.set(sourceFile.fileName, sourceFile.text);
777
+ }
778
+ }
779
+ return filesToTranspile;
780
+ }
781
+ function getFilesToTranspileFromProgram(program) {
782
+ const filesToTranspile = new Map();
783
+ for (const sourceFile of program.getSourceFiles()) {
784
+ if (!sourceFile.isDeclarationFile) {
785
+ filesToTranspile.set(sourceFile.fileName, sourceFile.text);
786
+ }
744
787
  }
745
- const replacementExtension = `${jsExtensionOverride}$1`;
746
- return (fileName, data, writeBOM, onError, sourceFiles) => {
747
- return baseWriteFile(fileName.replace(JS_EXTENSION_REGEX, replacementExtension), data, writeBOM, onError, sourceFiles);
748
- };
788
+ return filesToTranspile;
749
789
  }
750
790
  //# sourceMappingURL=TypeScriptBuilder.js.map