@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.
- package/dist/heft-typescript-plugin.d.ts +4 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/Performance.d.ts +2 -2
- package/lib/Performance.d.ts.map +1 -1
- package/lib/TranspilerWorker.d.ts +2 -0
- package/lib/TranspilerWorker.d.ts.map +1 -0
- package/lib/TranspilerWorker.js +80 -0
- package/lib/TranspilerWorker.js.map +1 -0
- package/lib/TypeScriptBuilder.d.ts +16 -7
- package/lib/TypeScriptBuilder.d.ts.map +1 -1
- package/lib/TypeScriptBuilder.js +172 -132
- package/lib/TypeScriptBuilder.js.map +1 -1
- package/lib/TypeScriptPlugin.d.ts +4 -0
- package/lib/TypeScriptPlugin.d.ts.map +1 -1
- package/lib/TypeScriptPlugin.js +1 -0
- package/lib/TypeScriptPlugin.js.map +1 -1
- package/lib/configureProgramForMultiEmit.d.ts +7 -0
- package/lib/configureProgramForMultiEmit.d.ts.map +1 -0
- package/lib/configureProgramForMultiEmit.js +99 -0
- package/lib/configureProgramForMultiEmit.js.map +1 -0
- package/lib/internalTypings/TypeScriptInternals.d.ts +6 -1
- package/lib/internalTypings/TypeScriptInternals.d.ts.map +1 -1
- package/lib/internalTypings/TypeScriptInternals.js.map +1 -1
- package/lib/schemas/typescript.schema.json +5 -0
- package/lib/types.d.ts +54 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/package.json +8 -8
package/lib/TypeScriptBuilder.js
CHANGED
|
@@ -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
|
|
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.
|
|
172
|
+
await this._runWatchAsync(this._tool);
|
|
183
173
|
}
|
|
184
174
|
else if (this._useSolutionBuilder) {
|
|
185
|
-
this.
|
|
175
|
+
await this._runSolutionBuildAsync(this._tool);
|
|
186
176
|
}
|
|
187
177
|
else {
|
|
188
178
|
await this._runBuildAsync(this._tool);
|
|
189
179
|
}
|
|
190
180
|
}
|
|
191
|
-
|
|
192
|
-
const
|
|
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,
|
|
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
|
-
|
|
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
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
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,
|
|
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:
|
|
612
|
-
readFile:
|
|
613
|
-
readDirectory:
|
|
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 } =
|
|
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
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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
|
-
|
|
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
|