Fix termination handling - #95692
Merged
Merged
Conversation
Contributor
Tests PassedCommit: 946e81f |
Contributor
Stats from current PR🔴 4 regressions
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (2 files)Files with changes:
View diffspages-api.ru..time.prod.jsDiff too large to display pages.runtime.prod.jsDiff too large to display 📎 Tarball URLCommit: 946e81f |
lukesandberg
marked this pull request as ready for review
July 10, 2026 19:46
lukesandberg
enabled auto-merge (squash)
July 13, 2026 05:37
andrewimm
approved these changes
Jul 13, 2026
lukesandberg
force-pushed
the
lukesandberg/ts-cli-followups
branch
from
July 13, 2026 20:16
43cfae9 to
946e81f
Compare
lukesandberg
added a commit
that referenced
this pull request
Jul 15, 2026
## Follow-ups for the experimental TypeScript CLI checker Two independent improvements to the `experimental.useTypeScriptCli` build path. ### 1. Make `tsc` responsive to interruption When `next build` is interrupted (Ctrl-C / `SIGTERM`), the TypeScript 7 native compiler could keep running to completion instead of stopping — leaving a CPU-heavy process alive after the build was abandoned. The teardown already handled termination signals and killed the whole process group; the problem was the signal it sent. The native compiler ignores `SIGTERM`/`SIGINT`, so the graceful signal never stopped it. We now escalate to `SIGKILL` (Windows: `taskkill /T /F`), which reaps the compiler on interrupt (measured ~200ms vs. running to completion). The compiler's signal handling may be improved upstream — see [microsoft/typescript-go#4592](microsoft/typescript-go#4592), which threads an interruption `context` through `tsc build`. That work is still in progress; until it lands and ships, this escalation is what makes interruption reliable. ### 2. Skip the jest worker for the CLI checker The type-check runs in a jest worker to isolate the TypeScript compiler-API heap so it can be freed after checking. In CLI mode the compiler runs in a separate `tsc` process, so there is no heap to isolate and the worker adds nothing but an extra process and indirection. CLI mode now runs the setup/config path in-process and spawns `tsc` directly. The TypeScript-API checker is unchanged and still uses the worker. ### Testing - Unit tests for `runTypeScriptCli` (spawn options, group-SIGKILL teardown, signal handling, listener cleanup, captured-output decoding). - Existing `test/production/app-dir/typescript-cli` integration suite passes (TS 6, TS 7, opt-in-required, `ignoreBuildErrors`, `--debug-build-paths`). - Manually verified against a TypeScript 7 project large enough to distinguish a real kill from natural completion: the native compiler is reaped ~200ms after interrupt. <!-- NEXT_JS_LLM_PR --> (cherry picked from commit 63375cd)
lukesandberg
added a commit
that referenced
this pull request
Jul 23, 2026
## Follow-ups for the experimental TypeScript CLI checker Two independent improvements to the `experimental.useTypeScriptCli` build path. ### 1. Make `tsc` responsive to interruption When `next build` is interrupted (Ctrl-C / `SIGTERM`), the TypeScript 7 native compiler could keep running to completion instead of stopping — leaving a CPU-heavy process alive after the build was abandoned. The teardown already handled termination signals and killed the whole process group; the problem was the signal it sent. The native compiler ignores `SIGTERM`/`SIGINT`, so the graceful signal never stopped it. We now escalate to `SIGKILL` (Windows: `taskkill /T /F`), which reaps the compiler on interrupt (measured ~200ms vs. running to completion). The compiler's signal handling may be improved upstream — see [microsoft/typescript-go#4592](microsoft/typescript-go#4592), which threads an interruption `context` through `tsc build`. That work is still in progress; until it lands and ships, this escalation is what makes interruption reliable. ### 2. Skip the jest worker for the CLI checker The type-check runs in a jest worker to isolate the TypeScript compiler-API heap so it can be freed after checking. In CLI mode the compiler runs in a separate `tsc` process, so there is no heap to isolate and the worker adds nothing but an extra process and indirection. CLI mode now runs the setup/config path in-process and spawns `tsc` directly. The TypeScript-API checker is unchanged and still uses the worker. ### Testing - Unit tests for `runTypeScriptCli` (spawn options, group-SIGKILL teardown, signal handling, listener cleanup, captured-output decoding). - Existing `test/production/app-dir/typescript-cli` integration suite passes (TS 6, TS 7, opt-in-required, `ignoreBuildErrors`, `--debug-build-paths`). - Manually verified against a TypeScript 7 project large enough to distinguish a real kill from natural completion: the native compiler is reaped ~200ms after interrupt. <!-- NEXT_JS_LLM_PR --> (cherry picked from commit 63375cd)
lukesandberg
added a commit
that referenced
this pull request
Jul 23, 2026
Backports the TypeScript 7 support fixes to the `16.2.x` release line to resolve #95801, where `next build` crashes with a silent `SIGSEGV`/`SIGABRT` when `typescript@7` is installed (the legacy TypeScript JavaScript API is unavailable in TS7). Cherry-picks the following, in order: - #92277 — Resolve `compilerOptions.paths` in tsconfigs without `compilerOptions.baseUrl` (prerequisite; source change only) - #95639 — (TypeScript 7 Support) Add experimental TypeScript CLI backend - #95692 — Fix termination handling - #95753 — Better support the CLI spinner when running the TSC CLI Together these add the opt-in `experimental.useTypeScriptCli` backend (runs the project-local `tsc` during `next build`, supporting TS7), preserve the TypeScript API backend as the default with actionable TS7 migration guidance instead of a crash, and fix worker termination and CLI spinner handling. ## Prerequisite: #92277 The TypeScript CLI backend tests exercise a `paths` alias that is inherited from an extended tsconfig and defined **without** a `baseUrl`. Resolving that alias in the **webpack** builder relies on the `load-jsconfig.ts` change from #92277 (compute the effective base URL from `pathsBasePath`), which had not been backported to `next-16-2`. Only the source change from #92277 is included here — its test reorganization is not. ## Test changes The `test/production/ci-missing-typescript-deps` and `test/production/next-server-nft` suites were converted from `createNext` to `nextTestSetup` on `canary` in #93799, which was never backported to `next-16-2`. Because #95639's test diffs were authored against that refactored shape, the `ci-missing-typescript-deps` suite is adapted back to this branch's existing `createNext` / `try‑finally` style rather than pulling in the #93799 refactor. ## Fixes Fixes #95801 ## Verification Automated (both bundlers): - `pnpm --filter=next build` - `pnpm test-start-turbo` and `pnpm test-start-webpack` for: - `test/production/app-dir/typescript-cli/typescript-cli.test.ts` - `test/production/ci-missing-typescript-deps/index.test.ts` - Unit: `runTypeScriptCli.test.ts`, `test/unit/typescript-cli-config-origin/index.test.ts` Against a `typescript@7.0.2` reproduction project, `next build` no longer crashes with an error about how `"id"` should be a string`. It now exits cleanly with actionable guidance: ``` ▲ Next.js 16.2.10 (Turbopack) Creating an optimized production build ... ✓ Compiled successfully in 785ms Running TypeScript .TypeScript 7.0.2 does not provide the compiler API required by Next.js. Enable experimental.useTypeScriptCli in your Next.js config to use the TypeScript CLI, or install TypeScript 6 instead. Next.js build worker exited with code: 1 and signal: null ``` The same clean error is produced under `CI=1` (previously the crash path). Enabling the new opt-in: ```ts experimental: { useTypeScriptCli: true, }, ``` makes the build succeed with TypeScript 7 installed. --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
m-kawafuji
pushed a commit
to m-kawafuji/next.js
that referenced
this pull request
Aug 8, 2026
## Follow-ups for the experimental TypeScript CLI checker Two independent improvements to the `experimental.useTypeScriptCli` build path. ### 1. Make `tsc` responsive to interruption When `next build` is interrupted (Ctrl-C / `SIGTERM`), the TypeScript 7 native compiler could keep running to completion instead of stopping — leaving a CPU-heavy process alive after the build was abandoned. The teardown already handled termination signals and killed the whole process group; the problem was the signal it sent. The native compiler ignores `SIGTERM`/`SIGINT`, so the graceful signal never stopped it. We now escalate to `SIGKILL` (Windows: `taskkill /T /F`), which reaps the compiler on interrupt (measured ~200ms vs. running to completion). The compiler's signal handling may be improved upstream — see [microsoft/typescript-go#4592](microsoft/typescript-go#4592), which threads an interruption `context` through `tsc build`. That work is still in progress; until it lands and ships, this escalation is what makes interruption reliable. ### 2. Skip the jest worker for the CLI checker The type-check runs in a jest worker to isolate the TypeScript compiler-API heap so it can be freed after checking. In CLI mode the compiler runs in a separate `tsc` process, so there is no heap to isolate and the worker adds nothing but an extra process and indirection. CLI mode now runs the setup/config path in-process and spawns `tsc` directly. The TypeScript-API checker is unchanged and still uses the worker. ### Testing - Unit tests for `runTypeScriptCli` (spawn options, group-SIGKILL teardown, signal handling, listener cleanup, captured-output decoding). - Existing `test/production/app-dir/typescript-cli` integration suite passes (TS 6, TS 7, opt-in-required, `ignoreBuildErrors`, `--debug-build-paths`). - Manually verified against a TypeScript 7 project large enough to distinguish a real kill from natural completion: the native compiler is reaped ~200ms after interrupt. <!-- NEXT_JS_LLM_PR -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Follow-ups for the experimental TypeScript CLI checker
Two independent improvements to the
experimental.useTypeScriptClibuild path.1. Make
tscresponsive to interruptionWhen
next buildis interrupted (Ctrl-C /SIGTERM), the TypeScript 7 native compiler could keep running to completion instead of stopping — leaving a CPU-heavy process alive after the build was abandoned.The teardown already handled termination signals and killed the whole process group; the problem was the signal it sent. The native compiler ignores
SIGTERM/SIGINT, so the graceful signal never stopped it. We now escalate toSIGKILL(Windows:taskkill /T /F), which reaps the compiler on interrupt (measured ~200ms vs. running to completion).The compiler's signal handling may be improved upstream — see microsoft/typescript-go#4592, in the mean time we should just send a kill signal
2. Skip the jest worker for the CLI checker
The type-check runs in a jest worker to isolate the TypeScript compiler-API heap so it can be freed after checking. In CLI mode the compiler runs in a separate
tscprocess, so there is no heap to isolate. Just spawn tsc from the parent process.Testing
runTypeScriptCli(spawn options, group-SIGKILL teardown, signal handling, listener cleanup, captured-output decoding).test/production/app-dir/typescript-cliintegration suite passes (TS 6, TS 7, opt-in-required,ignoreBuildErrors,--debug-build-paths).