diff --git a/packages/bundler-plugins/package.json b/packages/bundler-plugins/package.json index 0c9796eefd75..baddefef28e7 100644 --- a/packages/bundler-plugins/package.json +++ b/packages/bundler-plugins/package.json @@ -137,7 +137,8 @@ "@types/node": "^18.6.3", "@types/webpack": "npm:@types/webpack@^4", "premove": "^4.0.0", - "rolldown": "^1.0.0", + "rolldown": "1.1.2", + "rolldown-1-2-5": "npm:rolldown@1.2.5", "vitest": "^3.2.7", "webpack": "5.104.1" }, diff --git a/packages/bundler-plugins/src/rollup/debug-id-injection.ts b/packages/bundler-plugins/src/rollup/debug-id-injection.ts new file mode 100644 index 000000000000..2b59f3216192 --- /dev/null +++ b/packages/bundler-plugins/src/rollup/debug-id-injection.ts @@ -0,0 +1,69 @@ +import { stringToUUID } from '../core'; + +export const ROLLDOWN_DEBUG_ID_PLACEHOLDER = 'SENTRY_DEBUG_ID_PLACEHOLDER_00000000'; + +type GeneratedChunk = { + type: 'chunk'; + fileName: string; + code: string; +}; + +type GeneratedAsset = { + type: 'asset'; + fileName: string; +}; + +export type GeneratedBundle = Record; + +const SENTRY_DEBUG_ID_IDENTIFIER = '_sentryDebugIdIdentifier'; +const SENTRY_DEBUG_ID_IDENTIFIER_PREFIX = 'sentry-dbid-'; + +export function hasExistingDebugID(code: string): boolean { + const chunkStartSnippet = code.slice(0, 6000); + const chunkEndSnippet = code.slice(-500); + + return chunkStartSnippet.includes(SENTRY_DEBUG_ID_IDENTIFIER) || chunkEndSnippet.includes('//# debugId='); +} + +export function getDebugIdForChunk(code: string, isRolldown: boolean): string { + return isRolldown ? ROLLDOWN_DEBUG_ID_PLACEHOLDER : stringToUUID(code); +} + +function replaceAt(code: string, start: number, search: string, replacement: string): string { + return `${code.slice(0, start)}${replacement}${code.slice(start + search.length)}`; +} + +export function finalizeRolldownDebugIds(bundle: GeneratedBundle): void { + for (const [fileName, output] of Object.entries(bundle)) { + if (output.type !== 'chunk') { + continue; + } + + const identifier = `${SENTRY_DEBUG_ID_IDENTIFIER_PREFIX}${ROLLDOWN_DEBUG_ID_PLACEHOLDER}`; + const identifierPropertyStart = output.code.indexOf(SENTRY_DEBUG_ID_IDENTIFIER); + const identifierStart = output.code.indexOf( + identifier, + identifierPropertyStart + SENTRY_DEBUG_ID_IDENTIFIER.length, + ); + if (identifierStart === -1) { + continue; + } + + const identifierPlaceholderStart = identifierStart + SENTRY_DEBUG_ID_IDENTIFIER_PREFIX.length; + const debugIdsPlaceholderStart = output.code.lastIndexOf(ROLLDOWN_DEBUG_ID_PLACEHOLDER, identifierStart - 1); + if (debugIdsPlaceholderStart === -1) { + throw new Error(`Failed to locate the Sentry debug ID placeholder for chunk \`${fileName}\`.`); + } + + // Including the final filename disambiguates otherwise identical chunks. The fixed-width replacement deliberately + // happens after Rolldown computes [hash], so the emitted filename represents the placeholder-bearing chunk. + const debugId = stringToUUID(JSON.stringify([output.fileName, output.code])); + const codeWithIdentifier = replaceAt( + output.code, + identifierPlaceholderStart, + ROLLDOWN_DEBUG_ID_PLACEHOLDER, + debugId, + ); + output.code = replaceAt(codeWithIdentifier, debugIdsPlaceholderStart, ROLLDOWN_DEBUG_ID_PLACEHOLDER, debugId); + } +} diff --git a/packages/bundler-plugins/src/rollup/index.ts b/packages/bundler-plugins/src/rollup/index.ts index c53ce21245bd..13bd8545eae5 100644 --- a/packages/bundler-plugins/src/rollup/index.ts +++ b/packages/bundler-plugins/src/rollup/index.ts @@ -6,7 +6,6 @@ import { isJsFile, shouldSkipCodeInjection, getDebugIdSnippet, - stringToUUID, COMMENT_USE_STRICT_REGEX, createDebugIdUploadFunction, globFiles, @@ -14,89 +13,34 @@ import { replaceBooleanFlagsInCode, CodeInjection, } from '../core'; -import type { - ComponentAnnotationTransformMeta, - ComponentAnnotationTransformResult, -} from '../core/component-annotation-vite'; +import type { ComponentAnnotationTransformMeta } from '../core/component-annotation-vite'; import type { SourceMap } from 'magic-string'; import MagicString from 'magic-string'; import * as path from 'node:path'; -import { createRequire } from 'node:module'; +import { + finalizeRolldownDebugIds, + getDebugIdForChunk, + hasExistingDebugID, + type GeneratedBundle, +} from './debug-id-injection'; +import { getRollupMajorVersion } from './rollup-version'; +import { createViteAnnotationHooks } from './vite-annotations'; // The subset of Rollup's `TransformResult` that this plugin's `transform` // hook actually returns. Defined locally instead of imported from `rollup` // because `rollup` is an optional dependency. type TransformResult = { code: string; map?: SourceMap | string | { mappings: string } | null } | null | undefined; -type ViteModule = { - parseAstAsync?: (code: string, options: { lang: 'jsx' | 'tsx' }) => Promise; -}; - -type ViteParseAstAsync = NonNullable; -type ViteAnnotationHooks = { - transform( - code: string, - id: string, - meta?: ComponentAnnotationTransformMeta, - ): Promise; +type RenderChunkPluginContext = { + meta?: { + rolldownVersion?: string; + }; }; -let viteParseAstAsyncPromise: Promise | undefined; +type GenerateBundlePluginContext = RenderChunkPluginContext; const JS_MODULE_ID_FILTER = /\.[cm]?[jt]sx?(?:[?#].*)?$/; -function hasExistingDebugID(code: string): boolean { - // Check if a debug ID has already been injected to avoid duplicate injection (e.g. by another plugin or Sentry CLI) - const chunkStartSnippet = code.slice(0, 6000); - const chunkEndSnippet = code.slice(-500); - - if (chunkStartSnippet.includes('_sentryDebugIdIdentifier') || chunkEndSnippet.includes('//# debugId=')) { - return true; // Debug ID already present, skip injection - } - - return false; -} - -function getRollupMajorVersion(): string | undefined { - try { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - Rollup already transpiles this for us - const req = createRequire(import.meta.url); - const rollup = req('rollup') as { VERSION?: string }; - return rollup.VERSION?.split('.')[0]; - } catch { - // do nothing, we'll just not report a version - } - - return undefined; -} - -function getViteParseAstAsync(): Promise { - if (!viteParseAstAsyncPromise) { - viteParseAstAsyncPromise = Promise.resolve() - .then(async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - Vite is an optional runtime peer for this package - const viteModule = createRequire(import.meta.url)('vite') as ViteModule; - - if (typeof viteModule.parseAstAsync !== 'function') { - return null; - } - - try { - await viteModule.parseAstAsync('const x =
;', { lang: 'tsx' }); - } catch { - return null; - } - - return viteModule.parseAstAsync; - }) - .catch(() => null); - } - - return viteParseAstAsyncPromise; -} - /** * @ignore - this is the internal plugin factory function only used for the Vite plugin! */ @@ -165,25 +109,7 @@ export function _rollupPluginInternal( buildTool === 'vite' && buildToolMajorVersion === '8' && !options.reactComponentAnnotation?._experimentalInjectIntoHtml - ? (() => { - let viteAnnotationHooksPromise: Promise | undefined; - - return { - transform(code: string, id: string, meta?: ComponentAnnotationTransformMeta) { - if (!viteAnnotationHooksPromise) { - viteAnnotationHooksPromise = import('../core/component-annotation-vite').then( - ({ createViteComponentNameAnnotateHooks }) => - createViteComponentNameAnnotateHooks( - options.reactComponentAnnotation?.ignoredComponents || [], - getViteParseAstAsync, - ), - ); - } - - return viteAnnotationHooksPromise.then(hooks => hooks.transform(code, id, meta)); - }, - }; - })() + ? createViteAnnotationHooks(options.reactComponentAnnotation?.ignoredComponents || []) : undefined; const transformReplace = Object.keys(replacementValues).length > 0; @@ -230,6 +156,7 @@ export function _rollupPluginInternal( } function renderChunk( + this: RenderChunkPluginContext | undefined, code: string, chunk: { fileName: string; facadeModuleId?: string | null }, _?: unknown, @@ -250,7 +177,7 @@ export function _rollupPluginInternal( const injectCode = staticInjectionCode.clone(); if (sourcemapsEnabled && !hasExistingDebugID(code)) { - const debugId = stringToUUID(code); // generate a deterministic debug ID + const debugId = getDebugIdForChunk(code, !!this?.meta?.rolldownVersion); injectCode.append(getDebugIdSnippet(debugId)); } @@ -280,10 +207,25 @@ export function _rollupPluginInternal( return { code: ms.toString(), - map: ms.generateMap({ file: chunk.fileName, hires: 'boundary' as unknown as undefined }), + map: ms.generateMap({ + file: chunk.fileName, + hires: 'boundary' as unknown as undefined, + }), }; } + function generateBundle( + this: GenerateBundlePluginContext | undefined, + _outputOptions: unknown, + bundle: GeneratedBundle, + ): void { + if (!this?.meta?.rolldownVersion) { + return; + } + + finalizeRolldownDebugIds(bundle); + } + async function writeBundle( outputOptions: { dir?: string; file?: string }, bundle: { [fileName: string]: unknown }, @@ -302,7 +244,9 @@ export function _rollupPluginInternal( '/**/*.mjs.map', '/**/*.cjs.map', ].map(q => `${q}?(\\?*)?(#*)`); // We want to allow query and hash strings at the end of files - const buildArtifacts = await globFiles(JS_AND_MAP_PATTERNS, { root: outputDir }); + const buildArtifacts = await globFiles(JS_AND_MAP_PATTERNS, { + root: outputDir, + }); await upload(buildArtifacts); } else if (outputOptions.file) { await upload([outputOptions.file]); @@ -318,6 +262,14 @@ export function _rollupPluginInternal( } const name = `sentry-${buildTool}-plugin`; + function createGenerateBundleHook() { + if (buildTool === 'vite' && buildToolMajorVersion === '8') { + return { order: 'post' as const, handler: generateBundle }; + } + + return generateBundle; + } + const generateBundleHook = createGenerateBundleHook(); if (shouldTransform) { const transformHook = @@ -333,6 +285,7 @@ export function _rollupPluginInternal( buildStart, transform: transformHook, renderChunk, + generateBundle: generateBundleHook, writeBundle, }; } @@ -341,6 +294,7 @@ export function _rollupPluginInternal( name, buildStart, renderChunk, + generateBundle: generateBundleHook, writeBundle, }; } diff --git a/packages/bundler-plugins/src/rollup/rollup-version.ts b/packages/bundler-plugins/src/rollup/rollup-version.ts new file mode 100644 index 000000000000..7e04a1468ed5 --- /dev/null +++ b/packages/bundler-plugins/src/rollup/rollup-version.ts @@ -0,0 +1,13 @@ +import { createRequire } from 'node:module'; + +export function getRollupMajorVersion(): string | undefined { + try { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - Rollup already transpiles this for us + const req = createRequire(import.meta.url); + const rollup = req('rollup') as { VERSION?: string }; + return rollup.VERSION?.split('.')[0]; + } catch { + return undefined; + } +} diff --git a/packages/bundler-plugins/src/rollup/vite-annotations.ts b/packages/bundler-plugins/src/rollup/vite-annotations.ts new file mode 100644 index 000000000000..6ae8d28cdc36 --- /dev/null +++ b/packages/bundler-plugins/src/rollup/vite-annotations.ts @@ -0,0 +1,63 @@ +import { createRequire } from 'node:module'; +import type { + ComponentAnnotationTransformMeta, + ComponentAnnotationTransformResult, +} from '../core/component-annotation-vite'; + +type ViteModule = { + parseAstAsync?: (code: string, options: { lang: 'jsx' | 'tsx' }) => Promise; +}; + +type ViteParseAstAsync = NonNullable; + +type ViteAnnotationHooks = { + transform( + code: string, + id: string, + meta?: ComponentAnnotationTransformMeta, + ): Promise; +}; + +let viteParseAstAsyncPromise: Promise | undefined; + +export function getViteParseAstAsync(): Promise { + if (!viteParseAstAsyncPromise) { + viteParseAstAsyncPromise = Promise.resolve() + .then(async () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - Vite is an optional runtime peer for this package + const viteModule = createRequire(import.meta.url)('vite') as ViteModule; + + if (typeof viteModule.parseAstAsync !== 'function') { + return null; + } + + try { + await viteModule.parseAstAsync('const x =
;', { lang: 'tsx' }); + } catch { + return null; + } + + return viteModule.parseAstAsync; + }) + .catch(() => null); + } + + return viteParseAstAsyncPromise; +} + +export function createViteAnnotationHooks(ignoredComponents: string[]): ViteAnnotationHooks { + let hooksPromise: Promise | undefined; + + return { + transform(code, id, meta) { + if (!hooksPromise) { + hooksPromise = import('../core/component-annotation-vite').then(({ createViteComponentNameAnnotateHooks }) => + createViteComponentNameAnnotateHooks(ignoredComponents, getViteParseAstAsync), + ); + } + + return hooksPromise.then(hooks => hooks.transform(code, id, meta)); + }, + }; +} diff --git a/packages/bundler-plugins/test/rollup/debug-id-injection.test.ts b/packages/bundler-plugins/test/rollup/debug-id-injection.test.ts new file mode 100644 index 000000000000..5dcfd2682676 --- /dev/null +++ b/packages/bundler-plugins/test/rollup/debug-id-injection.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from 'vitest'; +import { + finalizeRolldownDebugIds, + getDebugIdForChunk, + hasExistingDebugID, + ROLLDOWN_DEBUG_ID_PLACEHOLDER, + type GeneratedBundle, +} from '../../src/rollup/debug-id-injection'; + +const UUID_PATTERN = /[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}/g; + +function provisionalCode(userCode = 'console.log("test");'): string { + return [ + `globalThis._sentryDebugIds[stack]="${ROLLDOWN_DEBUG_ID_PLACEHOLDER}";`, + `globalThis._sentryDebugIdIdentifier="sentry-dbid-${ROLLDOWN_DEBUG_ID_PLACEHOLDER}";`, + userCode, + ].join(''); +} + +function finalize(code: string, fileName = 'bundle.js'): string { + const bundle: GeneratedBundle = { + [fileName]: { type: 'chunk', fileName, code }, + }; + + finalizeRolldownDebugIds(bundle); + const output = bundle[fileName]; + expect(output?.type).toBe('chunk'); + + return output?.type === 'chunk' ? output.code : ''; +} + +function extractDebugId(code: string): string { + const debugIds = code.match(UUID_PATTERN); + expect(debugIds).toHaveLength(2); + expect(new Set(debugIds)).toHaveLength(1); + + return debugIds?.[0] ?? ''; +} + +describe('debug ID injection', () => { + it('uses a placeholder for Rolldown and a deterministic UUID for Rollup', () => { + expect(getDebugIdForChunk('code', true)).toBe(ROLLDOWN_DEBUG_ID_PLACEHOLDER); + expect(getDebugIdForChunk('code', false)).toMatch(UUID_PATTERN); + expect(getDebugIdForChunk('code', false)).toBe(getDebugIdForChunk('code', false)); + }); + + it('detects existing inline and comment debug IDs at chunk boundaries', () => { + expect(hasExistingDebugID('globalThis._sentryDebugIdIdentifier="sentry-dbid-existing";')).toBe(true); + expect(hasExistingDebugID('console.log("test");\n//# debugId=existing')).toBe(true); + expect(hasExistingDebugID('console.log("test");')).toBe(false); + }); + + it('generates stable IDs from finalized code and filenames', () => { + const firstBuild = finalize(provisionalCode()); + const secondBuild = finalize(provisionalCode()); + + expect(extractDebugId(firstBuild)).toBe(extractDebugId(secondBuild)); + }); + + it('changes the ID when code or the filename changes', () => { + const baseline = extractDebugId(finalize(provisionalCode('first'))); + + expect(extractDebugId(finalize(provisionalCode('second')))).not.toBe(baseline); + expect(extractDebugId(finalize(provisionalCode('first'), 'other.js'))).not.toBe(baseline); + }); + + it('does not replace placeholder-shaped user strings', () => { + const userCode = `console.log("${ROLLDOWN_DEBUG_ID_PLACEHOLDER}");`; + + expect(finalize(provisionalCode(userCode))).toContain(userCode); + }); + + it('does not replace marker-shaped strings before the injected identifier', () => { + const userCode = `// sentry-dbid-${ROLLDOWN_DEBUG_ID_PLACEHOLDER}\n`; + const finalizedCode = finalize(`${userCode}${provisionalCode()}`); + + expect(finalizedCode).toContain(userCode); + expect(extractDebugId(finalizedCode)).not.toBe(''); + }); + + it('fails when the injected placeholder is incomplete', () => { + const code = `globalThis._sentryDebugIdIdentifier="sentry-dbid-${ROLLDOWN_DEBUG_ID_PLACEHOLDER}";`; + + expect(() => finalize(code)).toThrow('Failed to locate the Sentry debug ID placeholder for chunk `bundle.js`.'); + }); + + it('ignores non-chunk assets and chunks without provisional IDs', () => { + const bundle: GeneratedBundle = { + 'asset.js': { type: 'asset', fileName: 'asset.js' }, + 'chunk.js': { type: 'chunk', fileName: 'chunk.js', code: 'console.log("test");' }, + }; + + finalizeRolldownDebugIds(bundle); + + expect(bundle).toEqual({ + 'asset.js': { type: 'asset', fileName: 'asset.js' }, + 'chunk.js': { type: 'chunk', fileName: 'chunk.js', code: 'console.log("test");' }, + }); + }); +}); diff --git a/packages/bundler-plugins/test/rollup/public-api.test.ts b/packages/bundler-plugins/test/rollup/public-api.test.ts index b54077fce2bc..1ddb07b58d31 100644 --- a/packages/bundler-plugins/test/rollup/public-api.test.ts +++ b/packages/bundler-plugins/test/rollup/public-api.test.ts @@ -9,7 +9,10 @@ const { babelCoreImportMock, transformAsyncMock, viteAnnotationModuleImportMock, babelCoreImportMock: vi.fn(), transformAsyncMock: vi.fn(async (code: string) => ({ code, map: null })), viteAnnotationModuleImportMock: vi.fn(), - viteAnnotationTransformMock: vi.fn(async () => ({ code: 'fast-path', map: null })), + viteAnnotationTransformMock: vi.fn(async () => ({ + code: 'fast-path', + map: null, + })), }; }); @@ -101,6 +104,12 @@ test('uses a Rollup 3-compatible function transform hook for Rollup builds', () expect(typeof vitePlugin.transform).toBe('object'); }); +test('runs Vite 8 debug ID finalization after other generateBundle hooks', () => { + const vitePlugin = _rollupPluginInternal({ release: { inject: false } }, 'vite', '8') as Plugin; + + expect(vitePlugin.generateBundle).toMatchObject({ order: 'post' }); +}); + describe('sentryRollupPlugin', () => { beforeEach(() => { vi.clearAllMocks(); @@ -123,7 +132,7 @@ describe('sentryRollupPlugin', () => { describe('Hooks', () => { const [plugin] = sentryRollupPlugin({ release: { inject: false } }) as [Plugin]; - const renderChunk = plugin.renderChunk as ( + const renderChunk = plugin.renderChunk as unknown as ( code: string, chunkInfo: { fileName: string; facadeModuleId?: string }, ) => { @@ -294,7 +303,9 @@ bootstrap();`; }); it('should inject into regular JS chunks (no HTML facade)', () => { - const result = renderChunk(`console.log("Hello");`, { fileName: 'bundle.js' }); + const result = renderChunk(`console.log("Hello");`, { + fileName: 'bundle.js', + }); expect(result).not.toBeNull(); expect(result?.code).toMatchInlineSnapshot( `"!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="79f18a7f-ca16-4168-9797-906c82058367",e._sentryDebugIdIdentifier="sentry-dbid-79f18a7f-ca16-4168-9797-906c82058367");}catch(e){}}();console.log("Hello");"`, diff --git a/packages/bundler-plugins/test/rollup/rolldown-determinism.test.ts b/packages/bundler-plugins/test/rollup/rolldown-determinism.test.ts new file mode 100644 index 000000000000..cf055cc6f9e6 --- /dev/null +++ b/packages/bundler-plugins/test/rollup/rolldown-determinism.test.ts @@ -0,0 +1,118 @@ +import { rolldown as rolldown112 } from 'rolldown'; +import { rolldown as rolldown125 } from 'rolldown-1-2-5'; +import { describe, expect, it } from 'vitest'; +import { sentryRollupPlugin } from '../../src/rollup'; + +const virtualModules: Record = { + 'virtual:app': `export async function loadShared() { return import('virtual:shared'); }`, + 'virtual:shared': `export const shared = 'shared';`, + 'virtual:unrelated': `console.log('unrelated');`, +}; + +type RolldownVersion = '1.1.2' | '1.2.5'; +type SourceMapMode = boolean | 'inline' | 'hidden'; +type OutputFormat = 'esm' | 'cjs'; + +const outputCases: [OutputFormat, SourceMapMode][] = [ + ['esm', true], + ['esm', false], + ['esm', 'inline'], + ['esm', 'hidden'], + ['cjs', true], + ['cjs', false], + ['cjs', 'inline'], + ['cjs', 'hidden'], +]; + +async function createBuild(version: RolldownVersion, includeUnrelatedEntry: boolean) { + const input: Record = includeUnrelatedEntry + ? { unrelated: 'virtual:unrelated', app: 'virtual:app' } + : { app: 'virtual:app' }; + const options = { + input, + plugins: [ + { + name: 'virtual-modules', + resolveId(id: string) { + return id in virtualModules ? id : null; + }, + load(id: string) { + return virtualModules[id] ?? null; + }, + }, + ...sentryRollupPlugin({ + release: { inject: false }, + sourcemaps: { disable: 'disable-upload' }, + telemetry: false, + }), + ], + }; + + return version === '1.1.2' ? rolldown112(options) : rolldown125(options); +} + +async function build( + version: RolldownVersion, + includeUnrelatedEntry: boolean, + sourcemap: SourceMapMode = true, + format: OutputFormat = 'esm', +) { + const bundle = await createBuild(version, includeUnrelatedEntry); + + try { + const { output } = await bundle.generate({ + format, + sourcemap, + entryFileNames: '[name]-[hash].js', + chunkFileNames: '[name]-[hash].js', + }); + + return output.filter(outputFile => outputFile.type === 'chunk'); + } finally { + await bundle.close(); + } +} + +function expectFinalizedDebugId(code: string): void { + expect(code).not.toContain('SENTRY_DEBUG_ID_PLACEHOLDER_00000000'); + const debugIds = code.match(/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}/g); + expect(debugIds).toHaveLength(2); + expect(new Set(debugIds)).toHaveLength(1); +} + +describe.each(['1.1.2', '1.2.5'] satisfies RolldownVersion[])('Rolldown %s debug ID determinism', version => { + it.each(outputCases)( + 'produces identical %s chunks in repeated builds with sourcemap=%s', + async (format, sourcemap) => { + const firstBuild = await build(version, false, sourcemap, format); + const secondBuild = await build(version, false, sourcemap, format); + + const comparableOutput = (chunks: typeof firstBuild) => + chunks.map(chunk => ({ + fileName: chunk.fileName, + code: chunk.code, + map: chunk.map?.toString(), + })); + expect(comparableOutput(secondBuild)).toEqual(comparableOutput(firstBuild)); + for (const chunk of firstBuild) { + expectFinalizedDebugId(chunk.code); + } + }, + ); + + it('keeps existing chunks stable when an unrelated entry changes placeholder allocation', async () => { + const firstBuild = await build(version, false); + const secondBuild = await build(version, true); + + for (const facadeModuleId of ['virtual:app', 'virtual:shared']) { + const firstChunk = firstBuild.find(chunk => chunk.facadeModuleId === facadeModuleId); + const secondChunk = secondBuild.find(chunk => chunk.facadeModuleId === facadeModuleId); + + expect(firstChunk).toBeDefined(); + expect(secondChunk).toBeDefined(); + expect(secondChunk?.fileName).toBe(firstChunk?.fileName); + expect(secondChunk?.code).toBe(firstChunk?.code); + expectFinalizedDebugId(firstChunk?.code ?? ''); + } + }); +}); diff --git a/yarn.lock b/yarn.lock index 0fb22843e4ea..cca22bce73df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3103,7 +3103,7 @@ resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260426.1.tgz#b21d2a24afe0b274982d7ccbe7163a5689da1507" integrity sha512-d3Xj/IjINRgNVwH+eKhpUn4xkkcEewbWXbOvBlapiirKWh5zl9m0Epi3qOqmjyRYK6MICqIGXg4qZBEt0lxudw== -"@cloudflare/workers-types-v5@npm:@cloudflare/workers-types@5.20260710.1": +"@cloudflare/workers-types-v5@npm:@cloudflare/workers-types@5.20260710.1", "@cloudflare/workers-types@5.20260710.1": version "5.20260710.1" resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-5.20260710.1.tgz#215c0cf84c3917552b53a1f5129150abf0b6009f" integrity sha512-4ooaY2Pb5XGwDn8Fzm6jnTAJkIX0R5LBvL9euQpp2T58sQItlAQd9yivAlkwGhpY5cM1u81/9HaXwKAjXwtyzA== @@ -3118,11 +3118,6 @@ resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20250922.0.tgz#a159fbf3bb785fa85b473ecfaa8c501525827885" integrity sha512-BaqlKnVc0Xzqm9xt3TC4v0yB9EHy5vVqpiWz+DAsbEmdcpUbqdBschvI9502p6FgFbZElD7XcxTEeViXLsoO0A== -"@cloudflare/workers-types@5.20260710.1": - version "5.20260710.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-5.20260710.1.tgz#215c0cf84c3917552b53a1f5129150abf0b6009f" - integrity sha512-4ooaY2Pb5XGwDn8Fzm6jnTAJkIX0R5LBvL9euQpp2T58sQItlAQd9yivAlkwGhpY5cM1u81/9HaXwKAjXwtyzA== - "@cloudflare/workers-types@^4.20260426.0": version "4.20260519.1" resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20260519.1.tgz#061b4594e874a0e506ddc6599221939e6718d2a7" @@ -6635,6 +6630,11 @@ resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.137.0.tgz#56e77f8bb221fa05f18b1cd34d73f94f0954a773" integrity sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA== +"@oxc-project/types@=0.146.0": + version "0.146.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.146.0.tgz#d57a2591abbf1f6e50981b07ee24ab269530d87a" + integrity sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA== + "@oxc-project/types@^0.143.0": version "0.143.0" resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.143.0.tgz#c3e4f3178b7b54e4dd194eac6d45258a60f0092b" @@ -7517,66 +7517,131 @@ dependencies: web-streams-polyfill "^3.1.1" +"@rolldown/binding-android-arm-eabi@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.5.tgz#165b80910de7cd33f772d5b7b045b259acb7420c" + integrity sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA== + "@rolldown/binding-android-arm64@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.2.tgz#88fd6b295a411e62b7926433a45eb5e17e68bba4" integrity sha512-2cZ+7xRS+DBcuJBJKnfzsbleumJhBqSlJVpuzHC0nTqfd3QQ7Vx2/x5YR/D7cBamKSeWplwo82Fn9lqYUDEMfA== +"@rolldown/binding-android-arm64@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.5.tgz#5ed74d4b8fa56c68eb1aeb81d0d207a85b6de05c" + integrity sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig== + "@rolldown/binding-darwin-arm64@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.2.tgz#2f840f7e6501cb52370411c2fb008119f1fbf400" integrity sha512-RkPMJnygxsgOYdkfqgpwY0/Fzm8d0VQe6HGU2/B00Xa9eqdLbrII+DOKAodbJAn3ZL1AJxGHkZRPYazgGY6Ljw== +"@rolldown/binding-darwin-arm64@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.5.tgz#6f27c7060e58ca03061fa7d50f9dc409bc377fe1" + integrity sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww== + "@rolldown/binding-darwin-x64@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.2.tgz#2ed3b66dded5140d22ca2ac58d4e1c1e3143f490" integrity sha512-Uiczh6vFhwyfd7WNe7Q7mCA4KxAiLdz7jPE/WGizfRpIieoyFuNVMmM8HqZ9HwudTkY6/AeMQwlNJ9NJijguWw== +"@rolldown/binding-darwin-x64@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.5.tgz#74ab897d134ede4072fdc6108f00193e6167ee28" + integrity sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A== + "@rolldown/binding-freebsd-x64@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.2.tgz#d3d8603ae480a505eb8c12643c901b2a3771b875" integrity sha512-+TpdtTRgHiJFjCVFbw311SuLk3KfytPOQQn+VlAEv+gBxYPtL7E6JS9e/tk+8CwxhIZvemJKo4rTKgfWNsKkkA== +"@rolldown/binding-freebsd-x64@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.5.tgz#7d337f9ae4b739674e1938747118ab0676c8ef8a" + integrity sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw== + "@rolldown/binding-linux-arm-gnueabihf@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.2.tgz#bc36e0e33566bc80877fe4bca56fd32b241dbacb" integrity sha512-4lv1/tkmi7ueIVHnyreaOeUpiZP26BH9rRy6hoYfR9310A2B9nUEVRDvBx69vx64Nr3eTPPRkyciqJJs+j9Jmw== +"@rolldown/binding-linux-arm-gnueabihf@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.5.tgz#a8195dc1091ade0f912b0613ef6500941e5615f4" + integrity sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg== + "@rolldown/binding-linux-arm64-gnu@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.2.tgz#6267a447e6bfc5a99eb030a6a99194ecc917a652" integrity sha512-gBSUVO0eaWgw1JMjK3gB8BMlX2Mk148s2lTiVT3e9vjVxbl7UDfMWWY8CfIaaqiXuM9fVTMxIpUz6CAo/B6Vlw== +"@rolldown/binding-linux-arm64-gnu@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.5.tgz#40fbbb97072b1acaa3e0e8fe9774fe524e860bba" + integrity sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA== + "@rolldown/binding-linux-arm64-musl@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.2.tgz#68fc068f5ebc1d137eecdb651d90830f330aad48" integrity sha512-LjQP/iZLBu8o8PjIfk4x3At0/mT6h282pvz8Z5LAyhGbu/kDezyO7ea62rF5uoqmgnIYqbN/MqJ3Si3Aymi7xQ== +"@rolldown/binding-linux-arm64-musl@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.5.tgz#3cfe8b0f7c13de29dace9a9fc6c03081164176ab" + integrity sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA== + "@rolldown/binding-linux-ppc64-gnu@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.2.tgz#fe072f0bc3b713ae25b357651ced38d39e3d81e0" integrity sha512-X/7bVLWelEsbyWDUSXt7zVsTniLLPIY2n1rH58qr78l9i7MNbbxBWD8gI2vRfBWf4NUXJCUuQnfZDsp32LqsfQ== +"@rolldown/binding-linux-ppc64-gnu@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.5.tgz#3bd890d96ae29f93718aa142ed0982f2ee2978ad" + integrity sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA== + "@rolldown/binding-linux-s390x-gnu@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.2.tgz#9492609384775c6edec9bfbe5b1cbba9660dddcc" integrity sha512-gb6dYKW/1KDorGXyy48glEBJs/sxVSC5pcVrox/pFGV4mvwSFeg2sK5L2tRkVsVlh7kueqOgg4GEcuipJcGuKg== +"@rolldown/binding-linux-s390x-gnu@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.5.tgz#0959a0d5af22741d5787918e27aef70dc8602804" + integrity sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ== + "@rolldown/binding-linux-x64-gnu@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.2.tgz#74029d9f86d60fa9bcf2670b1480e22438203c98" integrity sha512-JY4w85pU3iAiJVMh5nuk4/Mh9GjMsupe8MrIN53rwxAZW64GKrWeJBuN6SxQg9QTU5uB1cxyhDzW8jqRn1EABw== +"@rolldown/binding-linux-x64-gnu@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.5.tgz#7baa94e826328ac6f457d9e1abacffa0353e8d22" + integrity sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ== + "@rolldown/binding-linux-x64-musl@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.2.tgz#eb3004015027a7af12f9b0ac85ffa1634015c873" integrity sha512-xvpA7o5KCYLB0Rwscmuylb1/zHHSUx4g4xilm4prC5jP76pEUlzBmMbgpbh7bVDbId4NcfT96gN5i6mE6UDaiw== +"@rolldown/binding-linux-x64-musl@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.5.tgz#5f37597eaf0e22313d1e3d4be7d1be1fd332904e" + integrity sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA== + "@rolldown/binding-openharmony-arm64@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.2.tgz#6a02c49dc0f698614f97c68c6f7c21aadc7600b1" integrity sha512-p/ts6KBLjuk49Bp21XH77poQGt02iNz7ChgHep7tudPOaLinR/De/RHdxF8w8Yj4r/bF/bqXwH6PZrB2sA+Nvw== +"@rolldown/binding-openharmony-arm64@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.5.tgz#d096567af3f738cbe6aa858ab0a01aae9f357ef4" + integrity sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw== + "@rolldown/binding-wasm32-wasi@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.2.tgz#3f67c083e0762b8cd6c95e8edfe1a743d7ffdf78" @@ -7591,11 +7656,21 @@ resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.2.tgz#a69c5a03b3ba36cb0b1154709293e0cefc9dd69c" integrity sha512-xtUJqs8qEkuSviS0n1tsohaPuz3a1SPhZywOji4Oo+sgrJs8daEDMZ0QtqL0OS7dx8PoVpg2J/ZZycPY5I2+Zg== +"@rolldown/binding-win32-arm64-msvc@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.5.tgz#d53b911aa4e6b547b789c07747fabab2ac8c237d" + integrity sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw== + "@rolldown/binding-win32-x64-msvc@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.2.tgz#e1d9a6ccd29de00378f8dd6e275adbde5731d30a" integrity sha512-85YiLQqjUKgSO/Zjnf9e0XIn5Ymrh1fLDWBeAkZqpuBR/3R8TpfoHXuyblqyQrftSSgWO9qpcHN8mkyKsLraoA== +"@rolldown/binding-win32-x64-msvc@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.5.tgz#7bbd08cfda6a98de9b756472c772a36ebb7229bc" + integrity sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw== + "@rolldown/pluginutils@^1.0.0", "@rolldown/pluginutils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz#e3fcee093fbb5ce765e1ad088ff4de2889f6f9be" @@ -9263,12 +9338,7 @@ dependencies: "@types/unist" "*" -"@types/history-4@npm:@types/history@4.7.8": - version "4.7.8" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" - integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== - -"@types/history-5@npm:@types/history@4.7.8": +"@types/history-4@npm:@types/history@4.7.8", "@types/history-5@npm:@types/history@4.7.8": version "4.7.8" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== @@ -23497,7 +23567,8 @@ react-refresh@^0.14.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -"react-router-6@npm:react-router@6.30.4": +"react-router-6@npm:react-router@6.30.4", react-router@6.30.4: + name react-router-6 version "6.30.4" resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.30.4.tgz#638f35176527bd243d96d81d35d33b757bad46c2" integrity sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA== @@ -23512,13 +23583,6 @@ react-router-dom@6.30.4: "@remix-run/router" "1.23.3" react-router "6.30.4" -react-router@6.30.4: - version "6.30.4" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.30.4.tgz#638f35176527bd243d96d81d35d33b757bad46c2" - integrity sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA== - dependencies: - "@remix-run/router" "1.23.3" - react-router@^7.18.0: version "7.18.0" resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.18.0.tgz#e7d94b54745277aabe3cf93fac938cbebc9c1c5e" @@ -24288,7 +24352,31 @@ roarr@^7.0.4: safe-stable-stringify "^2.4.1" semver-compare "^1.0.0" -rolldown@^1.0.0, rolldown@^1.0.0-rc.15, rolldown@^1.0.0-rc.8: +"rolldown-1-2-5@npm:rolldown@1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.2.5.tgz#1f504a7d05260a769e617d950410bbb051498c50" + integrity sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA== + dependencies: + "@oxc-project/types" "=0.146.0" + "@rolldown/pluginutils" "^1.0.0" + optionalDependencies: + "@rolldown/binding-android-arm-eabi" "1.2.5" + "@rolldown/binding-android-arm64" "1.2.5" + "@rolldown/binding-darwin-arm64" "1.2.5" + "@rolldown/binding-darwin-x64" "1.2.5" + "@rolldown/binding-freebsd-x64" "1.2.5" + "@rolldown/binding-linux-arm-gnueabihf" "1.2.5" + "@rolldown/binding-linux-arm64-gnu" "1.2.5" + "@rolldown/binding-linux-arm64-musl" "1.2.5" + "@rolldown/binding-linux-ppc64-gnu" "1.2.5" + "@rolldown/binding-linux-s390x-gnu" "1.2.5" + "@rolldown/binding-linux-x64-gnu" "1.2.5" + "@rolldown/binding-linux-x64-musl" "1.2.5" + "@rolldown/binding-openharmony-arm64" "1.2.5" + "@rolldown/binding-win32-arm64-msvc" "1.2.5" + "@rolldown/binding-win32-x64-msvc" "1.2.5" + +rolldown@1.1.2, rolldown@^1.0.0-rc.15, rolldown@^1.0.0-rc.8: version "1.1.2" resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.1.2.tgz#accb41e26c872ad2c5198a39c1281c7b6b844097" integrity sha512-x0CrQQqCXWGeI8dTvFfN/Dnv3yMKT9hv5jFjlOreKAx9wqLq9wz7VvLLHyaAXC90/CpggTu9SisSbsJJTPSjNQ== @@ -25569,16 +25657,7 @@ string-similarity@^4.0.1: resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@4.2.3, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@4.2.3, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -25681,14 +25760,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -28288,16 +28360,7 @@ wrangler@4.86.0: optionalDependencies: fsevents "~2.3.2" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@7.0.0, wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@7.0.0, wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==