Skip to content

[Bug]: browserslist uses incorrect browsers #37

@andrzej-erli

Description

@andrzej-erli

I've been asked to report this issue. Originally posted here web-infra-dev/rsbuild#5847
I know nothing about Rust. I'm running a Node.js app which uses some link between Node and Rust app. Below snippets are results from Node CLI.
From my understanding, Rspack/Rsbuild team uses browserslist-rs to parse browser strings and my case (>0.2%, not dead, not op_mini all) produces some quiet fallback. From my tests, I tried chrome >= 200 which returned an empty array, and foo >= 200 which returned that fallback instead of some failure.

Version

System:
    OS: Linux 6.14 Ubuntu 24.04.2 LTS 24.04.2 LTS (Noble Numbat)
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
    Memory: 31.61 GB / 62.47 GB
    Container: Yes
    Shell: 5.9 - /usr/bin/zsh
  Browsers:
    Chrome: 138.0.7204.183
  npmPackages:
    @rsbuild/core: ~1.4.15 => 1.4.15 
    @rsbuild/plugin-react: ~1.3.5 => 1.3.5 
    @rsbuild/plugin-sass: ~1.3.5 => 1.3.5 
    @rsbuild/plugin-type-check: ~1.2.4 => 1.2.4

    browserslist: ~4.25.2 => 4.25.2
    caniuse-lite: ~1.0.30001735 => 1.0.30001734

Details

I'm migrating a Webpack project to Rsbuild. I was trying to figure out why core-js was adding unwanted polyfills in comparison to Webpack's output. I found that loadBrowserslist() is producing a different output than browserslist package. Here's a snippet from Node.js:

> {const ver = '>0.2%, not dead, not op_mini all';console.log(require('@rspack/binding').loadBrowserslist(ver, '/')),console.log(require('browserslist')(ver))}
[
  'and_chr 137',       'and_ff 139',
  'and_qq 14.9',       'and_uc 15.5',
  'android 137',       'chrome 137',
  'chrome 136',        'chrome 135',
  'chrome 134',        'chrome 133',
  'chrome 132',        'chrome 131',
  'chrome 109',        'edge 136',
  'edge 135',          'firefox 138',
  'ios_saf 18.5',      'ios_saf 18.4',
  'ios_saf 18.3',      'ios_saf 18.2',
  'ios_saf 18.1',      'ios_saf 17.6-17.7',
  'ios_saf 17.5',      'ios_saf 16.6-16.7',
  'ios_saf 15.6-15.8', 'ios_saf 11.0-11.2',
  'op_mob 80',         'safari 18.5',
  'safari 18.4',       'safari 18.3',
  'safari 17.6',       'samsung 28',
  'samsung 27'
]
[
  'and_chr 138',       'and_ff 140',
  'and_uc 15.5',       'android 138',
  'chrome 138',        'chrome 137',
  'chrome 136',        'chrome 135',
  'chrome 131',        'chrome 125',
  'chrome 112',        'chrome 109',
  'edge 138',          'edge 137',
  'firefox 141',       'firefox 140',
  'ios_saf 18.5',      'ios_saf 18.4',
  'ios_saf 18.3',      'ios_saf 18.1',
  'ios_saf 17.6-17.7', 'ios_saf 16.6-16.7',
  'ios_saf 15.6-15.8', 'ios_saf 11.0-11.2',
  'op_mob 80',         'safari 18.5',
  'samsung 28'
]

Later I noticed that loadBrowserslist() is not validating the input. It just returns a fallback. Here's a simple test with correct response:

> {const ver = 'chrome >= 200';console.log(require('@rspack/binding').loadBrowserslist(ver, '/a')),console.log(require('browserslist')(ver))}
[]
[]

And this one should fail. And it actually fails in browserslist but loadBrowserslist() ignores the error:

> {const ver = 'foo >= 200';console.log(require('@rspack/binding').loadBrowserslist(ver, '/a')),console.log(require('browserslist')(ver))}
[
  'and_chr 137',       'and_ff 139',
  'and_qq 14.9',       'and_uc 15.5',
  'android 137',       'chrome 138',
  'chrome 137',        'chrome 136',
  'chrome 135',        'chrome 134',
  'chrome 131',        'chrome 109',
  'edge 137',          'edge 136',
  'edge 135',          'firefox 140',
  'firefox 139',       'firefox 138',
  'firefox 128',       'ios_saf 18.5',
  'ios_saf 18.4',      'ios_saf 18.3',
  'ios_saf 17.6-17.7', 'ios_saf 16.6-16.7',
  'kaios 3.0-3.1',     'kaios 2.5',
  'op_mini all',       'op_mob 80',
  'opera 117',         'opera 116',
  'safari 18.5',       'safari 18.4',
  'samsung 28',        'samsung 27'
]
Uncaught Error [BrowserslistError]: Unknown browser foo
    at checkName (/web/node_modules/browserslist/index.js:278:20)
    at Function.select (/web/node_modules/browserslist/index.js:1038:18)
    at /web/node_modules/browserslist/index.js:332:29
    at Array.reduce (<anonymous>)
    at resolve (/web/node_modules/browserslist/index.js:322:32)
    at browserslist (/web/node_modules/browserslist/index.js:431:21) {
  browserslist: true
}

So the issue is that loadBrowserslist() fails to parse >0.2%, not dead, not op_mini all which is valid in browserslist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions