From af1af71523171cea1312723f2d0f36f36f404171 Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Mon, 6 Jul 2026 19:19:25 +0100 Subject: [PATCH 1/4] feat: compile against rspack 2 and add dual-major test infrastructure Bump @callstack/repack's @rspack/core devDependency to ^2.1.2 (the workspace catalog stays on v1) and absorb the type-level fallout with zero runtime behavior change for Rspack 1 / webpack users: - SwcLoaderOptions became a union discriminated on detectSyntax in v2 - introduce a local non-union SwcConfig alias and split builtin:swc-loader only options off before calling the raw swc transformSync (also more correct at runtime) - narrow devServer before reading .hot in RepackTargetPlugin (the key can be false in v2 types) - rest-destructure devServer off the config in the bundle command instead of delete (not assignable to v2's bundled DevServer type, and unused for bundling) - one documented cast in the start command: Re.Pack's devServer type augmentation and Rspack 2's bundled DevServer type are incompatible solely because each pulls proxy types from a different copy of http-proxy-middleware, and devServer cannot be stripped there because the dev server flow reads it back from compiler.options - getRspackCacheConfig accessor reading the persistent cache config from both the Rspack 1 (experiments.cache) and Rspack 2 (top-level cache) locations, with derived cache types extended for the legacy location @rspack/core v2 is ESM-only which Jest's sandboxed CJS runtime cannot load, so tests now run through a custom test environment that loads the real core outside the sandbox and bridges it back via moduleNameMapper. The environment is parameterized on RSPACK_MAJOR (v2 via import(), v1 via require of the aliased @rspack/core-v1 devDependency), exposes __RSPACK_MAJOR__ for major-gated assertions, and a permanent lane-guard test asserts the loaded major matches the requested lane. CI gains a Rspack 1 unit-suite lane, a Windows lane running the suite under both majors (the require(esm) loading path is Windows-sensitive), and the main-branch Node 18/20 matrix lanes run with RSPACK_MAJOR=1 since Rspack 2 requires Node ^20.19.0 || >=22.12.0. HermesBytecodePlugin test expectations are made platform-agnostic for the Windows lane. --- .github/workflows/test-main-matrix.yml | 7 + .github/workflows/test.yml | 39 ++ packages/repack/jest.config.js | 3 +- packages/repack/jest.environment.js | 32 ++ packages/repack/jest.rspack-core-bridge.js | 18 + packages/repack/package.json | 7 +- .../src/__tests__/rspackTestLane.test.ts | 10 + .../commands/common/resetPersistentCache.ts | 27 +- packages/repack/src/commands/rspack/bundle.ts | 26 +- packages/repack/src/commands/rspack/start.ts | 21 +- .../babelSwcLoader/__tests__/swc.test.ts | 45 +- .../loaders/babelSwcLoader/babelSwcLoader.ts | 22 +- .../src/loaders/babelSwcLoader/options.ts | 23 +- .../repack/src/loaders/babelSwcLoader/swc.ts | 54 +-- .../src/loaders/babelSwcLoader/utils.ts | 8 +- .../RepackTargetPlugin/RepackTargetPlugin.ts | 5 +- .../__tests__/HermesBytecodePlugin.test.ts | 13 +- pnpm-lock.yaml | 459 ++++++++++++++++-- turbo.json | 4 + 19 files changed, 696 insertions(+), 127 deletions(-) create mode 100644 packages/repack/jest.environment.js create mode 100644 packages/repack/jest.rspack-core-bridge.js create mode 100644 packages/repack/src/__tests__/rspackTestLane.test.ts diff --git a/.github/workflows/test-main-matrix.yml b/.github/workflows/test-main-matrix.yml index 2a3ddf9ec..aef4efc91 100644 --- a/.github/workflows/test-main-matrix.yml +++ b/.github/workflows/test-main-matrix.yml @@ -7,6 +7,9 @@ on: - 'website/**' workflow_dispatch: +permissions: + contents: read + jobs: test_main_matrix: name: Tests [Node ${{ matrix.node_version }}] @@ -23,5 +26,9 @@ jobs: with: node-version: ${{ matrix.node_version }} + # Rspack 2 requires Node ^20.19.0 || >=22.12.0, so the older Node + # lanes run the repack unit suite against Rspack 1 - name: Run tests run: pnpm test + env: + RSPACK_MAJOR: ${{ contains(fromJSON('["18", "20"]'), matrix.node_version) && '1' || '2' }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 32d0fcf46..b1777c63d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,9 @@ on: - 'website/**' workflow_dispatch: +permissions: + contents: read + jobs: lint: name: Lint @@ -53,3 +56,39 @@ jobs: - name: Run tests run: pnpm test + + test_pr_rspack1: + name: Tests [Rspack 1] + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24' + + - name: Run tests against Rspack 1 + run: pnpm turbo run test:rspack1 + + test_pr_windows: + name: Tests [Windows] + if: github.event_name == 'pull_request' + runs-on: windows-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24' + + # the require(esm) loading path of @rspack/core@2 and the version + # helpers' filesystem resolution are Windows-sensitive - run the + # repack unit suite under both majors + - name: Run repack tests + run: pnpm turbo run test --filter @callstack/repack + + - name: Run repack tests against Rspack 1 + run: pnpm turbo run test:rspack1 diff --git a/packages/repack/jest.config.js b/packages/repack/jest.config.js index 950eee740..b9857e366 100644 --- a/packages/repack/jest.config.js +++ b/packages/repack/jest.config.js @@ -2,8 +2,9 @@ module.exports = { clearMocks: true, moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', + '^@rspack/core$': '/jest.rspack-core-bridge.js', }, setupFiles: ['./jest.setup.js'], - testEnvironment: 'node', + testEnvironment: '/jest.environment.js', testMatch: ['**/__tests__/**/*.ts?(x)'], }; diff --git a/packages/repack/jest.environment.js b/packages/repack/jest.environment.js new file mode 100644 index 000000000..d4846842a --- /dev/null +++ b/packages/repack/jest.environment.js @@ -0,0 +1,32 @@ +const { TestEnvironment: NodeEnvironment } = require('jest-environment-node'); + +/** + * @rspack/core v2 is published as a pure ESM package, which Jest's sandboxed + * CJS module runtime cannot load (even `createRequire` inside the sandbox is + * wrapped by Jest and loops back into the module registry). + * + * Test environments are loaded outside the Jest sandbox with Node's real + * module system, where loading ESM through `require()`/`import()` is + * supported. Load @rspack/core here and expose it to the sandbox via a + * global - see jest.rspack-core-bridge.js for the consuming side. + * + * The environment is parameterized on RSPACK_MAJOR (default 2) so the suite + * can run against both supported Rspack majors: + * - v2: `await import('@rspack/core')` (ESM-only package), + * - v1: plain `require` of the aliased `@rspack/core-v1` devDependency - the + * package is CJS, and requiring it directly sidesteps any reliance on + * cjs-module-lexer named-export synthesis. + * `__RSPACK_MAJOR__` is exposed alongside so tests can gate major-specific + * assertions. + */ +class RspackCoreEnvironment extends NodeEnvironment { + async setup() { + await super.setup(); + const major = Number(process.env.RSPACK_MAJOR ?? '2'); + this.global.__RSPACK_CORE__ = + major === 1 ? require('@rspack/core-v1') : await import('@rspack/core'); + this.global.__RSPACK_MAJOR__ = major; + } +} + +module.exports = RspackCoreEnvironment; diff --git a/packages/repack/jest.rspack-core-bridge.js b/packages/repack/jest.rspack-core-bridge.js new file mode 100644 index 000000000..39703a0c1 --- /dev/null +++ b/packages/repack/jest.rspack-core-bridge.js @@ -0,0 +1,18 @@ +// @rspack/core v2 is published as a pure ESM package, which Jest's sandboxed +// CJS module runtime cannot load. The real module is loaded natively by the +// custom test environment (jest.environment.js) and exposed via a global; +// this bridge maps `require('@rspack/core')` inside tests onto it. +// +// The `__esModule` marker keeps Babel's import interop treating this as an +// ESM-like namespace, so named imports (`import { rspack } from '@rspack/core'`) +// keep working. +const core = globalThis.__RSPACK_CORE__; + +if (!core) { + throw new Error( + '@rspack/core was not preloaded by the test environment - ' + + 'make sure jest.environment.js is set as the testEnvironment' + ); +} + +module.exports = { __esModule: true, ...core, default: core.default ?? core }; diff --git a/packages/repack/package.json b/packages/repack/package.json index da0b7402c..af4cb615b 100644 --- a/packages/repack/package.json +++ b/packages/repack/package.json @@ -56,6 +56,7 @@ "build:ts": "tsc -p tsconfig.build.json --emitDeclarationOnly", "build": "pnpm run \"/^build:.*/\"", "test": "jest", + "test:rspack1": "cross-env RSPACK_MAJOR=1 jest", "typecheck": "tsc --noEmit", "archive": "pnpm build && pnpm pack", "clang-format": "pnpm clang-format:ios && pnpm clang-format:android", @@ -113,8 +114,9 @@ "@babel/plugin-transform-modules-commonjs": "^7.23.2", "@module-federation/enhanced": "0.8.9", "@module-federation/sdk": "0.6.10", - "@rspack/core": "catalog:", - "@swc/helpers": "catalog:", + "@rspack/core": "^2.1.2", + "@rspack/core-v1": "npm:@rspack/core@^1.7.12", + "@swc/helpers": "^0.5.23", "@types/babel__core": "^7.20.5", "@types/dedent": "^0.7.0", "@types/gradient-string": "^1.1.6", @@ -127,6 +129,7 @@ "@types/shallowequal": "^1.1.1", "babel-jest": "^29.7.0", "clang-format": "^1.8.0", + "cross-env": "^7.0.3", "jest": "^29.7.0", "react": "catalog:", "react-native": "catalog:", diff --git a/packages/repack/src/__tests__/rspackTestLane.test.ts b/packages/repack/src/__tests__/rspackTestLane.test.ts new file mode 100644 index 000000000..a5fbed3bb --- /dev/null +++ b/packages/repack/src/__tests__/rspackTestLane.test.ts @@ -0,0 +1,10 @@ +import { rspackVersion } from '@rspack/core'; + +// Guards the dual-major test wiring itself: the custom Jest environment +// (jest.environment.js) loads @rspack/core v2 by default and the aliased +// @rspack/core-v1 under RSPACK_MAJOR=1. If the env var stops being honored, +// the "v1 lane" silently tests v2 twice - this catches that. +test('the loaded @rspack/core major matches the requested RSPACK_MAJOR lane', () => { + const requested = Number(process.env.RSPACK_MAJOR ?? '2'); + expect(Number(rspackVersion.split('.')[0])).toBe(requested); +}); diff --git a/packages/repack/src/commands/common/resetPersistentCache.ts b/packages/repack/src/commands/common/resetPersistentCache.ts index 53dac9a59..eedfbdc4a 100644 --- a/packages/repack/src/commands/common/resetPersistentCache.ts +++ b/packages/repack/src/commands/common/resetPersistentCache.ts @@ -4,11 +4,33 @@ import type { Configuration as RspackConfiguration } from '@rspack/core'; import * as colorette from 'colorette'; import type { Configuration as WebpackConfiguration } from 'webpack'; -type RspackCacheOptions = NonNullable< +// Rspack 2 moved the persistent cache configuration from `experiments.cache` +// to the top-level `cache` option (same shape). The v2 types no longer +// declare the legacy location, so extend them with it to support configs +// written for either major. +type RspackCacheOptions = RspackConfiguration['cache']; +type RspackExperimentsWithLegacyCache = NonNullable< RspackConfiguration['experiments'] ->['cache']; +> & { cache?: RspackCacheOptions }; + +export interface RspackConfigurationWithLegacyCache { + cache?: RspackCacheOptions; + experiments?: RspackExperimentsWithLegacyCache; +} + type WebpackCacheOptions = WebpackConfiguration['cache']; +/** + * Reads the persistent cache configuration from a Rspack config, + * supporting both the Rspack 1 (`experiments.cache`) and + * Rspack 2 (top-level `cache`) locations. + */ +export function getRspackCacheConfig( + config: RspackConfigurationWithLegacyCache +): RspackCacheOptions { + return config.experiments?.cache ?? config.cache; +} + function getDefaultCacheDirectory( bundler: 'rspack' | 'webpack', rootDir: string @@ -31,6 +53,7 @@ function getRspackCachePaths( for (const cacheConfig of cacheConfigs) { if ( typeof cacheConfig === 'object' && + cacheConfig !== null && 'storage' in cacheConfig && cacheConfig.storage?.directory ) { diff --git a/packages/repack/src/commands/rspack/bundle.ts b/packages/repack/src/commands/rspack/bundle.ts index 6c0975144..810888178 100644 --- a/packages/repack/src/commands/rspack/bundle.ts +++ b/packages/repack/src/commands/rspack/bundle.ts @@ -4,6 +4,7 @@ import { CLIError } from '../../helpers/index.js'; import { makeCompilerConfig } from '../common/config/makeCompilerConfig.js'; import { getMaxWorkers, + getRspackCacheConfig, normalizeStatsOptions, resetPersistentCache, setupEnvironment, @@ -25,17 +26,15 @@ export async function bundle( cliConfig: CliConfig, args: BundleArguments ) { - const [config] = await makeCompilerConfig({ - args: args, - bundler: 'rspack', - command: 'bundle', - rootDir: cliConfig.root, - platforms: [args.platform], - reactNativePath: cliConfig.reactNativePath, - }); - - // remove devServer configuration to avoid schema validation errors - delete config.devServer; + const [{ devServer: _devServer, ...config }] = + await makeCompilerConfig({ + args: args, + bundler: 'rspack', + command: 'bundle', + rootDir: cliConfig.root, + platforms: [args.platform], + reactNativePath: cliConfig.reactNativePath, + }); // expose selected args as environment variables setupEnvironment(args); @@ -51,7 +50,7 @@ export async function bundle( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: [config.experiments?.cache], + cacheConfigs: [getRspackCacheConfig(config)], }); } @@ -86,6 +85,9 @@ export async function bundle( } }; + // `devServer` is split off above - it's not needed for bundling, and + // Re.Pack's own dev server options (augmented onto `Configuration`) are + // not assignable to Rspack's bundled `DevServer` type const compiler = rspack(config); return new Promise((resolve) => { diff --git a/packages/repack/src/commands/rspack/start.ts b/packages/repack/src/commands/rspack/start.ts index dc915ab4f..c2117b695 100644 --- a/packages/repack/src/commands/rspack/start.ts +++ b/packages/repack/src/commands/rspack/start.ts @@ -1,4 +1,4 @@ -import type { Configuration } from '@rspack/core'; +import type { Configuration, MultiRspackOptions } from '@rspack/core'; import packageJson from '../../../package.json'; import { VERBOSE_ENV_KEY } from '../../env.js'; import { CLIError, isTruthyEnv } from '../../helpers/index.js'; @@ -14,6 +14,7 @@ import { getDevMiddleware, getMaxWorkers, getMimeType, + getRspackCacheConfig, parseUrl, resetPersistentCache, resolveProjectPath, @@ -83,7 +84,7 @@ export async function start( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: configs.map((config) => config.experiments?.cache), + cacheConfigs: configs.map(getRspackCacheConfig), }); } @@ -96,7 +97,21 @@ export async function start( ); } - const compiler = new Compiler(configs, reporter, cliConfig.root); + // CAST - no clean solution available here: + // Re.Pack augments `Configuration.devServer` with its own dev server options + // (src/types/dev-server-options.d.ts), while Rspack 2 types `devServer` with + // its bundled `DevServer` type. The two are structurally incompatible solely + // because each pulls `proxy` types from a different copy of + // http-proxy-middleware, so no narrowing or `satisfies` can bridge them. + // Unlike `bundle`, `devServer` cannot be stripped from the config here - + // the dev server flow reads it back from `compiler.options`. At runtime + // Rspack accepts & preserves the key (validation is permissive, verified + // in agent_context/rspackv2-jul2026/07-verification-results.md). + const compiler = new Compiler( + configs as unknown as MultiRspackOptions, + reporter, + cliConfig.root + ); const { createServer } = await import('@callstack/repack-dev-server'); const { start, stop } = await createServer({ diff --git a/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts b/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts index c6413754c..605018841 100644 --- a/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts +++ b/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts @@ -1,5 +1,6 @@ -import { type SwcLoaderOptions, experiments } from '@rspack/core'; +import { experiments } from '@rspack/core'; import { buildFinalSwcConfig, partitionTransforms } from '../babelSwcLoader.js'; +import type { SwcConfig } from '../options.js'; import { addSwcComplementaryTransforms, getSupportedSwcConfigurableTransforms, @@ -84,7 +85,7 @@ describe('swc transforms support detection', () => { const { transformNames } = getSupportedSwcConfigurableTransforms( transforms, - baseSwcConfig as SwcLoaderOptions + baseSwcConfig as SwcConfig ); expect(transformNames).toEqual([ @@ -104,7 +105,7 @@ describe('swc transforms support detection', () => { ['transform-class-properties', { loose: true }], ['transform-private-methods', { loose: true }], ], - {} as SwcLoaderOptions + {} as SwcConfig ); expect(swcConfig.jsc?.assumptions).toEqual({ @@ -114,7 +115,7 @@ describe('swc transforms support detection', () => { }); it('applies loose mode to setSpreadProperties when not defined; preserves explicit true (snapshot)', () => { - const baseUndefined = {} as SwcLoaderOptions; + const baseUndefined = {} as SwcConfig; const { swcConfig: cfg1 } = getSupportedSwcConfigurableTransforms( [['transform-object-rest-spread', { loose: true }]], baseUndefined @@ -124,9 +125,9 @@ describe('swc transforms support detection', () => { 'object-rest-spread loose: setSpreadProperties' ); - const baseTrue: SwcLoaderOptions = { + const baseTrue: SwcConfig = { jsc: { assumptions: { setSpreadProperties: true } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: cfg2 } = getSupportedSwcConfigurableTransforms( [['transform-object-rest-spread', { loose: false }]], baseTrue @@ -138,9 +139,9 @@ describe('swc transforms support detection', () => { }); it('sets optional-chaining/nullish and for-of assumptions with loose mode and respects explicit values (snapshot)', () => { - const base: SwcLoaderOptions = { + const base: SwcConfig = { jsc: { assumptions: { noDocumentAll: true } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig } = getSupportedSwcConfigurableTransforms( [ @@ -157,14 +158,14 @@ describe('swc transforms support detection', () => { }); it('updates both privateFieldsAsProperties and setPublicClassFields for private-property-in-object but does not override explicit true', () => { - const base: SwcLoaderOptions = { + const base: SwcConfig = { jsc: { assumptions: { privateFieldsAsProperties: true, setPublicClassFields: true, }, }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig, transformNames } = getSupportedSwcConfigurableTransforms( @@ -200,7 +201,7 @@ describe('swc transforms support detection', () => { const { transformNames } = getSupportedSwcCustomTransforms( transforms, - baseSwcConfig as SwcLoaderOptions + baseSwcConfig as SwcConfig ); expect(transformNames).toEqual([ @@ -214,7 +215,7 @@ describe('swc transforms support detection', () => { }); it('overrides react runtime and importSource from transform-react-jsx config (snapshot)', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { runtime: 'classic', importSource: 'preact' } }, }, @@ -235,7 +236,7 @@ describe('swc transforms support detection', () => { }); it('should apply default react transform when plugin has no react transform options', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: {} }, }, @@ -252,7 +253,7 @@ describe('swc transforms support detection', () => { }); it('should preserve existing react transform config when plugin has none', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { runtime: 'automatic', importSource: 'nativewind' }, @@ -271,7 +272,7 @@ describe('swc transforms support detection', () => { }); it('should use plugin importSource option for react transform', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: {}, @@ -295,7 +296,7 @@ describe('swc transforms support detection', () => { }); it('should use plugin importSource option for react transform and override existing importSource', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { importSource: 'preact' }, @@ -319,7 +320,7 @@ describe('swc transforms support detection', () => { }); it('configures modules commonjs options based on provided config (snapshot)', () => { - const inputConfig: SwcLoaderOptions = {}; + const inputConfig: SwcConfig = {}; const { swcConfig } = getSupportedSwcCustomTransforms( [ [ @@ -333,7 +334,7 @@ describe('swc transforms support detection', () => { }); it('enables external helpers via transform-runtime (snapshot)', () => { - const inputConfig: SwcLoaderOptions = {}; + const inputConfig: SwcConfig = {}; const { swcConfig } = getSupportedSwcCustomTransforms( [['transform-runtime', {}]], inputConfig @@ -342,9 +343,9 @@ describe('swc transforms support detection', () => { }); it('sets exportDefaultFrom only for ecmascript parser; leaves typescript parser unchanged (snapshot)', () => { - const inputConfigTs: SwcLoaderOptions = { + const inputConfigTs: SwcConfig = { jsc: { parser: { syntax: 'typescript' } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: tsCfg } = getSupportedSwcCustomTransforms( [['proposal-export-default-from', {}]], @@ -352,9 +353,9 @@ describe('swc transforms support detection', () => { ); expect(tsCfg.jsc?.parser).toMatchSnapshot('parser: typescript unchanged'); - const inputConfigEcma: SwcLoaderOptions = { + const inputConfigEcma: SwcConfig = { jsc: { parser: { syntax: 'ecmascript' } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: ecmaCfg } = getSupportedSwcCustomTransforms( [['proposal-export-default-from', {}]], inputConfigEcma diff --git a/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts b/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts index 199a9a0ec..22b730d5f 100644 --- a/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts +++ b/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts @@ -1,7 +1,7 @@ import type { TransformOptions } from '@babel/core'; -import type { LoaderContext, SwcLoaderOptions } from '@rspack/core'; +import type { LoaderContext } from '@rspack/core'; import { transform } from '../babelLoader/babelLoader.js'; -import type { BabelSwcLoaderOptions } from './options.js'; +import type { BabelSwcLoaderOptions, SwcConfig } from './options.js'; import { addSwcComplementaryTransforms, getSupportedSwcConfigurableTransforms, @@ -30,7 +30,7 @@ export function partitionTransforms( let configurableTransforms: string[] = []; let customTransforms: string[] = []; - let swcConfig: SwcLoaderOptions = { + let swcConfig: SwcConfig = { jsc: { parser: getSwcParserConfig(filename), transform: { react: { useBuiltins: true } }, @@ -59,7 +59,7 @@ export function partitionTransforms( } export interface BuildFinalSwcConfigOptions { - swcConfig: SwcLoaderOptions; + swcConfig: SwcConfig; includedSwcTransforms: string[]; lazyImports: boolean | string[]; sourceType: 'module' | 'script' | undefined; @@ -67,7 +67,7 @@ export interface BuildFinalSwcConfigOptions { export function buildFinalSwcConfig( options: BuildFinalSwcConfigOptions -): SwcLoaderOptions { +): SwcConfig { const { swcConfig, includedSwcTransforms, lazyImports, sourceType } = options; return { ...swcConfig, @@ -163,8 +163,18 @@ export default async function babelSwcLoader( sourceType: babelResult.sourceType, }); + // `SwcConfig` can carry `builtin:swc-loader`-only options which the raw + // SWC transform API doesn't accept - split them off before calling it + const { + collectTypeScriptInfo: _collectTypeScriptInfo, + transformImport: _transformImport, + rspackExperiments: _rspackExperiments, + detectSyntax: _detectSyntax, + ...transformSwcConfig + } = finalSwcConfig; + const swcResult = swc.transformSync(babelResult?.code!, { - ...finalSwcConfig, + ...transformSwcConfig, caller: { name: '@callstack/repack' }, filename: this.resourcePath, configFile: false, diff --git a/packages/repack/src/loaders/babelSwcLoader/options.ts b/packages/repack/src/loaders/babelSwcLoader/options.ts index 674cf51a8..75668b301 100644 --- a/packages/repack/src/loaders/babelSwcLoader/options.ts +++ b/packages/repack/src/loaders/babelSwcLoader/options.ts @@ -1,9 +1,28 @@ import type { TransformOptions } from '@babel/core'; -import type { SwcLoaderOptions } from '@rspack/core'; +import type { SwcLoaderJscConfig, SwcLoaderOptions } from '@rspack/core'; import type { HermesParserOptions } from '../babelLoader/options.js'; +/** + * Rspack 2 turned `SwcLoaderOptions` into a union discriminated on + * `detectSyntax`, which cannot be spread & reassembled type-safely. + * Re.Pack never sets `detectSyntax`, so internal helpers operate on this + * non-union shape, which stays assignable to `SwcLoaderOptions`. + */ +export type SwcConfig = Omit & { + detectSyntax?: false; + jsc?: SwcLoaderJscConfig; +}; + type BabelOverrides = TransformOptions; -type SwcOverrides = Omit; +// overrides are passed to the raw SWC transform API, so +// `builtin:swc-loader`-only options are not accepted here +type SwcOverrides = Omit< + SwcConfig, + | 'rspackExperiments' + | 'transformImport' + | 'collectTypeScriptInfo' + | 'detectSyntax' +>; export type BabelSwcLoaderOptions = { hideParallelModeWarning?: boolean; diff --git a/packages/repack/src/loaders/babelSwcLoader/swc.ts b/packages/repack/src/loaders/babelSwcLoader/swc.ts index 35ab889ef..e346e1f5f 100644 --- a/packages/repack/src/loaders/babelSwcLoader/swc.ts +++ b/packages/repack/src/loaders/babelSwcLoader/swc.ts @@ -1,4 +1,4 @@ -import type { SwcLoaderOptions } from '@rspack/core'; +import type { SwcConfig } from './options.js'; const SWC_SUPPORTED_NORMAL_RULES = new Set([ 'transform-block-scoping', @@ -80,9 +80,7 @@ export function addSwcComplementaryTransforms( return finalTransforms; } -function getTransformRuntimeConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformRuntimeConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -92,9 +90,7 @@ function getTransformRuntimeConfig( }; } -function getTransformReactDevelopmentConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformReactDevelopmentConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -111,9 +107,9 @@ function getTransformReactDevelopmentConfig( } function getTransformReactRuntimeConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, reactRuntimeConfig: Record = {} -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -137,13 +133,13 @@ function getTransformReactRuntimeConfig( } function getTransformModulesCommonjsConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, moduleConfig: Record = { strict: true, strictMode: true, allowTopLevelThis: true, } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, module: { @@ -157,9 +153,7 @@ function getTransformModulesCommonjsConfig( }; } -function getTransformExportDefaultFromConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformExportDefaultFromConfig(swcConfig: SwcConfig): SwcConfig { if (swcConfig.jsc?.parser?.syntax === 'typescript') { return swcConfig; } @@ -176,9 +170,7 @@ function getTransformExportDefaultFromConfig( }; } -function getTransformDynamicImportConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformDynamicImportConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -193,9 +185,9 @@ function getTransformDynamicImportConfig( } function getTransformClassPropertiesConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -210,9 +202,9 @@ function getTransformClassPropertiesConfig( } function getTransformPrivateMethodsPropertyConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -230,9 +222,9 @@ function getTransformPrivateMethodsPropertyConfig( } function getTransformObjectRestSpreadConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -247,9 +239,9 @@ function getTransformObjectRestSpreadConfig( } function getTransformOptionalChainingNullishCoalescingConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -264,9 +256,9 @@ function getTransformOptionalChainingNullishCoalescingConfig( } function getTransformForOfConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -281,9 +273,7 @@ function getTransformForOfConfig( }; } -function getTransformTypescriptConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformTypescriptConfig(swcConfig: SwcConfig): SwcConfig { // passthrough return swcConfig; } @@ -322,7 +312,7 @@ export function getSupportedSwcNormalTransforms( export function getSupportedSwcConfigurableTransforms( transforms: [string, Record | undefined][], - swcConfig: SwcLoaderOptions + swcConfig: SwcConfig ) { const transformNames = transforms .filter(([transform]) => SWC_SUPPORTED_CONFIGURABLE_RULES.has(transform)) @@ -341,7 +331,7 @@ export function getSupportedSwcConfigurableTransforms( export function getSupportedSwcCustomTransforms( transforms: [string, Record | undefined][], - swcConfig: SwcLoaderOptions + swcConfig: SwcConfig ) { const transformNames = transforms .filter(([transform]) => SWC_SUPPORTED_CUSTOM_RULES.has(transform)) diff --git a/packages/repack/src/loaders/babelSwcLoader/utils.ts b/packages/repack/src/loaders/babelSwcLoader/utils.ts index 10e19ba26..bde4e504b 100644 --- a/packages/repack/src/loaders/babelSwcLoader/utils.ts +++ b/packages/repack/src/loaders/babelSwcLoader/utils.ts @@ -100,7 +100,13 @@ export function checkParallelModeAvailable( } // in parallel mode compiler.options.experiments are not available // but since we're already running in parallel mode, we can ignore this check - if (loaderContext._compiler.options?.experiments?.parallelLoader) { + // ('in' narrowing: `parallelLoader` no longer exists in Rspack 2 types) + const experiments = loaderContext._compiler.options?.experiments; + if ( + experiments && + 'parallelLoader' in experiments && + experiments.parallelLoader + ) { parallelModeWarningDisplayed = true; logger.warn(disabledParalleModeWarning); } diff --git a/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts b/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts index a06c0b7ad..a2b10f184 100644 --- a/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts +++ b/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts @@ -117,7 +117,10 @@ export class RepackTargetPlugin { compiler, { chunkId: chunk.id ?? undefined, - hmrEnabled: !!compiler.options.devServer?.hot, + // `devServer` can also be `false` in Rspack 2 types + hmrEnabled: + typeof compiler.options.devServer === 'object' && + !!compiler.options.devServer.hot, } ); diff --git a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts index f93c32447..fff3bb307 100644 --- a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts +++ b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts @@ -1,5 +1,6 @@ import fs from 'node:fs'; import os from 'node:os'; +import path from 'node:path'; import { type Compiler, ModuleFilenameHelpers } from '@rspack/core'; import execa from 'execa'; import { HermesBytecodePlugin } from '../HermesBytecodePlugin/index.js'; @@ -108,7 +109,7 @@ describe('HermesBytecodePlugin', () => { expect(execaNodeMock).toHaveBeenCalledTimes(1); expect(execaNodeMock.mock.calls[0][0]).toEqual( - 'path/to/react-native/scripts/compose-source-maps.js' + path.join('path/to/react-native', 'scripts', 'compose-source-maps.js') ); }); @@ -156,7 +157,7 @@ describe('HermesBytecodePlugin', () => { const hermesPath = getHermesCLIPath(reactNativePath); expect(hermesPath).toBe( - 'path/to/hermes-compiler/hermesc/osx-bin/hermesc' + path.join('path/to', 'hermes-compiler', 'hermesc', 'osx-bin', 'hermesc') ); }); @@ -167,7 +168,13 @@ describe('HermesBytecodePlugin', () => { const hermesPath = getHermesCLIPath(reactNativePath); expect(hermesPath).toBe( - 'path/to/react-native/sdks/hermesc/osx-bin/hermesc' + path.join( + 'path/to/react-native', + 'sdks', + 'hermesc', + 'osx-bin', + 'hermesc' + ) ); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af1b6547c..4fa9a1a9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -514,7 +514,7 @@ importers: version: link:../repack '@rspack/core': specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.18) + version: 1.6.0(@swc/helpers@0.5.23) '@types/node': specifier: 'catalog:' version: 20.19.31 @@ -533,7 +533,7 @@ importers: version: link:../repack '@rspack/core': specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.18) + version: 1.6.0(@swc/helpers@0.5.23) '@types/dedent': specifier: 0.7.2 version: 0.7.2 @@ -561,7 +561,7 @@ importers: version: link:../repack '@rspack/core': specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.18) + version: 1.6.0(@swc/helpers@0.5.23) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 @@ -667,16 +667,19 @@ importers: version: 7.24.8(@babel/core@7.25.2) '@module-federation/enhanced': specifier: 0.8.9 - version: 0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.3) + version: 0.8.9(@rspack/core@2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.3) '@module-federation/sdk': specifier: 0.6.10 version: 0.6.10 '@rspack/core': - specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.18) + specifier: ^2.1.2 + version: 2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23) + '@rspack/core-v1': + specifier: npm:@rspack/core@^1.7.12 + version: '@rspack/core@1.7.12(@swc/helpers@0.5.23)' '@swc/helpers': - specifier: 'catalog:' - version: 0.5.18 + specifier: ^0.5.23 + version: 0.5.23 '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 @@ -713,6 +716,9 @@ importers: clang-format: specifier: ^1.8.0 version: 1.8.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 jest: specifier: ^29.7.0 version: 29.7.0(@types/node@20.19.31) @@ -739,16 +745,16 @@ importers: version: link:../../packages/repack '@module-federation/enhanced': specifier: 2.0.1 - version: 2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3) + version: 2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3) '@module-federation/enhanced-v15': specifier: npm:@module-federation/enhanced@0.15.0 - version: '@module-federation/enhanced@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)' + version: '@module-federation/enhanced@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)' '@module-federation/enhanced-v21': specifier: npm:@module-federation/enhanced@0.21.0 - version: '@module-federation/enhanced@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)' + version: '@module-federation/enhanced@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)' '@rspack/core': specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.18) + version: 1.6.0(@swc/helpers@0.5.23) '@types/node': specifier: 'catalog:' version: 20.19.31 @@ -1887,15 +1893,24 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.7.0': resolution: {integrity: sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==} + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.7.0': resolution: {integrity: sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@esbuild/aix-ppc64@0.25.5': resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} @@ -2746,6 +2761,9 @@ packages: '@module-federation/error-codes@0.21.2': resolution: {integrity: sha512-mGbPAAApgjmQUl4J7WAt20aV04a26TyS21GDEpOGXFEQG5FqmZnSJ6FqB8K19HgTKioBT1+fF/Ctl5bGGao/EA==} + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + '@module-federation/error-codes@0.8.9': resolution: {integrity: sha512-yUA3GZjOy8Ll6l193faXir2veexDaUiLdmptbzC9tIee/iSQiSwIlibdTafCfqaJ62cLZaytOUdmAFAKLv8QQw==} @@ -2882,6 +2900,9 @@ packages: '@module-federation/runtime-core@0.21.2': resolution: {integrity: sha512-LtDnccPxjR8Xqa3daRYr1cH/6vUzK3mQSzgvnfsUm1fXte5syX4ftWw3Eu55VdqNY3yREFRn77AXdu9PfPEZRw==} + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + '@module-federation/runtime-core@0.6.17': resolution: {integrity: sha512-PXFN/TT9f64Un6NQYqH1Z0QLhpytW15jkZvTEOV8W7Ed319BECFI0Rv4xAsAGa8zJGFoaM/c7QOQfdFXtKj5Og==} @@ -2903,6 +2924,9 @@ packages: '@module-federation/runtime-tools@0.21.2': resolution: {integrity: sha512-SgG9NWTYGNYcHSd5MepO3AXf6DNXriIo4sKKM4mu4RqfYhHyP+yNjnF/gvYJl52VD61g0nADmzLWzBqxOqk2tg==} + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + '@module-federation/runtime-tools@0.8.9': resolution: {integrity: sha512-xBUGx1oOZNuxXjPGdTMrLtAIDrbrN6jE2Mgb9w1qr2mQ4AW9b5TOlxbARBoX4q98xt9oFCGU6Q0eW5XJpsl8AQ==} @@ -2924,6 +2948,9 @@ packages: '@module-federation/runtime@0.21.2': resolution: {integrity: sha512-97jlOx4RAnAHMBTfgU5FBK6+V/pfT6GNX0YjSf8G+uJ3lFy74Y6kg/BevEkChTGw5waCLAkw/pw4LmntYcNN7g==} + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + '@module-federation/runtime@0.8.9': resolution: {integrity: sha512-i+a+/hoT/c+EE52mT+gJrbA6DhL86PY9cd/dIv/oKpLz9i+yYBlG+RA+puc7YsUEO4irbFLvnIMq6AGDUKVzYA==} @@ -2945,6 +2972,9 @@ packages: '@module-federation/sdk@0.21.2': resolution: {integrity: sha512-t2vHSJ1a9zjg7LLJoEghcytNLzeFCqOat5TbXTav5dgU0xXw82Cf0EfLrxiJL6uUpgbtyvUdqqa2DVAvMPjiiA==} + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + '@module-federation/sdk@0.6.10': resolution: {integrity: sha512-i6ofHnImB4zCn/bt7Ft0zh9o/PxvsJj8Wc88EAeJg4IrY6+bzwwo1G2h44w1Yt3go4skZZFQCK0UxoaV6l/t/A==} @@ -2984,6 +3014,9 @@ packages: '@module-federation/webpack-bundler-runtime@0.21.2': resolution: {integrity: sha512-06R/NDY6Uh5RBIaBOFwYWzJCf1dIiQd/DFHToBVhejUT3ZFG7GzHEPIIsAGqMzne/JSmVsvjlXiJu7UthQ6rFA==} + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@module-federation/webpack-bundler-runtime@0.8.9': resolution: {integrity: sha512-DYLvVi4b2MUYu/B4g5wIC5SHxiODboKHkYGHYapOhCcqOchca/N16gtiAI8eSNjJPc+fgUXUGIyGiB18IlFEeQ==} @@ -2996,6 +3029,12 @@ packages: '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3': resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} @@ -3427,11 +3466,21 @@ packages: cpu: [arm64] os: [darwin] + '@rspack/binding-darwin-arm64@1.7.12': + resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==} + cpu: [arm64] + os: [darwin] + '@rspack/binding-darwin-arm64@2.0.0-alpha.1': resolution: {integrity: sha512-+6E6pYgpKvs41cyOlqRjpCT3djjL9hnntF61JumM/TNo1aTYXMNNG4b8ZsLMpBq5ZwCy9Dg8oEDe8AZ84rfM7A==} cpu: [arm64] os: [darwin] + '@rspack/binding-darwin-arm64@2.1.2': + resolution: {integrity: sha512-IYcxareUOYJZz+uNMSIwn+iDRiVyjZNOjoxO/zL4OFaPK8Ncrw0ka/9DqL9Gd7OpnAXN1zK3uS8yD0O1yIYI3Q==} + cpu: [arm64] + os: [darwin] + '@rspack/binding-darwin-x64@1.3.3': resolution: {integrity: sha512-OXtY2s4nlYtUXkeJt8TQKKNIcN7PI8yDq0nqI75OfJoS4u1ZmRXJ8IMeSALLo8I+xD2RAF79tf7yhM/Y/AaiKQ==} cpu: [x64] @@ -3442,11 +3491,21 @@ packages: cpu: [x64] os: [darwin] + '@rspack/binding-darwin-x64@1.7.12': + resolution: {integrity: sha512-jnOp+/UXOJa9xqUb8KXH03sysoO2e4Ij6tw6MqDdmdj8n/A8PQENRPUbW9AwXpPtVDJPus9r4fi7b3+6e4B8Hg==} + cpu: [x64] + os: [darwin] + '@rspack/binding-darwin-x64@2.0.0-alpha.1': resolution: {integrity: sha512-Ccf9NNupVe67vlaS9zKQJ+BvsAn385uBC1vXnYaUxxHoY/tEwNJf6t+XyDARt7mCtT7+Bu4L/iJ/JEF/MsO5zg==} cpu: [x64] os: [darwin] + '@rspack/binding-darwin-x64@2.1.2': + resolution: {integrity: sha512-aoifkILvx/XEHyvg8yW57xu95nx7f9f/3ah1+RguHSNKcJMcoCep9VX1Ct1N0ftqg8MC0JUObc7xWL5W14hmjA==} + cpu: [x64] + os: [darwin] + '@rspack/binding-linux-arm64-gnu@1.3.3': resolution: {integrity: sha512-Lluq3RLYzyCMdXr/HyALKEPGsr+196x8Ccuy5AmIRosOdWuwtSiomSRH1Ka8REUFNHfYy5y9SzfmIZo/E0QEmg==} cpu: [arm64] @@ -3459,12 +3518,24 @@ packages: os: [linux] libc: [glibc] + '@rspack/binding-linux-arm64-gnu@1.7.12': + resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-arm64-gnu@2.0.0-alpha.1': resolution: {integrity: sha512-B7omNsPSsinOq2VRD4d4VFrLgHceMQobqlLg0txFUZ7PDjE307gpTcGViWQlUhNCbkZXMPzDeXBFa5ZlEmxgnA==} cpu: [arm64] os: [linux] libc: [glibc] + '@rspack/binding-linux-arm64-gnu@2.1.2': + resolution: {integrity: sha512-My4m40tyJSgiCEf3bB2KIEX710q3nZg99LIjy+8Zxgi3oZTkg1bFmFRusFU5U4eN5408zfSqDDGvjDE3Yv7o4w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-arm64-musl@1.3.3': resolution: {integrity: sha512-PIsicXWjOqzmoOutUqxpMNkCoKo+8/wxDyKxHFeu+5WIAxVFphe2d3H5qvEjc2MasWSdRmAVn9XiuIj2LIXFzA==} cpu: [arm64] @@ -3477,12 +3548,36 @@ packages: os: [linux] libc: [musl] + '@rspack/binding-linux-arm64-musl@1.7.12': + resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-arm64-musl@2.0.0-alpha.1': resolution: {integrity: sha512-NCG401ofZcDKlTWD8VHv76Y+02Stmd9Nu5MRbVUBOCTVgXMj8Mgrm5XsGBWUjzd5J/Mvo2hstCKIZxNzmPd8uQ==} cpu: [arm64] os: [linux] libc: [musl] + '@rspack/binding-linux-arm64-musl@2.1.2': + resolution: {integrity: sha512-yt+GGWUH7WPE8K97cRc8OpZhH7Pbj1vU+lkvKbDtF/rR8X9a/bJsA/nBqyUV2oBKOVbrp5I8rFZlnDskMqgvKw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rspack/binding-linux-riscv64-gnu@2.1.2': + resolution: {integrity: sha512-uys8Jyw8Z3ralvICbN/L/nZfy5qELIwpOY72rhIqhoDYwFcL4fmMaY7WsvUcJOjCB2rqOcWPaWKuF2oPvo9iDQ==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-riscv64-musl@2.1.2': + resolution: {integrity: sha512-JYNVQwqCaRGQWvjHQYzZkIzQiwllMaJwh4Rdu3ww6W2OJcJUqT08sL1pkOtU0iCxT4VUYiRRcp93VGTGpHr8fg==} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-x64-gnu@1.3.3': resolution: {integrity: sha512-BtksK73ZFdny2T/wU1x0kxBF4ruYUUArZDyeGfpO+vd/1nNYqzzdhGvOksKmtdvsO38ETr2gZ9+XZyr1vpy9uQ==} cpu: [x64] @@ -3495,12 +3590,24 @@ packages: os: [linux] libc: [glibc] + '@rspack/binding-linux-x64-gnu@1.7.12': + resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-x64-gnu@2.0.0-alpha.1': resolution: {integrity: sha512-Xgp8wJ5gjpPG8I3VMEsVAesfckWryQVUhJkHcxPfNi72QTv8UkMER7Jl+JrlQk7K7nMO5ltokx/VGl1c3tMx+w==} cpu: [x64] os: [linux] libc: [glibc] + '@rspack/binding-linux-x64-gnu@2.1.2': + resolution: {integrity: sha512-KDoPy0Msf/JLhxgPPrJQzZeB4Qpqd32em8AP5lSW2s6jR5I35dHgAe9xc2A++EQtnSrU4GTn6DBvFC7q84SihQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-x64-musl@1.3.3': resolution: {integrity: sha512-jx86CxkTmyBz/eHDqZp1mCqBwY+UTEtaPlPoWFyGkJUR5ey6nQnxS+fhG34Rqz63chW+q/afwpGNGyALYdgc8g==} cpu: [x64] @@ -3513,20 +3620,40 @@ packages: os: [linux] libc: [musl] + '@rspack/binding-linux-x64-musl@1.7.12': + resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==} + cpu: [x64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-x64-musl@2.0.0-alpha.1': resolution: {integrity: sha512-lrYKcOgsPA1UMswxzFAV37ofkznbtTLCcEas6lxtlT3Dr28P6VRzC8TgVbIiprkm10I0BlThQWDJ3aGzzLj9Kg==} cpu: [x64] os: [linux] libc: [musl] + '@rspack/binding-linux-x64-musl@2.1.2': + resolution: {integrity: sha512-66hWmIGvn4zCKAYXJE9Bp5SNSLYnLFq2Ke/efE+ZtWy43Dd5vk9AAOmThVGBwdwmIxmGtHGCp+cAuS4G0wu0TA==} + cpu: [x64] + os: [linux] + libc: [musl] + '@rspack/binding-wasm32-wasi@1.6.0': resolution: {integrity: sha512-XGwX35XXnoTYVUGwDBsKNOkkk/yUsT/RF59u9BwT3QBM5eSXk767xVw/ZeiiyJf5YfI/52HDW2E4QZyvlYyv7g==} cpu: [wasm32] + '@rspack/binding-wasm32-wasi@1.7.12': + resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==} + cpu: [wasm32] + '@rspack/binding-wasm32-wasi@2.0.0-alpha.1': resolution: {integrity: sha512-rppGiT7CtXlM8st+IgzBDqb7V//1xx5Oe0SY1sxxw0cfOGMpIQCwhJqx/uI6ioqJLZLGX/obt359+hPXyqGl4w==} cpu: [wasm32] + '@rspack/binding-wasm32-wasi@2.1.2': + resolution: {integrity: sha512-EB4SqH8DW/E/OmqssNQvnIVGQiVUyYNlA/pcc6Ia4MlTNwu6eNDppcNLrToH+kSZpL4CpHSFfSM3eIsSuar2Rw==} + cpu: [wasm32] + '@rspack/binding-win32-arm64-msvc@1.3.3': resolution: {integrity: sha512-uXAdDzajFToVrH3fCNVDP/uKQ9i5FQjJc2aYxsnhS9Su/CZB+UQsOecbq6MnIN2s0B9GBKBG8QdQEtS3RtC6Hg==} cpu: [arm64] @@ -3537,11 +3664,21 @@ packages: cpu: [arm64] os: [win32] + '@rspack/binding-win32-arm64-msvc@1.7.12': + resolution: {integrity: sha512-8+h5fYDXYdmugbdfZ+D1y8IQ3rv2EhSfyGP7vBe+bjNyaMa4jWrpucmZbtxojUL1AzaeuHbvMdj9UO/gelk/+g==} + cpu: [arm64] + os: [win32] + '@rspack/binding-win32-arm64-msvc@2.0.0-alpha.1': resolution: {integrity: sha512-yD2g1JmnCxrix/344r7lBn+RH+Nv8uWP0UDP8kwv4kQGCWr4U7IP8PKFpoyulVOgOUjvJpgImeyrDJ7R8he+5w==} cpu: [arm64] os: [win32] + '@rspack/binding-win32-arm64-msvc@2.1.2': + resolution: {integrity: sha512-T6Fs/g32MRja/UpCq4AdyPRj8tA0cOkcEa4PrAcn/ztUgK8b/qMVxj5mhMI+n7k+kHZQnpeB1Q4HqdSJi6OocA==} + cpu: [arm64] + os: [win32] + '@rspack/binding-win32-ia32-msvc@1.3.3': resolution: {integrity: sha512-VBE6XsJ3IiAlozAywAIxAZ1Aqc2QVnEwBo0gP9998KkwL7wxB6Bg/OJnPbH3Q0ZaNWAQViC99rPC+5hSIdeSxw==} cpu: [ia32] @@ -3552,11 +3689,21 @@ packages: cpu: [ia32] os: [win32] + '@rspack/binding-win32-ia32-msvc@1.7.12': + resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==} + cpu: [ia32] + os: [win32] + '@rspack/binding-win32-ia32-msvc@2.0.0-alpha.1': resolution: {integrity: sha512-5qpQL5Qz3uYb56pwffEGzznXSX9TNkLpigQbIObfnUwX7WkdjgTT7oTHpjn2sRSLLNiJ/jCp2r4ZHvjmnNRsRA==} cpu: [ia32] os: [win32] + '@rspack/binding-win32-ia32-msvc@2.1.2': + resolution: {integrity: sha512-OtxkFVz14mVL4QK8QriSELn9B6PaYGHw1jGJwVDEzpu2ZxSHCTQPz9dVE1ekYtREEqZUkRU7Fp7VfhJSmjTt2Q==} + cpu: [ia32] + os: [win32] + '@rspack/binding-win32-x64-msvc@1.3.3': resolution: {integrity: sha512-rOsNz4/DFgSENjEh0t9kFn89feuXK14/9wbmmFlT8VMpYOCcj4tKcAHjWg+Nzzj4FL+NSOC/81SrUF9J+C2R7w==} cpu: [x64] @@ -3567,20 +3714,36 @@ packages: cpu: [x64] os: [win32] + '@rspack/binding-win32-x64-msvc@1.7.12': + resolution: {integrity: sha512-wIqFvlgFqrgUyj/6S/FJcvShnkZOmIeXTfqvheLY67MGq8qd8jb1YimQVKAIrmWB3yuJKUFACI3Ag1UBtEedEA==} + cpu: [x64] + os: [win32] + '@rspack/binding-win32-x64-msvc@2.0.0-alpha.1': resolution: {integrity: sha512-dZ76NN9tXLaF2gnB/pU+PcK4Adf9tj8dY06KcWk5F81ur2V4UbrMfkWJkQprur8cgL/F49YtFMRWa4yp/qNbpQ==} cpu: [x64] os: [win32] + '@rspack/binding-win32-x64-msvc@2.1.2': + resolution: {integrity: sha512-Am+nx9fLF3nzgD/K05Bs1Bb+WO8SFLWAYRbXkymaL1r+RQxjRj7jd5ap2PhGOCcfaNA4yVWkAFvmFP92eRu7bQ==} + cpu: [x64] + os: [win32] + '@rspack/binding@1.3.3': resolution: {integrity: sha512-zdwJ801tyC8k+Gu5RjNoc7bEtX0MgJzzVv9qpaMwcAUfUfwZgCzXPTqcGMDoNI+Z47Fw59/2fKCmgZhZn60AgA==} '@rspack/binding@1.6.0': resolution: {integrity: sha512-RqlCjvWg/LkJjHpsbI48ebo2SYpIBJsV1eh9SEMfXo1batAPvB5grhAbLX0MRUOtzuQOnZMCDGdr2v7l2L8Siw==} + '@rspack/binding@1.7.12': + resolution: {integrity: sha512-f4HHuLbvuld8Ba4iB/4ibse5XrKxFrgmM3S4P2AOKnPlekAFlBjmltCuaTL/W2ggYvILaVY+YcFXrEH1rrKeQA==} + '@rspack/binding@2.0.0-alpha.1': resolution: {integrity: sha512-Glz0SNFYPtNVM+ExJ4ocSzW+oQhb1iHTmxqVEAILbL17Hq3N/nwZpo1cWEs6hJjn8cosJIb1VKbbgb/1goEtCQ==} + '@rspack/binding@2.1.2': + resolution: {integrity: sha512-/mFcRSUW7Pl19KeaBIujJvZYNJQu0wD5D3aa5h+Qcph26v7nmLYlX7eajIHGi8tt2qTZX1lXifw2KLIXKwYaRQ==} + '@rspack/core@1.3.3': resolution: {integrity: sha512-+mXVlFcYr0tWezZfJ/gR0fj8njRc7pzEMtTFa2NO5cfsNAKPF/SXm4rb55kfa63r0b3U3N7f2nKrJG9wyG7zMQ==} engines: {node: '>=16.0.0'} @@ -3602,6 +3765,15 @@ packages: '@swc/helpers': optional: true + '@rspack/core@1.7.12': + resolution: {integrity: sha512-6CwFIHlhRmXfZoMj3v9MZ1SMTPBn+cHVXeMIeaGp5sufqinKsISbsqHu6ZMJu2wDSmZLdmQJX6zLxkhcAUlhkQ==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + '@rspack/core@2.0.0-alpha.1': resolution: {integrity: sha512-2KK3hbxrRqzxtzg+ka7LsiEKIWIGIQz317k9HHC2U4IC5yLJ31K8y/vQfA1aIT2QcFls9gW7GyRjp8A4X5cvLA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3614,6 +3786,18 @@ packages: '@swc/helpers': optional: true + '@rspack/core@2.1.2': + resolution: {integrity: sha512-crpNQKhHfnzrIl4Sa4fjH30Ho5aAPgyqpmJZ41SkUFOzyKHdZKYfE5LF3CMh7MiFQFPPxiiKf5BcpxmtZZx4MQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@module-federation/runtime-tools': ^0.24.1 || ^2.0.0 + '@swc/helpers': ^0.5.23 + peerDependenciesMeta: + '@module-federation/runtime-tools': + optional: true + '@swc/helpers': + optional: true + '@rspack/lite-tapable@1.0.1': resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} @@ -3867,6 +4051,9 @@ packages: '@swc/helpers@0.5.18': resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + '@swc/types@0.1.24': resolution: {integrity: sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==} @@ -3877,6 +4064,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/babel__code-frame@7.0.6': resolution: {integrity: sha512-Anitqkl3+KrzcW2k77lRlg/GfLZLWXBuNgbEcIOU6M92yw42vsd3xV/Z/yAHEj8m+KUjL6bWOVOFqX8PFPJ4LA==} @@ -4802,6 +4992,11 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -10006,12 +10201,23 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/core@1.7.0': dependencies: '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.7.0': dependencies: tslib: 2.8.1 @@ -10022,6 +10228,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.25.5': optional: true @@ -10596,25 +10807,25 @@ snapshots: '@modern-js/node-bundle-require@2.67.6': dependencies: '@modern-js/utils': 2.67.6 - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 esbuild: 0.17.19 '@modern-js/node-bundle-require@2.68.2': dependencies: '@modern-js/utils': 2.68.2 - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 esbuild: 0.25.5 '@modern-js/utils@2.67.6': dependencies: - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 caniuse-lite: 1.0.30001774 lodash: 4.17.21 rslog: 1.3.2 '@modern-js/utils@2.68.2': dependencies: - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 caniuse-lite: 1.0.30001774 lodash: 4.17.21 rslog: 1.3.2 @@ -10875,7 +11086,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': + '@module-federation/enhanced@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.15.0 '@module-federation/cli': 0.15.0(typescript@5.9.3) @@ -10885,7 +11096,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 0.15.0(@module-federation/runtime-tools@0.15.0) '@module-federation/managers': 0.15.0 '@module-federation/manifest': 0.15.0(typescript@5.9.3) - '@module-federation/rspack': 0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/rspack': 0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3) '@module-federation/runtime-tools': 0.15.0 '@module-federation/sdk': 0.15.0 btoa: 1.2.1 @@ -10903,7 +11114,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': + '@module-federation/enhanced@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.21.0 '@module-federation/cli': 0.21.0(typescript@5.9.3) @@ -10913,7 +11124,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 0.21.0(@module-federation/runtime-tools@0.21.0) '@module-federation/managers': 0.21.0 '@module-federation/manifest': 0.21.0(typescript@5.9.3) - '@module-federation/rspack': 0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/rspack': 0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3) '@module-federation/runtime-tools': 0.21.0 '@module-federation/sdk': 0.21.0 btoa: 1.2.1 @@ -10931,7 +11142,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.3)': + '@module-federation/enhanced@0.8.9(@rspack/core@2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.8.9 '@module-federation/data-prefetch': 0.8.9(react-dom@19.2.4(react@19.2.3))(react@19.2.3) @@ -10940,7 +11151,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 0.8.9(@module-federation/runtime-tools@0.8.9) '@module-federation/managers': 0.8.9 '@module-federation/manifest': 0.8.9(typescript@5.9.3) - '@module-federation/rspack': 0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/rspack': 0.8.9(@rspack/core@2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23))(typescript@5.9.3) '@module-federation/runtime-tools': 0.8.9 '@module-federation/sdk': 0.8.9 btoa: 1.2.1 @@ -10957,7 +11168,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.18))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': + '@module-federation/enhanced@2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(webpack@5.105.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 2.0.1 '@module-federation/cli': 2.0.1(typescript@5.9.3) @@ -10967,7 +11178,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 2.0.1(@module-federation/runtime-tools@2.0.1) '@module-federation/managers': 2.0.1 '@module-federation/manifest': 2.0.1(typescript@5.9.3) - '@module-federation/rspack': 2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3) + '@module-federation/rspack': 2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3) '@module-federation/runtime-tools': 2.0.1 '@module-federation/sdk': 2.0.1 btoa: 1.2.1 @@ -11021,6 +11232,8 @@ snapshots: '@module-federation/error-codes@0.21.2': {} + '@module-federation/error-codes@0.22.0': {} + '@module-federation/error-codes@0.8.9': {} '@module-federation/error-codes@2.0.1': {} @@ -11152,7 +11365,7 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/rspack@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3)': + '@module-federation/rspack@0.15.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.15.0 '@module-federation/dts-plugin': 0.15.0(typescript@5.9.3) @@ -11161,7 +11374,7 @@ snapshots: '@module-federation/manifest': 0.15.0(typescript@5.9.3) '@module-federation/runtime-tools': 0.15.0 '@module-federation/sdk': 0.15.0 - '@rspack/core': 1.6.0(@swc/helpers@0.5.18) + '@rspack/core': 1.6.0(@swc/helpers@0.5.23) btoa: 1.2.1 optionalDependencies: typescript: 5.9.3 @@ -11171,7 +11384,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/rspack@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3)': + '@module-federation/rspack@0.21.0(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.21.0 '@module-federation/dts-plugin': 0.21.0(typescript@5.9.3) @@ -11180,7 +11393,7 @@ snapshots: '@module-federation/manifest': 0.21.0(typescript@5.9.3) '@module-federation/runtime-tools': 0.21.0 '@module-federation/sdk': 0.21.0 - '@rspack/core': 1.6.0(@swc/helpers@0.5.18) + '@rspack/core': 1.6.0(@swc/helpers@0.5.23) btoa: 1.2.1 optionalDependencies: typescript: 5.9.3 @@ -11190,7 +11403,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/rspack@0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3)': + '@module-federation/rspack@0.8.9(@rspack/core@2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.8.9 '@module-federation/dts-plugin': 0.8.9(typescript@5.9.3) @@ -11199,7 +11412,7 @@ snapshots: '@module-federation/manifest': 0.8.9(typescript@5.9.3) '@module-federation/runtime-tools': 0.8.9 '@module-federation/sdk': 0.8.9 - '@rspack/core': 1.6.0(@swc/helpers@0.5.18) + '@rspack/core': 2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -11208,7 +11421,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/rspack@2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.18))(typescript@5.9.3)': + '@module-federation/rspack@2.0.1(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 2.0.1 '@module-federation/dts-plugin': 2.0.1(typescript@5.9.3) @@ -11217,7 +11430,7 @@ snapshots: '@module-federation/manifest': 2.0.1(typescript@5.9.3) '@module-federation/runtime-tools': 2.0.1 '@module-federation/sdk': 2.0.1 - '@rspack/core': 1.6.0(@swc/helpers@0.5.18) + '@rspack/core': 1.6.0(@swc/helpers@0.5.23) btoa: 1.2.1 optionalDependencies: typescript: 5.9.3 @@ -11266,6 +11479,11 @@ snapshots: '@module-federation/error-codes': 0.21.2 '@module-federation/sdk': 0.21.2 + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/runtime-core@0.6.17': dependencies: '@module-federation/error-codes': 0.8.9 @@ -11301,6 +11519,11 @@ snapshots: '@module-federation/runtime': 0.21.2 '@module-federation/webpack-bundler-runtime': 0.21.2 + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + '@module-federation/runtime-tools@0.8.9': dependencies: '@module-federation/runtime': 0.8.9 @@ -11340,6 +11563,12 @@ snapshots: '@module-federation/runtime-core': 0.21.2 '@module-federation/sdk': 0.21.2 + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/runtime@0.8.9': dependencies: '@module-federation/error-codes': 0.8.9 @@ -11366,6 +11595,8 @@ snapshots: '@module-federation/sdk@0.21.2': {} + '@module-federation/sdk@0.22.0': {} + '@module-federation/sdk@0.6.10': {} '@module-federation/sdk@0.8.9': @@ -11426,6 +11657,11 @@ snapshots: '@module-federation/runtime': 0.21.2 '@module-federation/sdk': 0.21.2 + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/webpack-bundler-runtime@0.8.9': dependencies: '@module-federation/runtime': 0.8.9 @@ -11448,6 +11684,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + '@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3': optional: true @@ -11882,9 +12125,9 @@ snapshots: '@rsbuild/core@1.3.5': dependencies: - '@rspack/core': 1.3.3(@swc/helpers@0.5.18) + '@rspack/core': 1.3.3(@swc/helpers@0.5.23) '@rspack/lite-tapable': 1.0.1 - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 core-js: 3.41.0 jiti: 2.6.1 transitivePeerDependencies: @@ -11892,9 +12135,9 @@ snapshots: '@rsbuild/core@2.0.0-alpha.4(@module-federation/runtime-tools@2.1.0)(core-js@3.41.0)': dependencies: - '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.18) + '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23) '@rspack/lite-tapable': 1.1.0 - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 jiti: 2.6.1 optionalDependencies: core-js: 3.41.0 @@ -12129,91 +12372,163 @@ snapshots: '@rspack/binding-darwin-arm64@1.6.0': optional: true + '@rspack/binding-darwin-arm64@1.7.12': + optional: true + '@rspack/binding-darwin-arm64@2.0.0-alpha.1': optional: true + '@rspack/binding-darwin-arm64@2.1.2': + optional: true + '@rspack/binding-darwin-x64@1.3.3': optional: true '@rspack/binding-darwin-x64@1.6.0': optional: true + '@rspack/binding-darwin-x64@1.7.12': + optional: true + '@rspack/binding-darwin-x64@2.0.0-alpha.1': optional: true + '@rspack/binding-darwin-x64@2.1.2': + optional: true + '@rspack/binding-linux-arm64-gnu@1.3.3': optional: true '@rspack/binding-linux-arm64-gnu@1.6.0': optional: true + '@rspack/binding-linux-arm64-gnu@1.7.12': + optional: true + '@rspack/binding-linux-arm64-gnu@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-arm64-gnu@2.1.2': + optional: true + '@rspack/binding-linux-arm64-musl@1.3.3': optional: true '@rspack/binding-linux-arm64-musl@1.6.0': optional: true + '@rspack/binding-linux-arm64-musl@1.7.12': + optional: true + '@rspack/binding-linux-arm64-musl@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-arm64-musl@2.1.2': + optional: true + + '@rspack/binding-linux-riscv64-gnu@2.1.2': + optional: true + + '@rspack/binding-linux-riscv64-musl@2.1.2': + optional: true + '@rspack/binding-linux-x64-gnu@1.3.3': optional: true '@rspack/binding-linux-x64-gnu@1.6.0': optional: true + '@rspack/binding-linux-x64-gnu@1.7.12': + optional: true + '@rspack/binding-linux-x64-gnu@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-x64-gnu@2.1.2': + optional: true + '@rspack/binding-linux-x64-musl@1.3.3': optional: true '@rspack/binding-linux-x64-musl@1.6.0': optional: true + '@rspack/binding-linux-x64-musl@1.7.12': + optional: true + '@rspack/binding-linux-x64-musl@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-x64-musl@2.1.2': + optional: true + '@rspack/binding-wasm32-wasi@1.6.0': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true + '@rspack/binding-wasm32-wasi@1.7.12': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + '@rspack/binding-wasm32-wasi@2.0.0-alpha.1': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true + '@rspack/binding-wasm32-wasi@2.1.2': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + '@rspack/binding-win32-arm64-msvc@1.3.3': optional: true '@rspack/binding-win32-arm64-msvc@1.6.0': optional: true + '@rspack/binding-win32-arm64-msvc@1.7.12': + optional: true + '@rspack/binding-win32-arm64-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-arm64-msvc@2.1.2': + optional: true + '@rspack/binding-win32-ia32-msvc@1.3.3': optional: true '@rspack/binding-win32-ia32-msvc@1.6.0': optional: true + '@rspack/binding-win32-ia32-msvc@1.7.12': + optional: true + '@rspack/binding-win32-ia32-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-ia32-msvc@2.1.2': + optional: true + '@rspack/binding-win32-x64-msvc@1.3.3': optional: true '@rspack/binding-win32-x64-msvc@1.6.0': optional: true + '@rspack/binding-win32-x64-msvc@1.7.12': + optional: true + '@rspack/binding-win32-x64-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-x64-msvc@2.1.2': + optional: true + '@rspack/binding@1.3.3': optionalDependencies: '@rspack/binding-darwin-arm64': 1.3.3 @@ -12239,6 +12554,19 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.6.0 '@rspack/binding-win32-x64-msvc': 1.6.0 + '@rspack/binding@1.7.12': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.12 + '@rspack/binding-darwin-x64': 1.7.12 + '@rspack/binding-linux-arm64-gnu': 1.7.12 + '@rspack/binding-linux-arm64-musl': 1.7.12 + '@rspack/binding-linux-x64-gnu': 1.7.12 + '@rspack/binding-linux-x64-musl': 1.7.12 + '@rspack/binding-wasm32-wasi': 1.7.12 + '@rspack/binding-win32-arm64-msvc': 1.7.12 + '@rspack/binding-win32-ia32-msvc': 1.7.12 + '@rspack/binding-win32-x64-msvc': 1.7.12 + '@rspack/binding@2.0.0-alpha.1': optionalDependencies: '@rspack/binding-darwin-arm64': 2.0.0-alpha.1 @@ -12252,14 +12580,29 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 2.0.0-alpha.1 '@rspack/binding-win32-x64-msvc': 2.0.0-alpha.1 - '@rspack/core@1.3.3(@swc/helpers@0.5.18)': + '@rspack/binding@2.1.2': + optionalDependencies: + '@rspack/binding-darwin-arm64': 2.1.2 + '@rspack/binding-darwin-x64': 2.1.2 + '@rspack/binding-linux-arm64-gnu': 2.1.2 + '@rspack/binding-linux-arm64-musl': 2.1.2 + '@rspack/binding-linux-riscv64-gnu': 2.1.2 + '@rspack/binding-linux-riscv64-musl': 2.1.2 + '@rspack/binding-linux-x64-gnu': 2.1.2 + '@rspack/binding-linux-x64-musl': 2.1.2 + '@rspack/binding-wasm32-wasi': 2.1.2 + '@rspack/binding-win32-arm64-msvc': 2.1.2 + '@rspack/binding-win32-ia32-msvc': 2.1.2 + '@rspack/binding-win32-x64-msvc': 2.1.2 + + '@rspack/core@1.3.3(@swc/helpers@0.5.23)': dependencies: '@module-federation/runtime-tools': 0.11.2 '@rspack/binding': 1.3.3 '@rspack/lite-tapable': 1.0.1 caniuse-lite: 1.0.30001774 optionalDependencies: - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 '@rspack/core@1.6.0(@swc/helpers@0.5.18)': dependencies: @@ -12269,13 +12612,36 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.18 - '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.18)': + '@rspack/core@1.6.0(@swc/helpers@0.5.23)': + dependencies: + '@module-federation/runtime-tools': 0.21.2 + '@rspack/binding': 1.6.0 + '@rspack/lite-tapable': 1.0.1 + optionalDependencies: + '@swc/helpers': 0.5.23 + + '@rspack/core@1.7.12(@swc/helpers@0.5.23)': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.12 + '@rspack/lite-tapable': 1.1.0 + optionalDependencies: + '@swc/helpers': 0.5.23 + + '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23)': dependencies: '@rspack/binding': 2.0.0-alpha.1 '@rspack/lite-tapable': 1.1.0 optionalDependencies: '@module-federation/runtime-tools': 2.1.0 - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.23 + + '@rspack/core@2.1.2(@module-federation/runtime-tools@2.1.0)(@swc/helpers@0.5.23)': + dependencies: + '@rspack/binding': 2.1.2 + optionalDependencies: + '@module-federation/runtime-tools': 2.1.0 + '@swc/helpers': 0.5.23 '@rspack/lite-tapable@1.0.1': {} @@ -12576,6 +12942,10 @@ snapshots: dependencies: tslib: 2.8.1 + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + '@swc/types@0.1.24': dependencies: '@swc/counter': 0.1.3 @@ -12587,6 +12957,11 @@ snapshots: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/babel__code-frame@7.0.6': {} '@types/babel__core@7.20.5': @@ -13565,6 +13940,10 @@ snapshots: dependencies: luxon: 3.5.0 + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 diff --git a/turbo.json b/turbo.json index 2ea4ab76f..29b69d2c2 100644 --- a/turbo.json +++ b/turbo.json @@ -9,6 +9,10 @@ "dependsOn": ["^build"] }, "test": { + "dependsOn": ["^build"], + "env": ["RSPACK_MAJOR"] + }, + "test:rspack1": { "dependsOn": ["^build"] }, "pods": { From 0b642c80e5714d4208bdc52312293ea1e70009db Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Mon, 6 Jul 2026 19:19:35 +0100 Subject: [PATCH 2/4] fix: resolve [projectRoot^N] paths reaching the filesystem root on Windows resolveProjectPath composed the result via string replacement plus path.join: joining enough ../ segments onto rootDir to reach the filesystem root yields a bare root ending in a separator, and concatenating the rest of the path after it produced a double-separator prefix that Windows path resolution interprets as a UNC path (e.g. [projectRoot^2]/shared/utils.js with rootDir /project/root resolved to \\shared\utils.js\ instead of \shared\utils.js). Resolve segment-by-segment with path.resolve instead, add a regression test for the root-collapse case, and make the existing expectations platform-agnostic (resolved paths carry a drive letter and win32 separators on Windows). --- .../common/__tests__/resolveProjectPath.test.ts | 14 +++++++++++++- .../src/commands/common/resolveProjectPath.ts | 10 +++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts index 89d2e06c2..aee1a62cc 100644 --- a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts +++ b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import { resolveProjectPath } from '../resolveProjectPath.js'; describe('resolveProjectPath', () => { @@ -6,7 +7,9 @@ describe('resolveProjectPath', () => { expected: string, root = '/project/root' ) => { - expect(resolveProjectPath(input, root)).toBe(expected); + // path.resolve makes the expectation platform-agnostic - on Windows the + // resolved paths carry a drive letter and win32 separators + expect(resolveProjectPath(input, root)).toBe(path.resolve(expected)); }; it('should resolve [projectRoot] prefix correctly', () => { @@ -41,4 +44,13 @@ describe('resolveProjectPath', () => { '/a/b/c/d/e/f' ); }); + + it('should resolve correctly when up-level navigation reaches the filesystem root', () => { + // regression: string-replace + path.join composition produced UNC-like + // `\\...` paths on Windows once the `../` navigation collapsed rootDir + // to the bare filesystem root + expectResolved('[projectRoot^1]/src/index.js', '/src/index.js', '/project'); + expectResolved('[projectRoot^2]/index.js', '/index.js', '/project/root'); + expectResolved('[projectRoot^4]/index.js', '/index.js', '/a/b'); + }); }); diff --git a/packages/repack/src/commands/common/resolveProjectPath.ts b/packages/repack/src/commands/common/resolveProjectPath.ts index f5c293aa9..a71e6a0c8 100644 --- a/packages/repack/src/commands/common/resolveProjectPath.ts +++ b/packages/repack/src/commands/common/resolveProjectPath.ts @@ -13,7 +13,11 @@ export function resolveProjectPath(filepath: string, rootDir: string) { if (!match) return filepath; const [prefix, upLevels] = match; - const upPath = '../'.repeat(Number(upLevels ?? 0)); - const rootPath = path.join(rootDir, upPath); - return path.resolve(filepath.replace(prefix, rootPath)); + const upSegments = Array.from({ length: Number(upLevels ?? 0) }, () => '..'); + const restPath = filepath.slice(prefix.length + 1); + // resolve segment-by-segment instead of string-replace + join composition: + // on Windows, joining enough `../` segments to reach the filesystem root + // yields a bare root ending in a separator, and concatenating the rest of + // the path after it produced a double-separator (UNC-like `\\...`) prefix + return path.resolve(rootDir, ...upSegments, restPath); } From de30460778e941343b8d624efc96758d35f4c13d Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Mon, 6 Jul 2026 20:25:54 +0100 Subject: [PATCH 3/4] fix: reset both legacy and top-level rspack cache locations getRspackCacheConfig preferred experiments.cache over the top-level cache option, but a merged or dual-major config can carry both keys (e.g. the experimental cache defaults set experiments.cache while a user config sets top-level cache). Which location is active depends on the installed Rspack major, so --reset-cache now collects both locations instead of picking one. --- .../__tests__/resetPersistentCache.test.ts | 40 +++++++++++++++++++ .../commands/common/resetPersistentCache.ts | 18 ++++++--- packages/repack/src/commands/rspack/bundle.ts | 4 +- packages/repack/src/commands/rspack/start.ts | 4 +- 4 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts diff --git a/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts b/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts new file mode 100644 index 000000000..ae35c0ca2 --- /dev/null +++ b/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts @@ -0,0 +1,40 @@ +import { getRspackCacheConfigs } from '../resetPersistentCache.js'; + +describe('getRspackCacheConfigs', () => { + it('should return the legacy experiments.cache config (Rspack 1)', () => { + const cache = { type: 'persistent' as const }; + expect(getRspackCacheConfigs({ experiments: { cache } })).toEqual([cache]); + }); + + it('should return the top-level cache config (Rspack 2)', () => { + const cache = { + type: 'persistent' as const, + storage: { type: 'filesystem' as const, directory: '.cache/custom' }, + }; + expect(getRspackCacheConfigs({ cache })).toEqual([cache]); + }); + + it('should collect both locations when a config carries both keys', () => { + // e.g. a dual-major config or defaults merged with a user config - + // which location is active depends on the installed Rspack major, + // so both need to be considered when resetting the cache + const legacyCache = { type: 'persistent' as const }; + const cache = { + type: 'persistent' as const, + storage: { type: 'filesystem' as const, directory: '.cache/custom' }, + }; + expect( + getRspackCacheConfigs({ cache, experiments: { cache: legacyCache } }) + ).toEqual([legacyCache, cache]); + }); + + it('should fall back to a single entry when no cache config is present', () => { + expect(getRspackCacheConfigs({})).toEqual([undefined]); + expect(getRspackCacheConfigs({ experiments: {} })).toEqual([undefined]); + }); + + it('should keep boolean cache configs', () => { + expect(getRspackCacheConfigs({ cache: true })).toEqual([true]); + expect(getRspackCacheConfigs({ cache: false })).toEqual([false]); + }); +}); diff --git a/packages/repack/src/commands/common/resetPersistentCache.ts b/packages/repack/src/commands/common/resetPersistentCache.ts index eedfbdc4a..933b1bee7 100644 --- a/packages/repack/src/commands/common/resetPersistentCache.ts +++ b/packages/repack/src/commands/common/resetPersistentCache.ts @@ -21,14 +21,20 @@ export interface RspackConfigurationWithLegacyCache { type WebpackCacheOptions = WebpackConfiguration['cache']; /** - * Reads the persistent cache configuration from a Rspack config, - * supporting both the Rspack 1 (`experiments.cache`) and - * Rspack 2 (top-level `cache`) locations. + * Collects the persistent cache configurations from a Rspack config, + * covering both the Rspack 1 (`experiments.cache`) and + * Rspack 2 (top-level `cache`) locations. A merged or dual-major config + * can carry both keys and which one is active depends on the installed + * Rspack major, so `--reset-cache` clears both locations. */ -export function getRspackCacheConfig( +export function getRspackCacheConfigs( config: RspackConfigurationWithLegacyCache -): RspackCacheOptions { - return config.experiments?.cache ?? config.cache; +): RspackCacheOptions[] { + const cacheConfigs = [config.experiments?.cache, config.cache].filter( + (cacheConfig) => cacheConfig !== undefined + ); + // without an explicit cache config, the default cache location still applies + return cacheConfigs.length > 0 ? cacheConfigs : [undefined]; } function getDefaultCacheDirectory( diff --git a/packages/repack/src/commands/rspack/bundle.ts b/packages/repack/src/commands/rspack/bundle.ts index 810888178..2b89a1cef 100644 --- a/packages/repack/src/commands/rspack/bundle.ts +++ b/packages/repack/src/commands/rspack/bundle.ts @@ -4,7 +4,7 @@ import { CLIError } from '../../helpers/index.js'; import { makeCompilerConfig } from '../common/config/makeCompilerConfig.js'; import { getMaxWorkers, - getRspackCacheConfig, + getRspackCacheConfigs, normalizeStatsOptions, resetPersistentCache, setupEnvironment, @@ -50,7 +50,7 @@ export async function bundle( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: [getRspackCacheConfig(config)], + cacheConfigs: getRspackCacheConfigs(config), }); } diff --git a/packages/repack/src/commands/rspack/start.ts b/packages/repack/src/commands/rspack/start.ts index c2117b695..9e786f53d 100644 --- a/packages/repack/src/commands/rspack/start.ts +++ b/packages/repack/src/commands/rspack/start.ts @@ -14,7 +14,7 @@ import { getDevMiddleware, getMaxWorkers, getMimeType, - getRspackCacheConfig, + getRspackCacheConfigs, parseUrl, resetPersistentCache, resolveProjectPath, @@ -84,7 +84,7 @@ export async function start( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: configs.map(getRspackCacheConfig), + cacheConfigs: configs.flatMap(getRspackCacheConfigs), }); } From 18e54f41e45cf0798aa04d47f20aec4c8e375d6d Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Tue, 7 Jul 2026 23:10:02 +0100 Subject: [PATCH 4/4] fix: keep resolveProjectPath inside project root on duplicate separators --- .../common/__tests__/resolveProjectPath.test.ts | 17 +++++++++++++++++ .../src/commands/common/resolveProjectPath.ts | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts index aee1a62cc..8f4c92e91 100644 --- a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts +++ b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts @@ -53,4 +53,21 @@ describe('resolveProjectPath', () => { expectResolved('[projectRoot^2]/index.js', '/index.js', '/project/root'); expectResolved('[projectRoot^4]/index.js', '/index.js', '/a/b'); }); + + it('should stay inside the project root on duplicated separators', () => { + // regression: a leading separator in the remainder made path.resolve + // treat it as an absolute path, escaping rootDir and dropping the + // [projectRoot^N] up-segments entirely + expectResolved('[projectRoot]//src/index.js', '/project/root/src/index.js'); + expectResolved( + '[projectRoot]/src//nested///index.js', + '/project/root/src/nested/index.js' + ); + expectResolved('[projectRoot^1]//src/index.js', '/project/src/index.js'); + expectResolved( + '[projectRoot^2]//shared/utils.js', + '/deep/shared/utils.js', + '/deep/nested/project' + ); + }); }); diff --git a/packages/repack/src/commands/common/resolveProjectPath.ts b/packages/repack/src/commands/common/resolveProjectPath.ts index a71e6a0c8..2c30cf765 100644 --- a/packages/repack/src/commands/common/resolveProjectPath.ts +++ b/packages/repack/src/commands/common/resolveProjectPath.ts @@ -14,10 +14,13 @@ export function resolveProjectPath(filepath: string, rootDir: string) { const [prefix, upLevels] = match; const upSegments = Array.from({ length: Number(upLevels ?? 0) }, () => '..'); - const restPath = filepath.slice(prefix.length + 1); + const restSegments = filepath + .slice(prefix.length + 1) + .split('/') + .filter(Boolean); // resolve segment-by-segment instead of string-replace + join composition: // on Windows, joining enough `../` segments to reach the filesystem root // yields a bare root ending in a separator, and concatenating the rest of // the path after it produced a double-separator (UNC-like `\\...`) prefix - return path.resolve(rootDir, ...upSegments, restPath); + return path.resolve(rootDir, ...upSegments, ...restSegments); }