Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@vitejs/plugin-legacy] Polyfills for Symbol make the app break on old browsers #18959

Open
7 tasks done
cdatehortuab opened this issue Dec 13, 2024 · 5 comments
Open
7 tasks done
Labels
bug: upstream Bug in a dependency of Vite has workaround p2-edge-case Bug, but has workaround or limited in scope (priority) plugin: legacy

Comments

@cdatehortuab
Copy link

Describe the bug

I'm using @vitejs/plugin-legacy to target Chrome >= 38, including polyfills so I expect the app work properly in Chrome 38. However, when I run the built app on that browser an error is displayed in the console: "Unhandled promise rejection TypeError: @@toPrimitive must return a primitive value".

In my app, I'm using Axios. One of its classes (AxiosHeaders) defines a [Symbol.iterator] property. So, when Babel transpiles this class, it defines this property calling Symbol.iterator[Symbol.toPrimitive]('string'). This call returns an object, not a primitive value, so the error is thrown.

As you can see in the reproduction, it will happen with any class that defines [Symbol.iterator] (and probably any other property identified for well known Symbol ([Symbol.toPrimitive] for example))

This makes Vite unusable to target those browsers. (Chrome 38 is important because it's the version of the engine running under SmartTVs LG with webOS 3.x, see https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#web-engine)

The same code, built with Webpack works fine.

This bug was initially reported on #12844 but it didn't provide a reproduction

Reproduction

https://github.com/cdatehortuab/vite-issue-plugin-legacy

Steps to reproduce

  1. Clone the repo https://github.com/cdatehortuab/vite-issue-plugin-legacy
  2. Run npm install
  3. Run npm run build
  4. Run npx vite preview
  5. Open the app in Chrome 38

System Info

System:
    OS: macOS 14.7.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 19.49 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.11.0 - ~/.nvm/versions/node/v22.11.0/bin/node
    Yarn: 4.5.1 - ~/.nvm/versions/node/v22.11.0/bin/yarn
    npm: 10.9.2 - ~/.nvm/versions/node/v22.11.0/bin/npm
  Browsers:
    Safari: 18.1.1
  npmPackages:
    @vitejs/plugin-legacy: ^6.0.0 => 6.0.0 
    vite: ^6.0.3 => 6.0.3

Used Package Manager

npm

Logs

Click to expand!
  vite:config bundled config file loaded in 130.74ms +0ms
[@vitejs/plugin-legacy] modernTargets: edge>=79, firefox>=67, chrome>=64, safari>=12, chromeAndroid>=64, iOS>=12
[@vitejs/plugin-legacy] targets: [ 'chrome >= 38' ]
  vite:config using resolved config: {
  vite:config   plugins: [
  vite:config     'vite:build-metadata',
  vite:config     'vite:watch-package-data',
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm-helper',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:legacy-config',
  vite:config     'vite:legacy-generate-polyfill-chunk',
  vite:config     'vite:wasm-fallback',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:build-html',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'vite:force-systemjs-wrap-complete',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'vite:rollup-options-plugins',
  vite:config     'vite:dynamic-import-vars',
  vite:config     'vite:import-glob',
  vite:config     'vite:legacy-post-process',
  vite:config     'vite:build-import-analysis',
  vite:config     'vite:esbuild-transpile',
  vite:config     'vite:terser',
  vite:config     'vite:manifest',
  vite:config     'vite:ssr-manifest',
  vite:config     'vite:reporter',
  vite:config     'vite:load-fallback'
  vite:config   ],
  vite:config   build: {
  vite:config     target: [ 'es2020', 'edge79', 'firefox67', 'chrome64', 'safari12' ],
  vite:config     polyfillModulePreload: true,
  vite:config     modulePreload: { polyfill: true },
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     sourcemap: false,
  vite:config     terserOptions: {},
  vite:config     rollupOptions: {
  vite:config       output: [
  vite:config         {
  vite:config           format: 'system',
  vite:config           entryFileNames: 'assets/[name]-legacy-[hash].js',
  vite:config           chunkFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config         },
  vite:config         {}
  vite:config       ]
  vite:config     },
  vite:config     commonjsOptions: { include: [ /node_modules/ ], extensions: [ '.js', '.cjs' ] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [ /node_modules/ ] },
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     copyPublicDir: true,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssrManifest: false,
  vite:config     ssrEmitAssets: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     cssCodeSplit: true,
  vite:config     minify: 'esbuild',
  vite:config     ssr: false,
  vite:config     emitAssets: true,
  vite:config     createEnvironment: [Function: createEnvironment],
  vite:config     cssTarget: 'chrome61',
  vite:config     cssMinify: true
  vite:config   },
  vite:config   define: { 'import.meta.env.LEGACY': '__VITE_IS_LEGACY__' },
  vite:config   environments: {
  vite:config     client: {
  vite:config       define: { 'import.meta.env.LEGACY': '__VITE_IS_LEGACY__' },
  vite:config       resolve: {
  vite:config         externalConditions: [ 'node' ],
  vite:config         extensions: [ '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json' ],
  vite:config         dedupe: [],
  vite:config         noExternal: [],
  vite:config         external: [],
  vite:config         preserveSymlinks: false,
  vite:config         alias: [
  vite:config           {
  vite:config             find: /^\/?@vite\/env/,
  vite:config             replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/env.mjs'
  vite:config           },
  vite:config           {
  vite:config             find: /^\/?@vite\/client/,
  vite:config             replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/client.mjs'
  vite:config           }
  vite:config         ],
  vite:config         mainFields: [ 'browser', 'module', 'jsnext:main', 'jsnext' ],
  vite:config         conditions: [ 'module', 'browser', 'development|production' ],
  vite:config         enableBuiltinNoExternalCheck: false
  vite:config       },
  vite:config       keepProcessEnv: false,
  vite:config       consumer: 'client',
  vite:config       optimizeDeps: {
  vite:config         include: [],
  vite:config         exclude: [],
  vite:config         needsInterop: [],
  vite:config         extensions: [],
  vite:config         disabled: undefined,
  vite:config         holdUntilCrawlEnd: true,
  vite:config         force: false,
  vite:config         noDiscovery: false,
  vite:config         esbuildOptions: { preserveSymlinks: false }
  vite:config       },
  vite:config       dev: {
  vite:config         warmup: [],
  vite:config         sourcemap: { js: true },
  vite:config         sourcemapIgnoreList: [Function: isInNodeModules$1],
  vite:config         preTransformRequests: true,
  vite:config         createEnvironment: [Function: defaultCreateClientDevEnvironment],
  vite:config         recoverable: true,
  vite:config         moduleRunnerTransform: false
  vite:config       },
  vite:config       build: {
  vite:config         target: [ 'es2020', 'edge79', 'firefox67', 'chrome64', 'safari12' ],
  vite:config         polyfillModulePreload: true,
  vite:config         modulePreload: { polyfill: true },
  vite:config         outDir: 'dist',
  vite:config         assetsDir: 'assets',
  vite:config         assetsInlineLimit: 4096,
  vite:config         sourcemap: false,
  vite:config         terserOptions: {},
  vite:config         rollupOptions: {
  vite:config           output: [
  vite:config             {
  vite:config               format: 'system',
  vite:config               entryFileNames: 'assets/[name]-legacy-[hash].js',
  vite:config               chunkFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config             },
  vite:config             {}
  vite:config           ]
  vite:config         },
  vite:config         commonjsOptions: { include: [ /node_modules/ ], extensions: [ '.js', '.cjs' ] },
  vite:config         dynamicImportVarsOptions: { warnOnError: true, exclude: [ /node_modules/ ] },
  vite:config         write: true,
  vite:config         emptyOutDir: null,
  vite:config         copyPublicDir: true,
  vite:config         manifest: false,
  vite:config         lib: false,
  vite:config         ssrManifest: false,
  vite:config         ssrEmitAssets: false,
  vite:config         reportCompressedSize: true,
  vite:config         chunkSizeWarningLimit: 500,
  vite:config         watch: null,
  vite:config         cssCodeSplit: true,
  vite:config         minify: 'esbuild',
  vite:config         ssr: false,
  vite:config         emitAssets: true,
  vite:config         createEnvironment: [Function: createEnvironment],
  vite:config         cssTarget: 'chrome61',
  vite:config         cssMinify: true
  vite:config       }
  vite:config     }
  vite:config   },
  vite:config   resolve: {
  vite:config     externalConditions: [ 'node' ],
  vite:config     extensions: [ '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json' ],
  vite:config     dedupe: [],
  vite:config     noExternal: [],
  vite:config     external: [],
  vite:config     preserveSymlinks: false,
  vite:config     alias: [
  vite:config       {
  vite:config         find: /^\/?@vite\/env/,
  vite:config         replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/env.mjs'
  vite:config       },
  vite:config       {
  vite:config         find: /^\/?@vite\/client/,
  vite:config         replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/client.mjs'
  vite:config       }
  vite:config     ],
  vite:config     mainFields: [ 'module', 'jsnext:main', 'jsnext' ],
  vite:config     conditions: [ 'module', 'node', 'development|production' ],
  vite:config     enableBuiltinNoExternalCheck: false
  vite:config   },
  vite:config   configFile: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/vite.config.js',
  vite:config   configFileDependencies: [
  vite:config     '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/vite.config.js'
  vite:config   ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     build: {
  vite:config       cssTarget: 'chrome61',
  vite:config       target: [ 'es2020', 'edge79', 'firefox67', 'chrome64', 'safari12' ]
  vite:config     }
  vite:config   },
  vite:config   root: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite',
  vite:config   base: '/',
  vite:config   decodedBase: '/',
  vite:config   rawBase: '/',
  vite:config   publicDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/public',
  vite:config   cacheDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/.vite',
  vite:config   command: 'build',
  vite:config   mode: 'production',
  vite:config   isWorker: false,
  vite:config   mainConfig: null,
  vite:config   bundleChain: [],
  vite:config   isProduction: true,
  vite:config   css: {
  vite:config     transformer: 'postcss',
  vite:config     preprocessorMaxWorkers: 0,
  vite:config     devSourcemap: false,
  vite:config     lightningcss: undefined
  vite:config   },
  vite:config   json: { namedExports: true, stringify: 'auto' },
  vite:config   esbuild: { jsxDev: false },
  vite:config   server: {
  vite:config     port: 5173,
  vite:config     strictPort: false,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: false,
  vite:config     proxy: undefined,
  vite:config     cors: true,
  vite:config     headers: {},
  vite:config     warmup: { clientFiles: [], ssrFiles: [] },
  vite:config     middlewareMode: false,
  vite:config     fs: {
  vite:config       strict: true,
  vite:config       deny: [ '.env', '.env.*', '*.{crt,pem}', '**/.git/**' ],
  vite:config       allow: [
  vite:config         '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite'
  vite:config       ]
  vite:config     },
  vite:config     preTransformRequests: true,
  vite:config     perEnvironmentStartEndDuringDev: false,
  vite:config     sourcemapIgnoreList: [Function: isInNodeModules$1]
  vite:config   },
  vite:config   builder: undefined,
  vite:config   preview: {
  vite:config     port: 4173,
  vite:config     strictPort: false,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: false,
  vite:config     proxy: undefined,
  vite:config     cors: true,
  vite:config     headers: {}
  vite:config   },
  vite:config   envDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite',
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(1) {
  vite:config     'fnpd_/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite' => {
  vite:config       dir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite',
  vite:config       data: {
  vite:config         name: 'corejs-babel-error',
  vite:config         version: '1.0.0',
  vite:config         main: 'index.js',
  vite:config         type: 'module',
  vite:config         scripts: {
  vite:config           build: 'vite build',
  vite:config           test: 'echo "Error: no test specified" && exit 1'
  vite:config         },
  vite:config         author: '',
  vite:config         license: 'ISC',
  vite:config         description: 'My vite project',
  vite:config         devDependencies: { '@vitejs/plugin-legacy': '^6.0.0', vite: '^6.0.3' },
  vite:config         packageManager: '[email protected]+sha256.dc2e45a77f87a9c2a76708d098ab54ca0cfdd5ec2cf7d9e3c1f24bf786a2383c'
  vite:config       },
  vite:config       hasSideEffects: [Function: hasSideEffects],
  vite:config       setResolvedCache: [Function: setResolvedCache],
  vite:config       getResolvedCache: [Function: getResolvedCache]
  vite:config     },
  vite:config     set: [Function (anonymous)]
  vite:config   },
  vite:config   worker: { format: 'iife', plugins: '() => plugins', rollupOptions: {} },
  vite:config   appType: 'spa',
  vite:config   experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false },
  vite:config   future: undefined,
  vite:config   ssr: {
  vite:config     target: 'node',
  vite:config     optimizeDeps: { esbuildOptions: { preserveSymlinks: false } },
  vite:config     resolve: { conditions: undefined, externalConditions: undefined }
  vite:config   },
  vite:config   optimizeDeps: {
  vite:config     include: [],
  vite:config     exclude: [],
  vite:config     needsInterop: [],
  vite:config     extensions: [],
  vite:config     disabled: undefined,
  vite:config     holdUntilCrawlEnd: true,
  vite:config     force: false,
  vite:config     noDiscovery: false,
  vite:config     esbuildOptions: { preserveSymlinks: false }
  vite:config   },
  vite:config   dev: {
  vite:config     warmup: [],
  vite:config     sourcemap: { js: true },
  vite:config     sourcemapIgnoreList: [Function: isInNodeModules$1],
  vite:config     preTransformRequests: false,
  vite:config     createEnvironment: [Function: defaultCreateDevEnvironment],
  vite:config     recoverable: false,
  vite:config     moduleRunnerTransform: false
  vite:config   },
  vite:config   getSortedPlugins: [Function: getSortedPlugins],
  vite:config   getSortedPluginHooks: [Function: getSortedPluginHooks],
  vite:config   createResolver: [Function: createResolver],
  vite:config   fsDenyGlob: [Function: arrayMatcher],
  vite:config   safeModulePaths: Set(0) {}
  vite:config } +68ms
vite v6.0.3 building for production...
✓ 3 modules transformed.
rendering chunks (1)...[@vitejs/plugin-legacy] legacy polyfills: Set(17) {
  'core-js/modules/es.symbol.js',
  'core-js/modules/es.symbol.description.js',
  'core-js/modules/es.symbol.iterator.js',
  'core-js/modules/es.symbol.to-primitive.js',
  'core-js/modules/es.error.cause.js',
  'core-js/modules/es.array.from.js',
  'core-js/modules/es.array.iterator.js',
  'core-js/modules/es.array.slice.js',
  'core-js/modules/es.date.to-primitive.js',
  'core-js/modules/es.number.constructor.js',
  'core-js/modules/es.object.to-string.js',
  'core-js/modules/es.promise.js',
  'core-js/modules/es.regexp.exec.js',
  'core-js/modules/es.regexp.test.js',
  'core-js/modules/es.regexp.to-string.js',
  'core-js/modules/es.string.iterator.js',
  'core-js/modules/web.dom-collections.iterator.js'
}
  vite:config using resolved config: {
  vite:config   mode: 'production',
  vite:config   root: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/dist',
  vite:config   configFile: undefined,
  vite:config   logLevel: 'error',
  vite:config   plugins: [
  vite:config     'vite:build-metadata',
  vite:config     'vite:watch-package-data',
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:json',
  vite:config     'vite:wasm-helper',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:legacy-polyfills',
  vite:config     'vite:wasm-fallback',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:build-html',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'vite:force-systemjs-wrap-complete',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'vite:rollup-options-plugins',
  vite:config     'vite:dynamic-import-vars',
  vite:config     'vite:import-glob',
  vite:config     'vite:build-import-analysis',
  vite:config     'vite:terser',
  vite:config     'vite:manifest',
  vite:config     'vite:ssr-manifest',
  vite:config     'vite:reporter',
  vite:config     'vite:load-fallback'
  vite:config   ],
  vite:config   build: {
  vite:config     target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ],
  vite:config     polyfillModulePreload: true,
  vite:config     modulePreload: { polyfill: true },
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     sourcemap: false,
  vite:config     terserOptions: {},
  vite:config     rollupOptions: {
  vite:config       input: { polyfills: '\x00vite/legacy-polyfills' },
  vite:config       output: {
  vite:config         format: 'iife',
  vite:config         entryFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config       }
  vite:config     },
  vite:config     commonjsOptions: { include: [ /node_modules/ ], extensions: [ '.js', '.cjs' ] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [ /node_modules/ ] },
  vite:config     write: false,
  vite:config     emptyOutDir: null,
  vite:config     copyPublicDir: true,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssrManifest: false,
  vite:config     ssrEmitAssets: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     cssCodeSplit: true,
  vite:config     minify: 'terser',
  vite:config     ssr: false,
  vite:config     emitAssets: true,
  vite:config     createEnvironment: [Function: createEnvironment],
  vite:config     cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ],
  vite:config     cssMinify: true
  vite:config   },
  vite:config   esbuild: false,
  vite:config   optimizeDeps: {
  vite:config     include: [],
  vite:config     exclude: [],
  vite:config     needsInterop: [],
  vite:config     extensions: [],
  vite:config     disabled: undefined,
  vite:config     holdUntilCrawlEnd: true,
  vite:config     force: false,
  vite:config     noDiscovery: false,
  vite:config     esbuildOptions: { preserveSymlinks: false, target: 'es5' }
  vite:config   },
  vite:config   environments: {
  vite:config     client: {
  vite:config       define: undefined,
  vite:config       resolve: {
  vite:config         externalConditions: [ 'node' ],
  vite:config         extensions: [ '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json' ],
  vite:config         dedupe: [],
  vite:config         noExternal: [],
  vite:config         external: [],
  vite:config         preserveSymlinks: false,
  vite:config         alias: [
  vite:config           {
  vite:config             find: /^\/?@vite\/env/,
  vite:config             replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/env.mjs'
  vite:config           },
  vite:config           {
  vite:config             find: /^\/?@vite\/client/,
  vite:config             replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/client.mjs'
  vite:config           }
  vite:config         ],
  vite:config         mainFields: [ 'browser', 'module', 'jsnext:main', 'jsnext' ],
  vite:config         conditions: [ 'module', 'browser', 'development|production' ],
  vite:config         enableBuiltinNoExternalCheck: false
  vite:config       },
  vite:config       keepProcessEnv: false,
  vite:config       consumer: 'client',
  vite:config       optimizeDeps: {
  vite:config         include: [],
  vite:config         exclude: [],
  vite:config         needsInterop: [],
  vite:config         extensions: [],
  vite:config         disabled: undefined,
  vite:config         holdUntilCrawlEnd: true,
  vite:config         force: false,
  vite:config         noDiscovery: false,
  vite:config         esbuildOptions: { preserveSymlinks: false, target: 'es5' }
  vite:config       },
  vite:config       dev: {
  vite:config         warmup: [],
  vite:config         sourcemap: { js: true },
  vite:config         sourcemapIgnoreList: [Function: isInNodeModules$1],
  vite:config         preTransformRequests: true,
  vite:config         createEnvironment: [Function: defaultCreateClientDevEnvironment],
  vite:config         recoverable: true,
  vite:config         moduleRunnerTransform: false
  vite:config       },
  vite:config       build: {
  vite:config         target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ],
  vite:config         polyfillModulePreload: true,
  vite:config         modulePreload: { polyfill: true },
  vite:config         outDir: 'dist',
  vite:config         assetsDir: 'assets',
  vite:config         assetsInlineLimit: 4096,
  vite:config         sourcemap: false,
  vite:config         terserOptions: {},
  vite:config         rollupOptions: {
  vite:config           input: { polyfills: '\x00vite/legacy-polyfills' },
  vite:config           output: {
  vite:config             format: 'iife',
  vite:config             entryFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config           }
  vite:config         },
  vite:config         commonjsOptions: { include: [ /node_modules/ ], extensions: [ '.js', '.cjs' ] },
  vite:config         dynamicImportVarsOptions: { warnOnError: true, exclude: [ /node_modules/ ] },
  vite:config         write: false,
  vite:config         emptyOutDir: null,
  vite:config         copyPublicDir: true,
  vite:config         manifest: false,
  vite:config         lib: false,
  vite:config         ssrManifest: false,
  vite:config         ssrEmitAssets: false,
  vite:config         reportCompressedSize: true,
  vite:config         chunkSizeWarningLimit: 500,
  vite:config         watch: null,
  vite:config         cssCodeSplit: true,
  vite:config         minify: 'terser',
  vite:config         ssr: false,
  vite:config         emitAssets: true,
  vite:config         createEnvironment: [Function: createEnvironment],
  vite:config         cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ],
  vite:config         cssMinify: true
  vite:config       }
  vite:config     }
  vite:config   },
  vite:config   resolve: {
  vite:config     externalConditions: [ 'node' ],
  vite:config     extensions: [ '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json' ],
  vite:config     dedupe: [],
  vite:config     noExternal: [],
  vite:config     external: [],
  vite:config     preserveSymlinks: false,
  vite:config     alias: [
  vite:config       {
  vite:config         find: /^\/?@vite\/env/,
  vite:config         replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/env.mjs'
  vite:config       },
  vite:config       {
  vite:config         find: /^\/?@vite\/client/,
  vite:config         replacement: '/@fs/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client/client.mjs'
  vite:config       }
  vite:config     ],
  vite:config     mainFields: [ 'module', 'jsnext:main', 'jsnext' ],
  vite:config     conditions: [ 'module', 'node', 'development|production' ],
  vite:config     enableBuiltinNoExternalCheck: false
  vite:config   },
  vite:config   configFileDependencies: [],
  vite:config   inlineConfig: {
  vite:config     mode: 'production',
  vite:config     root: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/dist',
  vite:config     configFile: false,
  vite:config     logLevel: 'error',
  vite:config     plugins: [
  vite:config       {
  vite:config         name: 'vite:legacy-polyfills',
  vite:config         resolveId: [Function: resolveId],
  vite:config         load: [Function: load]
  vite:config       },
  vite:config       undefined
  vite:config     ],
  vite:config     build: {
  vite:config       write: false,
  vite:config       minify: 'terser',
  vite:config       assetsDir: 'assets',
  vite:config       sourcemap: false,
  vite:config       rollupOptions: {
  vite:config         input: { polyfills: '\x00vite/legacy-polyfills' },
  vite:config         output: {
  vite:config           format: 'iife',
  vite:config           entryFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config         }
  vite:config       }
  vite:config     },
  vite:config     esbuild: false,
  vite:config     optimizeDeps: { esbuildOptions: { target: 'es5' } },
  vite:config     environments: {
  vite:config       client: {
  vite:config         define: undefined,
  vite:config         resolve: undefined,
  vite:config         dev: {},
  vite:config         build: {
  vite:config           write: false,
  vite:config           minify: 'terser',
  vite:config           assetsDir: 'assets',
  vite:config           sourcemap: false,
  vite:config           rollupOptions: {
  vite:config             input: { polyfills: '\x00vite/legacy-polyfills' },
  vite:config             output: {
  vite:config               format: 'iife',
  vite:config               entryFileNames: 'assets/[name]-legacy-[hash].js'
  vite:config             }
  vite:config           }
  vite:config         },
  vite:config         optimizeDeps: { esbuildOptions: { target: 'es5' } }
  vite:config       }
  vite:config     },
  vite:config     resolve: { conditions: undefined, mainFields: undefined }
  vite:config   },
  vite:config   base: '/',
  vite:config   decodedBase: '/',
  vite:config   rawBase: '/',
  vite:config   publicDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/dist/public',
  vite:config   cacheDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/node_modules/.vite',
  vite:config   command: 'build',
  vite:config   isWorker: false,
  vite:config   mainConfig: null,
  vite:config   bundleChain: [],
  vite:config   isProduction: true,
  vite:config   css: {
  vite:config     transformer: 'postcss',
  vite:config     preprocessorMaxWorkers: 0,
  vite:config     devSourcemap: false,
  vite:config     lightningcss: undefined
  vite:config   },
  vite:config   json: { namedExports: true, stringify: 'auto' },
  vite:config   server: {
  vite:config     port: 5173,
  vite:config     strictPort: false,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: false,
  vite:config     proxy: undefined,
  vite:config     cors: true,
  vite:config     headers: {},
  vite:config     warmup: { clientFiles: [], ssrFiles: [] },
  vite:config     middlewareMode: false,
  vite:config     fs: {
  vite:config       strict: true,
  vite:config       deny: [ '.env', '.env.*', '*.{crt,pem}', '**/.git/**' ],
  vite:config       allow: [
  vite:config         '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy',
  vite:config         '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/vite/dist/client'
  vite:config       ]
  vite:config     },
  vite:config     preTransformRequests: true,
  vite:config     perEnvironmentStartEndDuringDev: false,
  vite:config     sourcemapIgnoreList: [Function: isInNodeModules$1]
  vite:config   },
  vite:config   builder: undefined,
  vite:config   preview: {
  vite:config     port: 4173,
  vite:config     strictPort: false,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: false,
  vite:config     proxy: undefined,
  vite:config     cors: true,
  vite:config     headers: {}
  vite:config   },
  vite:config   envDir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/dist',
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(2) {
  vite:config     'fnpd_/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy' => {
  vite:config       dir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy',
  vite:config       data: {
  vite:config         name: '@vitejs/plugin-legacy',
  vite:config         version: '6.0.0',
  vite:config         type: 'module',
  vite:config         license: 'MIT',
  vite:config         author: 'Evan You',
  vite:config         files: [ 'dist' ],
  vite:config         keywords: [ 'frontend', 'vite', 'vite-plugin', '@vitejs/plugin-legacy' ],
  vite:config         main: './dist/index.cjs',
  vite:config         module: './dist/index.mjs',
  vite:config         types: './dist/index.d.ts',
  vite:config         exports: {
  vite:config           '.': { import: './dist/index.mjs', require: './dist/index.cjs' }
  vite:config         },
  vite:config         engines: { node: '^18.0.0 || ^20.0.0 || >=22.0.0' },
  vite:config         repository: {
  vite:config           type: 'git',
  vite:config           url: 'git+https://github.com/vitejs/vite.git',
  vite:config           directory: 'packages/plugin-legacy'
  vite:config         },
  vite:config         bugs: { url: 'https://github.com/vitejs/vite/issues' },
  vite:config         homepage: 'https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme',
  vite:config         funding: 'https://github.com/vitejs/vite?sponsor=1',
  vite:config         dependencies: {
  vite:config           '@babel/core': '^7.26.0',
  vite:config           '@babel/preset-env': '^7.26.0',
  vite:config           browserslist: '^4.24.2',
  vite:config           'browserslist-to-esbuild': '^2.1.1',
  vite:config           'core-js': '^3.39.0',
  vite:config           'magic-string': '^0.30.13',
  vite:config           'regenerator-runtime': '^0.14.1',
  vite:config           systemjs: '^6.15.1'
  vite:config         },
  vite:config         peerDependencies: { terser: '^5.16.0', vite: '^6.0.0' },
  vite:config         devDependencies: {
  vite:config           acorn: '^8.14.0',
  vite:config           picocolors: '^1.1.1',
  vite:config           unbuild: '^3.0.0-rc.11',
  vite:config           vite: '6.0.0'
  vite:config         },
  vite:config         scripts: {
  vite:config           dev: 'unbuild --stub',
  vite:config           build: 'unbuild && pnpm run patch-cjs',
  vite:config           'patch-cjs': 'tsx ../../scripts/patchCJS.ts'
  vite:config         }
  vite:config       },
  vite:config       hasSideEffects: [Function: hasSideEffects],
  vite:config       setResolvedCache: [Function: setResolvedCache],
  vite:config       getResolvedCache: [Function: getResolvedCache]
  vite:config     },
  vite:config     'fnpd_/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy/dist' => {
  vite:config       dir: '/Users/cristian.atehortua/Documents/Projects/corejs-babel-error/vite/node_modules/@vitejs/plugin-legacy',
  vite:config       data: {
  vite:config         name: '@vitejs/plugin-legacy',
  vite:config         version: '6.0.0',
  vite:config         type: 'module',
  vite:config         license: 'MIT',
  vite:config         author: 'Evan You',
  vite:config         files: [ 'dist' ],
  vite:config         keywords: [ 'frontend', 'vite', 'vite-plugin', '@vitejs/plugin-legacy' ],
  vite:config         main: './dist/index.cjs',
  vite:config         module: './dist/index.mjs',
  vite:config         types: './dist/index.d.ts',
  vite:config         exports: {
  vite:config           '.': { import: './dist/index.mjs', require: './dist/index.cjs' }
  vite:config         },
  vite:config         engines: { node: '^18.0.0 || ^20.0.0 || >=22.0.0' },
  vite:config         repository: {
  vite:config           type: 'git',
  vite:config           url: 'git+https://github.com/vitejs/vite.git',
  vite:config           directory: 'packages/plugin-legacy'
  vite:config         },
  vite:config         bugs: { url: 'https://github.com/vitejs/vite/issues' },
  vite:config         homepage: 'https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme',
  vite:config         funding: 'https://github.com/vitejs/vite?sponsor=1',
  vite:config         dependencies: {
  vite:config           '@babel/core': '^7.26.0',
  vite:config           '@babel/preset-env': '^7.26.0',
  vite:config           browserslist: '^4.24.2',
  vite:config           'browserslist-to-esbuild': '^2.1.1',
  vite:config           'core-js': '^3.39.0',
  vite:config           'magic-string': '^0.30.13',
  vite:config           'regenerator-runtime': '^0.14.1',
  vite:config           systemjs: '^6.15.1'
  vite:config         },
  vite:config         peerDependencies: { terser: '^5.16.0', vite: '^6.0.0' },
  vite:config         devDependencies: {
  vite:config           acorn: '^8.14.0',
  vite:config           picocolors: '^1.1.1',
  vite:config           unbuild: '^3.0.0-rc.11',
  vite:config           vite: '6.0.0'
  vite:config         },
  vite:config         scripts: {
  vite:config           dev: 'unbuild --stub',
  vite:config           build: 'unbuild && pnpm run patch-cjs',
  vite:config           'patch-cjs': 'tsx ../../scripts/patchCJS.ts'
  vite:config         }
  vite:config       },
  vite:config       hasSideEffects: [Function: hasSideEffects],
  vite:config       setResolvedCache: [Function: setResolvedCache],
  vite:config       getResolvedCache: [Function: getResolvedCache]
  vite:config     },
  vite:config     set: [Function (anonymous)]
  vite:config   },
  vite:config   worker: { format: 'iife', plugins: '() => plugins', rollupOptions: {} },
  vite:config   appType: 'spa',
  vite:config   experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false },
  vite:config   future: undefined,
  vite:config   ssr: {
  vite:config     target: 'node',
  vite:config     optimizeDeps: { esbuildOptions: { preserveSymlinks: false } },
  vite:config     resolve: { conditions: undefined, externalConditions: undefined }
  vite:config   },
  vite:config   dev: {
  vite:config     warmup: [],
  vite:config     sourcemap: { js: true },
  vite:config     sourcemapIgnoreList: [Function: isInNodeModules$1],
  vite:config     preTransformRequests: false,
  vite:config     createEnvironment: [Function: defaultCreateDevEnvironment],
  vite:config     recoverable: false,
  vite:config     moduleRunnerTransform: false
  vite:config   },
  vite:config   getSortedPlugins: [Function: getSortedPlugins],
  vite:config   getSortedPluginHooks: [Function: getSortedPluginHooks],
  vite:config   createResolver: [Function: createResolver],
  vite:config   fsDenyGlob: [Function: arrayMatcher],
  vite:config   safeModulePaths: Set(0) {}
  vite:config } +1s
dist/assets/index-legacy-DE2YCvsT.js       1.02 kB │ gzip:  0.55 kB
dist/assets/polyfills-legacy-Cesharnc.js  59.12 kB │ gzip: 22.97 kB
dist/index.html                1.57 kB │ gzip: 0.72 kB
dist/assets/index-Bs_Y2buo.js  0.98 kB │ gzip: 0.56 kB
✓ built in 2.64s

Validations

@cdatehortuab
Copy link
Author

Investigating this a little, I found that the cause that this happens with Vite and not with Webpack is because @vitejs/plugin-legacy modifies the code before passing it to Babel adding this to the beginning:

      __VITE_IS_MODERN__&&(function polyfill() {
        const relList = document.createElement("link").relList;
        if (relList && relList.supports && relList.supports("modulepreload")) {
          return;
        }
        for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
          processPreload(link);
        }
        new MutationObserver((mutations) => {
          for (const mutation of mutations) {
            if (mutation.type !== "childList") {
              continue;
            }
            for (const node of mutation.addedNodes) {
              if (node.tagName === "LINK" && node.rel === "modulepreload")
                processPreload(node);
            }
          }
        }).observe(document, { childList: true, subtree: true });
        function getFetchOpts(link) {
          const fetchOpts = {};
          if (link.integrity) fetchOpts.integrity = link.integrity;
          if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
          if (link.crossOrigin === "use-credentials")
            fetchOpts.credentials = "include";
          else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
          else fetchOpts.credentials = "same-origin";
          return fetchOpts;
        }
        function processPreload(link) {
          if (link.ep)
            return;
          link.ep = true;
          const fetchOpts = getFetchOpts(link);
          fetch(link.href, fetchOpts);
        }
      }());

This code uses for...of syntax, which causes Babel to add more transpilation and helpers. So, the same error can be replicated with webpack by adding a for...of clause to the code.

In particular, when using for...of syntax, Babel adds the core-js/es.symbol.js polyfill. It's curious because Symbol is supported on Chrome 38 but is added to patch a particular behavior necessary for the for...of syntax. (See https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/symbol-constructor-detection.js)

The problematic part is that this polyfill creates a new Symbol constructor that returns an object. So when you use typeof Symbol() it returns "object". Babel has the _typeof helper that is intended for this use case but, since Symbol is supported in Chrome 38 typeof clauses are not replaced.

A workaround for this is to target a version that has no native support for Symbol, for example, Chrome 37. With this, babel will add the _typeof helper so "symbol" will be returned on typeof Symbol.

@cdatehortuab
Copy link
Author

Additional info: This doesn't happen with Create React App because it enables "loose" on transforms for define class properties. Because of that "defineProperties" babel helper (which internally uses toPrimitive) is not used.

@sapphi-red sapphi-red added bug: upstream Bug in a dependency of Vite has workaround plugin: legacy p2-edge-case Bug, but has workaround or limited in scope (priority) labels Dec 17, 2024
@sapphi-red
Copy link
Member

That sounds like a bug in babel. Would you report it to babel?

@cdatehortuab
Copy link
Author

Hi @sapphi-red, yes I will.

@cdatehortuab
Copy link
Author

Babel issue created: babel/babel#17030

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug: upstream Bug in a dependency of Vite has workaround p2-edge-case Bug, but has workaround or limited in scope (priority) plugin: legacy
Projects
None yet
Development

No branches or pull requests

2 participants