Skip to content

Oxc minifier removes if guard and changes runtime behavior #21457

@NullEnt1ty

Description

@NullEnt1ty

Describe the bug

Since upgrading to Vite 8, the default Oxc minifier appears to incorrectly optimize one of my functions and changes its runtime behavior. I reported the bug downstream in vitejs/vite#22234 but was told to report it here.

Here is a stripped down version of my code:

let rafId: number | undefined;

function foo() {
  if (rafId == null) {
    rafId = requestAnimationFrame(() => {
      console.log('callback');
    });
  }
}

Minified build output using oxc:

function e(){requestAnimationFrame(()=>{console.log(`callback`)})}

Minified build output using esbuild:

function c(){n==null&&(n=requestAnimationFrame(()=>{console.log("callback")}))}

The if (rafId == null) guard is gone entirely (when using oxc), which changes the behavior of the program. The original function schedules at most one pending animation frame at a time, while the minified output schedules a new one on every call.

Reproduction

The bug only happens when using "Transformer" with target >= 2021 and "Minify Syntax" checked.

https://playground.oxc.rs/?options=%7B%22run%22%3A%7B%22lint%22%3Afalse%2C%22formatter%22%3Afalse%2C%22transform%22%3Atrue%2C%22isolatedDeclarations%22%3Afalse%2C%22whitespace%22%3Afalse%2C%22mangle%22%3Afalse%2C%22compress%22%3Atrue%2C%22scope%22%3Atrue%2C%22symbol%22%3Atrue%2C%22cfg%22%3Afalse%7D%2C%22parser%22%3A%7B%22extension%22%3A%22tsx%22%2C%22allowReturnOutsideFunction%22%3Atrue%2C%22preserveParens%22%3Atrue%2C%22allowV8Intrinsics%22%3Atrue%2C%22semanticErrors%22%3Atrue%7D%2C%22linter%22%3A%7B%7D%2C%22formatter%22%3A%7B%22useTabs%22%3Afalse%2C%22tabWidth%22%3A2%2C%22endOfLine%22%3A%22lf%22%2C%22printWidth%22%3A80%2C%22singleQuote%22%3Afalse%2C%22jsxSingleQuote%22%3Afalse%2C%22quoteProps%22%3A%22as-needed%22%2C%22trailingComma%22%3A%22all%22%2C%22semi%22%3Atrue%2C%22arrowParens%22%3A%22always%22%2C%22bracketSpacing%22%3Atrue%2C%22bracketSameLine%22%3Afalse%2C%22objectWrap%22%3A%22preserve%22%2C%22singleAttributePerLine%22%3Afalse%7D%2C%22transformer%22%3A%7B%22target%22%3A%22es2022%22%2C%22useDefineForClassFields%22%3Atrue%2C%22experimentalDecorators%22%3Atrue%2C%22emitDecoratorMetadata%22%3Atrue%7D%2C%22isolatedDeclarations%22%3A%7B%22stripInternal%22%3Afalse%7D%2C%22codegen%22%3A%7B%22normal%22%3Atrue%2C%22jsdoc%22%3Atrue%2C%22annotation%22%3Atrue%2C%22legal%22%3Atrue%7D%2C%22compress%22%3A%7B%7D%2C%22mangle%22%3A%7B%22topLevel%22%3Atrue%2C%22keepNames%22%3Afalse%7D%2C%22controlFlow%22%3A%7B%22verbose%22%3Afalse%7D%2C%22inject%22%3A%7B%22inject%22%3A%7B%7D%7D%2C%22define%22%3A%7B%22define%22%3A%7B%7D%7D%7D&code=let+rafId%3A+number+%7C+undefined%3B%0A%0Afunction+foo%28%29+%7B%0A++if+%28rafId+%3D%3D+null%29+%7B%0A++++rafId+%3D+requestAnimationFrame%28%28%29+%3D%3E+%7B%0A++++++console.log%28%27callback%27%29%3B%0A++++%7D%29%3B%0A++%7D%0A%7D

Minimal Vite 8 project

https://stackblitz.com/edit/vitejs-vite-byj9asxu?file=src%2Fmain.ts

Steps to reproduce

npm run build:oxc to minify using oxc
npm run build:esbuild to minify using esbuild

You can check the build output in dist/assets/

System Info

System:
    OS: macOS 26.3
    CPU: (12) arm64 Apple M2 Max
    Memory: 1.55 GB / 32.00 GB
    Shell: 5.3.9 - /opt/homebrew/bin/bash
  Binaries:
    Node: 24.13.0 - /Users/dominique/.local/state/fnm_multishells/19928_1775543807061/bin/node
    Yarn: 1.22.22 - /Users/dominique/.local/state/fnm_multishells/19928_1775543807061/bin/yarn
    npm: 11.6.2 - /Users/dominique/.local/state/fnm_multishells/19928_1775543807061/bin/npm
    pnpm: 10.33.0 - /opt/homebrew/bin/pnpm
    bun: 1.3.11 - /opt/homebrew/bin/bun
    Deno: 2.7.11 - /opt/homebrew/bin/deno
  Browsers:
    Brave Browser: 144.1.86.142
    Chrome: 147.0.7727.56
    Firefox: 149.0
    Safari: 26.3
  npmPackages:
    @vitejs/plugin-react: 6.0.1 => 6.0.1
    vite: 8.0.1 => 8.0.1

Used Package Manager

npm

Metadata

Metadata

Assignees

Labels

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions