diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index 7be0092054e..7c99ee74b53 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -73,6 +73,7 @@ impl ContextModuleFactory { let resolve_args = ResolveArgs { context: data.context.clone(), importer: None, + issuer: data.issuer.as_deref(), specifier, dependency_type: dependency.dependency_type(), dependency_category: dependency.category(), diff --git a/crates/rspack_core/src/diagnostics.rs b/crates/rspack_core/src/diagnostics.rs index f8aba0d59c5..9269b08b60a 100644 --- a/crates/rspack_core/src/diagnostics.rs +++ b/crates/rspack_core/src/diagnostics.rs @@ -114,3 +114,62 @@ pub fn map_box_diagnostics_to_module_parse_diagnostics( .map(|e| rspack_error::miette::Error::new(ModuleParseError::new(e, loaders)).into()) .collect() } + +///////////////////// Diagnostic helpers ///////////////////// + +/// Wrap diagnostic with additional help message. +#[derive(Debug, Error)] +#[error("{0}")] +pub struct WithHelp(Box, Option); + +impl WithHelp { + pub fn with_help(mut self, help: impl Into) -> Self { + let mut help = help.into(); + if let Some(prev) = self.0.help().map(|h| h.to_string()) { + help = format!("{prev}\n{help}"); + } + self.1 = Some(help); + self + } +} + +impl From> for WithHelp { + fn from(value: Box) -> Self { + Self(value, None) + } +} + +impl miette::Diagnostic for WithHelp { + fn code<'a>(&'a self) -> Option> { + (*self.0).code() + } + + fn severity(&self) -> Option { + (*self.0).severity() + } + + fn help<'a>(&'a self) -> Option> { + // Use overwritten help message instead. + self.1.as_ref().map(Box::new).map(|h| h as Box) + } + + fn url<'a>(&'a self) -> Option> { + (*self.0).url() + } + + fn source_code(&self) -> Option<&dyn miette::SourceCode> { + (*self.0).source_code() + } + + fn labels(&self) -> Option + '_>> { + (*self.0).labels() + } + + fn related<'a>(&'a self) -> Option + 'a>> { + (*self.0).related() + } + + fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { + (*self.0).diagnostic_source() + } +} diff --git a/crates/rspack_core/src/normal_module_factory.rs b/crates/rspack_core/src/normal_module_factory.rs index 32383c8a110..6b1616f016d 100644 --- a/crates/rspack_core/src/normal_module_factory.rs +++ b/crates/rspack_core/src/normal_module_factory.rs @@ -278,6 +278,7 @@ impl NormalModuleFactory { let resolve_args = ResolveArgs { importer, + issuer: data.issuer.as_deref(), context: if context_scheme != Scheme::None { self.options.context.clone() } else { @@ -337,58 +338,6 @@ impl NormalModuleFactory { Err(err) => { data.add_file_dependencies(file_dependencies); data.add_missing_dependencies(missing_dependencies); - // let mut file_dependencies = Default::default(); - // let mut missing_dependencies = Default::default(); - // let mut from_cache_result = from_cache; - // if !data - // .resolve_options - // .as_ref() - // .and_then(|x| x.fully_specified) - // .unwrap_or(false) - // { - // let new_args = ResolveArgs { - // importer, - // context: if context_scheme != Scheme::None { - // self.options.context.clone() - // } else { - // data.context.clone() - // }, - // specifier: request_without_match_resource, - // dependency_type: dependency.dependency_type(), - // dependency_category: dependency.category(), - // resolve_options: data.resolve_options.take(), - // span: dependency.span(), - // resolve_to_context: false, - // optional, - // missing_dependencies: &mut missing_dependencies, - // file_dependencies: &mut file_dependencies, - // }; - // let (resource_data, from_cache) = match self - // .cache - // .resolve_module_occasion - // .use_cache(new_args, |args| resolve(args, plugin_driver)) - // .await - // { - // Ok(result) => result, - // Err(err) => (Err(err), false), - // }; - // from_cache_result = from_cache; - // if let Ok(ResolveResult::Resource(resource)) = resource_data { - // // TODO: Here windows resolver will return normalized path. - // // eg. D:\a\rspack\rspack\packages\rspack\tests\fixtures\errors\resolve-fail-esm\answer.js - // if let Some(_extension) = resource.path.extension() { - // // let resource = format!( - // // "{request_without_match_resource}.{}", - // // extension.to_string_lossy() - // // ); - // // diagnostics[0].add_notes(vec![format!("Did you mean '{resource}'? - // // BREAKING CHANGE: The request '{request_without_match_resource}' failed to resolve only because it was resolved as fully specified - // // (probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\"type\": \"module\"'). - // // The extension in the request is mandatory for it to be fully specified. - // // Add the extension to the request.")]); - // } - // } - // } return Err(err); } } diff --git a/crates/rspack_core/src/options/resolve/mod.rs b/crates/rspack_core/src/options/resolve/mod.rs index ad927122a97..bbde27fdc6f 100644 --- a/crates/rspack_core/src/options/resolve/mod.rs +++ b/crates/rspack_core/src/options/resolve/mod.rs @@ -122,6 +122,21 @@ impl From for oxc_resolver::TsconfigReferences { } } +macro_rules! impl_resolve_by_dependency { + ($ident:ident) => { + pub fn $ident(&self, cat: Option<&DependencyCategory>) -> Option { + cat + .and_then(|cat| { + self + .by_dependency + .as_ref() + .and_then(|by_dep| by_dep.get(cat).and_then(|d| d.$ident)) + }) + .or(self.$ident) + } + }; +} + impl Resolve { pub fn merge_by_dependency(mut self, dependency_type: DependencyCategory) -> Self { let Some(mut by_dependency) = self.by_dependency.as_mut().map(std::mem::take) else { @@ -139,6 +154,9 @@ impl Resolve { pub fn merge(self, value: Self) -> Self { clever_merge::merge_resolve(self, value) } + + impl_resolve_by_dependency!(fully_specified); + impl_resolve_by_dependency!(prefer_relative); } type DependencyCategoryStr = Cow<'static, str>; diff --git a/crates/rspack_core/src/plugin/args.rs b/crates/rspack_core/src/plugin/args.rs index 04bc7492ecd..6e87982bdb5 100644 --- a/crates/rspack_core/src/plugin/args.rs +++ b/crates/rspack_core/src/plugin/args.rs @@ -101,6 +101,7 @@ pub struct NormalModuleAfterResolveArgs<'a> { #[derive(Debug)] pub struct ResolveArgs<'a> { pub importer: Option<&'a ModuleIdentifier>, + pub issuer: Option<&'a str>, pub context: Context, pub specifier: &'a str, pub dependency_type: &'a DependencyType, diff --git a/crates/rspack_core/src/resolver/mod.rs b/crates/rspack_core/src/resolver/mod.rs index 3609ceb3864..94b2212bc42 100644 --- a/crates/rspack_core/src/resolver/mod.rs +++ b/crates/rspack_core/src/resolver/mod.rs @@ -3,13 +3,26 @@ mod resolver_impl; use std::{fmt, path::PathBuf}; -use rspack_error::Error; +use once_cell::sync::Lazy; +use regex::Regex; +use rspack_error::{DiagnosticExt, Error}; use rspack_loader_runner::DescriptionData; +use sugar_path::{AsPath, SugarPath}; pub use self::factory::{ResolveOptionsWithDependencyType, ResolverFactory}; pub use self::resolver_impl::{ResolveInnerOptions, Resolver}; +use crate::diagnostics::WithHelp; use crate::{ResolveArgs, SharedPluginDriver}; +static RELATIVE_PATH_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^\.\.?\/").expect("should init regex")); + +static PARENT_PATH_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^\.\.[\/]").expect("should init regex")); + +static CURRENT_DIR_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^(\.[\/])").expect("should init regex")); + /// A successful path resolution or an ignored path. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ResolveResult { @@ -55,13 +68,112 @@ impl Resource { } } +pub fn resolve_for_error_hints( + args: ResolveArgs<'_>, + plugin_driver: &SharedPluginDriver, +) -> Option { + let dep = ResolveOptionsWithDependencyType { + resolve_options: args.resolve_options.clone(), + resolve_to_context: args.resolve_to_context, + dependency_category: *args.dependency_category, + }; + + let base_dir = args.context.clone(); + let base_dir = base_dir.as_ref(); + + let fully_specified = dep + .resolve_options + .as_ref() + .and_then(|o| o.fully_specified(Some(args.dependency_category))) + .unwrap_or_default(); + + let prefer_relative = dep + .resolve_options + .as_ref() + .and_then(|o| o.prefer_relative(Some(args.dependency_category))) + .unwrap_or_default(); + + // Try to resolve without fully specified + if fully_specified { + let mut dep = dep.clone(); + dep.resolve_options = dep.resolve_options.map(|mut options| { + options.fully_specified = Some(false); + options + }); + let resolver = plugin_driver.resolver_factory.get(dep); + match resolver.resolve(base_dir, args.specifier) { + Ok(ResolveResult::Resource(resource)) => { + let relative_path = resource.path.relative(args.context.as_path()); + let suggestion = if let Some((_, [prefix])) = CURRENT_DIR_REGEX + .captures_iter(args.specifier) + .next() + .map(|c| c.extract()) + { + // If the specifier is a relative path pointing to the current directory, + // we can suggest the path relative to the current directory. + format!("{}{}", prefix, relative_path.to_string_lossy()) + } else if PARENT_PATH_REGEX.is_match(args.specifier) { + // If the specifier is a relative path to which the parent directory is, + // then we return the relative path directly. + relative_path.to_string_lossy().to_string() + } else { + // If the specifier is a package name like or some arbitrary alias, + // then we return the full path. + resource.path.to_string_lossy().to_string() + }; + return Some(format!("Did you mean '{}'? + +The request '{}' failed to resolve only because it was resolved as fully specified, +probably because the origin is strict EcmaScript Module, +e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\"type\": \"module\"'. + +The extension in the request is mandatory for it to be fully specified. +Add the extension to the request.", suggestion, args.specifier)); + } + Err(_) => return None, + _ => {} + } + } + + // Try to resolve with relative path if request is not relative + if !RELATIVE_PATH_REGEX.is_match(args.specifier) && !prefer_relative { + let dep = dep.clone(); + let module_directories = dep + .resolve_options + .as_deref() + .or(Some(&plugin_driver.options.resolve)) + .and_then(|o| o.modules.as_ref().map(|m| m.join(", "))) + .expect("module directories should exist"); + let resolver = plugin_driver.resolver_factory.get(dep); + let request = format!("./{}", args.specifier); + match resolver.resolve(base_dir, &request) { + Ok(ResolveResult::Resource(_)) => { + return Some(format!( + "Did you mean './{}'? + +Requests that should resolve in the current directory need to start with './'. +Requests that start with a name are treated as module requests and resolve within module directories ({module_directories}). + +If changing the source code is not an option, there is also a resolve options called 'preferRelative' +which tries to resolve these kind of requests in the current directory too.", + args.specifier + )); + } + Err(_) => return None, + _ => {} + } + } + + None +} + /// Main entry point for module resolution. pub async fn resolve( - mut args: ResolveArgs<'_>, + args: ResolveArgs<'_>, plugin_driver: &SharedPluginDriver, ) -> Result { let dep = ResolveOptionsWithDependencyType { - resolve_options: args.resolve_options.take(), + resolve_options: args.resolve_options.clone(), resolve_to_context: args.resolve_to_context, dependency_category: *args.dependency_category, }; @@ -71,7 +183,7 @@ pub async fn resolve( let mut context = Default::default(); let resolver = plugin_driver.resolver_factory.get(dep); - let result = resolver + let mut result = resolver .resolve_with_context(base_dir, args.specifier, &mut context) .map_err(|error| error.into_resolve_error(&args)); @@ -80,5 +192,11 @@ pub async fn resolve( .missing_dependencies .extend(context.missing_dependencies); - result + if result.is_err() + && let Some(hint) = resolve_for_error_hints(args, plugin_driver) + { + result = result.map_err(|err| WithHelp::from(err).with_help(hint).boxed()) + }; + + result.map_err(Error::new_boxed) } diff --git a/crates/rspack_core/src/resolver/resolver_impl.rs b/crates/rspack_core/src/resolver/resolver_impl.rs index be4ea44f810..3f7544cb098 100644 --- a/crates/rspack_core/src/resolver/resolver_impl.rs +++ b/crates/rspack_core/src/resolver/resolver_impl.rs @@ -5,7 +5,8 @@ use std::{ }; use rspack_error::{ - error, miette::miette, DiagnosticError, Error, ErrorExt, Severity, TraceableError, + miette::{diagnostic, Diagnostic}, + DiagnosticExt, Severity, TraceableError, }; use rspack_loader_runner::DescriptionData; use rustc_hash::FxHashSet as HashSet; @@ -176,7 +177,7 @@ impl Resolver { } impl ResolveInnerError { - pub fn into_resolve_error(self, args: &ResolveArgs<'_>) -> Error { + pub fn into_resolve_error(self, args: &ResolveArgs<'_>) -> Box { match self { Self::OxcResolver(error) => map_oxc_resolver_error(error, args), } @@ -283,22 +284,28 @@ fn to_oxc_resolver_options( } } -fn map_oxc_resolver_error(error: oxc_resolver::ResolveError, args: &ResolveArgs<'_>) -> Error { +fn map_oxc_resolver_error( + error: oxc_resolver::ResolveError, + args: &ResolveArgs<'_>, +) -> Box { match error { - oxc_resolver::ResolveError::IOError(error) => DiagnosticError::from(error.boxed()).into(), + oxc_resolver::ResolveError::IOError(error) => diagnostic!("{}", error).boxed(), oxc_resolver::ResolveError::Recursion => map_resolver_error(true, args), oxc_resolver::ResolveError::NotFound(_) => map_resolver_error(false, args), - _ => error!("{}", error), + _ => diagnostic!("{}", error).boxed(), } } -fn map_resolver_error(is_recursion: bool, args: &ResolveArgs<'_>) -> Error { +fn map_resolver_error( + is_recursion: bool, + args: &ResolveArgs<'_>, +) -> Box { let request = &args.specifier; let context = &args.context; let importer = args.importer; if importer.is_none() { - return miette!("Resolve error: Can't resolve '{request}' in '{context}'"); + return diagnostic!("Resolve error: Can't resolve '{request}' in '{context}'").boxed(); } let span = args.span.unwrap_or_default(); @@ -322,5 +329,5 @@ fn map_resolver_error(is_recursion: bool, args: &ResolveArgs<'_>) -> Error { Severity::Error }, ) - .into() + .boxed() } diff --git a/crates/rspack_error/src/diagnostic.rs b/crates/rspack_error/src/diagnostic.rs index ac3277f6ee4..fea190f05cc 100644 --- a/crates/rspack_error/src/diagnostic.rs +++ b/crates/rspack_error/src/diagnostic.rs @@ -91,6 +91,7 @@ impl Diagnostic { impl Diagnostic { pub fn render_report(&self, colored: bool) -> crate::Result { + let mut buf = String::new(); let h = GraphicalReportHandler::new() .with_theme(if colored { GraphicalTheme::unicode() @@ -98,7 +99,6 @@ impl Diagnostic { GraphicalTheme::unicode_nocolor() }) .with_context_lines(2); - let mut buf = String::new(); h.render_report(&mut buf, self.as_ref()).into_diagnostic()?; Ok(buf) } diff --git a/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts b/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts index 1c4be026fdd..d4230789ec0 100644 --- a/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts +++ b/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts @@ -607,9 +607,7 @@ const SIMPLE_PRINTERS: Record< // "error.details": (details, { formatError }) => formatError(details), // "error.stack": stack => stack, // "error.moduleTrace": moduleTrace => undefined, - // "error.separator!": () => "\n", - // Error was already formatted on the native. - // error: error => error, + "error.separator!": () => "\n", "loggingEntry(error).loggingEntry.message": (message, { red }) => mapLines(message, x => ` ${red(x)}`), diff --git a/packages/rspack/tests/Errors.test.ts b/packages/rspack/tests/Errors.test.ts index 7b73930a461..864c9ff84fa 100644 --- a/packages/rspack/tests/Errors.test.ts +++ b/packages/rspack/tests/Errors.test.ts @@ -146,8 +146,8 @@ it("should emit warnings for resolve failure in esm", async () => { Object { "errors": Array [ Object { - "formatted": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n", - "message": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n", + "formatted": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n help: Did you mean './answer.js'?\\n \\n The request './answer' failed to resolve only because it was resolved as fully specified,\\n probably because the origin is strict EcmaScript Module,\\n e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\\"type\\": \\"module\\"'.\\n \\n The extension in the request is mandatory for it to be fully specified.\\n Add the extension to the request.\\n", + "message": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n help: Did you mean './answer.js'?\\n \\n The request './answer' failed to resolve only because it was resolved as fully specified,\\n probably because the origin is strict EcmaScript Module,\\n e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\\"type\\": \\"module\\"'.\\n \\n The extension in the request is mandatory for it to be fully specified.\\n Add the extension to the request.\\n", "moduleId": "./resolve-fail-esm/index.js", "moduleIdentifier": "javascript/esm|/tests/fixtures/errors/resolve-fail-esm/index.js", "moduleName": "./resolve-fail-esm/index.js", diff --git a/packages/rspack/tests/Stats.test.ts b/packages/rspack/tests/Stats.test.ts index 35bccd1429e..b6eca134cc4 100644 --- a/packages/rspack/tests/Stats.test.ts +++ b/packages/rspack/tests/Stats.test.ts @@ -66,7 +66,8 @@ describe("Stats", () => { ./fixtures/c.js ./fixtures/abc.js - ERROR in ./fixtures/b.js ModuleParseError + ERROR in ./fixtures/b.js + ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Return statement is not allowed here diff --git a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap index 6386d37a7e9..6901edd57d9 100644 --- a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap +++ b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap @@ -1171,7 +1171,8 @@ exports[`StatsTestCases should print correct stats for identifier-let-strict-mod `; exports[`StatsTestCases should print correct stats for identifier-let-strict-mode 2`] = ` -"ERROR in ./index.js ModuleParseError +"ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: \`let\` cannot be used as an identifier in strict mode @@ -1183,7 +1184,8 @@ exports[`StatsTestCases should print correct stats for identifier-let-strict-mod help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: \`let\` cannot be used as an identifier in strict mode @@ -4212,7 +4214,8 @@ exports[`StatsTestCases should print correct stats for loader-builtin-swc-plugin `; exports[`StatsTestCases should print correct stats for loader-builtin-swc-plugin-warn 2`] = ` -"WARNING in ./index.js builtin:swc-loader +"WARNING in ./index.js +builtin:swc-loader ⚠ Experimental plugins are not currently supported. @@ -4389,7 +4392,8 @@ exports[`StatsTestCases should print correct stats for normal-errors 1`] = ` `; exports[`StatsTestCases should print correct stats for normal-errors 2`] = ` -"ERROR in ./index.js × Resolve error: Can't resolve 'not-exist' in '/tests/statsCases/normal-errors' +"ERROR in ./index.js + × Resolve error: Can't resolve 'not-exist' in '/tests/statsCases/normal-errors' ╭──── 1 │ import "not-exist"; · ─────────── @@ -5013,7 +5017,8 @@ exports[`StatsTestCases should print correct stats for parse-error 1`] = ` `; exports[`StatsTestCases should print correct stats for parse-error 2`] = ` -"ERROR in ./b.js ModuleParseError +"ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ';', '}' or @@ -5065,7 +5070,8 @@ exports[`StatsTestCases should print correct stats for parse-error-builtin-swc-l `; exports[`StatsTestCases should print correct stats for parse-error-builtin-swc-loader 2`] = ` -"ERROR in ./index.ts × x Expected '{', got 'error' +"ERROR in ./index.ts + × x Expected '{', got 'error' │ ,-[/tests/statsCases/parse-error-builtin-swc-loader/index.ts:1:1] │ 1 | export error; │ : ^^^^^ @@ -5341,7 +5347,8 @@ chunk {909} bundle.js (main) [entry] webpack/runtime/make_namespace_object {909} -ERROR in ./index.js × Resolve error: Can't resolve 'cycle-alias/a' in '/tests/statsCases/resolve-overflow' +ERROR in ./index.js + × Resolve error: Can't resolve 'cycle-alias/a' in '/tests/statsCases/resolve-overflow' ╭─[1:1] 1 │ import { a } from "cycle-alias/a"; · ─────────────── @@ -5545,7 +5552,8 @@ chunk {909} bundle.js (main) [entry] webpack/runtime/make_namespace_object {909} -ERROR in ./index.js × Invalid "exports" target "../../index.js" defined for '.' in the package config /tests/statsCases/resolve-unexpected-exports-in-pkg/node_modules/pkg-a/package.json +ERROR in ./index.js + × Invalid "exports" target "../../index.js" defined for '.' in the package config /tests/statsCases/resolve-unexpected-exports-in-pkg/node_modules/pkg-a/package.json Rspack compiled with 1 error (d522bd63336c0fb69e32)" `; @@ -6463,7 +6471,8 @@ exports[`StatsTestCases should print correct stats for try-require--module 1`] = `; exports[`StatsTestCases should print correct stats for try-require--module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require--module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require--module' ╭─[1:1] 1 │ try { 2 │ require('./missing-module'); @@ -6507,7 +6516,8 @@ exports[`StatsTestCases should print correct stats for try-require-resolve-modul `; exports[`StatsTestCases should print correct stats for try-require-resolve-module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-module' ╭─[1:1] 1 │ try { 2 │ require.resolve('./missing-module'); @@ -6551,7 +6561,8 @@ exports[`StatsTestCases should print correct stats for try-require-resolve-weak- `; exports[`StatsTestCases should print correct stats for try-require-resolve-weak-module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-weak-module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-weak-module' ╭─[1:1] 1 │ try { 2 │ require.resolveWeak('./missing-module'); diff --git a/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err index 6462796cf7d..ce8f38d2fe2 100644 --- a/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err @@ -1,4 +1,5 @@ -ERROR in ./logo.svg NapiError +ERROR in ./logo.svg +NapiError × Napi Error: Error: Failed to load │ at Object..module.exports (/tests/diagnostics/factorize/asset-module-build-failed/my-loader.js:2:8) diff --git a/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err b/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err index 5f89a3d05ae..4a8975875a9 100644 --- a/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve-with-loader' +ERROR in ./index.js + × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve-with-loader' ╭─[1:1] 1 │ // THIS SHOULD BE INCLUDED IN THE DIAGNOSTIC 2 │ require("./a"); diff --git a/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err b/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err index da84aaaf5e4..8db176f6886 100644 --- a/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve' +ERROR in ./index.js + × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve' ╭──── 1 │ import "./a"; · ───── diff --git a/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err b/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err index 3d809720fcd..cd243f78629 100644 --- a/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err @@ -1,4 +1,5 @@ -WARNING in ./index.css ModuleParseWarning +WARNING in ./index.css +ModuleParseWarning ⚠ Module parse warning: ╰─▶ ⚠ css: Deprecated '~' diff --git a/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err b/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err index a0d90f344b0..a7a81a509c7 100644 --- a/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './non-exist' in '/tests/diagnostics/factorize/dynamic-import-non-exist-module' +ERROR in ./index.js + × Resolve error: Can't resolve './non-exist' in '/tests/diagnostics/factorize/dynamic-import-non-exist-module' ╭─[2:1] 2 │ let errored = false; 3 │ try { diff --git a/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err b/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err index 21ccc68da9e..e6f4381923f 100644 --- a/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err @@ -1,11 +1,13 @@ -ERROR in ./index.js × Empty dependency: Expected a non-empty request +ERROR in ./index.js + × Empty dependency: Expected a non-empty request ╭─[1:1] 1 │ require(""); · ─────────── 2 │ import ""; ╰──── -ERROR in ./index.js × Empty dependency: Expected a non-empty request +ERROR in ./index.js + × Empty dependency: Expected a non-empty request ╭─[1:1] 1 │ require(""); 2 │ import ""; diff --git a/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err b/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err new file mode 100644 index 00000000000..923a85a4fad --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err @@ -0,0 +1 @@ +ERROR in × Resolve error: Can't resolve './' in '/tests/diagnostics/factorize/experiments-disable-transform-parse-error' diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/foo.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/foo.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js new file mode 100644 index 00000000000..5003c98cd2f --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js @@ -0,0 +1 @@ +import "./foo" diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err new file mode 100644 index 00000000000..1706b778f6a --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err @@ -0,0 +1,14 @@ +ERROR in ./index.js + × Resolve error: Can't resolve './foo' in '/tests/diagnostics/factorize/fully-specified-resolve-suggestions' + ╭──── + 1 │ import "./foo"; + · ─────── + ╰──── + help: Did you mean './foo.js'? + + The request './foo' failed to resolve only because it was resolved as fully specified, + probably because the origin is strict EcmaScript Module, + e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"'. + + The extension in the request is mandatory for it to be fully specified. + Add the extension to the request. diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js new file mode 100644 index 00000000000..e35d3db6c18 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js @@ -0,0 +1,13 @@ +module.exports = { + module: { + rules: [ + { + test: /\.js$/, + resolve: { + fullySpecified: true + }, + type: "javascript/esm" + } + ] + } +} diff --git a/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err index 9ffe2ea480d..dba96be250c 100644 --- a/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err @@ -1,4 +1,5 @@ -ERROR in ./syntax-error.json × Json parsing error: Unexpected character } +ERROR in ./syntax-error.json + × Json parsing error: Unexpected character } ╭─[1:1] 1 │ { 2 │ "a" diff --git a/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err b/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err index 6371e5f42b2..c2c3a5618ea 100644 --- a/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./lib.js NapiError +ERROR in ./lib.js +NapiError × Napi Error: Error: Failed to load │ at Object..module.exports (/tests/diagnostics/factorize/loader-throw-error/my-loader.js:2:9) diff --git a/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err b/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err index 4aa3cd58772..f7e0448390f 100644 --- a/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err @@ -1,4 +1,5 @@ -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Unterminated regexp literal @@ -12,7 +13,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -26,7 +28,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -40,7 +43,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Unterminated regexp literal @@ -54,7 +58,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -68,7 +73,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -82,7 +88,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.ts ModuleParseError +ERROR in ./app.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ',', got ':' @@ -97,4 +104,5 @@ ERROR in ./app.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js × No parser registered for 'ts' +ERROR in ./index.js + × No parser registered for 'ts' diff --git a/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err index efffb8fd925..0d2f3c15b94 100644 Binary files a/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err and b/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err differ diff --git a/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err b/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err index f63b248cb14..c320f14bd90 100644 --- a/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err @@ -1,4 +1,5 @@ -WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/diagnostics/factorize/missing-module' +WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/diagnostics/factorize/missing-module' ╭─[2:1] 2 │ let errored = false; 3 │ try { diff --git a/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err b/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err index 0a5f12360f2..1d96a704762 100644 --- a/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./non-recoverable.js ModuleParseError +ERROR in ./non-recoverable.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ident @@ -10,7 +11,8 @@ ERROR in ./non-recoverable.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./recoverable.js ModuleParseError +ERROR in ./recoverable.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/foo.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/foo.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js new file mode 100644 index 00000000000..46ff4caab26 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js @@ -0,0 +1 @@ +import "foo.js" diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err new file mode 100644 index 00000000000..9295c4ced1c --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err @@ -0,0 +1,13 @@ +ERROR in ./index.js + × Resolve error: Can't resolve 'foo.js' in '/tests/diagnostics/factorize/prefer-relative-resolve-suggestions' + ╭──── + 1 │ import "foo.js"; + · ──────── + ╰──── + help: Did you mean './foo.js'? + + Requests that should resolve in the current directory need to start with './'. + Requests that start with a name are treated as module requests and resolve within module directories (node_modules). + + If changing the source code is not an option, there is also a resolve options called 'preferRelative' + which tries to resolve these kind of requests in the current directory too. diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js new file mode 100644 index 00000000000..cc432c6ebad --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js @@ -0,0 +1,10 @@ +module.exports = { + module: { + rules: [ + { + test: /\.js$/, + type: "javascript/esm" + } + ] + } +} diff --git a/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err b/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err index fa927685d4d..39d59392a23 100644 --- a/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./jsx.jsx ModuleParseError +ERROR in ./jsx.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -10,7 +11,8 @@ ERROR in ./jsx.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./jsx.jsx ModuleParseError +ERROR in ./jsx.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -22,7 +24,8 @@ ERROR in ./jsx.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./ts.ts ModuleParseError +ERROR in ./ts.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -34,7 +37,8 @@ ERROR in ./ts.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./ts.ts ModuleParseError +ERROR in ./ts.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: An arrow function is not allowed here @@ -46,7 +50,8 @@ ERROR in ./ts.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./tsx.tsx ModuleParseError +ERROR in ./tsx.tsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected '(', got '<' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err index fb40c349b59..39108f5db66 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ',', got ':' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err new file mode 100644 index 00000000000..1ef732528ac --- /dev/null +++ b/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err @@ -0,0 +1 @@ +ERROR in × Resolve error: Can't resolve './' in '/tests/diagnostics/module-parse-failed/jsx_syntax_error' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err index 439fe3dd6c0..d0b74333e36 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -12,7 +13,8 @@ ERROR in ./index.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err index 801dff5a9a3..c2f698b3883 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./a.json × Json parsing error: Unexpected character } +ERROR in ./a.json + × Json parsing error: Unexpected character } ╭─[1:1] 1 │ { 2 │ "a" @@ -6,7 +7,8 @@ ERROR in ./a.json × Json parsing error: Unexpected character } · ─ ╰──── -ERROR in ./b.json × Json parsing error: Unexpected end of JSON +ERROR in ./b.json + × Json parsing error: Unexpected end of JSON ╭──── 1 │ "测试utf8/" · ▲ diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err index 5a907147756..9a46656cb21 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./a.js ModuleParseError +ERROR in ./a.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -12,7 +13,8 @@ ERROR in ./a.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./a.js ModuleParseError +ERROR in ./a.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -27,7 +29,8 @@ ERROR in ./a.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./b.js ModuleParseError +ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -41,7 +44,8 @@ ERROR in ./b.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./b.js ModuleParseError +ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -56,7 +60,8 @@ ERROR in ./b.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./c.js ModuleParseError +ERROR in ./c.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -70,7 +75,8 @@ ERROR in ./c.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./c.js ModuleParseError +ERROR in ./c.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -85,7 +91,8 @@ ERROR in ./c.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./d.js ModuleParseError +ERROR in ./d.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -99,7 +106,8 @@ ERROR in ./d.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./d.js ModuleParseError +ERROR in ./d.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -114,7 +122,8 @@ ERROR in ./d.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./e.js ModuleParseError +ERROR in ./e.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -128,7 +137,8 @@ ERROR in ./e.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./e.js ModuleParseError +ERROR in ./e.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -143,7 +153,8 @@ ERROR in ./e.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./f.js ModuleParseError +ERROR in ./f.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -157,7 +168,8 @@ ERROR in ./f.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./f.js ModuleParseError +ERROR in ./f.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -172,7 +184,8 @@ ERROR in ./f.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./g.js ModuleParseError +ERROR in ./g.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -186,7 +199,8 @@ ERROR in ./g.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./g.js ModuleParseError +ERROR in ./g.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon