From 212d4e8b9563d1072225c3524997898fdd892430 Mon Sep 17 00:00:00 2001 From: Cong-Cong Date: Wed, 11 Sep 2024 11:17:31 +0800 Subject: [PATCH] feat: lazy context dep critical --- .../node_binding/src/plugins/interceptor.rs | 2 + .../rspack_core/src/context_module_factory.rs | 10 +-- .../src/dependency/context_dependency.rs | 14 +++- .../common_js_require_context_dependency.rs | 18 +++-- .../context/import_context_dependency.rs | 18 +++-- .../context/import_meta_context_dependency.rs | 19 +++-- .../context/require_context_dependency.rs | 19 +++-- .../common_js_imports_parse_plugin.rs | 20 ++++-- .../src/parser_plugin/import_parser_plugin.rs | 69 ++++++++++--------- .../dependency/context_dependency_helper.rs | 32 ++++++--- 10 files changed, 147 insertions(+), 74 deletions(-) diff --git a/crates/node_binding/src/plugins/interceptor.rs b/crates/node_binding/src/plugins/interceptor.rs index 83910c620461..2e1d6e6cf19d 100644 --- a/crates/node_binding/src/plugins/interceptor.rs +++ b/crates/node_binding/src/plugins/interceptor.rs @@ -1533,6 +1533,8 @@ impl ContextModuleFactoryBeforeResolve for ContextModuleFactoryBeforeResolveTap request: d.request, reg_exp, recursive: d.recursive, + // TODO + dependencies: vec![], }; Ok(BeforeResolveResult::Data(Box::new(data))) } diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index f6f1315f2475..6ccce844981c 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -7,9 +7,10 @@ use rspack_regex::RspackRegex; use tracing::instrument; use crate::{ - resolve, ContextModule, ContextModuleOptions, DependencyCategory, ModuleExt, ModuleFactory, - ModuleFactoryCreateData, ModuleFactoryResult, ModuleIdentifier, RawModule, ResolveArgs, - ResolveOptionsWithDependencyType, ResolveResult, Resolver, ResolverFactory, SharedPluginDriver, + resolve, ContextModule, ContextModuleOptions, DependencyCategory, DependencyId, ModuleExt, + ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult, ModuleIdentifier, RawModule, + ResolveArgs, ResolveOptionsWithDependencyType, ResolveResult, Resolver, ResolverFactory, + SharedPluginDriver, }; #[derive(Clone)] @@ -25,7 +26,7 @@ pub struct BeforeResolveData { pub context: String, pub request: Option, // assertions - // dependencies + pub dependencies: Vec, // dependency_type // file_dependencies // missing_dependencies @@ -132,6 +133,7 @@ impl ContextModuleFactory { request: data.request().map(|r| r.to_string()), recursive: dependency_options.recursive, reg_exp: dependency_options.reg_exp.clone(), + dependencies: vec![*dependency.id()], }; match self diff --git a/crates/rspack_core/src/dependency/context_dependency.rs b/crates/rspack_core/src/dependency/context_dependency.rs index 94421cf57742..bcb1b3c25cc0 100644 --- a/crates/rspack_core/src/dependency/context_dependency.rs +++ b/crates/rspack_core/src/dependency/context_dependency.rs @@ -1,4 +1,6 @@ -use crate::{ContextOptions, ContextTypePrefix, Dependency}; +use rspack_error::Diagnostic; + +use crate::{ContextOptions, ContextTypePrefix, Dependency, ModuleGraph}; pub trait ContextDependency: Dependency { fn request(&self) -> &str; @@ -12,6 +14,16 @@ pub trait ContextDependency: Dependency { } fn type_prefix(&self) -> ContextTypePrefix; + + fn critical(&self) -> &Option; + fn critical_mut(&mut self) -> &mut Option; + + fn get_diagnostics(&self, _module_graph: &ModuleGraph) -> Option> { + if let Some(critical) = self.critical() { + return Some(vec![critical.clone()]); + } + None + } } pub trait AsContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs index 1638ce7d4ff9..1cd2b1a92e4f 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/common_js_require_context_dependency.rs @@ -1,9 +1,9 @@ use rspack_core::{ - AsModuleDependency, Compilation, ContextDependency, RealDependencyLocation, RuntimeSpec, + AsModuleDependency, Compilation, ContextDependency, ContextOptions, Dependency, + DependencyCategory, DependencyId, DependencyTemplate, DependencyType, ErrorSpan, + RealDependencyLocation, RuntimeSpec, TemplateContext, TemplateReplaceSource, }; -use rspack_core::{ContextOptions, Dependency, TemplateReplaceSource}; -use rspack_core::{DependencyCategory, DependencyId, DependencyTemplate}; -use rspack_core::{DependencyType, ErrorSpan, TemplateContext}; +use rspack_error::Diagnostic; use super::{ context_dependency_template_as_require_call, create_resource_identifier_for_context_dependency, @@ -17,6 +17,7 @@ pub struct CommonJsRequireContextDependency { resource_identifier: String, options: ContextOptions, optional: bool, + critical: Option, } impl CommonJsRequireContextDependency { @@ -34,6 +35,7 @@ impl CommonJsRequireContextDependency { resource_identifier, optional, id: DependencyId::new(), + critical: None, } } } @@ -88,6 +90,14 @@ impl ContextDependency for CommonJsRequireContextDependency { fn type_prefix(&self) -> rspack_core::ContextTypePrefix { rspack_core::ContextTypePrefix::Normal } + + fn critical(&self) -> &Option { + &self.critical + } + + fn critical_mut(&mut self) -> &mut Option { + &mut self.critical + } } impl DependencyTemplate for CommonJsRequireContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs index da5f52c38aef..c8ffd3da30fa 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/import_context_dependency.rs @@ -1,9 +1,9 @@ use rspack_core::{ - AsModuleDependency, Compilation, ContextDependency, RealDependencyLocation, RuntimeSpec, + AsModuleDependency, Compilation, ContextDependency, ContextOptions, Dependency, + DependencyCategory, DependencyId, DependencyTemplate, DependencyType, ErrorSpan, + RealDependencyLocation, RuntimeSpec, TemplateContext, TemplateReplaceSource, }; -use rspack_core::{ContextOptions, Dependency, TemplateReplaceSource}; -use rspack_core::{DependencyCategory, DependencyId, DependencyTemplate}; -use rspack_core::{DependencyType, ErrorSpan, TemplateContext}; +use rspack_error::Diagnostic; use super::{ context_dependency_template_as_require_call, create_resource_identifier_for_context_dependency, @@ -17,6 +17,7 @@ pub struct ImportContextDependency { range_callee: (u32, u32), resource_identifier: String, optional: bool, + critical: Option, } impl ImportContextDependency { @@ -34,6 +35,7 @@ impl ImportContextDependency { id: DependencyId::new(), resource_identifier, optional, + critical: None, } } } @@ -88,6 +90,14 @@ impl ContextDependency for ImportContextDependency { fn type_prefix(&self) -> rspack_core::ContextTypePrefix { rspack_core::ContextTypePrefix::Import } + + fn critical(&self) -> &Option { + &self.critical + } + + fn critical_mut(&mut self) -> &mut Option { + &mut self.critical + } } impl DependencyTemplate for ImportContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs index 5d98a7b1a6a7..62eb3eeef861 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/import_meta_context_dependency.rs @@ -1,10 +1,9 @@ use rspack_core::{ - module_raw, AsModuleDependency, Compilation, ContextDependency, RealDependencyLocation, - RuntimeSpec, + module_raw, AsModuleDependency, Compilation, ContextDependency, ContextOptions, Dependency, + DependencyCategory, DependencyId, DependencyTemplate, DependencyType, ErrorSpan, + RealDependencyLocation, RuntimeSpec, TemplateContext, TemplateReplaceSource, }; -use rspack_core::{ContextOptions, Dependency, DependencyCategory, DependencyId}; -use rspack_core::{DependencyTemplate, DependencyType, ErrorSpan}; -use rspack_core::{TemplateContext, TemplateReplaceSource}; +use rspack_error::TraceableError; use super::create_resource_identifier_for_context_dependency; @@ -15,6 +14,7 @@ pub struct ImportMetaContextDependency { range: RealDependencyLocation, resource_identifier: String, optional: bool, + critical: Option, } impl ImportMetaContextDependency { @@ -26,6 +26,7 @@ impl ImportMetaContextDependency { resource_identifier, optional, id: DependencyId::new(), + critical: None, } } } @@ -80,6 +81,14 @@ impl ContextDependency for ImportMetaContextDependency { fn type_prefix(&self) -> rspack_core::ContextTypePrefix { rspack_core::ContextTypePrefix::Normal } + + fn critical(&self) -> &Option { + &self.critical + } + + fn critical_mut(&mut self) -> &mut Option { + &mut self.critical + } } impl DependencyTemplate for ImportMetaContextDependency { diff --git a/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs index 18db2189956d..5be81904a489 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/require_context_dependency.rs @@ -1,10 +1,9 @@ use rspack_core::{ - module_raw, AsModuleDependency, Compilation, ContextDependency, RealDependencyLocation, - RuntimeSpec, + module_raw, AsModuleDependency, Compilation, ContextDependency, ContextOptions, Dependency, + DependencyCategory, DependencyId, DependencyTemplate, DependencyType, ErrorSpan, + RealDependencyLocation, RuntimeSpec, TemplateContext, TemplateReplaceSource, }; -use rspack_core::{ContextOptions, Dependency, DependencyCategory, DependencyId}; -use rspack_core::{DependencyTemplate, DependencyType, ErrorSpan}; -use rspack_core::{TemplateContext, TemplateReplaceSource}; +use rspack_error::Diagnostic; use super::create_resource_identifier_for_context_dependency; @@ -15,6 +14,7 @@ pub struct RequireContextDependency { range: RealDependencyLocation, resource_identifier: String, optional: bool, + critical: Option, } impl RequireContextDependency { @@ -26,6 +26,7 @@ impl RequireContextDependency { id: DependencyId::new(), resource_identifier, optional, + critical: None, } } } @@ -80,6 +81,14 @@ impl ContextDependency for RequireContextDependency { fn type_prefix(&self) -> rspack_core::ContextTypePrefix { rspack_core::ContextTypePrefix::Normal } + + fn critical(&self) -> &Option { + &self.critical + } + + fn critical_mut(&mut self) -> &mut Option { + &mut self.critical + } } impl DependencyTemplate for RequireContextDependency { 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 9afe27ba55f7..ba8711e08ff4 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,8 +1,9 @@ use rspack_core::{ - ConstDependency, ContextMode, DependencyCategory, RealDependencyLocation, SpanExt, + ConstDependency, ContextDependency, ContextMode, DependencyCategory, RealDependencyLocation, + SpanExt, }; use rspack_core::{ContextNameSpaceObject, ContextOptions}; -use rspack_error::Severity; +use rspack_error::{DiagnosticExt, Severity}; use swc_core::common::{Span, Spanned}; use swc_core::ecma::ast::{CallExpr, Expr, Ident, Lit, MemberExpr, UnaryExpr}; @@ -44,7 +45,10 @@ fn create_commonjs_require_context_dependency( referenced_exports: None, attributes: None, }; - CommonJsRequireContextDependency::new(options, span.into(), (start, end), parser.in_try) + let mut dep = + CommonJsRequireContextDependency::new(options, span.into(), (start, end), parser.in_try); + *dep.critical_mut() = result.critical; + dep } pub struct CommonJsImportsParserPlugin; @@ -200,7 +204,7 @@ impl CommonJsImportsParserPlugin { ) -> Option { let start = ident.span().real_lo(); let end = ident.span().real_hi(); - let dep = CommonJsRequireContextDependency::new( + let mut dep = CommonJsRequireContextDependency::new( ContextOptions { mode: ContextMode::Sync, recursive: true, @@ -222,7 +226,7 @@ impl CommonJsImportsParserPlugin { (start, end), parser.in_try, ); - parser.warning_diagnostics.push(Box::new( + *dep.critical_mut() = Some( create_traceable_error( "Critical dependency".into(), "require function is used in a way in which dependencies cannot be statically extracted" @@ -230,8 +234,10 @@ impl CommonJsImportsParserPlugin { parser.source_file, ident.span().into(), ) - .with_severity(Severity::Warn), - )); + .with_severity(Severity::Warn) + .boxed() + .into(), + ); parser.dependencies.push(Box::new(dep)); 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 f1e640d8c42f..459c5e54ac5b 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,7 +1,7 @@ use itertools::Itertools; use rspack_core::{ - AsyncDependenciesBlock, DependencyLocation, DynamicImportMode, GroupOptions, ImportAttributes, - RealDependencyLocation, + AsyncDependenciesBlock, ContextDependency, DependencyLocation, DynamicImportMode, GroupOptions, + ImportAttributes, RealDependencyLocation, }; use rspack_core::{ChunkGroupOptions, DynamicImportFetchPriority}; use rspack_core::{ContextNameSpaceObject, ContextOptions, DependencyCategory, SpanExt}; @@ -147,41 +147,42 @@ impl JavascriptParserPlugin for ImportParserPlugin { query, fragment, replaces, + critical, } = create_context_dependency(¶m, &dyn_imported.expr, parser); let reg_exp = context_reg_exp(®, "", Some(dyn_imported.span().into()), parser); - parser - .dependencies - .push(Box::new(ImportContextDependency::new( - ContextOptions { - mode: mode.into(), - recursive: true, - reg_exp, - include, - exclude, - category: DependencyCategory::Esm, - request: format!("{}{}{}", context.clone(), query, fragment), - context, - namespace_object: if parser.build_meta.strict_harmony_module { - ContextNameSpaceObject::Strict - } else { - ContextNameSpaceObject::Bool(true) - }, - group_options: Some(GroupOptions::ChunkGroup(ChunkGroupOptions::new( - chunk_name, - chunk_preload, - chunk_prefetch, - fetch_priority, - ))), - replaces, - start: node.span().real_lo(), - end: node.span().real_hi(), - referenced_exports: exports, - attributes, + let mut dep = ImportContextDependency::new( + ContextOptions { + mode: mode.into(), + recursive: true, + reg_exp, + include, + exclude, + category: DependencyCategory::Esm, + request: format!("{}{}{}", context.clone(), query, fragment), + context, + namespace_object: if parser.build_meta.strict_harmony_module { + ContextNameSpaceObject::Strict + } else { + ContextNameSpaceObject::Bool(true) }, - node.span().into(), - (import_call.span.real_lo(), import_call.span.real_hi()), - parser.in_try, - ))); + group_options: Some(GroupOptions::ChunkGroup(ChunkGroupOptions::new( + chunk_name, + chunk_preload, + chunk_prefetch, + fetch_priority, + ))), + replaces, + start: node.span().real_lo(), + end: node.span().real_hi(), + referenced_exports: exports, + attributes, + }, + node.span().into(), + (import_call.span.real_lo(), import_call.span.real_hi()), + parser.in_try, + ); + *dep.critical_mut() = critical; + parser.dependencies.push(Box::new(dep)); 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 4c3966643c45..dc86b3b037a7 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 @@ -4,7 +4,7 @@ use std::sync::LazyLock; use itertools::Itertools; use regex::Regex; use rspack_core::parse_resource; -use rspack_error::Severity; +use rspack_error::{Diagnostic, DiagnosticExt, Severity}; use rspack_util::json_stringify; use swc_core::ecma::ast::Expr; @@ -19,6 +19,8 @@ pub fn create_context_dependency( expr: &Expr, parser: &mut crate::visitors::JavascriptParser, ) -> ContextModuleScanResult { + let mut critical = None; + if param.is_template_string() { let quasis = param.quasis(); let Some(prefix) = quasis.first() else { @@ -84,15 +86,17 @@ pub fn create_context_dependency( if parser.javascript_options.wrapped_context_critical { let range = param.range(); - parser.warning_diagnostics.push(Box::new( + critical = Some( create_traceable_error( "Critical dependency".into(), "a part of the request of a dependency is an expression".to_string(), parser.source_file, rspack_core::ErrorSpan::new(range.0, range.1), ) - .with_severity(Severity::Warn), - )); + .with_severity(Severity::Warn) + .boxed() + .into(), + ); } // Webpack will walk only the expression parts of the template string @@ -107,6 +111,7 @@ pub fn create_context_dependency( query, fragment, replaces, + critical, } } else if param.is_wrapped() && let prefix_is_string = param @@ -158,15 +163,17 @@ pub fn create_context_dependency( if parser.javascript_options.wrapped_context_critical { let range = param.range(); - parser.warning_diagnostics.push(Box::new( + critical = Some( create_traceable_error( "Critical dependency".into(), "a part of the request of a dependency is an expression".to_string(), parser.source_file, rspack_core::ErrorSpan::new(range.0, range.1), ) - .with_severity(Severity::Warn), - )); + .with_severity(Severity::Warn) + .boxed() + .into(), + ); } // Webpack will walk only the dynamic parts of evaluated expression @@ -181,19 +188,22 @@ pub fn create_context_dependency( query, fragment, replaces, + critical, } } else { if parser.javascript_options.expr_context_critical { let range = param.range(); - parser.warning_diagnostics.push(Box::new( + critical = Some( create_traceable_error( "Critical dependency".into(), "the request of a dependency is an expression".to_string(), parser.source_file, rspack_core::ErrorSpan::new(range.0, range.1), ) - .with_severity(Severity::Warn), - )); + .with_severity(Severity::Warn) + .boxed() + .into(), + ); } parser.walk_expression(expr); @@ -204,6 +214,7 @@ pub fn create_context_dependency( query: String::new(), fragment: String::new(), replaces: Vec::new(), + critical, } } } @@ -214,6 +225,7 @@ pub struct ContextModuleScanResult { pub query: String, pub fragment: String, pub replaces: Vec<(String, u32, u32)>, + pub critical: Option, } pub(super) fn split_context_from_prefix(prefix: String) -> (String, String) {