diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs index 75199a68b0c..390e734c0de 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs @@ -20,12 +20,13 @@ use crate::visitors::{extract_require_call_info, is_require_call_start}; fn create_commonjs_require_context_dependency( parser: &mut JavascriptParser, param: &BasicEvaluatedExpression, + expr: &Expr, callee_start: u32, callee_end: u32, args_end: u32, span: Option, ) -> CommonJsRequireContextDependency { - let result = create_context_dependency(param, parser); + let result = create_context_dependency(param, expr, parser); let options = ContextOptions { mode: ContextMode::Sync, recursive: true, @@ -137,14 +138,13 @@ impl CommonJsImportsParserPlugin { let dep = create_commonjs_require_context_dependency( parser, param, + argument_expr, call_expr.callee.span().real_lo(), call_expr.callee.span().real_hi(), call_expr.span.real_hi(), Some(call_expr.span.into()), ); parser.dependencies.push(Box::new(dep)); - // FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper` - parser.walk_expression(argument_expr); Some(true) } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs index c0887b84ffb..fce8c2d1e85 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs @@ -113,7 +113,7 @@ impl JavascriptParserPlugin for ImportParserPlugin { query, fragment, replaces, - } = create_context_dependency(¶m, parser); + } = create_context_dependency(¶m, &dyn_imported.expr, parser); parser .dependencies .push(Box::new(ImportContextDependency::new( @@ -146,8 +146,6 @@ impl JavascriptParserPlugin for ImportParserPlugin { Some(node.span.into()), parser.in_try, ))); - // FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper` - parser.walk_expression(&dyn_imported.expr); Some(true) } } diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/context_dependency_helper.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/context_dependency_helper.rs index ab1d90d5aeb..78cbab833f2 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/context_dependency_helper.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/context_dependency_helper.rs @@ -1,9 +1,15 @@ use std::borrow::Cow; +use itertools::Either; use itertools::Itertools; use rspack_core::parse_resource; +use rspack_core::SpanExt; use rspack_error::Severity; use rspack_util::json_stringify; +use swc_core::common::Spanned; +use swc_core::ecma::ast::Expr; +use swc_core::ecma::visit::Visit; +use swc_core::ecma::visit::VisitWith; use super::context_helper::{quote_meta, split_context_from_prefix}; use super::{create_traceable_error, ContextModuleScanResult}; @@ -14,6 +20,7 @@ const DEFAULT_WRAPPED_CONTEXT_REGEXP: &str = ".*"; pub fn create_context_dependency( param: &BasicEvaluatedExpression, + expr: &Expr, parser: &mut crate::visitors::JavascriptParser, ) -> ContextModuleScanResult { if param.is_template_string() { @@ -51,34 +58,49 @@ pub fn create_context_dependency( ); let mut replaces = Vec::new(); - let parts = param.parts(); - for (i, part) in parts.iter().enumerate() { - if i % 2 == 0 { - if i == 0 { - let value = format!( - "{}{prefix}", - match param.template_string_kind() { - TemplateStringKind::Cooked => "`", - TemplateStringKind::Raw => "String.raw`", - } - ); - replaces.push((value, param.range().0, part.range().1)); - } else if i == parts.len() - 1 { - let value = format!("{postfix}`"); - replaces.push((value, part.range().0, param.range().1)); - } else { - let value = match param.template_string_kind() { - TemplateStringKind::Cooked => { - json_stringify(part.string()).trim_matches('"').to_owned() - } - TemplateStringKind::Raw => part.string().to_owned(), - }; - let range = part.range(); - replaces.push((value, range.0, range.1)); - } + let (even_parts, odd_parts): (Vec<_>, Vec<_>) = + param + .parts() + .iter() + .enumerate() + .partition_map(|(index, part)| { + if index % 2 == 0 { + Either::Left(part) + } else { + Either::Right(part) + } + }); + let last_index = even_parts.len() - 1; + + for (i, part) in even_parts.into_iter().enumerate() { + if i == 0 { + let value = format!( + "{}{prefix}", + match param.template_string_kind() { + TemplateStringKind::Cooked => "`", + TemplateStringKind::Raw => "String.raw`", + } + ); + replaces.push((value, param.range().0, part.range().1)); + } else if i == last_index { + let value = format!("{postfix}`"); + replaces.push((value, part.range().0, param.range().1)); + } else { + let value = match param.template_string_kind() { + TemplateStringKind::Cooked => json_stringify(part.string()).trim_matches('"').to_owned(), + TemplateStringKind::Raw => part.string().to_owned(), + }; + let range = part.range(); + replaces.push((value, range.0, range.1)); } } + let mut walker = BasicEvaluatedExpressionVisitor { + targets: odd_parts, + on_visit: |n| parser.walk_expression(n), + }; + expr.visit_with(&mut walker); + if parser.javascript_options.wrapped_context_critical { let range = param.range(); parser.warning_diagnostics.push(Box::new( @@ -160,6 +182,14 @@ pub fn create_context_dependency( )); } + if let Some(wrapped_inner_expressions) = param.wrapped_inner_expressions() { + let mut walker = BasicEvaluatedExpressionVisitor { + targets: wrapped_inner_expressions.iter().collect_vec(), + on_visit: |n| parser.walk_expression(n), + }; + expr.visit_with(&mut walker); + } + ContextModuleScanResult { context, reg, @@ -167,7 +197,6 @@ pub fn create_context_dependency( fragment, replaces, } - // TODO: handle `param.wrappedInnerExpressions` } else { if parser.javascript_options.expr_context_critical { let range = param.range(); @@ -181,6 +210,7 @@ pub fn create_context_dependency( .with_severity(Severity::Warn), )); } + parser.walk_expression(expr); ContextModuleScanResult { context: String::from("."), reg: String::new(), @@ -190,3 +220,23 @@ pub fn create_context_dependency( } } } + +struct BasicEvaluatedExpressionVisitor<'a, F: FnMut(&Expr)> { + targets: Vec<&'a BasicEvaluatedExpression>, + on_visit: F, +} + +impl<'a, F: FnMut(&Expr)> Visit for BasicEvaluatedExpressionVisitor<'a, F> { + fn visit_expr(&mut self, n: &Expr) { + self.targets.retain(|evaluated_expr| { + let span = n.span(); + let (lo, hi) = evaluated_expr.range(); + if span.real_lo() == lo && span.hi().0 == hi { + (self.on_visit)(n); + return false; + } + true + }); + n.visit_children_with(self); + } +} diff --git a/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/__snapshots__/output.snap.txt index 1b1817fba1d..c8b815a0dfc 100644 --- a/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/__snapshots__/output.snap.txt @@ -71,6 +71,9 @@ __webpack_require__.e(/* import() */ "child_b_js").then(__webpack_require__.bind __webpack_require__("./child lazy recursive ^\\.\\/.*\\.js$")(`./${request}.js`).then(({ a }) => console.log("context_module_tpl", a) ); +__webpack_require__.e(/* import() */ "child_a_js").then(__webpack_require__.bind(__webpack_require__, "./child/a.js")).then(({ a }) => + console.log("context_module_tpl_with_cond", a) +); __webpack_require__("./child lazy recursive ^\\.\\/.*\\.js$")("./" + request + ".js").then(({ a }) => console.log("context_module_bin", a) ); @@ -78,7 +81,6 @@ __webpack_require__("./child lazy recursive ^\\.\\/.*\\.js$")("./".concat(reques console.log("context_module_concat", a) ); - }), },function(__webpack_require__) { diff --git a/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/index.js b/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/index.js index 553b27b29c7..d6e0cdcd5a1 100644 --- a/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/index.js +++ b/packages/rspack-test-tools/tests/builtinCases/rspack/dynamic-import/index.js @@ -4,9 +4,12 @@ import(`./child/b.js`).then(({ b }) => console.log("Template Literal", b)); import(`./child/${request}.js`).then(({ a }) => console.log("context_module_tpl", a) ); +import(`./child/${true ? "a" : "b"}.js`).then(({ a }) => + console.log("context_module_tpl_with_cond", a) +); import("./child/" + request + ".js").then(({ a }) => console.log("context_module_bin", a) ); import("./child/".concat(request, ".js")).then(({ a }) => console.log("context_module_concat", a) -); +); \ No newline at end of file