@rushstack/heft-typescript-plugin 0.1.0-rc.4 → 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 +17 -9
- package/lib/TypeScriptBuilder.d.ts.map +1 -1
- package/lib/TypeScriptBuilder.js +213 -133
- 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 -48
- 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 +11 -11
- package/lib/EmitFilesPatch.d.ts +0 -28
- package/lib/EmitFilesPatch.d.ts.map +0 -1
- package/lib/EmitFilesPatch.js +0 -99
- package/lib/EmitFilesPatch.js.map +0 -1
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 TypeScriptCachedFileSystem_1 = require("./fileSystem/TypeScriptCachedFileSystem");
|
|
35
|
-
const EMPTY_JSON = {};
|
|
34
|
+
const configureProgramForMultiEmit_1 = require("./configureProgramForMultiEmit");
|
|
36
35
|
const OLDEST_SUPPORTED_TS_MAJOR_VERSION = 2;
|
|
37
36
|
const OLDEST_SUPPORTED_TS_MINOR_VERSION = 9;
|
|
38
|
-
const NEWEST_SUPPORTED_TS_MAJOR_VERSION =
|
|
39
|
-
const NEWEST_SUPPORTED_TS_MINOR_VERSION =
|
|
37
|
+
const NEWEST_SUPPORTED_TS_MAJOR_VERSION = 5;
|
|
38
|
+
const NEWEST_SUPPORTED_TS_MINOR_VERSION = 0;
|
|
40
39
|
class TypeScriptBuilder {
|
|
41
|
-
constructor(configuration) {
|
|
42
|
-
this.__tsCacheFilePath = undefined;
|
|
43
|
-
this._tsReadJsonCache = new Map();
|
|
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,7 +56,16 @@ 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) {
|
|
68
|
+
var _a, _b;
|
|
70
69
|
if (!this._tool) {
|
|
71
70
|
// Determine the compiler version
|
|
72
71
|
const compilerPackageJsonFilename = path.join(this._configuration.typeScriptToolPath, 'package.json');
|
|
@@ -111,6 +110,18 @@ class TypeScriptBuilder {
|
|
|
111
110
|
`(${NEWEST_SUPPORTED_TS_MAJOR_VERSION}.${NEWEST_SUPPORTED_TS_MINOR_VERSION}); it may not work correctly.`);
|
|
112
111
|
}
|
|
113
112
|
const ts = require(this._configuration.typeScriptToolPath);
|
|
113
|
+
ts.performance.enable();
|
|
114
|
+
const suppressedCodes = [
|
|
115
|
+
(_a = ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor) === null || _a === void 0 ? void 0 : _a.code,
|
|
116
|
+
// This diagnostic code is not present in old versions of TypeScript
|
|
117
|
+
(_b = ts.Diagnostics
|
|
118
|
+
.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1) === null || _b === void 0 ? void 0 : _b.code
|
|
119
|
+
];
|
|
120
|
+
for (const code of suppressedCodes) {
|
|
121
|
+
if (code !== undefined) {
|
|
122
|
+
this._suppressedDiagnosticCodes.add(code);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
114
125
|
const measureTsPerformance = (measurementName, fn) => {
|
|
115
126
|
const beforeName = `before${measurementName}`;
|
|
116
127
|
ts.performance.mark(beforeName);
|
|
@@ -120,23 +131,12 @@ class TypeScriptBuilder {
|
|
|
120
131
|
ts.performance.measure(measurementName, beforeName, afterName);
|
|
121
132
|
return Object.assign(Object.assign({}, result), { duration: ts.performance.getDuration(measurementName), count: ts.performance.getCount(beforeName) });
|
|
122
133
|
};
|
|
123
|
-
const measureTsPerformanceAsync = async (measurementName, fn) => {
|
|
124
|
-
const beforeName = `before${measurementName}`;
|
|
125
|
-
ts.performance.mark(beforeName);
|
|
126
|
-
const resultPromise = fn();
|
|
127
|
-
const result = await resultPromise;
|
|
128
|
-
const afterName = `after${measurementName}`;
|
|
129
|
-
ts.performance.mark(afterName);
|
|
130
|
-
ts.performance.measure(measurementName, beforeName, afterName);
|
|
131
|
-
return Object.assign(Object.assign({}, result), { duration: ts.performance.getDuration(measurementName) });
|
|
132
|
-
};
|
|
133
134
|
this._typescriptTerminal.writeLine(`Using TypeScript version ${ts.version}`);
|
|
134
135
|
const rawDiagnostics = [];
|
|
135
136
|
const pendingOperations = new Set();
|
|
136
137
|
this._tool = {
|
|
137
138
|
ts,
|
|
138
139
|
measureSync: measureTsPerformance,
|
|
139
|
-
measureAsync: measureTsPerformanceAsync,
|
|
140
140
|
sourceFileCache: new Map(),
|
|
141
141
|
watchProgram: undefined,
|
|
142
142
|
solutionBuilder: undefined,
|
|
@@ -158,7 +158,10 @@ class TypeScriptBuilder {
|
|
|
158
158
|
onChangeDetected();
|
|
159
159
|
}
|
|
160
160
|
return timeout;
|
|
161
|
-
}
|
|
161
|
+
},
|
|
162
|
+
worker: undefined,
|
|
163
|
+
pendingTranspilePromises: new Map(),
|
|
164
|
+
pendingTranspileSignals: new Map()
|
|
162
165
|
};
|
|
163
166
|
}
|
|
164
167
|
const { performance } = this._tool.ts;
|
|
@@ -166,17 +169,17 @@ class TypeScriptBuilder {
|
|
|
166
169
|
performance.disable();
|
|
167
170
|
performance.enable();
|
|
168
171
|
if (onChangeDetected !== undefined) {
|
|
169
|
-
this.
|
|
172
|
+
await this._runWatchAsync(this._tool);
|
|
170
173
|
}
|
|
171
174
|
else if (this._useSolutionBuilder) {
|
|
172
|
-
this.
|
|
175
|
+
await this._runSolutionBuildAsync(this._tool);
|
|
173
176
|
}
|
|
174
177
|
else {
|
|
175
178
|
await this._runBuildAsync(this._tool);
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
|
-
|
|
179
|
-
const { ts, measureSync: measureTsPerformance, pendingOperations, rawDiagnostics } = tool;
|
|
181
|
+
async _runWatchAsync(tool) {
|
|
182
|
+
const { ts, measureSync: measureTsPerformance, pendingOperations, rawDiagnostics, pendingTranspilePromises } = tool;
|
|
180
183
|
if (!tool.solutionBuilder && !tool.watchProgram) {
|
|
181
184
|
//#region CONFIGURE
|
|
182
185
|
const { duration: configureDurationMs, tsconfig } = measureTsPerformance('Configure', () => {
|
|
@@ -206,15 +209,23 @@ class TypeScriptBuilder {
|
|
|
206
209
|
pendingOperations.delete(operation);
|
|
207
210
|
operation();
|
|
208
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
|
|
209
221
|
tool.executing = false;
|
|
210
222
|
}
|
|
211
223
|
this._logDiagnostics(ts, rawDiagnostics);
|
|
212
224
|
}
|
|
213
225
|
async _runBuildAsync(tool) {
|
|
214
|
-
const { ts, measureSync: measureTsPerformance,
|
|
226
|
+
const { ts, measureSync: measureTsPerformance, pendingTranspilePromises } = tool;
|
|
215
227
|
//#region CONFIGURE
|
|
216
228
|
const { duration: configureDurationMs, tsconfig, compilerHost } = measureTsPerformance('Configure', () => {
|
|
217
|
-
this._overrideTypeScriptReadJson(ts);
|
|
218
229
|
const _tsconfig = this._loadTsconfig(ts);
|
|
219
230
|
this._validateTsconfig(ts, _tsconfig);
|
|
220
231
|
const _compilerHost = this._buildIncrementalCompilerHost(tool, _tsconfig);
|
|
@@ -228,13 +239,20 @@ class TypeScriptBuilder {
|
|
|
228
239
|
//#region PROGRAM
|
|
229
240
|
// There will be only one program here; emit will get a bit abused if we produce multiple outputs
|
|
230
241
|
let builderProgram = undefined;
|
|
231
|
-
let
|
|
242
|
+
let innerProgram;
|
|
243
|
+
const isolatedModules = !!this._configuration.useTranspilerWorker && !!tsconfig.options.isolatedModules;
|
|
244
|
+
const mode = isolatedModules ? 'declaration' : 'both';
|
|
245
|
+
let filesToTranspile;
|
|
232
246
|
if (tsconfig.options.incremental) {
|
|
233
|
-
|
|
234
|
-
|
|
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);
|
|
252
|
+
innerProgram = builderProgram.getProgram();
|
|
235
253
|
}
|
|
236
254
|
else {
|
|
237
|
-
|
|
255
|
+
innerProgram = ts.createProgram({
|
|
238
256
|
rootNames: tsconfig.fileNames,
|
|
239
257
|
options: tsconfig.options,
|
|
240
258
|
projectReferences: tsconfig.projectReferences,
|
|
@@ -242,11 +260,16 @@ class TypeScriptBuilder {
|
|
|
242
260
|
oldProgram: undefined,
|
|
243
261
|
configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(tsconfig)
|
|
244
262
|
});
|
|
263
|
+
filesToTranspile = getFilesToTranspileFromProgram(innerProgram);
|
|
245
264
|
}
|
|
246
265
|
// Prefer the builder program, since it is what gives us incremental builds
|
|
247
|
-
const genericProgram = builderProgram ||
|
|
266
|
+
const genericProgram = builderProgram || innerProgram;
|
|
248
267
|
this._logReadPerformance(ts);
|
|
249
268
|
//#endregion
|
|
269
|
+
if (isolatedModules) {
|
|
270
|
+
// Kick the transpilation worker.
|
|
271
|
+
this._queueTranspileInWorker(tool, genericProgram.getCompilerOptions(), filesToTranspile);
|
|
272
|
+
}
|
|
250
273
|
//#region ANALYSIS
|
|
251
274
|
const { duration: diagnosticsDurationMs, diagnostics: preDiagnostics } = measureTsPerformance('Analyze', () => {
|
|
252
275
|
const rawDiagnostics = [
|
|
@@ -261,29 +284,34 @@ class TypeScriptBuilder {
|
|
|
261
284
|
this._typescriptTerminal.writeVerboseLine(`Analyze: ${diagnosticsDurationMs}ms`);
|
|
262
285
|
//#endregion
|
|
263
286
|
//#region EMIT
|
|
264
|
-
const
|
|
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();
|
|
265
292
|
//#endregion
|
|
266
293
|
this._logEmitPerformance(ts);
|
|
267
294
|
//#region FINAL_ANALYSIS
|
|
268
295
|
// Need to ensure that we include emit diagnostics, since they might not be part of the other sets
|
|
269
296
|
const rawDiagnostics = [...preDiagnostics, ...emitResult.diagnostics];
|
|
270
297
|
//#endregion
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
}
|
|
278
307
|
this._logDiagnostics(ts, rawDiagnostics);
|
|
279
308
|
// Reset performance counters in case any are used in the callback
|
|
280
309
|
ts.performance.disable();
|
|
281
310
|
ts.performance.enable();
|
|
282
|
-
this._configuration.emitChangedFilesCallback(tsProgram, emitResult.changedSourceFiles);
|
|
283
311
|
}
|
|
284
|
-
|
|
312
|
+
async _runSolutionBuildAsync(tool) {
|
|
285
313
|
this._typescriptTerminal.writeVerboseLine(`Using solution mode`);
|
|
286
|
-
const { ts, measureSync, rawDiagnostics } = tool;
|
|
314
|
+
const { ts, measureSync, rawDiagnostics, pendingTranspilePromises } = tool;
|
|
287
315
|
rawDiagnostics.length = 0;
|
|
288
316
|
if (!tool.solutionBuilder) {
|
|
289
317
|
//#region CONFIGURE
|
|
@@ -308,7 +336,16 @@ class TypeScriptBuilder {
|
|
|
308
336
|
//#region EMIT
|
|
309
337
|
// Ignoring the exit status because we only care about presence of diagnostics
|
|
310
338
|
tool.solutionBuilder.build();
|
|
339
|
+
this._cleanupWorker();
|
|
311
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
|
+
}
|
|
312
349
|
this._logDiagnostics(ts, rawDiagnostics);
|
|
313
350
|
}
|
|
314
351
|
_logDiagnostics(ts, rawDiagnostics) {
|
|
@@ -329,6 +366,7 @@ class TypeScriptBuilder {
|
|
|
329
366
|
this._typescriptTerminal.writeVerboseLine(`Print: ${ts.performance.getDuration('printTime')}ms ` +
|
|
330
367
|
`(${ts.performance.getCount('beforePrint')} files) (Includes Transform)`);
|
|
331
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)`);
|
|
332
370
|
}
|
|
333
371
|
_logReadPerformance(ts) {
|
|
334
372
|
this._typescriptTerminal.writeVerboseLine(`I/O Read: ${ts.performance.getDuration('I/O Read')}ms (${ts.performance.getCount('beforeIORead')} files)`);
|
|
@@ -382,31 +420,11 @@ class TypeScriptBuilder {
|
|
|
382
420
|
return ts.DiagnosticCategory.Warning;
|
|
383
421
|
}
|
|
384
422
|
// These pedantic checks also should not be treated as hard errors
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
.code:
|
|
388
|
-
case ts.Diagnostics
|
|
389
|
-
.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1.code:
|
|
390
|
-
return ts.DiagnosticCategory.Warning;
|
|
423
|
+
if (this._suppressedDiagnosticCodes.has(diagnostic.code)) {
|
|
424
|
+
return ts.DiagnosticCategory.Warning;
|
|
391
425
|
}
|
|
392
426
|
return diagnostic.category;
|
|
393
427
|
}
|
|
394
|
-
_emit(ts, genericProgram) {
|
|
395
|
-
const filesToWrite = [];
|
|
396
|
-
const changedFiles = new Set();
|
|
397
|
-
EmitFilesPatch_1.EmitFilesPatch.install(ts, genericProgram.getCompilerOptions(), this._moduleKindsToEmit, changedFiles);
|
|
398
|
-
const writeFileCallback = (filePath, data) => {
|
|
399
|
-
filesToWrite.push({ filePath, data });
|
|
400
|
-
};
|
|
401
|
-
try {
|
|
402
|
-
const result = genericProgram.emit(undefined, // Target source file
|
|
403
|
-
writeFileCallback);
|
|
404
|
-
return Object.assign(Object.assign({}, result), { changedSourceFiles: changedFiles, filesToWrite });
|
|
405
|
-
}
|
|
406
|
-
finally {
|
|
407
|
-
EmitFilesPatch_1.EmitFilesPatch.uninstall(ts);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
428
|
_validateTsconfig(ts, tsconfig) {
|
|
411
429
|
if ((tsconfig.options.module && !tsconfig.options.outDir) ||
|
|
412
430
|
(!tsconfig.options.module && tsconfig.options.outDir)) {
|
|
@@ -537,13 +555,12 @@ class TypeScriptBuilder {
|
|
|
537
555
|
return `${outFolderName}:${jsExtensionOverride || '.js'}`;
|
|
538
556
|
}
|
|
539
557
|
_loadTsconfig(ts) {
|
|
540
|
-
const parsedConfigFile = ts.readConfigFile(this._configuration.tsconfigPath,
|
|
558
|
+
const parsedConfigFile = ts.readConfigFile(this._configuration.tsconfigPath, ts.sys.readFile);
|
|
541
559
|
const currentFolder = path.dirname(this._configuration.tsconfigPath);
|
|
542
560
|
const tsconfig = ts.parseJsonConfigFileContent(parsedConfigFile.config, {
|
|
543
|
-
fileExists:
|
|
544
|
-
readFile:
|
|
545
|
-
readDirectory:
|
|
546
|
-
/* 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,
|
|
547
564
|
useCaseSensitiveFileNames: true
|
|
548
565
|
}, currentFolder,
|
|
549
566
|
/*existingOptions:*/ undefined, this._configuration.tsconfigPath);
|
|
@@ -552,41 +569,41 @@ class TypeScriptBuilder {
|
|
|
552
569
|
}
|
|
553
570
|
return tsconfig;
|
|
554
571
|
}
|
|
555
|
-
_getCreateBuilderProgram(
|
|
556
|
-
const {
|
|
557
|
-
const
|
|
558
|
-
const createMultiEmitProgram = (fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
|
572
|
+
_getCreateBuilderProgram(ts) {
|
|
573
|
+
const { _configuration: { emitChangedFilesCallback } } = this;
|
|
574
|
+
const createMultiEmitBuilderProgram = (fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
|
559
575
|
// Reset performance counters
|
|
560
576
|
ts.performance.disable();
|
|
561
577
|
ts.performance.enable();
|
|
562
578
|
this._typescriptTerminal.writeVerboseLine(`Reading program "${compilerOptions.configFilePath}"`);
|
|
563
579
|
const newProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
|
564
580
|
this._logReadPerformance(ts);
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
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);
|
|
568
587
|
}
|
|
569
|
-
const emit
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
EmitFilesPatch_1.EmitFilesPatch.uninstall(ts);
|
|
584
|
-
}
|
|
588
|
+
const { emit: originalEmit } = newProgram;
|
|
589
|
+
const emit = (outerTargetSourceFile, outerWriteFile, outerCancellationToken, outerEmitOnlyDtsFiles, outerCustomTransformers) => {
|
|
590
|
+
const innerProgram = newProgram.getProgram();
|
|
591
|
+
const innerCompilerOptions = innerProgram.getCompilerOptions();
|
|
592
|
+
const { changedFiles } = (0, configureProgramForMultiEmit_1.configureProgramForMultiEmit)(innerProgram, ts, this._moduleKindsToEmit, mode);
|
|
593
|
+
const result = originalEmit.call(newProgram, outerTargetSourceFile, outerWriteFile, outerCancellationToken, outerEmitOnlyDtsFiles, outerCustomTransformers);
|
|
594
|
+
result.changedSourceFiles = changedFiles;
|
|
595
|
+
this._typescriptTerminal.writeVerboseLine(`Emitting program "${innerCompilerOptions.configFilePath}"`);
|
|
596
|
+
this._logEmitPerformance(ts);
|
|
597
|
+
// Reset performance counters
|
|
598
|
+
ts.performance.disable();
|
|
599
|
+
ts.performance.enable();
|
|
600
|
+
emitChangedFilesCallback(innerProgram, changedFiles);
|
|
601
|
+
return result;
|
|
585
602
|
};
|
|
586
603
|
newProgram.emit = emit;
|
|
587
604
|
return newProgram;
|
|
588
605
|
};
|
|
589
|
-
return
|
|
606
|
+
return createMultiEmitBuilderProgram;
|
|
590
607
|
}
|
|
591
608
|
_buildSolutionBuilderHost(tool) {
|
|
592
609
|
const reportSolutionBuilderStatus = tool.reportDiagnostic;
|
|
@@ -594,7 +611,7 @@ class TypeScriptBuilder {
|
|
|
594
611
|
// Do nothing
|
|
595
612
|
};
|
|
596
613
|
const { ts } = tool;
|
|
597
|
-
const solutionBuilderHost = ts.createSolutionBuilderHost(ts.sys, this._getCreateBuilderProgram(
|
|
614
|
+
const solutionBuilderHost = ts.createSolutionBuilderHost(ts.sys, this._getCreateBuilderProgram(ts), tool.reportDiagnostic, reportSolutionBuilderStatus, reportEmitErrorSummary);
|
|
598
615
|
solutionBuilderHost.afterProgramEmitAndDiagnostics = (program) => {
|
|
599
616
|
// Use the native metric since we aren't overwriting the writer
|
|
600
617
|
this._typescriptTerminal.writeVerboseLine(`I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount('beforeIOWrite')} files)`);
|
|
@@ -618,7 +635,7 @@ class TypeScriptBuilder {
|
|
|
618
635
|
const reportWatchStatus = (diagnostic) => {
|
|
619
636
|
this._printDiagnosticMessage(ts, diagnostic);
|
|
620
637
|
};
|
|
621
|
-
const compilerHost = ts.createWatchCompilerHost(tsconfig.fileNames, tsconfig.options, ts.sys, this._getCreateBuilderProgram(
|
|
638
|
+
const compilerHost = ts.createWatchCompilerHost(tsconfig.fileNames, tsconfig.options, ts.sys, this._getCreateBuilderProgram(ts), tool.reportDiagnostic, reportWatchStatus, tsconfig.projectReferences, tsconfig.watchOptions);
|
|
622
639
|
compilerHost.clearTimeout = tool.clearTimeout;
|
|
623
640
|
compilerHost.setTimeout = tool.setTimeout;
|
|
624
641
|
return compilerHost;
|
|
@@ -651,42 +668,11 @@ class TypeScriptBuilder {
|
|
|
651
668
|
}
|
|
652
669
|
_buildWatchSolutionBuilderHost(tool) {
|
|
653
670
|
const { reportDiagnostic, ts } = tool;
|
|
654
|
-
const host = ts.createSolutionBuilderWithWatchHost(ts.sys, this._getCreateBuilderProgram(
|
|
671
|
+
const host = ts.createSolutionBuilderWithWatchHost(ts.sys, this._getCreateBuilderProgram(ts), reportDiagnostic, reportDiagnostic, reportDiagnostic);
|
|
655
672
|
host.clearTimeout = tool.clearTimeout;
|
|
656
673
|
host.setTimeout = tool.setTimeout;
|
|
657
674
|
return host;
|
|
658
675
|
}
|
|
659
|
-
_overrideTypeScriptReadJson(ts) {
|
|
660
|
-
const cachedReadJson = (filePath) => {
|
|
661
|
-
let jsonData = this._tsReadJsonCache.get(filePath);
|
|
662
|
-
if (jsonData) {
|
|
663
|
-
return jsonData;
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
try {
|
|
667
|
-
const fileContents = this._cachedFileSystem.readFile(filePath);
|
|
668
|
-
if (!fileContents) {
|
|
669
|
-
jsonData = EMPTY_JSON;
|
|
670
|
-
}
|
|
671
|
-
else {
|
|
672
|
-
const parsedFile = ts.parseConfigFileTextToJson(filePath, fileContents);
|
|
673
|
-
if (parsedFile.error) {
|
|
674
|
-
jsonData = EMPTY_JSON;
|
|
675
|
-
}
|
|
676
|
-
else {
|
|
677
|
-
jsonData = parsedFile.config;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
catch (error) {
|
|
682
|
-
jsonData = EMPTY_JSON;
|
|
683
|
-
}
|
|
684
|
-
this._tsReadJsonCache.set(filePath, jsonData);
|
|
685
|
-
return jsonData;
|
|
686
|
-
}
|
|
687
|
-
};
|
|
688
|
-
ts.readJson = cachedReadJson;
|
|
689
|
-
}
|
|
690
676
|
_parseModuleKind(ts, moduleKindName) {
|
|
691
677
|
switch (moduleKindName.toLowerCase()) {
|
|
692
678
|
case 'commonjs':
|
|
@@ -705,6 +691,100 @@ class TypeScriptBuilder {
|
|
|
705
691
|
throw new Error(`"${moduleKindName}" is not a valid module kind name.`);
|
|
706
692
|
}
|
|
707
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
|
+
}
|
|
708
768
|
}
|
|
709
769
|
exports.TypeScriptBuilder = TypeScriptBuilder;
|
|
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
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return filesToTranspile;
|
|
789
|
+
}
|
|
710
790
|
//# sourceMappingURL=TypeScriptBuilder.js.map
|