From 61ec868f7ef3e71cceb243f9ce41f47dbcf7ad72 Mon Sep 17 00:00:00 2001 From: Rayan Salhab Date: Thu, 26 Mar 2026 18:34:01 +0000 Subject: [PATCH 1/2] fix(utils): hasBothRollupOptionsAndRolldownOptions returns false for proxy case When mergeConfig sets up rollupOptions to rolldownOptions proxy, both properties exist but point to the same object. The function hasBothRollupOptionsAndRolldownOptions should return false in this case to avoid false positive warnings about both options being set. Fixes #22040 --- .../vite/src/node/__tests__/config.spec.ts | 51 ++++++++++++++++++- packages/vite/src/node/utils.ts | 5 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/__tests__/config.spec.ts b/packages/vite/src/node/__tests__/config.spec.ts index 6ccbe75f421c27..7a44000b1e7b85 100644 --- a/packages/vite/src/node/__tests__/config.spec.ts +++ b/packages/vite/src/node/__tests__/config.spec.ts @@ -6,7 +6,7 @@ import type { InlineConfig, PluginOption } from '..' import type { UserConfig, UserConfigExport } from '../config' import { defineConfig, loadConfigFromFile, resolveConfig } from '../config' import { resolveEnvPrefix } from '../env' -import { mergeConfig } from '../utils' +import { hasBothRollupOptionsAndRolldownOptions, mergeConfig } from '../utils' import { createLogger } from '../logger' describe('mergeConfig', () => { @@ -560,6 +560,55 @@ describe('mergeConfig', () => { expect(downOutput.hashCharacters).toBe('base36') }) + test('hasBothRollupOptionsAndRolldownOptions returns false when only rollupOptions is set (proxy case)', () => { + // When mergeConfig is called with only rollupOptions in the override, + // setupRollupOptionCompat creates a proxy where rollupOptions === rolldownOptions. + // hasBothRollupOptionsAndRolldownOptions should return false in this case + // to avoid false positive warnings. + const baseConfig = defineConfig({ + build: {}, // Need existing build object for recursive merge to happen + }) + + const newConfig = defineConfig({ + build: { + rollupOptions: { + treeshake: false, + }, + }, + }) + + const mergedConfig = mergeConfig(baseConfig, newConfig) as UserConfig + + // After merge, both rollupOptions and rolldownOptions exist, + // but they point to the same object (proxy relationship) + expect(mergedConfig.build!.rollupOptions).toBeDefined() + expect(mergedConfig.build!.rolldownOptions).toBeDefined() + expect(mergedConfig.build!.rollupOptions).toBe( + mergedConfig.build!.rolldownOptions, + ) + + // hasBothRollupOptionsAndRolldownOptions should return false + // because they are the same object (proxy) + expect(hasBothRollupOptionsAndRolldownOptions(mergedConfig)).toBe(false) + }) + + test('hasBothRollupOptionsAndRolldownOptions returns true when both are explicitly set to different values', () => { + // When both rollupOptions and rolldownOptions are explicitly set to different values, + // hasBothRollupOptionsAndRolldownOptions should return true + const config = defineConfig({ + build: { + rollupOptions: { + treeshake: false, + }, + rolldownOptions: { + platform: 'neutral', + }, + }, + }) + + expect(hasBothRollupOptionsAndRolldownOptions(config)).toBe(true) + }) + test('rollupOptions/rolldownOptions.platform', async () => { const testRollupOptions = await resolveConfig( { diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 52ba8b067c1609..970966aa9ec30c 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -1317,7 +1317,10 @@ export function hasBothRollupOptionsAndRolldownOptions( if ( opt != null && opt.rollupOptions != null && - opt.rolldownOptions != null + opt.rolldownOptions != null && + // Check that they are actually different objects + // (not just a proxy relationship created by setupRollupOptionCompat) + opt.rollupOptions !== opt.rolldownOptions ) { return true } From 97f70b8f019693c811a899227911f961215131cd Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 27 Mar 2026 13:05:32 +0900 Subject: [PATCH 2/2] chore: tweak --- packages/vite/src/node/__tests__/config.spec.ts | 13 ++----------- packages/vite/src/node/utils.ts | 3 +-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/vite/src/node/__tests__/config.spec.ts b/packages/vite/src/node/__tests__/config.spec.ts index 7a44000b1e7b85..85737eafe3f8fb 100644 --- a/packages/vite/src/node/__tests__/config.spec.ts +++ b/packages/vite/src/node/__tests__/config.spec.ts @@ -560,7 +560,7 @@ describe('mergeConfig', () => { expect(downOutput.hashCharacters).toBe('base36') }) - test('hasBothRollupOptionsAndRolldownOptions returns false when only rollupOptions is set (proxy case)', () => { + test('hasBothRollupOptionsAndRolldownOptions returns false when only rollupOptions is set', () => { // When mergeConfig is called with only rollupOptions in the override, // setupRollupOptionCompat creates a proxy where rollupOptions === rolldownOptions. // hasBothRollupOptionsAndRolldownOptions should return false in this case @@ -568,7 +568,6 @@ describe('mergeConfig', () => { const baseConfig = defineConfig({ build: {}, // Need existing build object for recursive merge to happen }) - const newConfig = defineConfig({ build: { rollupOptions: { @@ -576,25 +575,18 @@ describe('mergeConfig', () => { }, }, }) + const mergedConfig: UserConfig = mergeConfig(baseConfig, newConfig) - const mergedConfig = mergeConfig(baseConfig, newConfig) as UserConfig - - // After merge, both rollupOptions and rolldownOptions exist, - // but they point to the same object (proxy relationship) expect(mergedConfig.build!.rollupOptions).toBeDefined() expect(mergedConfig.build!.rolldownOptions).toBeDefined() expect(mergedConfig.build!.rollupOptions).toBe( mergedConfig.build!.rolldownOptions, ) - // hasBothRollupOptionsAndRolldownOptions should return false - // because they are the same object (proxy) expect(hasBothRollupOptionsAndRolldownOptions(mergedConfig)).toBe(false) }) test('hasBothRollupOptionsAndRolldownOptions returns true when both are explicitly set to different values', () => { - // When both rollupOptions and rolldownOptions are explicitly set to different values, - // hasBothRollupOptionsAndRolldownOptions should return true const config = defineConfig({ build: { rollupOptions: { @@ -605,7 +597,6 @@ describe('mergeConfig', () => { }, }, }) - expect(hasBothRollupOptionsAndRolldownOptions(config)).toBe(true) }) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 970966aa9ec30c..8576b8e2b05261 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -1318,8 +1318,7 @@ export function hasBothRollupOptionsAndRolldownOptions( opt != null && opt.rollupOptions != null && opt.rolldownOptions != null && - // Check that they are actually different objects - // (not just a proxy relationship created by setupRollupOptionCompat) + // Check they are not just proxy values created by setupRollupOptionCompat opt.rollupOptions !== opt.rolldownOptions ) { return true