Skip to content

Commit f1a24d7

Browse files
authored
fix(js): close typescript watch program on SIGINT/SIGTERM (#11722)
Close typescript watch program and complete iterator to ensure program can exit.
1 parent b17893c commit f1a24d7

File tree

2 files changed

+66
-37
lines changed

2 files changed

+66
-37
lines changed

packages/js/src/executors/tsc/tsc.impl.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -144,22 +144,6 @@ export async function* tscExecutor(
144144
assets: _options.assets,
145145
});
146146

147-
if (options.watch) {
148-
const disposeWatchAssetChanges =
149-
await assetHandler.watchAndProcessOnAssetChange();
150-
const disposePackageJsonChanges = await watchForSingleFileChanges(
151-
join(context.root, projectRoot),
152-
'package.json',
153-
() => updatePackageJson(options, context, target, dependencies)
154-
);
155-
const handleTermination = async () => {
156-
await disposeWatchAssetChanges();
157-
await disposePackageJsonChanges();
158-
};
159-
process.on('SIGINT', () => handleTermination());
160-
process.on('SIGTERM', () => handleTermination());
161-
}
162-
163147
const tsCompilationOptions = createTypeScriptCompilationOptions(
164148
options,
165149
context
@@ -175,7 +159,7 @@ export async function* tscExecutor(
175159
tsCompilationOptions.rootDir = '.';
176160
}
177161

178-
return yield* compileTypeScriptFiles(
162+
const typescriptCompilation = compileTypeScriptFiles(
179163
options,
180164
tsCompilationOptions,
181165
async () => {
@@ -188,6 +172,26 @@ export async function* tscExecutor(
188172
);
189173
}
190174
);
175+
176+
if (options.watch) {
177+
const disposeWatchAssetChanges =
178+
await assetHandler.watchAndProcessOnAssetChange();
179+
const disposePackageJsonChanges = await watchForSingleFileChanges(
180+
join(context.root, projectRoot),
181+
'package.json',
182+
() => updatePackageJson(options, context, target, dependencies)
183+
);
184+
const handleTermination = async (exitCode: number) => {
185+
await disposeWatchAssetChanges();
186+
await disposePackageJsonChanges();
187+
await typescriptCompilation.close();
188+
process.exit(exitCode);
189+
};
190+
process.on('SIGINT', () => handleTermination(128 + 2));
191+
process.on('SIGTERM', () => handleTermination(128 + 15));
192+
}
193+
194+
return yield* typescriptCompilation.iterator;
191195
}
192196

193197
export default tscExecutor;

packages/js/src/utils/typescript/compile-typescript-files.ts

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,58 @@ function getErrorCountFromMessage(messageText: string) {
1616
return Number.parseInt(ERROR_COUNT_REGEX.exec(messageText)[1]);
1717
}
1818

19-
export async function* compileTypeScriptFiles(
19+
export interface TypescriptCompilationResult {
20+
success: boolean;
21+
outfile: string;
22+
}
23+
24+
export function compileTypeScriptFiles(
2025
normalizedOptions: NormalizedExecutorOptions,
2126
tscOptions: TypeScriptCompilationOptions,
2227
postCompilationCallback: () => void | Promise<void>
23-
) {
28+
): {
29+
iterator: AsyncIterable<TypescriptCompilationResult>;
30+
close: () => void | Promise<void>;
31+
} {
2432
const getResult = (success: boolean) => ({
2533
success,
2634
outfile: normalizedOptions.mainOutputPath,
2735
});
2836

29-
return yield* createAsyncIterable<{ success: boolean; outfile: string }>(
30-
async ({ next, done }) => {
31-
if (normalizedOptions.watch) {
32-
compileTypeScriptWatcher(tscOptions, async (d: Diagnostic) => {
33-
if (d.code === TYPESCRIPT_FOUND_N_ERRORS_WATCHING_FOR_FILE_CHANGES) {
34-
await postCompilationCallback();
35-
next(
36-
getResult(getErrorCountFromMessage(d.messageText as string) === 0)
37-
);
38-
}
39-
});
40-
} else {
41-
const { success } = compileTypeScript(tscOptions);
42-
await postCompilationCallback();
43-
next(getResult(success));
44-
done();
37+
let tearDown: (() => void) | undefined;
38+
39+
return {
40+
iterator: createAsyncIterable<TypescriptCompilationResult>(
41+
async ({ next, done }) => {
42+
if (normalizedOptions.watch) {
43+
const host = compileTypeScriptWatcher(
44+
tscOptions,
45+
async (d: Diagnostic) => {
46+
if (
47+
d.code === TYPESCRIPT_FOUND_N_ERRORS_WATCHING_FOR_FILE_CHANGES
48+
) {
49+
await postCompilationCallback();
50+
next(
51+
getResult(
52+
getErrorCountFromMessage(d.messageText as string) === 0
53+
)
54+
);
55+
}
56+
}
57+
);
58+
59+
tearDown = () => {
60+
host.close();
61+
done();
62+
};
63+
} else {
64+
const { success } = compileTypeScript(tscOptions);
65+
await postCompilationCallback();
66+
next(getResult(success));
67+
done();
68+
}
4569
}
46-
}
47-
);
70+
),
71+
close: () => tearDown?.(),
72+
};
4873
}

0 commit comments

Comments
 (0)