fix(codegen): drop redundant whitespace in minified TypeScript output#23038
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b702bfe1b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 161e67e193
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
as next to a string name when minifying189a599 to
b798f6f
Compare
b798f6f to
258ffe5
Compare
Merge activity
|
…#23038) Removes redundant whitespace from minified output across many TypeScript constructs. Each change is minify-only: pretty-print output is byte-identical, all outputs round-trip, and a conservative `type_starts_with_non_identifier` helper only drops a space when the following token definitely begins with punctuation. ### Fixes - **Decorators** — `@dec()class`, `export@dec class`, `accessor#x` - **`as` / `satisfies`** — `foo()as X`, `` `s`as const ``, `as{a:1}`, `as(x)=>y`, `as[T]` - **Non-null `!`** — `opts!.x`, `x!;`, `a!()`; the separator is kept only before `=`/`==`/`===` (which would retokenize as `!=`/`!==`), in both binary and assignment positions - **`enum`** — `enum E{…}` - **Conditional types** — `T extends[U]?X:Y`, `Foo<T>extends…`; the `? ?C` separator is preserved for a prefix JSDoc-nullable true branch - **Heritage & constraints** — `class A<T>extends B<T>implements I`, `interface I<T=string>extends…`, `<T extends[a,b]>` - **Type operators / constructors** — `readonly[…]`, `keyof[a,b]`, `readonly(keyof T)[]`, `new()=>T`, mapped-type `readonly[P in …]`, `export type*from` ### Verification A whitespace analyzer over ~400 real-world `.ts` files went from **1410 → 4** removable spaces. The remaining 4 are a deliberate `i-->0` tie (handled elsewhere) and two higher-risk edge cases (`f<T>,` instantiation, mapped `in` before a template literal). `oxc_codegen` and `oxc_minifier` suites pass, `just minsize` shows no drift, clippy is clean, and regression tests were added for each construct.
258ffe5 to
a4b1bf7
Compare
### 💥 BREAKING CHANGES - ee4dc73 ast: [**BREAKING**] Add `#[non_exhaustive]` to AST nodes (#23046) (overlookmotel) - 4c35362 ast: [**BREAKING**] Add `AstBuilder::template_element_escape_raw` and `template_element_escape_raw_with_lone_surrogates` methods (#23047) (overlookmotel) ### 🚀 Features - b846ab2 react_compiler: Integrate the Rust port of the React Compiler (#22942) (Boshen) - 5b8dd68 parser: Report TS1255 for invalid class definite assertions (#22917) (camc314) - 85efabf semantic: Make building the class table optional, off by default (#22862) (Boshen) ### 🐛 Bug Fixes - 556acdc codegen: Parenthesize TS-cast assignment targets (#23112) (Boshen) - 37169ff codegen: Don't emit space between postfix `--` and `>` when minifying (#23036) (Boshen) - a4b1bf7 codegen: Drop redundant whitespace in minified TypeScript output (#23038) (Boshen) - cf53285 parser: Report reserved type-declaration names in the parser (#23035) (Boshen) - 4e44969 ast: Fix UB in `escape_template_element_raw` (#23052) (overlookmotel) - c543154 parser: Report comma operator in JSX expression in the parser (#23030) (Boshen) - 325c94f codegen: Tighten conditional-type and constructor-type whitespace when minifying (#23033) (Boshen) - 95dd3a2 parser: Report `import type` alias to a non-external reference in the parser (#23032) (Boshen) - 90180b8 codegen: Drop space after `:` in function return type when minifying (#23028) (Boshen) - 6da876e parser: Report `abstract` private class field in the parser (#23029) (Boshen) - 28467ce codegen: Don't emit space before a postfix update operand when minifying (#23027) (Boshen) - cb29926 codegen: Drop redundant space after `export default` when minifying (#23024) (Boshen) - 62965ae codegen: Drop redundant space after `else` when minifying (#23025) (Boshen) - 989230a parser: Report compound assignment to non-simple target in the parser (#23022) (Boshen) - 06f367c parser: Report `super.#field` private access in the parser (#23014) (Boshen) - 184edef codegen: Print space before `const`/`declare` enum modifier (#23013) (Boshen) - 4d722e0 parser: Report duplicate switch `default` clause in the parser (#23012) (Boshen) - 597ed85 codegen: Parenthesize `let`/`async` for-of head target (#23008) (Boshen) - 8b631bf codegen: Remove stray space before mapped type value colon (#23010) (Boshen) - c08407e codegen: Don't over-parenthesize `in` inside an arrow in a for-init (#23009) (Boshen) - 600cd6f codegen: Parenthesize lower-precedence `TSInstantiationExpression` operand (#23007) (Boshen) - 187e1a5 codegen: Don't leak space after comment-only JSX expression container (#23006) (Boshen) - 294c473 codegen: Don't over-parenthesize `TSTypeAssertion` operand (#23004) (Boshen) - 786d96f codegen: Give `TSTypeAssertion` unary precedence (#23002) (Boshen) - 1295882 parser: Report `new.target` and `import.meta` syntax errors in the parser (#23003) (Boshen) - d727b6b codegen: Parenthesize `await` expression as base of `**` (#23001) (Boshen) - 67dfa08 codegen: Keep parentheses around `new` callees containing a call (#22997) (Boshen) - 17e7cf3 parser: Disallow unerasable `as`/`satisfies` assertions (#22986) (Boshen) - beb46d3 parser: Commit to module goal on decorated exports (#22941) (Boshen) - 49e63f7 isolated-declarations: Require annotations for satisfies initializers (#22898) (camc314) - 8c93601 isolated-declarations: Allow unknown enum initializer in non-const enum (#22900) (camc314) ### ⚡ Performance - 7d89909 parser: Peek instead of lookahead for yield disambiguation (#23071) (Boshen) - bf872f0 parser: Skip arrow lookahead for a parenthesized literal (#23070) (Boshen) - d19fc54 parser: Guard type-argument speculation behind an angle-token check (#23069) (Boshen) - 8eb5507 parser: Skip redundant member-rest re-scan on call entry (#23068) (Boshen) - 883dfc1 parser: Skip parse_call_expression_rest when no call follows (#23063) (Boshen) - b171153 parser: Peek before the await-using lookahead (#23059) (Boshen) - 56f21bd parser: Use peek_token for the TS `asserts` type predicate (#23058) (Boshen) - 68805ac parser: Use peek_token instead of checkpoint/rewind for single-token decisions (#23056) (Boshen) - 1f9d8eb ast: `AstBuilder::template_element_escape_raw` avoid allocation if no escape required (#23053) (overlookmotel) - 502b04d semantic: Move cold function redeclaration handling into `#[cold]` function (#22973) (overlookmotel) ### 📚 Documentation - 275d318 napi/minifier: Point `target` to oxc docs (#23102) (camc314) Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Removes redundant whitespace from minified output across many TypeScript constructs. Each change is minify-only: pretty-print output is byte-identical, all outputs round-trip, and a conservative
type_starts_with_non_identifierhelper only drops a space when the following token definitely begins with punctuation.Fixes
@dec()class,export@dec class,accessor#xas/satisfies—foo()as X,`s`as const,as{a:1},as(x)=>y,as[T]!—opts!.x,x!;,a!(); the separator is kept only before=/==/===(which would retokenize as!=/!==), in both binary and assignment positionsenum—enum E{…}T extends[U]?X:Y,Foo<T>extends…; the? ?Cseparator is preserved for a prefix JSDoc-nullable true branchclass A<T>extends B<T>implements I,interface I<T=string>extends…,<T extends[a,b]>readonly[…],keyof[a,b],readonly(keyof T)[],new()=>T, mapped-typereadonly[P in …],export type*fromVerification
A whitespace analyzer over ~400 real-world
.tsfiles went from 1410 → 4 removable spaces. The remaining 4 are a deliberatei-->0tie (handled elsewhere) and two higher-risk edge cases (f<T>,instantiation, mappedinbefore a template literal).oxc_codegenandoxc_minifiersuites pass,just minsizeshows no drift, clippy is clean, and regression tests were added for each construct.