Avatar for the swc-project user
swc-project
swc
BlogDocsChangelog

Performance History

Latest Results

fix(es/minifier): Preserve new async and generator (#12558) **Related issue:** - A following of #12416
main
3 hours ago
fix(es/minifier): keep directive prologue when merging if returns (#12580) The `if_return` pass merged the directive prologue of a function body into a sequence expression. A directive such as `"use strict"` then became a discarded `void` operand and stopped being a directive. The function lost strict mode. For example, `this` in a strict function became the global object, and `arguments` aliased its parameters. This change keeps the leading string-literal statements of a function body out of the `if_return` merge. The pass still merges the statements after them. This applies to ordinary functions and to block-bodied arrow functions. Tests: - Add the fixtures `issues/9238`, `issues/9238-arrow` and `issues/9238-prologue`. They check `arguments` aliasing, `this` in a strict function, a returned function in a strict arrow, multiple directives, and safe merging of ordinary statements. Each fixture also has a `expected.repeat-stdout` check for two minification rounds. All new fixtures fail without the fix. - Update the `next/swc-4559` snapshot. It now keeps `"use strict"`, which the old output wrongly dropped. - Update the antd gzipped size in `libs-size.snapshot.md` (+0.01 KiB) for the same reason. Local validation (on the final revision): `cargo fmt --all`, `cargo clippy --all --all-targets -- -D warnings`, `cargo test -p swc_ecma_minifier` and `crates/swc_ecma_minifier/scripts/exec.sh` passed. CI was not run locally. Closes #9238 --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
main
4 hours ago
fix(ts/fast-strip): preserve runtime boundaries during type erasure (#12575) **Description:** Rewrite `swc_ts_fast_strip` around explicit source edits and shared statement/member context to preserve runtime boundaries during type erasure. The examples below omit the whitespace padding left by in-place erasure. 1. Preserve optional fields named `get`, `set`, or `static`. Erasing `?` can cause the field name to be parsed as an accessor keyword or a `static` modifier for the following member. Insert a semicolon to preserve the field boundary. Input: ```ts class C { get? foo() {} } ``` Before — becomes a getter: ```js class C { get foo() {} } ``` After — retains a field and a method: ```js class C { get; foo() {} } ``` 2. Preserve initializer boundaries across erased class members. Erasing a `declare` or `abstract` member can cause the following computed member to continue the preceding field initializer. Input: ```ts abstract class C { x = 1 abstract m(): void ["n"]() {} } ``` Before — the computed key continues the initializer, producing invalid JavaScript: ```js class C { x = 1 ["n"]() {} } ``` After — the erased member leaves a semicolon separator: ```js class C { x = 1 ; ["n"]() {} } ``` 3. Preserve statement boundaries after `as const`. Erasing the assertion can cause the following statement to be parsed as a call, property access, or tagged template on the preceding expression. Input: ```ts 0 as const (() => {})(); ``` Before — attempts to call `0`: ```js 0 (() => {})(); ``` After — executes two separate statements: ```js 0; (() => {})(); ``` 4. Preserve directive boundaries across erased declarations. A type declaration terminates the directive prologue. Erasing it must not allow a subsequent string literal statement to join the prologue, even when preceded by earlier directives. Input: ```ts "custom"; type T = number; "use strict"; ``` Before — unintentionally enables strict mode: ```js "custom"; "use strict"; ``` After — preserves the original directive boundary: ```js "custom"; ; "use strict"; ``` 5. Preserve required labeled statement bodies. Erasing a labeled statement's body can leave invalid JavaScript or cause the label to capture the following statement. Retain an empty statement instead. Input: ```ts label: interface I {} ``` Before — leaves a dangling label: ```js label: ``` After: ```js label: ; ``` 6. Reject assertions that expose invalid exponentiation operands. A type assertion can hide an unparenthesized unary or `await` expression on the left-hand side of `**`. Report an error during type erasure instead of emitting invalid JavaScript. Input: ```ts const y = -x as number ** 2; ``` Before — emits invalid JavaScript: ```js const y = -x ** 2; ``` After — reports an error: ```text UnsupportedSyntax ``` Explicitly parenthesized operands and transform mode remain supported. Separators are written into erased source spans while preserving UTF-16 offsets and line terminators. Also reorganize and expand the fixture suites by syntax category and issue number, retain existing diagnostic fixtures, and reparse all successful fixture outputs to catch invalid JavaScript. **Related issue (if exists):** - Closes #12568 - Supersedes #12573
main
5 hours ago
chore: Add changeset
kdy1/fix-issue-9238
5 hours ago
chore(ci): Ignore inapplicable Wasmtime component handle advisory (#12577) <!-- Note: CI script will automatically rebase your PR so please do not rebase unless required --> <!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. --> **Description:** <!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? --> The dependency check in [this job](https://github.com/swc-project/swc/actions/runs/39372463733/job/118463782777) fails on RUSTSEC-2026-0363. The advisory affects component-model resource handle tables. The SWC Wasmtime backend disables default features, does not enable `component-model`, and instantiates core Wasm modules through `wasmtime::Module` and `wasmtime::Linker`. Add a documented exception for this advisory, following the existing component-model exception. Wasmtime 38 has no patched release; reconsider the exception when upgrading the backend. No release changeset is needed because this change only updates CI policy; no Rust crate or runtime behavior changes. Validation: - `cargo tree --locked -e features -i wasmtime`: confirmed that `component-model` is disabled. - `cargo fmt --all`: passed. - `cargo test -p swc-releaser --test changesets`: passed after removing an unsupported empty changeset. - `cargo clippy --all --all-targets -- -D warnings`: passed. - `cargo deny check`: reproduced RUSTSEC-2026-0363 before the change; it is absent after the change. The current advisory database also reports RUSTSEC-2026-0379 and RUSTSEC-2026-0380, which were absent from the linked job and remain outside this change. **Related issue (if exists):** No associated issue.
main
5 hours ago
fix(es/fixer): wrap function declarations in sloppy-mode loop bodies (#12567) **Description:** With the default options, a script with a function declaration alone in a loop body is minified to code that does not parse: ```js var n = 0; while (n++ < 2) { function g() { return n; } } console.log(typeof g, g()); ``` `minifySync(code, { compress: {}, mangle: {} })` gives `for(var n=0;n++<2;)function g(){return n}console.log(typeof g,g());`, a SyntaxError, so the whole file fails to load; the original prints `function 3`. The minifier unwraps the block, and since #12416 the fixer's `wrap_single_function` puts it back around a function declaration used as a loop body or an `if` clause, but only in strict mode code. Skipping it in sloppy mode is right only for a plain function declaration as an `if` clause, which Annex B allows. A loop body can never be a function declaration, and Annex B does not cover async functions or generators either: `if (c) { async function g() {} }` becomes `if(c)async function g(){}`, also a SyntaxError. `wrap_single_function` now takes `is_if_clause` and skips the block only for a plain function declaration as an `if` clause in sloppy mode. Loop bodies (all five loops) are always wrapped, and so are async and generator declarations in an `if`. `if (c) function f() {}` in a script is still printed without braces. A `with` body has the same problem, but the fixer has no handler for `with` statements, so it is not part of this change. The fixer runs after the minifier, so on valid input no minifier pass sees the change. Performance: one more boolean argument per loop and `if` statement. **Tests:** - `tests/fixture/issues/12565/` in `swc_ecma_minifier` (`defaults: true`, script), with `expected.stdout`. The five loops, an async `if` clause and a generator `else` fail without the change: node cannot parse the output. The control, a plain function as an `if` clause, keeps its unwrapped output. - No existing fixture or snapshot changes. Minifying every `input.js` under `swc_ecma_minifier/tests` and the test262-parser `pass` files with the default options, as a script and as a module, the only outputs that change are the new fixtures and `terser/compress/blocks/issue_1672_for` as a script; none of them parsed before. Checks: `cargo test -p swc_ecma_transforms_base` (7847 passed), `cargo test -p swc_ecma_minifier` (8041 passed), `cargo test -p swc` (same results as on `main`), `./scripts/exec.sh`, `cargo clippy --all-targets -- -D warnings` on both crates and `cargo fmt --all -- --check`. **Related issue (if exists):** Closes #12565 --- Found with a differential fuzzer. Drafted with AI assistance; I confirmed locally that the new fixtures (except the control) fail without the fix and that all of them pass with it, and that @swc/core 1.16.18 gives the output above.
main
6 hours ago

Latest Branches

CodSpeed Performance Gauge
+6%
fix(es/typescript): Fix merged namespace bindings and enum evaluation#12455
6 days ago
ec177e4
fix/ts-namespace-enum-bindings
CodSpeed Performance Gauge
0%
fix(es/minifier): keep directive prologue when merging if returns#12580
5 hours ago
a981064
kdy1/fix-issue-9238
CodSpeed Performance Gauge
0%
6 hours ago
04434a4
kdy1/fix-ci-job
© 2026 CodSpeed Technology
Home Terms Privacy Docs