diff --git a/.changeset/eight-geckos-tease.md b/.changeset/eight-geckos-tease.md new file mode 100644 index 0000000000..853d812bb3 --- /dev/null +++ b/.changeset/eight-geckos-tease.md @@ -0,0 +1,3 @@ +--- + +--- diff --git a/.changeset/flat-hats-flow.md b/.changeset/flat-hats-flow.md new file mode 100644 index 0000000000..ab2b2c9bb8 --- /dev/null +++ b/.changeset/flat-hats-flow.md @@ -0,0 +1,5 @@ +--- +"@lynx-js/chunk-loading-webpack-plugin": patch +--- + +Add `StartupChunkDependenciesRuntimeModule` to fix `RuntimeGlobals.ensureChunkHandler` not found when using chunk splitting diff --git a/.changeset/itchy-islands-float.md b/.changeset/itchy-islands-float.md new file mode 100644 index 0000000000..347393e8f7 --- /dev/null +++ b/.changeset/itchy-islands-float.md @@ -0,0 +1,5 @@ +--- +"@lynx-js/rspeedy": patch +--- + +Support `performance.profile`. diff --git a/.changeset/lovely-pots-tap.md b/.changeset/lovely-pots-tap.md new file mode 100644 index 0000000000..853d812bb3 --- /dev/null +++ b/.changeset/lovely-pots-tap.md @@ -0,0 +1,3 @@ +--- + +--- diff --git a/.changeset/three-baboons-hunt.md b/.changeset/three-baboons-hunt.md new file mode 100644 index 0000000000..1909b6f51b --- /dev/null +++ b/.changeset/three-baboons-hunt.md @@ -0,0 +1,23 @@ +--- +"@lynx-js/rspeedy": patch +--- + +Enable native Rsdoctor plugin by default. + +Set `tools.rsdoctor.experiments.enableNativePlugin` to `false` to use the old JS plugin. + +```js +import { defineConfig } from '@lynx-js/rspeedy'; + +export default defineConfig({ + tools: { + rsdoctor: { + experiments: { + enableNativePlugin: false, + }, + }, + }, +}); +``` + +See [Rsdoctor - 1.0](https://rsdoctor.dev/blog/release/release-note-1_0#-faster-analysis) for more details. diff --git a/.dprint.jsonc b/.dprint.jsonc index 008ff6f9be..ba882d4fc1 100644 --- a/.dprint.jsonc +++ b/.dprint.jsonc @@ -61,12 +61,12 @@ "plugins": [ "https://plugins.dprint.dev/dockerfile-0.3.2.wasm", "https://plugins.dprint.dev/exec-0.5.1.json@492414e39dea4dccc07b4af796d2f4efdb89e84bae2bd4e1e924c0cc050855bf", - "https://plugins.dprint.dev/typescript-0.94.0.wasm", + "https://plugins.dprint.dev/typescript-0.95.0.wasm", "https://plugins.dprint.dev/json-0.20.0.wasm", "https://plugins.dprint.dev/markdown-0.18.0.wasm", "https://plugins.dprint.dev/toml-0.7.0.wasm", - "https://plugins.dprint.dev/g-plane/malva-v0.11.2.wasm", - "https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm", + "https://plugins.dprint.dev/g-plane/malva-v0.12.0.wasm", + "https://plugins.dprint.dev/g-plane/markup_fmt-v0.20.0.wasm", "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", ], } diff --git a/package.json b/package.json index daf39ee813..0d4d6fce3e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.9.4", - "@changesets/cli": "^2.29.2", + "@changesets/cli": "^2.29.3", "@codspeed/vitest-plugin": "^4.0.1", "@eslint/js": "^9.25.1", "@microsoft/api-extractor": "catalog:", @@ -24,9 +24,9 @@ "@tsconfig/node20": "^20.1.5", "@tsconfig/strictest": "^2.0.5", "@types/node": "^22.15.3", - "@vitest/coverage-v8": "^3.1.2", + "@vitest/coverage-v8": "^3.1.3", "@vitest/eslint-plugin": "^1.1.44", - "@vitest/ui": "^3.1.2", + "@vitest/ui": "^3.1.3", "cspell": "^8.19.3", "dprint": "^0.49.1", "eslint": "^9.25.1", @@ -40,12 +40,12 @@ "globals": "^16.0.0", "husky": "^9.1.7", "lint-staged": "^15.5.1", - "sort-package-json": "^3.1.0", + "sort-package-json": "^3.2.0", "ts-patch": "^3.3.0", "turbo": "^2.5.2", "typescript": "^5.8.3", "typescript-eslint": "^8.31.1", - "vitest": "^3.1.2" + "vitest": "^3.1.3" }, "packageManager": "pnpm@10.10.0", "engines": { diff --git a/packages/react/runtime/package.json b/packages/react/runtime/package.json index 93b9f2dd7a..9c2d747d9b 100644 --- a/packages/react/runtime/package.json +++ b/packages/react/runtime/package.json @@ -23,11 +23,11 @@ "@lynx-js/react-transform": "workspace:*", "@types/react": "^18.3.20", "@vitejs/plugin-react": "4.4.1", - "@vitest/coverage-v8": "^3.1.2", - "@vitest/ui": "^3.1.2", + "@vitest/coverage-v8": "^3.1.3", + "@vitest/ui": "^3.1.3", "esbuild": "^0.25.3", "pretty-format": "^29.7.0", - "vitest": "^3.1.2" + "vitest": "^3.1.3" }, "peerDependencies": { "@types/react": "^18.0.0" diff --git a/packages/react/transform/src/swc_plugin_worklet/extract_ident.rs b/packages/react/transform/src/swc_plugin_worklet/extract_ident.rs index c0a9aab5e0..241f069aed 100644 --- a/packages/react/transform/src/swc_plugin_worklet/extract_ident.rs +++ b/packages/react/transform/src/swc_plugin_worklet/extract_ident.rs @@ -4,14 +4,14 @@ use crate::swc_plugin_worklet::decl_collect::{ use crate::swc_plugin_worklet::globals::{DEFAULT_GLOBALS, LYNX_GLOBALS}; use rustc_hash::FxHashSet; use std::cmp::max; -use std::mem::swap; +use std::mem::{swap, take}; use std::ops::Deref; use swc_core::common::util::take::Take; -use swc_core::common::{EqIgnoreSpan, DUMMY_SP}; +use swc_core::common::EqIgnoreSpan; use swc_core::ecma::ast::*; use swc_core::ecma::utils::quote_ident; use swc_core::ecma::visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; -use swc_core::{quote, quote_expr}; +use swc_core::quote; pub struct ExtractingIdentsCollectorConfig { pub custom_global_ident_names: Option>, @@ -31,7 +31,7 @@ pub struct ExtractingIdentsCollector { values_extracted: Box, idents_to_extract: Vec, this_expr_to_extract: Box, - js_fns_to_extract: Box, + js_fns_to_extract: Vec<(IdentName, Box)>, id_of_last_js_fn: u32, next_block_decls_collected: bool, scope_env: Vec, @@ -51,7 +51,7 @@ impl ExtractingIdentsCollector { values_extracted: quote!("{}" as Expr).into(), idents_to_extract: vec![], this_expr_to_extract: quote!("{}" as Expr).into(), - js_fns_to_extract: quote!("{}" as Expr).into(), + js_fns_to_extract: vec![], id_of_last_js_fn: 0, next_block_decls_collected: false, scope_env: vec![ScopeEnv { @@ -76,8 +76,8 @@ impl ExtractingIdentsCollector { self.this_expr_to_extract.take() } - pub fn take_js_fns(&mut self) -> Box { - self.js_fns_to_extract.take() + pub fn take_js_fns(&mut self) -> Vec<(IdentName, Box)> { + take(&mut self.js_fns_to_extract) } fn is_at_global(&self, s: &str) -> bool { @@ -350,20 +350,7 @@ impl VisitMut for ExtractingIdentsCollector { let fn_ident = quote_ident!(format!("_jsFn{}", self.id_of_last_js_fn)); let mut fn_expr = Box::new(fn_ident.clone().into()); swap(&mut fn_expr, &mut n.args[0].expr); - self.js_fns_to_extract.as_mut_object().unwrap().props.push( - Prop::KeyValue(KeyValueProp { - key: fn_ident.into(), - value: CallExpr { - ctxt: Default::default(), - span: DUMMY_SP, - args: vec![fn_expr.into()], - callee: Callee::Expr(quote_expr!("transformToWorklet")), - type_args: None, - } - .into(), - }) - .into(), - ); + self.js_fns_to_extract.push((fn_ident.clone(), fn_expr)); // skip visit_mut_children_with() here } diff --git a/packages/react/transform/src/swc_plugin_worklet/gen_stmt.rs b/packages/react/transform/src/swc_plugin_worklet/gen_stmt.rs index 17e9c74dcf..0647832279 100644 --- a/packages/react/transform/src/swc_plugin_worklet/gen_stmt.rs +++ b/packages/react/transform/src/swc_plugin_worklet/gen_stmt.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use std::vec; use swc_core::common::DUMMY_SP; use swc_core::ecma::ast::*; -use swc_core::quote; +use swc_core::{quote, quote_expr}; pub struct StmtGen {} @@ -66,11 +66,11 @@ impl StmtGen { target: TransformTarget, extracted_value: Box, extracted_this_expr: Box, - extracted_js_fns: Box, + extracted_js_fns: Vec<(IdentName, Box)>, hash: Expr, named_imports: &mut HashSet, ) -> Box { - if target == TransformTarget::JS && !extracted_js_fns.as_object().unwrap().props.is_empty() { + if target == TransformTarget::JS && !extracted_js_fns.is_empty() { named_imports.insert("transformToWorklet".into()); } @@ -99,11 +99,37 @@ impl StmtGen { .into(), ); - if target == TransformTarget::JS && !extracted_js_fns.as_object().unwrap().props.is_empty() { + if target == TransformTarget::JS && !extracted_js_fns.is_empty() { + let value: Box = Expr::Object(ObjectLit { + span: DUMMY_SP, + props: extracted_js_fns + .into_iter() + .map(|(key, value)| { + { + match target { + TransformTarget::JS => Prop::KeyValue(KeyValueProp { + key: key.into(), + value: CallExpr { + ctxt: Default::default(), + span: DUMMY_SP, + args: vec![value.into()], + callee: Callee::Expr(quote_expr!("transformToWorklet")), + type_args: None, + } + .into(), + }), + _ => unreachable!(), + } + } + .into() + }) + .collect(), + }) + .into(); props.push( Prop::KeyValue(KeyValueProp { key: Ident::from("_jsFn").into(), - value: extracted_js_fns, + value: value, }) .into(), ); @@ -141,7 +167,7 @@ impl StmtGen { function_name: Ident, function: Box, extracted_idents: Vec, - extracted_js_fns: Box, + extracted_js_fns: Vec<(IdentName, Box)>, hash: Expr, is_class_member: bool, named_imports: &mut HashSet, @@ -184,7 +210,7 @@ impl StmtGen { function: Box, function_name: Ident, extracted_idents: Vec, - extracted_js_fns: Box, + extracted_js_fns: Vec<(IdentName, Box)>, hash: Expr, is_class_member: bool, ) -> Function { @@ -201,15 +227,10 @@ impl StmtGen { } // let { _jsFn1, _jsFn2 } = this._jsFn; - let fn_props = extracted_js_fns.expect_object().props; - if !fn_props.is_empty() { - let fn_ids = fn_props - .into_iter() - .map(|prop| match *prop.expect_prop() { - Prop::Shorthand(id) => id, - Prop::KeyValue(kv) => kv.key.expect_ident().into(), - _ => unreachable!(), - }) + if !extracted_js_fns.is_empty() { + let fn_ids = extracted_js_fns + .iter() + .map(|(k, _)| Ident::from(k.clone())) .collect(); stmts.push(StmtGen::gen_destructure_stmt( Ident::new("_jsFn".into(), DUMMY_SP, Default::default()).into(), diff --git a/packages/rspeedy/core/CHANGELOG.md b/packages/rspeedy/core/CHANGELOG.md index 864cf9e622..792aa502fd 100644 --- a/packages/rspeedy/core/CHANGELOG.md +++ b/packages/rspeedy/core/CHANGELOG.md @@ -10,7 +10,7 @@ ### Patch Changes -- Support cli option `--no-env` to disable loading of .env files ([#483](https://github.com/lynx-family/lynx-stack/pull/483)) +- Support CLI option `--no-env` to disable loading of `.env` files ([#483](https://github.com/lynx-family/lynx-stack/pull/483)) - Bump Rsbuild v1.3.8 with Rspack v1.3.5. ([#579](https://github.com/lynx-family/lynx-stack/pull/579)) @@ -46,9 +46,9 @@ ### Patch Changes -- Support cli flag `--base` to specify the base path of the server. ([#387](https://github.com/lynx-family/lynx-stack/pull/387)) +- Support CLI flag `--base` to specify the base path of the server. ([#387](https://github.com/lynx-family/lynx-stack/pull/387)) -- Support cli option `--environment` to specify the name of environment to build ([#462](https://github.com/lynx-family/lynx-stack/pull/462)) +- Support CLI option `--environment` to specify the name of environment to build ([#462](https://github.com/lynx-family/lynx-stack/pull/462)) - Select the most appropriate network interface. ([#457](https://github.com/lynx-family/lynx-stack/pull/457)) @@ -58,7 +58,7 @@ See [Node.js - TypeScript](https://nodejs.org/api/typescript.html) for more details. -- Support cli option `--env-mode` to specify the env mode to load the `.env.[mode]` file. ([#453](https://github.com/lynx-family/lynx-stack/pull/453)) +- Support CLI option `--env-mode` to specify the env mode to load the `.env.[mode]` file. ([#453](https://github.com/lynx-family/lynx-stack/pull/453)) - Support `dev.hmr` and `dev.liveReload`. ([#458](https://github.com/lynx-family/lynx-stack/pull/458)) diff --git a/packages/rspeedy/core/etc/rspeedy.api.md b/packages/rspeedy/core/etc/rspeedy.api.md index 87f30549e7..55e7044917 100644 --- a/packages/rspeedy/core/etc/rspeedy.api.md +++ b/packages/rspeedy/core/etc/rspeedy.api.md @@ -233,6 +233,7 @@ export interface Output { export interface Performance { chunkSplit?: ChunkSplit | ChunkSplitBySize | ChunkSplitCustom | undefined; printFileSize?: PerformanceConfig['printFileSize'] | undefined; + profile?: boolean | undefined; removeConsole?: boolean | ConsoleType[] | undefined; } diff --git a/packages/rspeedy/core/package.json b/packages/rspeedy/core/package.json index 514d6077e8..bab705123e 100644 --- a/packages/rspeedy/core/package.json +++ b/packages/rspeedy/core/package.json @@ -78,7 +78,7 @@ "type-fest": "^4.40.1", "typia": "9.1.1", "typia-rspack-plugin": "2.0.1", - "vitest": "^3.1.2", + "vitest": "^3.1.3", "webpack": "^5.99.7" }, "peerDependencies": { diff --git a/packages/rspeedy/core/src/cli/build.ts b/packages/rspeedy/core/src/cli/build.ts index fdab475ba2..2fd49209f2 100644 --- a/packages/rspeedy/core/src/cli/build.ts +++ b/packages/rspeedy/core/src/cli/build.ts @@ -6,10 +6,9 @@ import { logger } from '@rsbuild/core' import type { Command } from 'commander' import type { CommonOptions } from './commands.js' -import type { CreateRspeedyOptions } from '../create-rspeedy.js' import { exit } from './exit.js' -import { loadConfig } from '../config/loadConfig.js' import { createRspeedy } from '../create-rspeedy.js' +import { init } from './init.js' import { isCI } from '../utils/is-ci.js' export type BuildOptions = CommonOptions & { @@ -26,27 +25,9 @@ export async function build( const shouldExit = process.env['RSDOCTOR'] !== 'true' || isCI() try { - const { content: rspeedyConfig } = await loadConfig({ - cwd, - configPath: buildOptions.config, - }) - - const options: CreateRspeedyOptions = { - cwd, - rspeedyConfig, - } - - if (buildOptions.noEnv) { - options.loadEnv = false - } else if (buildOptions.envMode) { - options.loadEnv = { mode: buildOptions.envMode } - } - - if (buildOptions.environment) { - options.environment = buildOptions.environment - } + const { createRspeedyOptions } = await init(cwd, buildOptions) - const rspeedy = await createRspeedy(options) + const rspeedy = await createRspeedy(createRspeedyOptions) await rspeedy.build() } catch (error) { diff --git a/packages/rspeedy/core/src/cli/dev.ts b/packages/rspeedy/core/src/cli/dev.ts index 97e7cb49d6..c5ac98b5b3 100644 --- a/packages/rspeedy/core/src/cli/dev.ts +++ b/packages/rspeedy/core/src/cli/dev.ts @@ -9,10 +9,9 @@ import type { Command } from 'commander' import color from 'picocolors' import type { CommonOptions } from './commands.js' -import { loadConfig, resolveConfigPath } from '../config/loadConfig.js' import { createRspeedy } from '../create-rspeedy.js' -import type { CreateRspeedyOptions } from '../create-rspeedy.js' import { exit } from './exit.js' +import { init } from './init.js' export interface DevOptions extends CommonOptions { base?: string | undefined @@ -26,17 +25,10 @@ export async function dev( ): Promise { let onBeforeRestart: (() => Promise)[] = [] try { - const configPath = resolveConfigPath(cwd, devOptions.config) - - const { content: rspeedyConfig } = await loadConfig({ + const { rspeedyConfig, configPath, createRspeedyOptions } = await init( cwd, - configPath, - }) - - if (devOptions.base) { - rspeedyConfig.server ??= {} - rspeedyConfig.server.base = devOptions.base - } + devOptions, + ) const watchedFiles = [configPath] @@ -65,22 +57,7 @@ export async function dev( }, ) - const options: CreateRspeedyOptions = { - cwd, - rspeedyConfig, - } - - if (devOptions.noEnv) { - options.loadEnv = false - } else if (devOptions.envMode) { - options.loadEnv = { mode: devOptions.envMode } - } - - if (devOptions.environment) { - options.environment = devOptions.environment - } - - const rspeedy = await createRspeedy(options) + const rspeedy = await createRspeedy(createRspeedyOptions) const server = await rspeedy.createDevServer() diff --git a/packages/rspeedy/core/src/cli/init.ts b/packages/rspeedy/core/src/cli/init.ts new file mode 100644 index 0000000000..b306defa95 --- /dev/null +++ b/packages/rspeedy/core/src/cli/init.ts @@ -0,0 +1,46 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +import type { Config } from '../config/index.js' +import { loadConfig } from '../config/loadConfig.js' +import type { CreateRspeedyOptions } from '../create-rspeedy.js' +import type { BuildOptions } from './build.js' +import type { DevOptions } from './dev.js' +import type { InspectOptions } from './inspect.js' +import type { PreviewOptions } from './preview.js' + +export async function init( + cwd: string, + options: BuildOptions | DevOptions | InspectOptions | PreviewOptions, +): Promise<{ + configPath: string + createRspeedyOptions: CreateRspeedyOptions + rspeedyConfig: Config +}> { + const { content: rspeedyConfig, configPath } = await loadConfig({ + cwd, + configPath: options.config, + }) + + const createRspeedyOptions: CreateRspeedyOptions = { + cwd, + rspeedyConfig, + } + + if (options.noEnv) { + createRspeedyOptions.loadEnv = false + } else if (options.envMode) { + createRspeedyOptions.loadEnv = { mode: options.envMode } + } + + if ('base' in options && options.base) { + rspeedyConfig.server ??= {} + rspeedyConfig.server.base = options.base + } + + if ('environment' in options && options.environment) { + createRspeedyOptions.environment = options.environment + } + + return { createRspeedyOptions, configPath, rspeedyConfig } +} diff --git a/packages/rspeedy/core/src/cli/inspect.ts b/packages/rspeedy/core/src/cli/inspect.ts index 6c775883cc..cc157c44a8 100644 --- a/packages/rspeedy/core/src/cli/inspect.ts +++ b/packages/rspeedy/core/src/cli/inspect.ts @@ -8,9 +8,8 @@ import type { Command } from 'commander' import type { CommonOptions } from './commands.js' import { exit } from './exit.js' -import { loadConfig } from '../config/loadConfig.js' import { createRspeedy } from '../create-rspeedy.js' -import type { CreateRspeedyOptions } from '../create-rspeedy.js' +import { init } from './init.js' export interface InspectOptions extends CommonOptions { mode?: 'production' | 'development' | undefined @@ -24,23 +23,8 @@ export async function inspect( inspectOptions: InspectOptions, ): Promise { try { - const { content: rspeedyConfig } = await loadConfig({ - cwd, - configPath: inspectOptions.config, - }) - - const options: CreateRspeedyOptions = { - cwd, - rspeedyConfig, - } - - if (inspectOptions.noEnv) { - options.loadEnv = false - } else if (inspectOptions.envMode) { - options.loadEnv = { mode: inspectOptions.envMode } - } - - const rspeedy = await createRspeedy(options) + const { createRspeedyOptions } = await init(cwd, inspectOptions) + const rspeedy = await createRspeedy(createRspeedyOptions) await rspeedy.inspectConfig({ mode: inspectOptions.mode diff --git a/packages/rspeedy/core/src/cli/preview.ts b/packages/rspeedy/core/src/cli/preview.ts index 814d3575a2..67a7477bab 100644 --- a/packages/rspeedy/core/src/cli/preview.ts +++ b/packages/rspeedy/core/src/cli/preview.ts @@ -9,9 +9,8 @@ import color from 'picocolors' import type { CommonOptions } from './commands.js' import { exit } from './exit.js' -import { loadConfig, resolveConfigPath } from '../config/loadConfig.js' import { createRspeedy } from '../create-rspeedy.js' -import type { CreateRspeedyOptions } from '../create-rspeedy.js' +import { init } from './init.js' export interface PreviewOptions extends CommonOptions { base?: string | undefined @@ -23,30 +22,9 @@ export async function preview( previewOptions: PreviewOptions, ): Promise { try { - const configPath = resolveConfigPath(cwd, previewOptions.config) + const { createRspeedyOptions } = await init(cwd, previewOptions) - const { content: rspeedyConfig } = await loadConfig({ - cwd, - configPath, - }) - - if (previewOptions.base) { - rspeedyConfig.server ??= {} - rspeedyConfig.server.base = previewOptions.base - } - - const options: CreateRspeedyOptions = { - cwd, - rspeedyConfig, - } - - if (previewOptions.noEnv) { - options.loadEnv = false - } else if (previewOptions.envMode) { - options.loadEnv = { mode: previewOptions.envMode } - } - - const rspeedy = await createRspeedy(options) + const rspeedy = await createRspeedy(createRspeedyOptions) await rspeedy.initConfigs() diff --git a/packages/rspeedy/core/src/config/defaults.ts b/packages/rspeedy/core/src/config/defaults.ts index b717d8baf5..e387826ea1 100644 --- a/packages/rspeedy/core/src/config/defaults.ts +++ b/packages/rspeedy/core/src/config/defaults.ts @@ -8,14 +8,22 @@ import type { Filename } from './output/filename.js' import type { Config } from './index.js' export function applyDefaultRspeedyConfig(config: Config): Config { - const ret = mergeRsbuildConfig(config, { + const ret = mergeRsbuildConfig({ output: { // We are applying the default filename to the config // since some plugin(e.g.: `@lynx-js/qrcode-rsbuild-plugin`) will read // from the `output.filename.bundle` field. filename: getFilename(config.output?.filename), }, - }) + + tools: { + rsdoctor: { + experiments: { + enableNativePlugin: true, + }, + }, + }, + }, config) return ret } diff --git a/packages/rspeedy/core/src/config/performance/index.ts b/packages/rspeedy/core/src/config/performance/index.ts index 012c22a6e9..cf56ab0a99 100644 --- a/packages/rspeedy/core/src/config/performance/index.ts +++ b/packages/rspeedy/core/src/config/performance/index.ts @@ -37,6 +37,33 @@ export interface Performance { */ chunkSplit?: ChunkSplit | ChunkSplitBySize | ChunkSplitCustom | undefined + /** + * Whether capture timing information in the build time and the runtime, the same as the {@link https://rspack.dev/config/other-options#profile | profile} config of Rspack. + * + * @remarks + * + * This option would be `true` when `DEBUG` environment variable contains `rspeedy`. + * + * @example + * + * Enable profile. + * + * - Rsbuild will auto-generate `dist/stats.json` file through bundle analyzer. + * + * - Rspack will include the build time information when generating `stats.json`. + * + * - Frameworks like ReactLynx will include runtime information using `console.profile`. + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { profile: true }, + * }) + * ``` + */ + profile?: boolean | undefined + /** * Whether to remove `console.[methodName]` in production build. * diff --git a/packages/rspeedy/core/src/config/rsbuild/index.ts b/packages/rspeedy/core/src/config/rsbuild/index.ts index e943329b59..dfec2cefdd 100644 --- a/packages/rspeedy/core/src/config/rsbuild/index.ts +++ b/packages/rspeedy/core/src/config/rsbuild/index.ts @@ -87,6 +87,8 @@ export function toRsbuildConfig( performance: { chunkSplit: config.performance?.chunkSplit, + profile: config.performance?.profile, + removeConsole: toRsbuildRemoveConsole(config) as | ConsoleType[] | false diff --git a/packages/rspeedy/core/src/plugins/stats.plugin.ts b/packages/rspeedy/core/src/plugins/stats.plugin.ts index 0b876413fc..f03a9805ff 100644 --- a/packages/rspeedy/core/src/plugins/stats.plugin.ts +++ b/packages/rspeedy/core/src/plugins/stats.plugin.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. -import type { RsbuildConfig, RsbuildPlugin } from '@rsbuild/core' +import type { RsbuildPlugin } from '@rsbuild/core' export function pluginStats(): RsbuildPlugin { return { @@ -11,14 +11,9 @@ export function pluginStats(): RsbuildPlugin { api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => { return mergeRsbuildConfig(config, { performance: { - bundleAnalyze: { - // Failed to parse background.js, so analyzerMode is disabled here. - // Please use Webpack Bundle Analyzer in rsdoctor. - analyzerMode: 'disabled', - generateStatsFile: true, - }, + profile: true, }, - } as RsbuildConfig) + }) }) }, } diff --git a/packages/rspeedy/core/test/config/performance.test-d.ts b/packages/rspeedy/core/test/config/performance.test-d.ts index d2638db4a0..d0752e29f1 100644 --- a/packages/rspeedy/core/test/config/performance.test-d.ts +++ b/packages/rspeedy/core/test/config/performance.test-d.ts @@ -189,6 +189,20 @@ describe('Config - Performance', () => { }) }) + test('performance.profile', () => { + assertType({ + profile: undefined, + }) + + assertType({ + profile: true, + }) + + assertType({ + profile: false, + }) + }) + test('performance.removeConsole true', () => { assertType({ removeConsole: true, diff --git a/packages/rspeedy/core/test/config/rsbuild.test.ts b/packages/rspeedy/core/test/config/rsbuild.test.ts index 8a2bd70495..df9b6b6e1b 100644 --- a/packages/rspeedy/core/test/config/rsbuild.test.ts +++ b/packages/rspeedy/core/test/config/rsbuild.test.ts @@ -418,6 +418,13 @@ describe('Config - toRsBuildConfig', () => { }) describe('Performance', () => { + test('transform performance.profile', () => { + const rsbuildConfig = toRsbuildConfig({ + performance: { profile: true }, + }) + expect(rsbuildConfig.performance?.profile).toBe(true) + }) + test('transform performance.removeConsole true', () => { const rsbuildConfig = toRsbuildConfig({ performance: { removeConsole: true }, diff --git a/packages/rspeedy/core/test/config/tools/tools.test-d.ts b/packages/rspeedy/core/test/config/tools/tools.test-d.ts index 3f94af0835..36d61d7472 100644 --- a/packages/rspeedy/core/test/config/tools/tools.test-d.ts +++ b/packages/rspeedy/core/test/config/tools/tools.test-d.ts @@ -160,6 +160,28 @@ describe('Config - Tools', () => { }) }) + test('tools.rsdoctor', () => { + assertType({ + rsdoctor: {}, + }) + + assertType({ + rsdoctor: { + experiments: { + enableNativePlugin: true, + }, + }, + }) + + assertType({ + rsdoctor: { + experiments: { + enableNativePlugin: false, + }, + }, + }) + }) + test('tools.rspack', () => { // Object assertType({ diff --git a/packages/rspeedy/core/test/config/validate.test.ts b/packages/rspeedy/core/test/config/validate.test.ts index c222bb1b03..af0d5918a0 100644 --- a/packages/rspeedy/core/test/config/validate.test.ts +++ b/packages/rspeedy/core/test/config/validate.test.ts @@ -1284,6 +1284,8 @@ describe('Config Validation', () => { }, }, }, + { profile: true }, + { profile: false }, { removeConsole: true, }, @@ -1487,6 +1489,21 @@ describe('Config Validation', () => { ] `) + expect(() => + validate({ + performance: { + profile: 'ALL', + }, + }) + ).toThrowErrorMatchingInlineSnapshot(` + [Error: Invalid configuration. + + Invalid config on \`$input.performance.profile\`. + - Expect to be (boolean | undefined) + - Got: string + ] + `) + expect(() => validate({ performance: { diff --git a/packages/rspeedy/core/test/plugins/output.plugin.test.ts b/packages/rspeedy/core/test/plugins/output.plugin.test.ts index 39ca93dfb7..b654932295 100644 --- a/packages/rspeedy/core/test/plugins/output.plugin.test.ts +++ b/packages/rspeedy/core/test/plugins/output.plugin.test.ts @@ -698,12 +698,7 @@ describe('Plugins - Output', () => { await rsbuild.unwrapConfig() expect(rsbuild.getRspeedyConfig().output?.filename).toMatchInlineSnapshot( - ` - { - "bundle": "static/bundle/[name].bundle", - "template": "static/bundle/[name].bundle", - } - `, + `"static/bundle/[name].bundle"`, ) }) @@ -758,7 +753,7 @@ describe('Plugins - Output', () => { .toMatchInlineSnapshot(` { "bundle": "[name].bundle", - "template": "[name].bundle", + "template": "[name].template", } `) }) diff --git a/packages/rspeedy/core/test/plugins/rsdoctor.plugin.test.ts b/packages/rspeedy/core/test/plugins/rsdoctor.plugin.test.ts index 5a22a49d51..b84a8fb71c 100644 --- a/packages/rspeedy/core/test/plugins/rsdoctor.plugin.test.ts +++ b/packages/rspeedy/core/test/plugins/rsdoctor.plugin.test.ts @@ -29,6 +29,33 @@ describe('Plugins - Rsdoctor', () => { }) expect(options.supports.banner).toBe(true) + + expect(options.experiments?.enableNativePlugin).toBe(true) + }) + + test('experiments.enableNativePlugin: false', async () => { + vi.stubEnv('RSDOCTOR', 'true') + + const { createStubRspeedy } = await import('../createStubRspeedy.js') + + const rsbuild = await createStubRspeedy({ + tools: { + rsdoctor: { + experiments: { + enableNativePlugin: false, + }, + }, + }, + }) + + const compiler = await rsbuild.createCompiler() + + const { options } = compiler.options.plugins.find( + (plugin) => (typeof plugin === 'object' + && plugin?.['isRsdoctorPlugin'] === true), + ) as RsdoctorRspackPlugin<[]> + + expect(options.experiments?.enableNativePlugin).toBe(false) }) test('linter.rules.ecma-version-check', async () => { diff --git a/packages/rspeedy/core/test/plugins/stats.plugin.test.ts b/packages/rspeedy/core/test/plugins/stats.plugin.test.ts new file mode 100644 index 0000000000..f0abfa8b80 --- /dev/null +++ b/packages/rspeedy/core/test/plugins/stats.plugin.test.ts @@ -0,0 +1,40 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +import { describe, expect, test, vi } from 'vitest' + +import { createStubRspeedy } from '../createStubRspeedy.js' + +describe('stats plugin', () => { + test('no DEBUG', async () => { + vi.stubEnv('DEBUG', '') + const rspeedy = await createStubRspeedy({}) + await rspeedy.unwrapConfig() + + const config = rspeedy.getRsbuildConfig() + + expect(config.performance?.profile).toBe(false) + }) + + test('DEBUG', async () => { + vi.stubEnv('DEBUG', 'rspeedy') + const rspeedy = await createStubRspeedy({}) + await rspeedy.unwrapConfig() + + const config = rspeedy.getRsbuildConfig() + + expect(config.performance?.profile).toBe(true) + }) + + test('override performance.profile', async () => { + vi.stubEnv('DEBUG', 'rspeedy') + const rspeedy = await createStubRspeedy({ + performance: { profile: false }, + }) + await rspeedy.unwrapConfig() + + const config = rspeedy.getRsbuildConfig() + + expect(config.performance?.profile).toBe(true) + }) +}) diff --git a/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/package.json b/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/package.json index 4276f38487..89f1c7a4b0 100644 --- a/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/package.json +++ b/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/package.json @@ -17,7 +17,7 @@ "@lynx-js/rspeedy": "workspace:*", "@testing-library/jest-dom": "^6.6.3", "jsdom": "^26.1.0", - "vitest": "^3.1.2" + "vitest": "^3.1.3" }, "engines": { "node": ">=18" diff --git a/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/package.json b/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/package.json index 674c2276c8..527a0ec26a 100644 --- a/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/package.json +++ b/packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/package.json @@ -20,7 +20,7 @@ "@types/react": "^18.3.20", "jsdom": "^26.1.0", "typescript": "~5.8.3", - "vitest": "^3.1.2" + "vitest": "^3.1.3" }, "engines": { "node": ">=18" diff --git a/packages/rspeedy/plugin-react-alias/src/index.ts b/packages/rspeedy/plugin-react-alias/src/index.ts index 37ff03a4a3..e0ff8285bd 100644 --- a/packages/rspeedy/plugin-react-alias/src/index.ts +++ b/packages/rspeedy/plugin-react-alias/src/index.ts @@ -102,6 +102,7 @@ export function pluginReactAlias(options: Options): RsbuildPlugin { // react-transform may add imports of the following entries // We need to add aliases for that const transformedEntries = [ + 'experimental/lazy/import', 'internal', 'legacy-react-runtime', 'runtime-components', diff --git a/packages/rspeedy/plugin-react-alias/test/index.test.ts b/packages/rspeedy/plugin-react-alias/test/index.test.ts index 5fe3ca2755..18b0d8983a 100644 --- a/packages/rspeedy/plugin-react-alias/test/index.test.ts +++ b/packages/rspeedy/plugin-react-alias/test/index.test.ts @@ -51,6 +51,11 @@ describe('React - alias', () => { expect.stringContaining('/packages/react/runtime/lib/internal.js'), ) + expect(config.resolve.alias).toHaveProperty( + '@lynx-js/react/experimental/lazy/import$', + expect.stringContaining('/packages/react/runtime/lazy/import.js'), + ) + expect(config.resolve.alias).toHaveProperty( 'preact$', expect.stringContaining('/preact/dist/preact.mjs'), diff --git a/packages/tools/vitest-setup/package.json b/packages/tools/vitest-setup/package.json index 02bdcadd50..9d433c7048 100644 --- a/packages/tools/vitest-setup/package.json +++ b/packages/tools/vitest-setup/package.json @@ -18,7 +18,7 @@ "types": "index.ts", "devDependencies": { "path-serializer": "^0.4.0", - "vitest": "^3.1.2", + "vitest": "^3.1.3", "webpack": "^5.99.7" }, "engines": { diff --git a/packages/web-platform/web-rsbuild-plugin/package.json b/packages/web-platform/web-rsbuild-plugin/package.json index a337b1448a..001f9dd74e 100644 --- a/packages/web-platform/web-rsbuild-plugin/package.json +++ b/packages/web-platform/web-rsbuild-plugin/package.json @@ -35,7 +35,7 @@ "@types/loader-utils": "^2.0.6", "@types/webpack": "^5.28.5", "typescript": "^5.8.3", - "vitest": "^3.1.2" + "vitest": "^3.1.3" }, "peerDependencies": { "@lynx-js/web-core": ">0.13.0", diff --git a/packages/webpack/chunk-loading-webpack-plugin/src/ChunkLoadingWebpackPlugin.ts b/packages/webpack/chunk-loading-webpack-plugin/src/ChunkLoadingWebpackPlugin.ts index 9c164e4d2e..ad6723db3e 100644 --- a/packages/webpack/chunk-loading-webpack-plugin/src/ChunkLoadingWebpackPlugin.ts +++ b/packages/webpack/chunk-loading-webpack-plugin/src/ChunkLoadingWebpackPlugin.ts @@ -8,11 +8,13 @@ import { RuntimeGlobals as LynxRuntimeGlobals } from '@lynx-js/webpack-runtime-g import { createChunkLoadingRuntimeModule } from './ChunkLoadingRuntimeModule.js'; import { createCssChunkLoadingRuntimeModule } from './CssChunkLoadingRuntimeModule.js'; +import { StartupChunkDependenciesPlugin } from './StartupChunkDependenciesPlugin.js'; import type { ChunkLoadingWebpackPluginOptions } from './index.js'; export class ChunkLoadingWebpackPluginImpl { name = 'ChunkLoadingWebpackPlugin'; + _asyncChunkLoading = true; static chunkLoadingValue = 'lynx'; @@ -34,6 +36,11 @@ export class ChunkLoadingWebpackPluginImpl { return; } + new StartupChunkDependenciesPlugin({ + chunkLoading: ChunkLoadingWebpackPluginImpl.chunkLoadingValue, + asyncChunkLoading: this._asyncChunkLoading, + }).apply(compiler); + // javascript chunk loading compiler.hooks.thisCompilation.tap(this.name, (compilation) => { const ChunkLoadingRuntimeModule = createChunkLoadingRuntimeModule( diff --git a/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesPlugin.ts b/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesPlugin.ts new file mode 100644 index 0000000000..a639258838 --- /dev/null +++ b/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesPlugin.ts @@ -0,0 +1,76 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +import type { Chunk, Compiler } from 'webpack'; + +import { createStartupChunkDependenciesRuntimeModule } from './StartupChunkDependenciesRuntimeModule.js'; + +/** + * The options for StartupChunkDependenciesPlugin + */ +interface StartupChunkDependenciesPluginOptions { + /** + * Specifies the chunk loading method + * @defaultValue 'lynx' + * @remarks Currently only 'lynx' is supported + */ + chunkLoading: string; + + /** + * Whether to enable async chunk loading + * @defaultValue true + * @remarks Currently only async loading mode is supported + */ + asyncChunkLoading: boolean; +} + +const PLUGIN_NAME = 'StartupChunkDependenciesPlugin'; + +export class StartupChunkDependenciesPlugin { + chunkLoading: string; + asyncChunkLoading: boolean; + + constructor( + public options: StartupChunkDependenciesPluginOptions, + ) { + this.chunkLoading = options.chunkLoading; + this.asyncChunkLoading = typeof options.asyncChunkLoading === 'boolean' + ? options.asyncChunkLoading + : true; + } + + apply(compiler: Compiler): void { + const { RuntimeGlobals } = compiler.webpack; + + const StartupChunkDependenciesRuntimeModule = + createStartupChunkDependenciesRuntimeModule( + compiler.webpack, + ); + + compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => { + const globalChunkLoading = compilation.outputOptions.chunkLoading; + + const isEnabledForChunk = (chunk: Chunk): boolean => { + const options = chunk.getEntryOptions(); + const chunkLoading = options && options.chunkLoading !== undefined + ? options.chunkLoading + : globalChunkLoading; + return chunkLoading === this.chunkLoading; + }; + + compilation.hooks.additionalTreeRuntimeRequirements.tap( + PLUGIN_NAME, + (chunk, set) => { + if (!isEnabledForChunk(chunk)) return; + set.add(RuntimeGlobals.startup); + set.add(RuntimeGlobals.ensureChunk); + set.add(RuntimeGlobals.ensureChunkIncludeEntries); + compilation.addRuntimeModule( + chunk, + new StartupChunkDependenciesRuntimeModule(this.asyncChunkLoading), + ); + }, + ); + }); + } +} diff --git a/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesRuntimeModule.ts b/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesRuntimeModule.ts new file mode 100644 index 0000000000..2ef59b082b --- /dev/null +++ b/packages/webpack/chunk-loading-webpack-plugin/src/StartupChunkDependenciesRuntimeModule.ts @@ -0,0 +1,78 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. + +import type { RuntimeModule } from 'webpack'; + +type StartupChunkDependenciesRuntimeModule = new( + asyncChunkLoading: boolean, +) => RuntimeModule; + +const runtimeTemplateBasicFunction = (args: string, body: string[]) => { + return `(${args}) => {\n${body.join('\n')}\n}`; +}; + +export function createStartupChunkDependenciesRuntimeModule( + webpack: typeof import('webpack'), +): StartupChunkDependenciesRuntimeModule { + const { RuntimeGlobals, RuntimeModule, Template } = webpack; + return class ChunkLoadingRuntimeModule extends RuntimeModule { + asyncChunkLoading: boolean; + + constructor(asyncChunkLoading: boolean) { + super('Lynx startup chunk dependencies', RuntimeModule.STAGE_ATTACH); + this.asyncChunkLoading = asyncChunkLoading; + } + + override generate(): string { + const chunkGraph = this.chunkGraph!; + const chunk = this.chunk!; + const chunkIds = Array.from( + chunkGraph.getChunkEntryDependentChunksIterable(chunk), + ).map(chunk => chunk.id); + let startupCode: string[]; + + if (this.asyncChunkLoading === false) { + startupCode = chunkIds + .map(id => `${RuntimeGlobals.ensureChunk}(${JSON.stringify(id)});`) + .concat('return next();'); + // lazy bundle can't exports Promise + // TODO: handle Promise in lazy bundle exports to support chunk splitting + } else if (chunkIds.length === 0) { + startupCode = ['return next();']; + } else if (chunkIds.length === 1) { + startupCode = [ + `return ${RuntimeGlobals.ensureChunk}(${ + JSON.stringify(chunkIds[0]) + }).then(next);`, + ]; + } else if (chunkIds.length > 2) { + startupCode = [ + `return Promise.all(${ + JSON.stringify(chunkIds) + }.map(${RuntimeGlobals.ensureChunk}, ${RuntimeGlobals.require})).then(next);`, + ]; + } else { + startupCode = [ + 'return Promise.all([', + Template.indent( + chunkIds.map(id => + `${RuntimeGlobals.ensureChunk}(${JSON.stringify(id)})` + ).join(',\n'), + ), + ']).then(next);', + ]; + } + + return Template.asString([ + `var next = ${RuntimeGlobals.startup};`, + `${RuntimeGlobals.startup} = ${ + runtimeTemplateBasicFunction( + '', + startupCode, + ) + };`, + ]); + } + }; +} diff --git a/packages/webpack/chunk-loading-webpack-plugin/test/cases/chunk-loading/development/index.js b/packages/webpack/chunk-loading-webpack-plugin/test/cases/chunk-loading/development/index.js index 32cf30d826..dba0995121 100644 --- a/packages/webpack/chunk-loading-webpack-plugin/test/cases/chunk-loading/development/index.js +++ b/packages/webpack/chunk-loading-webpack-plugin/test/cases/chunk-loading/development/index.js @@ -36,3 +36,17 @@ it('should work with chunk loading require', async function() { expect(lynx.requireModuleAsync).toBeCalled(); }); }); + +it('should contain startup chunk dependencies code', async () => { + const bundlePath = path.join( + __dirname, + 'rspack.bundle.js', + ); + const content = await fs.promises.readFile(bundlePath, 'utf-8'); + // why appears twice: + // 1. Injected by StartupChunkDependenciesPlugin + // 2. Existing in test case's own bundle + expect((content.match(/Lynx startup chunk dependencies/g) || []).length).toBe( + 2, + ); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e43eede091..e5f1457482 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,11 +53,11 @@ importers: specifier: ^1.9.4 version: 1.9.4 '@changesets/cli': - specifier: ^2.29.2 - version: 2.29.2 + specifier: ^2.29.3 + version: 2.29.3 '@codspeed/vitest-plugin': specifier: ^4.0.1 - version: 4.0.1(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))(vitest@3.1.2) + version: 4.0.1(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))(vitest@3.1.3) '@eslint/js': specifier: ^9.25.1 version: 9.25.1 @@ -83,14 +83,14 @@ importers: specifier: ^22.15.3 version: 22.15.3 '@vitest/coverage-v8': - specifier: ^3.1.2 - version: 3.1.2(vitest@3.1.2) + specifier: ^3.1.3 + version: 3.1.3(vitest@3.1.3) '@vitest/eslint-plugin': specifier: ^1.1.44 - version: 1.1.44(@typescript-eslint/utils@8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2) + version: 1.1.44(@typescript-eslint/utils@8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.3) '@vitest/ui': - specifier: ^3.1.2 - version: 3.1.2(vitest@3.1.2) + specifier: ^3.1.3 + version: 3.1.3(vitest@3.1.3) cspell: specifier: ^8.19.3 version: 8.19.3 @@ -131,8 +131,8 @@ importers: specifier: ^15.5.1 version: 15.5.1 sort-package-json: - specifier: ^3.1.0 - version: 3.1.0 + specifier: ^3.2.0 + version: 3.2.0 ts-patch: specifier: ^3.3.0 version: 3.3.0 @@ -146,8 +146,8 @@ importers: specifier: ^8.31.1 version: 8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) vitest: - specifier: ^3.1.2 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) .github/actions/eco-ci: dependencies: @@ -223,11 +223,11 @@ importers: specifier: 4.4.1 version: 4.4.1(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6)) '@vitest/coverage-v8': - specifier: ^3.1.2 - version: 3.1.2(vitest@3.1.2) + specifier: ^3.1.3 + version: 3.1.3(vitest@3.1.3) '@vitest/ui': - specifier: ^3.1.2 - version: 3.1.2(vitest@3.1.2) + specifier: ^3.1.3 + version: 3.1.3(vitest@3.1.3) esbuild: specifier: ^0.25.3 version: 0.25.3 @@ -235,8 +235,8 @@ importers: specifier: ^29.7.0 version: 29.7.0 vitest: - specifier: ^3.1.2 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) packages/react/testing-library: devDependencies: @@ -356,8 +356,8 @@ importers: specifier: 2.0.1 version: 2.0.1(typescript@5.8.3)(typia@9.1.1(@samchon/openapi@4.1.0)(typescript@5.8.3)) vitest: - specifier: ^3.1.2 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) webpack: specifier: ^5.99.7 version: 5.99.7 @@ -620,8 +620,8 @@ importers: specifier: ^0.4.0 version: 0.4.0 vitest: - specifier: ^3.1.2 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) webpack: specifier: ^5.99.7 version: 5.99.7 @@ -752,8 +752,8 @@ importers: specifier: ^5.8.3 version: 5.8.3 vitest: - specifier: ^3.1.2 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + specifier: ^3.1.3 + version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) packages/web-platform/web-style-transformer: {} @@ -1501,14 +1501,14 @@ packages: '@changesets/apply-release-plan@7.0.12': resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} - '@changesets/assemble-release-plan@6.0.6': - resolution: {integrity: sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==} + '@changesets/assemble-release-plan@6.0.7': + resolution: {integrity: sha512-vS5J92Rm7ZUcrvtu6WvggGWIdohv8s1/3ypRYQX8FsPO+KPDx6JaNC3YwSfh2umY/faGGfNnq42A7PRT0aZPFw==} '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/cli@2.29.2': - resolution: {integrity: sha512-vwDemKjGYMOc0l6WUUTGqyAWH3AmueeyoJa1KmFRtCYiCoY5K3B68ErYpDB6H48T4lLI4czum4IEjh6ildxUeg==} + '@changesets/cli@2.29.3': + resolution: {integrity: sha512-TNhKr6Loc7I0CSD9LpAyVNSxWBHElXVmmvQYIZQvaMan5jddmL7geo3+08Wi7ImgHFVNB0Nhju/LzXqlrkoOxg==} hasBin: true '@changesets/config@3.1.1': @@ -1523,8 +1523,8 @@ packages: '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.10': - resolution: {integrity: sha512-CCJ/f3edYaA3MqoEnWvGGuZm0uMEMzNJ97z9hdUR34AOvajSwySwsIzC/bBu3+kuGDsB+cny4FljG8UBWAa7jg==} + '@changesets/get-release-plan@4.0.11': + resolution: {integrity: sha512-4DZpsewsc/1m5TArVg5h1c0U94am+cJBnu3izAM3yYIZr8+zZwa3AXYdEyCNURzjx0wWr80u/TWoxshbwdZXOA==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -3492,11 +3492,11 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 - '@vitest/coverage-v8@3.1.2': - resolution: {integrity: sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==} + '@vitest/coverage-v8@3.1.3': + resolution: {integrity: sha512-cj76U5gXCl3g88KSnf80kof6+6w+K4BjOflCl7t6yRJPDuCrHtVu0SgNYOUARJOL5TI8RScDbm5x4s1/P9bvpw==} peerDependencies: - '@vitest/browser': 3.1.2 - vitest: 3.1.2 + '@vitest/browser': 3.1.3 + vitest: 3.1.3 peerDependenciesMeta: '@vitest/browser': optional: true @@ -3514,11 +3514,11 @@ packages: vitest: optional: true - '@vitest/expect@3.1.2': - resolution: {integrity: sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==} + '@vitest/expect@3.1.3': + resolution: {integrity: sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==} - '@vitest/mocker@3.1.2': - resolution: {integrity: sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==} + '@vitest/mocker@3.1.3': + resolution: {integrity: sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 @@ -3528,25 +3528,25 @@ packages: vite: optional: true - '@vitest/pretty-format@3.1.2': - resolution: {integrity: sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==} + '@vitest/pretty-format@3.1.3': + resolution: {integrity: sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==} - '@vitest/runner@3.1.2': - resolution: {integrity: sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==} + '@vitest/runner@3.1.3': + resolution: {integrity: sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==} - '@vitest/snapshot@3.1.2': - resolution: {integrity: sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==} + '@vitest/snapshot@3.1.3': + resolution: {integrity: sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==} - '@vitest/spy@3.1.2': - resolution: {integrity: sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==} + '@vitest/spy@3.1.3': + resolution: {integrity: sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==} - '@vitest/ui@3.1.2': - resolution: {integrity: sha512-+YPgKiLpFEyBVJNHDkRcSDcLrrnr20lyU4HQoI9Jtq1MdvoX8usql9h38mQw82MBU1Zo5BPC6sw+sXZ6NS18CQ==} + '@vitest/ui@3.1.3': + resolution: {integrity: sha512-IipSzX+8DptUdXN/GWq3hq5z18MwnpphYdOMm0WndkRGYELzfq7NDP8dMpZT7JGW1uXFrIGxOW2D0Xi++ulByg==} peerDependencies: - vitest: 3.1.2 + vitest: 3.1.3 - '@vitest/utils@3.1.2': - resolution: {integrity: sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==} + '@vitest/utils@3.1.3': + resolution: {integrity: sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==} '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -4661,8 +4661,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} @@ -7658,8 +7658,8 @@ packages: sort-object-keys@1.1.3: resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - sort-package-json@3.1.0: - resolution: {integrity: sha512-PxeCIzE+s88Qj6IXkn1SX9aPJSNkLP7epn6xj0J3Pq12SIM5+XMSaC7iLrszTDYaNfxdqZvI1z6W6LHyd1G4Hw==} + sort-package-json@3.2.0: + resolution: {integrity: sha512-jadbj4vvIlevL578X5+1qVX/Nn9Jk7/U+cLVjR1IqfDFo3ISY0eoyksd3ylyTwGunlEMUgbTRYowLr0CkSxcQw==} hasBin: true source-map-js@1.2.1: @@ -8268,8 +8268,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-node@3.1.2: - resolution: {integrity: sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==} + vite-node@3.1.3: + resolution: {integrity: sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -8304,16 +8304,16 @@ packages: terser: optional: true - vitest@3.1.2: - resolution: {integrity: sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==} + vitest@3.1.3: + resolution: {integrity: sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.1.2 - '@vitest/ui': 3.1.2 + '@vitest/browser': 3.1.3 + '@vitest/ui': 3.1.3 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -8943,7 +8943,7 @@ snapshots: resolve-from: 5.0.0 semver: 7.7.1 - '@changesets/assemble-release-plan@6.0.6': + '@changesets/assemble-release-plan@6.0.7': dependencies: '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 @@ -8956,15 +8956,15 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.29.2': + '@changesets/cli@2.29.3': dependencies: '@changesets/apply-release-plan': 7.0.12 - '@changesets/assemble-release-plan': 6.0.6 + '@changesets/assemble-release-plan': 6.0.7 '@changesets/changelog-git': 0.2.1 '@changesets/config': 3.1.1 '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 - '@changesets/get-release-plan': 4.0.10 + '@changesets/get-release-plan': 4.0.11 '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 '@changesets/pre': 2.0.2 @@ -9015,9 +9015,9 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.10': + '@changesets/get-release-plan@4.0.11': dependencies: - '@changesets/assemble-release-plan': 6.0.6 + '@changesets/assemble-release-plan': 6.0.7 '@changesets/config': 3.1.1 '@changesets/pre': 2.0.2 '@changesets/read': 0.6.5 @@ -9111,11 +9111,11 @@ snapshots: transitivePeerDependencies: - debug - '@codspeed/vitest-plugin@4.0.1(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))(vitest@3.1.2)': + '@codspeed/vitest-plugin@4.0.1(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))(vitest@3.1.3)': dependencies: '@codspeed/core': 4.0.1 vite: 5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) - vitest: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) transitivePeerDependencies: - debug @@ -11206,7 +11206,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@3.1.2(vitest@3.1.2)': + '@vitest/coverage-v8@3.1.3(vitest@3.1.3)': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -11220,66 +11220,66 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.1.44(@typescript-eslint/utils@8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2)': + '@vitest/eslint-plugin@1.1.44(@typescript-eslint/utils@8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.3)': dependencies: '@typescript-eslint/utils': 8.31.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) eslint: 9.25.1(jiti@2.4.2) optionalDependencies: typescript: 5.8.3 - vitest: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) - '@vitest/expect@3.1.2': + '@vitest/expect@3.1.3': dependencies: - '@vitest/spy': 3.1.2 - '@vitest/utils': 3.1.2 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.2(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))': + '@vitest/mocker@3.1.3(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6))': dependencies: - '@vitest/spy': 3.1.2 + '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: vite: 5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) - '@vitest/pretty-format@3.1.2': + '@vitest/pretty-format@3.1.3': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.1.2': + '@vitest/runner@3.1.3': dependencies: - '@vitest/utils': 3.1.2 + '@vitest/utils': 3.1.3 pathe: 2.0.3 - '@vitest/snapshot@3.1.2': + '@vitest/snapshot@3.1.3': dependencies: - '@vitest/pretty-format': 3.1.2 + '@vitest/pretty-format': 3.1.3 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.1.2': + '@vitest/spy@3.1.3': dependencies: tinyspy: 3.0.2 - '@vitest/ui@3.1.2(vitest@3.1.2)': + '@vitest/ui@3.1.3(vitest@3.1.3)': dependencies: - '@vitest/utils': 3.1.2 + '@vitest/utils': 3.1.3 fflate: 0.8.2 flatted: 3.3.3 pathe: 2.0.3 sirv: 3.0.1 tinyglobby: 0.2.13 tinyrainbow: 2.0.0 - vitest: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6) - '@vitest/utils@3.1.2': + '@vitest/utils@3.1.3': dependencies: - '@vitest/pretty-format': 3.1.2 + '@vitest/pretty-format': 3.1.3 loupe: 3.1.3 tinyrainbow: 2.0.0 @@ -12526,7 +12526,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@1.6.0: {} + es-module-lexer@1.7.0: {} es-object-atoms@1.0.0: dependencies: @@ -16108,7 +16108,7 @@ snapshots: sort-object-keys@1.1.3: {} - sort-package-json@3.1.0: + sort-package-json@3.2.0: dependencies: detect-indent: 7.0.1 detect-newline: 4.0.1 @@ -16804,11 +16804,11 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@3.1.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6): + vite-node@3.1.3(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6): dependencies: cac: 6.7.14 debug: 4.4.0 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) transitivePeerDependencies: @@ -16833,15 +16833,15 @@ snapshots: sass-embedded: 1.86.0 terser: 5.31.6 - vitest@3.1.2(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6): + vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.3)(jsdom@26.1.0)(sass-embedded@1.86.0)(terser@5.31.6): dependencies: - '@vitest/expect': 3.1.2 - '@vitest/mocker': 3.1.2(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6)) - '@vitest/pretty-format': 3.1.2 - '@vitest/runner': 3.1.2 - '@vitest/snapshot': 3.1.2 - '@vitest/spy': 3.1.2 - '@vitest/utils': 3.1.2 + '@vitest/expect': 3.1.3 + '@vitest/mocker': 3.1.3(vite@5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6)) + '@vitest/pretty-format': 3.1.3 + '@vitest/runner': 3.1.3 + '@vitest/snapshot': 3.1.3 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 chai: 5.2.0 debug: 4.4.0 expect-type: 1.2.1 @@ -16854,12 +16854,12 @@ snapshots: tinypool: 1.0.2 tinyrainbow: 2.0.0 vite: 5.4.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) - vite-node: 3.1.2(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) + vite-node: 3.1.3(@types/node@22.15.3)(sass-embedded@1.86.0)(terser@5.31.6) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 22.15.3 - '@vitest/ui': 3.1.2(vitest@3.1.2) + '@vitest/ui': 3.1.3(vitest@3.1.3) jsdom: 26.1.0 transitivePeerDependencies: - less @@ -16990,7 +16990,7 @@ snapshots: browserslist: 4.24.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.1 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -17021,7 +17021,7 @@ snapshots: browserslist: 4.24.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.1 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -17052,7 +17052,7 @@ snapshots: browserslist: 4.24.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.1 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1