From 376910763c410f09e5e053deb724c2a11f0eba7b Mon Sep 17 00:00:00 2001 From: Gengkun Date: Thu, 4 Jul 2024 17:33:13 +0800 Subject: [PATCH 1/3] fix: add warning for context module flag g and y (#7044) --- crates/rspack_core/src/context_module.rs | 17 - .../common_js_imports_parse_plugin.rs | 9 +- ...t_meta_context_dependency_parser_plugin.rs | 21 +- .../src/parser_plugin/import_parser_plugin.rs | 9 +- ...equire_context_dependency_parser_plugin.rs | 23 +- .../dependency/context_dependency_helper.rs | 29 +- .../src/visitors/dependency/context_helper.rs | 312 ------------------ .../src/visitors/dependency/mod.rs | 4 +- .../src/visitors/dependency/util.rs | 49 +++ .../cases/context/issue-5750/test.filter.js | 4 - .../cases/parsing/issue-627/test.filter.js | 4 - 11 files changed, 112 insertions(+), 369 deletions(-) delete mode 100644 crates/rspack_plugin_javascript/src/visitors/dependency/context_helper.rs delete mode 100644 tests/webpack-test/cases/context/issue-5750/test.filter.js delete mode 100644 tests/webpack-test/cases/parsing/issue-627/test.filter.js diff --git a/crates/rspack_core/src/context_module.rs b/crates/rspack_core/src/context_module.rs index 5aac13a9e7e..207a0a8c038 100644 --- a/crates/rspack_core/src/context_module.rs +++ b/crates/rspack_core/src/context_module.rs @@ -116,23 +116,6 @@ impl ContextNameSpaceObject { } } -pub fn context_reg_exp(expr: &str, flags: &str) -> Option { - if expr.is_empty() { - return None; - } - let regexp = RspackRegex::with_flags(expr, flags).expect("reg failed"); - clean_regexp_in_context_module(regexp) -} - -pub fn clean_regexp_in_context_module(regexp: RspackRegex) -> Option { - if regexp.sticky() || regexp.global() { - // TODO: warning - None - } else { - Some(regexp) - } -} - #[derive(Debug, Clone, Copy, Hash, PartialEq, PartialOrd, Ord, Eq)] pub enum ContextTypePrefix { Import, 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..3e51a553d95 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 @@ -1,7 +1,5 @@ use itertools::Itertools; -use rspack_core::{ - context_reg_exp, ConstDependency, ContextMode, DependencyCategory, ErrorSpan, SpanExt, -}; +use rspack_core::{ConstDependency, ContextMode, DependencyCategory, ErrorSpan, SpanExt}; use rspack_core::{ContextNameSpaceObject, ContextOptions}; use rspack_error::Severity; use swc_core::common::{Span, Spanned}; @@ -13,7 +11,8 @@ use crate::dependency::{CommonJsFullRequireDependency, CommonJsRequireContextDep use crate::dependency::{CommonJsRequireDependency, RequireResolveDependency}; use crate::utils::eval::{self, BasicEvaluatedExpression}; use crate::visitors::{ - create_context_dependency, create_traceable_error, expr_matcher, expr_name, JavascriptParser, + context_reg_exp, create_context_dependency, create_traceable_error, expr_matcher, expr_name, + JavascriptParser, }; use crate::visitors::{extract_require_call_info, is_require_call_start}; @@ -29,7 +28,7 @@ fn create_commonjs_require_context_dependency( let options = ContextOptions { mode: ContextMode::Sync, recursive: true, - reg_exp: context_reg_exp(&result.reg, ""), + reg_exp: context_reg_exp(&result.reg, "", None, parser), include: None, exclude: None, category: DependencyCategory::CommonJS, diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs index b01d1aaff8e..62b9740479b 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_context_dependency_parser_plugin.rs @@ -1,6 +1,5 @@ use rspack_core::{ - clean_regexp_in_context_module, context_reg_exp, ContextMode, ContextNameSpaceObject, - ContextOptions, DependencyCategory, SpanExt, + ContextMode, ContextNameSpaceObject, ContextOptions, DependencyCategory, SpanExt, }; use rspack_regex::RspackRegex; use swc_core::common::Spanned; @@ -10,11 +9,13 @@ use super::JavascriptParserPlugin; use crate::dependency::ImportMetaContextDependency; use crate::utils::eval::{self, BasicEvaluatedExpression}; use crate::utils::{get_bool_by_obj_prop, get_literal_str_by_obj_prop, get_regex_by_obj_prop}; -use crate::visitors::{expr_name, JavascriptParser}; +use crate::visitors::{ + clean_regexp_in_context_module, context_reg_exp, expr_name, JavascriptParser, +}; fn create_import_meta_context_dependency( node: &CallExpr, - optional: bool, + parser: &mut JavascriptParser, ) -> Option { assert!(node.callee.is_expr()); let dyn_imported = node.args.first()?; @@ -43,7 +44,9 @@ fn create_import_meta_context_dependency( })?; let reg = r"^\.\/.*$"; let context_options = if let Some(obj) = node.args.get(1).and_then(|arg| arg.expr.as_object()) { - let regexp = get_regex_by_obj_prop(obj, "regExp") + let regexp = get_regex_by_obj_prop(obj, "regExp"); + let regexp_span = regexp.map(|r| r.span().into()); + let regexp = regexp .map(|regexp| RspackRegex::try_from(regexp).expect("reg failed")) .unwrap_or(RspackRegex::new(reg).expect("reg failed")); // let include = get_regex_by_obj_prop(obj, "include") @@ -57,7 +60,7 @@ fn create_import_meta_context_dependency( .map(|bool| bool.value) .unwrap_or(true); ContextOptions { - reg_exp: clean_regexp_in_context_module(regexp), + reg_exp: clean_regexp_in_context_module(regexp, regexp_span, parser), include: None, exclude: None, recursive, @@ -77,7 +80,7 @@ fn create_import_meta_context_dependency( mode: ContextMode::Sync, include: None, exclude: None, - reg_exp: context_reg_exp(reg, ""), + reg_exp: context_reg_exp(reg, "", None, parser), category: DependencyCategory::Esm, request: context.clone(), context, @@ -93,7 +96,7 @@ fn create_import_meta_context_dependency( node.span.real_hi(), context_options, Some(node.span.into()), - optional, + parser.in_try, )) } @@ -131,7 +134,7 @@ impl JavascriptParserPlugin for ImportMetaContextDependencyParserPlugin { || expr.args.len() > 2 { None - } else if let Some(dep) = create_import_meta_context_dependency(expr, parser.in_try) { + } else if let Some(dep) = create_import_meta_context_dependency(expr, parser) { parser.dependencies.push(Box::new(dep)); Some(true) } else { 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 a641b6c7193..d31dd8dd1b0 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 @@ -1,6 +1,5 @@ use rspack_core::{ - context_reg_exp, AsyncDependenciesBlock, DependencyLocation, DynamicImportMode, ErrorSpan, - GroupOptions, + AsyncDependenciesBlock, DependencyLocation, DynamicImportMode, ErrorSpan, GroupOptions, }; use rspack_core::{ChunkGroupOptions, DynamicImportFetchPriority}; use rspack_core::{ContextNameSpaceObject, ContextOptions, DependencyCategory, SpanExt}; @@ -10,7 +9,8 @@ use swc_core::ecma::ast::{CallExpr, Callee}; use super::JavascriptParserPlugin; use crate::dependency::{ImportContextDependency, ImportDependency, ImportEagerDependency}; use crate::visitors::{ - create_context_dependency, parse_order_string, ContextModuleScanResult, JavascriptParser, + context_reg_exp, create_context_dependency, parse_order_string, ContextModuleScanResult, + JavascriptParser, }; use crate::webpack_comment::try_extract_webpack_magic_comment; @@ -120,6 +120,7 @@ impl JavascriptParserPlugin for ImportParserPlugin { fragment, replaces, } = create_context_dependency(¶m, parser); + let reg_exp = context_reg_exp(®, "", Some(dyn_imported.span().into()), parser); parser .dependencies .push(Box::new(ImportContextDependency::new( @@ -129,7 +130,7 @@ impl JavascriptParserPlugin for ImportParserPlugin { ContextOptions { mode: mode.into(), recursive: true, - reg_exp: context_reg_exp(®, ""), + reg_exp, include: None, exclude: None, category: DependencyCategory::Esm, diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs index c8af97be329..93d9269abf6 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/require_context_dependency_parser_plugin.rs @@ -1,4 +1,4 @@ -use rspack_core::{clean_regexp_in_context_module, try_convert_str_to_context_mode}; +use rspack_core::try_convert_str_to_context_mode; use rspack_core::{ContextMode, ContextOptions, DependencyCategory, SpanExt}; use rspack_regex::RspackRegex; use swc_core::common::Spanned; @@ -7,7 +7,7 @@ use swc_core::ecma::ast::CallExpr; use super::JavascriptParserPlugin; use crate::dependency::RequireContextDependency; use crate::visitors::expr_matcher::is_require_context; -use crate::visitors::JavascriptParser; +use crate::visitors::{clean_regexp_in_context_module, JavascriptParser}; pub struct RequireContextDependencyParserPlugin; @@ -37,17 +37,21 @@ impl JavascriptParserPlugin for RequireContextDependencyParserPlugin { ContextMode::Sync }; - let reg_exp = if expr.args.len() >= 3 { + let (reg_exp, reg_exp_span) = if expr.args.len() >= 3 { let reg_exp_expr = parser.evaluate_expression(&expr.args[2].expr); - if !reg_exp_expr.is_regexp() { + let reg_exp = if !reg_exp_expr.is_regexp() { // FIXME: return `None` in webpack RspackRegex::new(DEFAULT_REGEXP_STR).expect("reg should success") } else { let (expr, flags) = reg_exp_expr.regexp(); RspackRegex::with_flags(expr.as_str(), flags.as_str()).expect("reg should success") - } + }; + (reg_exp, Some(expr.args[2].expr.span().into())) } else { - RspackRegex::new(DEFAULT_REGEXP_STR).expect("reg should success") + ( + RspackRegex::new(DEFAULT_REGEXP_STR).expect("reg should success"), + None, + ) }; let recursive = if expr.args.len() >= 2 { @@ -62,12 +66,13 @@ impl JavascriptParserPlugin for RequireContextDependencyParserPlugin { true }; - if !expr.args.is_empty() { - let request_expr = parser.evaluate_expression(&expr.args[0].expr); + if let Some(arg) = expr.args.first() { + let request_expr = parser.evaluate_expression(&arg.expr); if !request_expr.is_string() { return None; } + let reg_exp = clean_regexp_in_context_module(reg_exp, reg_exp_span, parser); parser .dependencies .push(Box::new(RequireContextDependency::new( @@ -76,7 +81,7 @@ impl JavascriptParserPlugin for RequireContextDependencyParserPlugin { ContextOptions { mode, recursive, - reg_exp: clean_regexp_in_context_module(reg_exp), + reg_exp, include: None, exclude: None, category: DependencyCategory::CommonJS, 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..d3f94e94e59 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,12 +1,13 @@ use std::borrow::Cow; use itertools::Itertools; +use once_cell::sync::Lazy; +use regex::Regex; use rspack_core::parse_resource; use rspack_error::Severity; use rspack_util::json_stringify; -use super::context_helper::{quote_meta, split_context_from_prefix}; -use super::{create_traceable_error, ContextModuleScanResult}; +use super::create_traceable_error; use crate::utils::eval::{BasicEvaluatedExpression, TemplateStringKind}; // FIXME: delete this after `parserOptions.wrappedContextRegExp.source` @@ -190,3 +191,27 @@ pub fn create_context_dependency( } } } + +pub struct ContextModuleScanResult { + pub context: String, + pub reg: String, + pub query: String, + pub fragment: String, + pub replaces: Vec<(String, u32, u32)>, +} + +pub(super) fn split_context_from_prefix(prefix: String) -> (String, String) { + if let Some(idx) = prefix.rfind('/') { + (prefix[..idx].to_string(), format!(".{}", &prefix[idx..])) + } else { + (".".to_string(), prefix) + } +} + +static META_REG: Lazy = Lazy::new(|| { + Regex::new(r"[-\[\]\\/{}()*+?.^$|]").expect("Failed to initialize `MATCH_RESOURCE_REGEX`") +}); + +pub fn quote_meta(str: &str) -> Cow { + META_REG.replace_all(str, "\\$0") +} diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/context_helper.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/context_helper.rs deleted file mode 100644 index 7b8e08a700b..00000000000 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/context_helper.rs +++ /dev/null @@ -1,312 +0,0 @@ -use std::borrow::Cow; - -use once_cell::sync::Lazy; -use regex::Regex; -use rspack_core::{parse_resource, SpanExt}; -use rspack_util::json_stringify; -use swc_core::ecma::ast::{ - BinExpr, BinaryOp, CallExpr, Callee, Expr, Lit, MemberProp, TaggedTpl, Tpl, -}; - -use crate::utils::eval::TemplateStringKind; - -pub struct ContextModuleScanResult { - pub context: String, - pub reg: String, - pub query: String, - pub fragment: String, - pub replaces: Vec<(String, u32, u32)>, -} - -pub(super) fn split_context_from_prefix(prefix: String) -> (String, String) { - if let Some(idx) = prefix.rfind('/') { - (prefix[..idx].to_string(), format!(".{}", &prefix[idx..])) - } else { - (".".to_string(), prefix) - } -} - -/// FIXME: remove this function -pub fn scanner_context_module(expr: &Expr) -> Option { - match expr { - Expr::Tpl(tpl) if !tpl.exprs.is_empty() => { - Some(scan_context_module_tpl(tpl, TemplateStringKind::Cooked)) - } - Expr::Bin(bin) => scan_context_module_bin(bin), - Expr::Call(call) => scan_context_module_concat_call(call), - Expr::TaggedTpl(t_tpl) => Some(scan_context_module_tagged_tpl(t_tpl)), - _ => None, - } -} - -static META_REG: Lazy = Lazy::new(|| { - Regex::new(r"[-\[\]\\/{}()*+?.^$|]").expect("Failed to initialize `MATCH_RESOURCE_REGEX`") -}); - -pub fn quote_meta(str: &str) -> Cow { - META_REG.replace_all(str, "\\$0") -} - -// require(`./${a}.js`) -fn scan_context_module_tpl(tpl: &Tpl, kind: TemplateStringKind) -> ContextModuleScanResult { - let prefix_raw = tpl - .quasis - .first() - .expect("should have one quasis") - .raw - .to_string(); - let postfix_raw = if tpl.quasis.len() > 1 { - tpl - .quasis - .last() - .expect("should have last quasis") - .raw - .to_string() - } else { - String::new() - }; - let (context, prefix) = split_context_from_prefix(prefix_raw); - let inner_reg = tpl - .quasis - .iter() - .skip(tpl.quasis.len()) - .skip(1) - .map(|s| { - match kind { - TemplateStringKind::Raw => s.raw.as_ref(), - TemplateStringKind::Cooked => s.cooked.as_ref().unwrap_or(&s.raw), - } - .to_string() - + ".*" - }) - .collect::>() - .join(""); - - let (postfix, query, fragment) = match parse_resource(&postfix_raw) { - Some(data) => ( - data.path.to_string_lossy().to_string(), - data.query.unwrap_or_default(), - data.fragment.unwrap_or_default(), - ), - None => (postfix_raw, String::new(), String::new()), - }; - - let reg = format!( - "^{prefix}.*{inner_reg}{postfix_raw}$", - prefix = quote_meta(&prefix), - postfix_raw = quote_meta(&postfix) - ); - ContextModuleScanResult { - context, - reg, - query, - fragment, - replaces: Vec::new(), - } -} - -// require("./" + a + ".js") -fn scan_context_module_bin(bin: &BinExpr) -> Option { - if !is_add_op_bin_expr(bin) { - return None; - } - let (prefix_raw, prefix_range) = - if let Some((prefix, start, end)) = find_expr_prefix_string(&bin.left) { - (prefix, Some((start, end))) - } else { - ("".to_string(), None) - }; - let (postfix_raw, postfix_range) = - if let Some((postfix, start, end)) = find_expr_prefix_string(&bin.right) { - (postfix, Some((start, end))) - } else { - ("".to_string(), None) - }; - - if prefix_raw.is_empty() && postfix_raw.is_empty() { - return None; - } - - let (context, prefix) = split_context_from_prefix(prefix_raw); - - let (postfix, query, fragment) = match parse_resource(&postfix_raw) { - Some(data) => ( - data.path.to_string_lossy().to_string(), - data.query.unwrap_or_default(), - data.fragment.unwrap_or_default(), - ), - None => (postfix_raw, String::new(), String::new()), - }; - - let reg = format!( - "^{prefix}.*{postfix_raw}$", - prefix = quote_meta(&prefix), - postfix_raw = quote_meta(&postfix) - ); - - let mut replaces = Vec::new(); - if let Some((start, end)) = prefix_range { - replaces.push((json_stringify(&prefix), start, end)); - } - if let Some((start, end)) = postfix_range { - replaces.push((json_stringify(&postfix), start, end)); - } - - Some(ContextModuleScanResult { - context, - reg, - query, - fragment, - replaces, - }) -} - -fn find_expr_prefix_string(expr: &Expr) -> Option<(String, u32, u32)> { - match &expr { - Expr::Lit(Lit::Str(str)) => Some(( - str.value.to_string(), - str.span.real_lo(), - str.span.real_hi(), - )), - Expr::Lit(Lit::Num(num)) => Some(( - num.value.to_string(), - num.span.real_lo(), - num.span.real_hi(), - )), - Expr::Bin(bin) => find_expr_prefix_string(&bin.left), - _ => None, - } -} - -fn is_add_op_bin_expr(bin: &BinExpr) -> bool { - if !matches!(&bin.op, BinaryOp::Add) { - return false; - } - match bin.left.as_ref() { - Expr::Bin(bin) => is_add_op_bin_expr(bin), - _ => true, - } -} - -// require("./".concat(a, ".js")) -// babel/swc will transform template literal to string concat, so we need to handle this case -// see https://github.com/webpack/webpack/pull/5679 -fn scan_context_module_concat_call(expr: &CallExpr) -> Option { - if !is_concat_call(expr) { - return None; - } - let prefix_raw = if let Some(prefix) = find_concat_expr_prefix_string(expr) { - prefix - } else { - "".to_string() - }; - let postfix_raw = if let Some(postfix) = find_concat_expr_postfix_string(expr) { - postfix - } else { - "".to_string() - }; - - if prefix_raw.is_empty() && postfix_raw.is_empty() { - return None; - } - - let (context, prefix) = split_context_from_prefix(prefix_raw); - let (postfix, query, fragment) = match parse_resource(&postfix_raw) { - Some(data) => ( - data.path.to_string_lossy().to_string(), - data.query.unwrap_or_default(), - data.fragment.unwrap_or_default(), - ), - None => (postfix_raw, String::new(), String::new()), - }; - let reg = format!( - "^{prefix}.*{postfix_raw}$", - prefix = quote_meta(&prefix), - postfix_raw = quote_meta(&postfix) - ); - - Some(ContextModuleScanResult { - context, - reg, - query, - fragment, - replaces: Vec::new(), - }) -} - -// require(String.raw`./${a}.js`) -fn scan_context_module_tagged_tpl(tpl: &TaggedTpl) -> ContextModuleScanResult { - match tpl.tag.as_member() { - Some(tag) - if tag - .obj - .as_ident() - .map(|ident| ident.sym == *"String") - .unwrap_or(false) - && tag - .prop - .as_ident() - .map(|ident| ident.sym == *"raw") - .unwrap_or(false) => - { - scan_context_module_tpl(tpl.tpl.as_ref(), TemplateStringKind::Raw) - } - _ => ContextModuleScanResult { - context: String::from("."), - reg: String::new(), - query: String::new(), - fragment: String::new(), - replaces: Vec::new(), - }, - } -} - -fn is_concat_call(expr: &CallExpr) -> bool { - match &expr.callee { - Callee::Expr(box Expr::Member(member_expr)) => { - if let MemberProp::Ident(ident) = &member_expr.prop { - if ident.sym != *"concat" { - return false; - } - } else { - return false; - } - - if let Expr::Call(call) = member_expr.obj.as_ref() { - return is_concat_call(call); - } - true - } - _ => false, - } -} - -fn find_concat_expr_prefix_string(expr: &CallExpr) -> Option { - match &expr.callee { - Callee::Expr(box Expr::Member(member_expr)) => { - if let Expr::Lit(Lit::Str(str)) = member_expr.obj.as_ref() { - return Some(str.value.to_string()); - } - if let Expr::Lit(Lit::Num(num)) = member_expr.obj.as_ref() { - return Some(num.value.to_string()); - } - if let Expr::Call(call) = member_expr.obj.as_ref() { - return find_concat_expr_prefix_string(call); - } - None - } - _ => None, - } -} - -fn find_concat_expr_postfix_string(expr: &CallExpr) -> Option { - expr.args.last().and_then(|arg| { - if let Expr::Lit(Lit::Str(str)) = arg.expr.as_ref() { - return Some(str.value.to_string()); - } - if let Expr::Lit(Lit::Num(num)) = arg.expr.as_ref() { - return Some(num.value.to_string()); - } - None - }) -} diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs index 1923acb81ca..4b135de95e9 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs @@ -1,5 +1,4 @@ mod context_dependency_helper; -mod context_helper; mod parser; mod util; @@ -15,8 +14,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use swc_core::common::{comments::Comments, BytePos, SourceFile, SourceMap, Span}; use swc_core::ecma::atoms::Atom; -pub use self::context_dependency_helper::create_context_dependency; -pub use self::context_helper::{scanner_context_module, ContextModuleScanResult}; +pub use self::context_dependency_helper::{create_context_dependency, ContextModuleScanResult}; pub use self::parser::{ AllowedMemberTypes, CallExpressionInfo, CallHooksName, ExportedVariableInfo, PathIgnoredSpans, }; diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/util.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/util.rs index cfa0deabbb0..4919af8b65b 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/util.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/util.rs @@ -1,12 +1,16 @@ use itertools::Itertools; use rspack_core::extract_member_expression_chain; use rspack_core::{ConstDependency, DependencyLocation, ErrorSpan, ExpressionInfoKind, SpanExt}; +use rspack_error::miette::diagnostic; use rspack_error::{miette::Severity, DiagnosticKind, TraceableError}; +use rspack_regex::RspackRegex; use rustc_hash::FxHashSet as HashSet; use swc_core::common::{SourceFile, Spanned}; use swc_core::ecma::ast::*; use swc_core::ecma::atoms::Atom; +use super::JavascriptParser; + pub fn collect_destructuring_assignment_properties( object_pat: &ObjectPat, ) -> Option> { @@ -343,6 +347,51 @@ pub fn create_traceable_error( .with_kind(DiagnosticKind::JavaScript) } +pub fn context_reg_exp( + expr: &str, + flags: &str, + error_span: Option, + parser: &mut JavascriptParser, +) -> Option { + if expr.is_empty() { + return None; + } + let regexp = RspackRegex::with_flags(expr, flags).expect("reg failed"); + clean_regexp_in_context_module(regexp, error_span, parser) +} + +pub fn clean_regexp_in_context_module( + regexp: RspackRegex, + error_span: Option, + parser: &mut JavascriptParser, +) -> Option { + if regexp.sticky() || regexp.global() { + if let Some(error_span) = error_span { + parser.warning_diagnostics.push(Box::new( + create_traceable_error( + "Critical dependency".into(), + "Contexts can't use RegExps with the 'g' or 'y' flags".to_string(), + parser.source_file, + error_span, + ) + .with_severity(rspack_error::RspackSeverity::Warn), + )); + } else { + parser.warning_diagnostics.push( + diagnostic!( + severity = Severity::Warning, + code = "Critical dependency", + "Contexts can't use RegExps with the 'g' or 'y' flags" + ) + .into(), + ); + } + None + } else { + Some(regexp) + } +} + #[cfg(test)] mod test { use swc_core::common::DUMMY_SP; diff --git a/tests/webpack-test/cases/context/issue-5750/test.filter.js b/tests/webpack-test/cases/context/issue-5750/test.filter.js deleted file mode 100644 index b9d31b649c5..00000000000 --- a/tests/webpack-test/cases/context/issue-5750/test.filter.js +++ /dev/null @@ -1,4 +0,0 @@ - -module.exports = () => {return "https://github.com/web-infra-dev/rspack/issues/4328"} - - \ No newline at end of file diff --git a/tests/webpack-test/cases/parsing/issue-627/test.filter.js b/tests/webpack-test/cases/parsing/issue-627/test.filter.js deleted file mode 100644 index 044c0aa1633..00000000000 --- a/tests/webpack-test/cases/parsing/issue-627/test.filter.js +++ /dev/null @@ -1,4 +0,0 @@ - -module.exports = () => {return "https://github.com/web-infra-dev/rspack/issues/4429"} - - \ No newline at end of file From 1ee6de83b2c3e81af6bfe82b7c9a4dde12f98388 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Thu, 4 Jul 2024 17:38:43 +0800 Subject: [PATCH 2/3] fix: deduplicate extracted comments (#7040) * Deduplicate extracted comments * Remove leading space * Update testcase --- .../src/minify.rs | 18 ++++++++++++------ .../plugins/minify-extract-comments/index.js | 7 +++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/crates/rspack_plugin_swc_js_minimizer/src/minify.rs b/crates/rspack_plugin_swc_js_minimizer/src/minify.rs index 68fea431193..cf4087a97a6 100644 --- a/crates/rspack_plugin_swc_js_minimizer/src/minify.rs +++ b/crates/rspack_plugin_swc_js_minimizer/src/minify.rs @@ -246,28 +246,34 @@ pub fn minify( leading_trivial.iter().for_each(|(_, comments)| { comments.iter().for_each(|c| { if extract_comments.condition.is_match(&c.text) { - extracted_comments.push(match c.kind { + let comment = match c.kind { CommentKind::Line => { - format!("// {}", c.text) + format!("//{}", c.text) } CommentKind::Block => { format!("/*{}*/", c.text) } - }); + }; + if !extracted_comments.contains(&comment) { + extracted_comments.push(comment); + } } }); }); trailing_trivial.iter().for_each(|(_, comments)| { comments.iter().for_each(|c| { if extract_comments.condition.is_match(&c.text) { - extracted_comments.push(match c.kind { + let comment = match c.kind { CommentKind::Line => { - format!("// {}", c.text) + format!("//{}", c.text) } CommentKind::Block => { format!("/*{}*/", c.text) } - }); + }; + if !extracted_comments.contains(&comment) { + extracted_comments.push(comment); + } } }); }); diff --git a/packages/rspack-test-tools/tests/configCases/plugins/minify-extract-comments/index.js b/packages/rspack-test-tools/tests/configCases/plugins/minify-extract-comments/index.js index 54ae0e75e94..7f05d8c9f30 100644 --- a/packages/rspack-test-tools/tests/configCases/plugins/minify-extract-comments/index.js +++ b/packages/rspack-test-tools/tests/configCases/plugins/minify-extract-comments/index.js @@ -2,6 +2,13 @@ const fs = require("fs"); const path = require("path"); /*! Legal Comment */ +/** + * @preserve Copyright 2009 SomeThirdParty. + * Here is the full license text and copyright + * notice for this file. Note that the notice can span several + * lines and is only terminated by the closing star and slash: + */ + /** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright From add78bb588c8b67b9c3bdb6566c4fafa6a2195fd Mon Sep 17 00:00:00 2001 From: jinrui Date: Thu, 4 Jul 2024 19:11:47 +0800 Subject: [PATCH 3/3] chore: release run macos test when arch match (#7046) --- .github/workflows/reusable-build.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index e2e3c991614..bb0d1473442 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -283,12 +283,20 @@ jobs: # if: ${{ inputs.target == 'x86_64-unknown-linux-gnu' && !inputs.skipable }} # run: node ./scripts/test/diff.cjs - ### x86_64-apple-darwin + ### *-apple-darwin - - name: Test x86_64-apple-darwin + - name: Test apple-darwin timeout-minutes: 15 # Tests should finish within 15 mins, please fix your tests instead of changing this to a higher timeout. - if: ${{ inputs.target == 'x86_64-apple-darwin' && !inputs.skipable }} - run: pnpm run test:ci + if: ${{ contains(inputs.target, 'apple-darwin') && !inputs.skipable }} + run: | + # arch is ARM and target is ARM + if [[ '${{ runner.arch }}' == ARM* && '${{ inputs.target }}' == 'aarch64-apple-darwin' ]]; then + pnpm run test:ci + fi + # arch is x64 and target is x64 + if [[ '${{ runner.arch }}' != ARM* && '${{ inputs.target }}' != 'aarch64-apple-darwin' ]]; then + pnpm run test:ci + fi ### x86_64-pc-windows-msvc