Skip to content

fix(compiler): adopt jsx and lib from the project's tsconfig in ts7 - #196

Open
techfreaque wants to merge 2 commits into
vercel-labs:mainfrom
techfreaque:fix-ts7-jsx-lib-adoption
Open

fix(compiler): adopt jsx and lib from the project's tsconfig in ts7#196
techfreaque wants to merge 2 commits into
vercel-labs:mainfrom
techfreaque:fix-ts7-jsx-lib-adoption

Conversation

@techfreaque

Copy link
Copy Markdown

Problem

Two related bugs in the ts7 (tsgo) tsconfig-adoption path in packages/compiler/src/frontend/program.ts.

jsx crashes instead of being unsupported. jsx isn't in the adopted-options allowlist, so any .tsx file fails type-checking with tsgo's --jsx is not set even when the project's own tsconfig.json sets "jsx": "react-jsx". Worse, naively adding jsx to the adopted set alone crashes the whole compile, because serializeOptions() in packages/compiler/src/frontend/ts7/program.ts has a hardcoded switch that converts TypeScript's numeric enum-valued compiler options (target/module/moduleResolution/moduleDetection/lib) back to their string spelling for the synthesized in-memory tsconfig, and throws for any numeric option it doesn't recognize:

Error: ts7 createProgram: unhandled enum-valued compiler option 'jsx'

lib is unconditionally forced, with no override. lib is forced to ["lib.es2025.d.ts"] in FORCED_OPTIONS (by design not overridable by adoption) regardless of what the real tsconfig.json specifies. A project whose tsconfig.json sets "lib": ["ES2025", "DOM"] has no way to get DOM globals into the checked program.

Root cause

adoptProjectConfig7() merges options as { ...BASE_OPTIONS, ...adopted, ...FORCED_OPTIONS } — anything in FORCED_OPTIONS always wins, and anything not in the ADOPTED_OPTIONS allowlist is silently dropped. jsx was in neither the allowlist nor serializeOptions()'s enum switch; lib was in FORCED_OPTIONS, which can never be overridden.

Fix

  • Moved the lib default from FORCED_OPTIONS to BASE_OPTIONS, so it still applies when a project sets nothing, but is now overridable by adoption.
  • In adoptProjectConfig7(), adopt jsx, jsxImportSource, and lib from the project's parsed tsconfig when present.
  • Added the missing jsx case to serializeOptions()'s enum-reverse-mapping switch (TypeScript's JsxEmit enum: None/Preserve/React/ReactNative/ReactJSX/ReactJSXDev), mirroring the existing target/module/moduleResolution/moduleDetection/lib cases.

Verification

  • cd packages/compiler && node node_modules/typescript5/bin/tsc -p tsconfig.json — 0 errors.
  • Ran the existing packages/compiler/test/ts7/program.test.ts, order-parity.test.ts, and resolver-parity.test.ts suites via vitest; no new failures introduced by this change (pre-existing failures on this Windows environment are path-separator related and reproduce identically on unmodified main).
  • Sanity-checked with a throwaway .tsx fixture (jsx: "react-jsx", lib: ["es2025", "dom"] in a synthesized tsconfig) compiled through loadProgram/checkPreflight: the previous crash (unhandled enum-valued compiler option 'jsx') is gone, and the checker instead reports ordinary, expected type diagnostics (missing @types/react, resolved DOM globals), confirming both options are now correctly adopted end to end.

@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

@mabr-pcvisit is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

Comment thread packages/compiler/src/frontend/ts7/program.ts Outdated
Both bugs share one root cause: the ts7 tsconfig-adoption mechanism in
adoptProjectConfig7() only lets a fixed allowlist of options through,
forcing everything else — including jsx and lib — to scriptc's own
defaults with no override.

jsx wasn't adopted at all, so any .tsx file failed type-checking with
tsgo's "--jsx is not set" even when the project's tsconfig.json sets
jsx. Worse, jsx also wasn't handled by serializeOptions()'s enum-to-
string switch (which converts TypeScript's numeric enum-valued
compiler options back to tsconfig string form), so naively adopting it
crashed with "unhandled enum-valued compiler option 'jsx'" instead of
just failing to type-check.

lib was unconditionally FORCED to ["lib.es2025.d.ts"] with no way to
widen it, so a project whose tsconfig sets "lib": ["ES2025", "DOM"]
could never get DOM globals into scope, even for code reachable only
through type-only imports.

Fix: move the lib default from FORCED_OPTIONS (never overridable) to
BASE_OPTIONS (overridden by adopted config), adopt jsx/jsxImportSource/
lib from the project's tsconfig when set, and add the missing jsx case
to serializeOptions()'s enum-reverse-mapping switch.
@techfreaque
techfreaque force-pushed the fix-ts7-jsx-lib-adoption branch from 92384f1 to 7e81976 Compare August 22, 2026 09:29
vercel[bot]'s review caught that the hardcoded jsx string table used
TypeScript 5.9.3's JsxEmit ordering (React=2/ReactNative=3), but 7.0.2
renumbers it (ReactNative=2/React=3) - silently swapping "react" and
"react-native". Verified against the real dist/enums/jsxEmit.js module.

Fixed properly rather than just correcting the numbers: JsxEmit now
goes through the same loadHiddenEnum + enumKeyOf symbolic reverse-
mapping as ModuleResolutionKind/ModuleDetectionKind, so no numeric
enum value is ever hardcoded in this file again (matching enums.ts's
own stated invariant). Only the enum-key-name -> tsconfig-spelling
step (ReactNative -> "react-native", etc.) stays a fixed table, since
that's a spelling convention, not a value that could renumber.
@techfreaque
techfreaque force-pushed the fix-ts7-jsx-lib-adoption branch from 090905a to 763ed24 Compare August 22, 2026 10:10
techfreaque added a commit to techfreaque/scriptc that referenced this pull request Aug 22, 2026
# Conflicts:
#	packages/compiler/src/frontend/program.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant