From 39435177d7196bf5aa8a84de8bc0d9c156c4fc61 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Mon, 16 Oct 2023 15:32:05 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=F0=9F=A4=96=20update=20add=20variable?= =?UTF-8?q?=20usage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snapshot/new_treeshaking.snap | 11 +- .../default_export/snapshot/snap.diff | 37 ------ .../snapshot/new_treeshaking.snap | 43 ++++++- .../snapshot/snap.diff | 80 ++++-------- .../harmony_import_specifier_dependency.rs | 1 + .../src/parser_and_generator/mod.rs | 1 + .../src/plugin/inner_graph_plugin.rs | 117 ++++++++++++------ .../harmony_export_dependency_scanner.rs | 25 +++- .../harmony_import_dependency_scanner.rs | 23 ++-- .../src/visitors/dependency/mod.rs | 16 ++- 10 files changed, 208 insertions(+), 146 deletions(-) delete mode 100644 crates/rspack/tests/tree-shaking/default_export/snapshot/snap.diff diff --git a/crates/rspack/tests/tree-shaking/default_export/snapshot/new_treeshaking.snap b/crates/rspack/tests/tree-shaking/default_export/snapshot/new_treeshaking.snap index 70002f4c5b7d..cd892fcd8fb8 100644 --- a/crates/rspack/tests/tree-shaking/default_export/snapshot/new_treeshaking.snap +++ b/crates/rspack/tests/tree-shaking/default_export/snapshot/new_treeshaking.snap @@ -6,6 +6,9 @@ source: crates/rspack_testing/src/run_fixture.rs "./answer.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 'use strict'; __webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + 'answer': function() { return answer; } +}); const answer = 103330; // export default answer; }, "./app.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { @@ -20,7 +23,7 @@ __webpack_require__.d(__webpack_exports__, { function render() { function test() { const container = document.getElementById("root"); - container.innerHTML = `adddd333:${secret}:${myanswer}`; + container.innerHTML = `adddd333:${_lib__WEBPACK_IMPORTED_MODULE_0_.secret}:${_lib__WEBPACK_IMPORTED_MODULE_0_.myanswer}`; } } function result() {} @@ -35,10 +38,14 @@ __webpack_require__.r(__webpack_exports__); "./lib.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 'use strict'; __webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + 'secret': function() { return secret; }, + 'myanswer': function() { return myanswer; } +}); /* harmony import */var _answer__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./answer */"./answer.js"); const secret = "888"; - const myanswer = answer, result = 20000; + const myanswer = _answer__WEBPACK_IMPORTED_MODULE_0_.answer, result = 20000; }, },function(__webpack_require__) { diff --git a/crates/rspack/tests/tree-shaking/default_export/snapshot/snap.diff b/crates/rspack/tests/tree-shaking/default_export/snapshot/snap.diff deleted file mode 100644 index 8787cb4fd8b3..000000000000 --- a/crates/rspack/tests/tree-shaking/default_export/snapshot/snap.diff +++ /dev/null @@ -1,37 +0,0 @@ ---- expected -+++ actual -@@ -6,9 +6,6 @@ - "./answer.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { - 'use strict'; - __webpack_require__.r(__webpack_exports__); --__webpack_require__.d(__webpack_exports__, { -- 'answer': function() { return answer; } --}); - const answer = 103330; // export default answer; - }, - "./app.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { -@@ -23,7 +20,7 @@ - function render() { - function test() { - const container = document.getElementById("root"); -- container.innerHTML = `adddd333:${_lib__WEBPACK_IMPORTED_MODULE_0_.secret}:${_lib__WEBPACK_IMPORTED_MODULE_0_.myanswer}`; -+ container.innerHTML = `adddd333:${secret}:${myanswer}`; - } - } - function result() {} -@@ -38,14 +35,10 @@ - "./lib.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { - 'use strict'; - __webpack_require__.r(__webpack_exports__); --__webpack_require__.d(__webpack_exports__, { -- 'secret': function() { return secret; }, -- 'myanswer': function() { return myanswer; } --}); - /* harmony import */var _answer__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./answer */"./answer.js"); - - const secret = "888"; -- const myanswer = _answer__WEBPACK_IMPORTED_MODULE_0_.answer, result = 20000; -+ const myanswer = answer, result = 20000; - }, - - },function(__webpack_require__) { diff --git a/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/new_treeshaking.snap b/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/new_treeshaking.snap index 71df4f60855e..980ac3534e7f 100644 --- a/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/new_treeshaking.snap +++ b/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/new_treeshaking.snap @@ -20,9 +20,10 @@ __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { 'test': function() { return test; } }); +/* harmony import */var _module__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./module */"./module.js"); function test() { - doSomething({ + (0, _module__WEBPACK_IMPORTED_MODULE_0_["default"])({ type: "inline" }); } @@ -36,6 +37,46 @@ it("should generate correct code when pure expressions are in dead branches", () ]); }); }, +"./module.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { +'use strict'; +__webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + 'default': function() { return __WEBPACK_DEFAULT_EXPORT__; } +}); + +function getType(obj) { + return obj.type; +} +// Local functions +function doSomethingWithBlock(obj) { + return Block.doSomething(obj); +} +function doSomethingWithInline(obj) { + return Inline.doSomething(obj); +} +function doSomethingWithDocument(obj) { + return Document.doSomething(obj); +} +// Exported functions +function doSomething(obj) { + const type = getType(obj); + switch(type){ + case "document": + return doSomethingWithDocument(obj); + case "block": + return doSomethingWithBlock(obj); + case "inline": + return doSomethingWithInline(obj); + default: + throw new Error(); + } +} +function useDocument(obj) { + return doSomethingWithDocument(obj); +} + +var __WEBPACK_DEFAULT_EXPORT__ = doSomething; +}, },function(__webpack_require__) { var __webpack_exec__ = function(moduleId) { return __webpack_require__(__webpack_require__.s = moduleId) } diff --git a/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/snap.diff b/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/snap.diff index 17ec9d8703d1..e3284fa21ecc 100644 --- a/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/snap.diff +++ b/crates/rspack/tests/tree-shaking/webpack-inner-graph-switch/snapshot/snap.diff @@ -1,74 +1,48 @@ --- expected +++ actual -@@ -20,10 +20,9 @@ +@@ -43,20 +43,19 @@ __webpack_require__.d(__webpack_exports__, { - 'test': function() { return test; } + 'default': function() { return __WEBPACK_DEFAULT_EXPORT__; } }); --/* harmony import */var _module__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./module */"./module.js"); +-/* harmony import */var _some_module__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./some-module */"./some-module.js"); - function test() { -- (0, _module__WEBPACK_IMPORTED_MODULE_0_["default"])({ -+ doSomething({ - type: "inline" - }); + function getType(obj) { + return obj.type; } -@@ -37,47 +36,17 @@ - ]); - }); - }, --"./module.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { --'use strict'; --__webpack_require__.r(__webpack_exports__); --__webpack_require__.d(__webpack_exports__, { -- 'default': function() { return __WEBPACK_DEFAULT_EXPORT__; } --}); --/* harmony import */var _some_module__WEBPACK_IMPORTED_MODULE_0_ = __webpack_require__(/* ./some-module */"./some-module.js"); + // Local functions + function doSomethingWithBlock(obj) { +- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Block.doSomething(obj); ++ return Block.doSomething(obj); + } + function doSomethingWithInline(obj) { +- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Inline.doSomething(obj); ++ return Inline.doSomething(obj); + } + function doSomethingWithDocument(obj) { +- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Document.doSomething(obj); ++ return Document.doSomething(obj); + } + // Exported functions + function doSomething(obj) { +@@ -78,6 +77,17 @@ --function getType(obj) { -- return obj.type; + var __WEBPACK_DEFAULT_EXPORT__ = doSomething; + }, ++ +},function(__webpack_require__) { +var __webpack_exec__ = function(moduleId) { return __webpack_require__(__webpack_require__.s = moduleId) } +var __webpack_exports__ = (__webpack_exec__("./index.js")); + - } --// Local functions --function doSomethingWithBlock(obj) { -- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Block.doSomething(obj); --} --function doSomethingWithInline(obj) { -- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Inline.doSomething(obj); --} --function doSomethingWithDocument(obj) { -- return _some_module__WEBPACK_IMPORTED_MODULE_0_.Document.doSomething(obj); --} --// Exported functions --function doSomething(obj) { -- const type = getType(obj); -- switch(type){ -- case "document": -- return doSomethingWithDocument(obj); -- case "block": -- return doSomethingWithBlock(obj); -- case "inline": -- return doSomethingWithInline(obj); -- default: -- throw new Error(); -- } --} --function useDocument(obj) { -- return doSomethingWithDocument(obj); --} ++} +]); +``` - --var __WEBPACK_DEFAULT_EXPORT__ = doSomething; --}, ++ +```js title=some-module_js.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["some-module_js"], { "./some-module.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { 'use strict'; __webpack_require__.r(__webpack_exports__); -@@ -98,10 +67,5 @@ +@@ -98,10 +108,5 @@ }, diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/harmony_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/harmony_import_specifier_dependency.rs index 06a08f2c75a2..266281789159 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/harmony_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/harmony_import_specifier_dependency.rs @@ -241,6 +241,7 @@ impl ModuleDependency for HarmonyImportSpecifierDependency { } fn get_condition(&self) -> Option { + // dbg!(&self.ids, self.request(), self.used_by_exports.as_ref()); get_dependency_used_by_exports_condition(self.id, self.used_by_exports.as_ref()) } diff --git a/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs b/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs index 6318883b06ed..ff4253d60b78 100644 --- a/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs +++ b/crates/rspack_plugin_javascript/src/parser_and_generator/mod.rs @@ -208,6 +208,7 @@ impl ParserAndGenerator for JavaScriptParserAndGenerator { RawSource::from(content).boxed() } if let Some(mut inner_graph) = inner_graph { + dbg!(module_identifier); inner_graph.infer_dependency_usage(); } diff --git a/crates/rspack_plugin_javascript/src/plugin/inner_graph_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/inner_graph_plugin.rs index 6cddecdf7713..600ab68a22e7 100644 --- a/crates/rspack_plugin_javascript/src/plugin/inner_graph_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/inner_graph_plugin.rs @@ -1,4 +1,4 @@ -use std::collections::hash_map::Entry; +use std::{collections::hash_map::Entry, hash::Hash}; use rspack_core::{Dependency, SpanExt, UsedByExports}; use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; @@ -7,8 +7,8 @@ use swc_core::{ ecma::{ ast::{ ArrowExpr, CallExpr, Callee, Class, ClassDecl, ClassMember, DefaultDecl, ExportDecl, - ExportDefaultDecl, ExportDefaultExpr, Expr, FnDecl, FnExpr, Ident, MemberExpr, Pat, Program, - Prop, VarDeclarator, + ExportDefaultDecl, ExportDefaultExpr, ExportSpecifier, Expr, FnDecl, FnExpr, Ident, + MemberExpr, NamedExport, Pat, Program, Prop, VarDeclarator, }, atoms::JsWord, visit::{noop_visit_type, Visit, VisitWith}, @@ -18,7 +18,7 @@ use swc_core::{ use crate::{ dependency::PureExpressionDependency, plugin::side_effects_flag_plugin::{is_pure_class, is_pure_expression}, - visitors::harmony_import_dependency_scanner::ImportMap, + visitors::{harmony_import_dependency_scanner::ImportMap, ExtraSpanInfo}, ClassKey, }; @@ -79,7 +79,7 @@ pub struct InnerGraphPlugin<'a> { top_level_ctxt: SyntaxContext, state: InnerGraphState, scope_level: usize, - rewrite_usage_span: &'a mut HashSet, + rewrite_usage_span: &'a mut HashMap, import_map: &'a ImportMap, } @@ -107,15 +107,19 @@ impl<'a> Visit for InnerGraphPlugin<'a> { } fn visit_member_expr(&mut self, member_expr: &MemberExpr) { - if self.rewrite_usage_span.contains(&member_expr.span) { - let span = member_expr.span; - self.on_usage(Box::new(move |deps, used_by_exports| { - let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); - if let Some(dep) = target_dep { - dep.set_used_by_exports(used_by_exports); - } - })); - } + match self.rewrite_usage_span.get(&member_expr.span) { + Some(ExtraSpanInfo::ReWriteUsedByExports) => { + let span = member_expr.span; + self.on_usage(Box::new(move |deps, used_by_exports| { + let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); + if let Some(dep) = target_dep { + dep.set_used_by_exports(used_by_exports); + } + })); + } + // member_expr is not possible to add a variable usage + _ => {} + }; } fn visit_class_member(&mut self, node: &ClassMember) { @@ -144,13 +148,12 @@ impl<'a> Visit for InnerGraphPlugin<'a> { self.set_symbol_if_is_top_level(node.ident.sym.clone()); let scope_level = self.scope_level; self.scope_level += 1; - println!("enter fun{}", node.ident.sym); node.function.visit_children_with(self); - println!("leave fun{}", node.ident.sym); self.scope_level = scope_level; self.clear_symbol_if_is_top_level(); } + // TODO: expr fn visit_fn_expr(&mut self, node: &FnExpr) { let scope_level = self.scope_level; self.scope_level += 1; @@ -178,15 +181,19 @@ impl<'a> Visit for InnerGraphPlugin<'a> { } fn visit_ident(&mut self, ident: &Ident) { - if self.rewrite_usage_span.contains(&ident.span) { - let span = ident.span; - self.on_usage(Box::new(move |deps, used_by_exports| { - let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); - if let Some(dep) = target_dep { - dep.set_used_by_exports(used_by_exports); - } - })); - } + match self.rewrite_usage_span.get(&ident.span) { + Some(ExtraSpanInfo::ReWriteUsedByExports) => { + let span = ident.span; + self.on_usage(Box::new(move |deps, used_by_exports| { + let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); + if let Some(dep) = target_dep { + dep.set_used_by_exports(used_by_exports); + } + })); + } + // ident is impossible to add a variable usage + _ => {} + }; // imported binding isn't considered as a top level symbol. if self.import_map.contains_key(&ident.to_id()) { return; @@ -243,20 +250,30 @@ impl<'a> Visit for InnerGraphPlugin<'a> { fn visit_prop(&mut self, n: &Prop) { match n { Prop::Shorthand(shorthand) => { - if self.rewrite_usage_span.contains(&shorthand.span) { - let span = shorthand.span; - self.on_usage(Box::new(move |deps, used_by_exports| { - let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); - if let Some(dep) = target_dep { - dep.set_used_by_exports(used_by_exports); - } - })); - } + match self.rewrite_usage_span.get(&shorthand.span) { + Some(ExtraSpanInfo::ReWriteUsedByExports) => { + let span = shorthand.span; + self.on_usage(Box::new(move |deps, used_by_exports| { + let target_dep = deps.iter_mut().find(|item| item.is_span_equal(&span)); + if let Some(dep) = target_dep { + dep.set_used_by_exports(used_by_exports); + } + })); + } + // prop is impossible to add a variable usage + _ => {} + }; } _ => n.visit_children_with(self), } } fn visit_export_decl(&mut self, export_decl: &ExportDecl) { + match self.rewrite_usage_span.get(&export_decl.span) { + Some(ExtraSpanInfo::AddVariableUsage(sym, usage)) => { + self.add_variable_usage(sym.clone(), usage.clone()); + } + _ => {} + } // match &export_decl.decl { // Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => { // // self.add_variable_usage(ident.sym.clone(), ident.sym.clone()); @@ -272,11 +289,29 @@ impl<'a> Visit for InnerGraphPlugin<'a> { // } export_decl.visit_children_with(self); } + + fn visit_named_export(&mut self, named_export: &NamedExport) { + if named_export.src.is_none() { + named_export + .specifiers + .iter() + .for_each(|specifier| match specifier { + ExportSpecifier::Named(named) => match self.rewrite_usage_span.get(&named.span) { + Some(ExtraSpanInfo::AddVariableUsage(sym, usage)) => { + self.add_variable_usage(sym.clone(), usage.clone()); + } + _ => {} + }, + _ => unreachable!(), + }); + } + } fn visit_export_default_expr(&mut self, node: &ExportDefaultExpr) { if !self.is_enabled() { return; } // exportExpression start + // TODO: use rewrite Usage span instead let symbol: JsWord = "*default*".into(); let usage_name = match node.expr { box Expr::Fn(ref func) => func @@ -346,7 +381,7 @@ impl<'a> InnerGraphPlugin<'a> { dependencies: &'a mut Vec>, unresolved_ctxt: SyntaxContext, top_level_ctxt: SyntaxContext, - rewrite_usage_span: &'a mut HashSet, + rewrite_usage_span: &'a mut HashMap, import_map: &'a ImportMap, ) -> Self { Self { @@ -485,8 +520,9 @@ impl<'a> InnerGraphPlugin<'a> { for key in non_terminal.iter() { let mut new_set = HashSet::default(); // Using enum to manipulate original is pretty hard, so I use an extra variable to - //mark if the new set has changed to an set - let mut new_set_is_true = false; + // flagging the new set has changed to boolean `true` + // you could refer https://github.com/webpack/webpack/blob/ac7e531436b0d47cd88451f497cdfd0dad41535d/lib/optimize/InnerGraph.js#L150 + let mut set_is_true = false; let mut is_terminal = true; let already_processed = processed.entry(key.clone()).or_default(); if let Some(InnerGraphMapValue::Set(names)) = state.inner_graph.get(key) { @@ -502,7 +538,7 @@ impl<'a> InnerGraphPlugin<'a> { let item_value = state.inner_graph.get(v); match item_value { Some(InnerGraphMapValue::True) => { - new_set_is_true = true; + set_is_true = true; break; } Some(InnerGraphMapValue::Set(item_value)) => { @@ -524,7 +560,7 @@ impl<'a> InnerGraphPlugin<'a> { } } } - if new_set_is_true { + if set_is_true { state .inner_graph .insert(key.clone(), InnerGraphMapValue::True); @@ -575,8 +611,10 @@ impl<'a> InnerGraphPlugin<'a> { } } + dbg!(&state.inner_graph); for (symbol, cbs) in state.usage_callback_map.iter() { let usage = state.inner_graph.get(symbol); + dbg!(symbol, usage); for cb in cbs { let used_by_exports = if let Some(usage) = usage { match usage { @@ -591,6 +629,7 @@ impl<'a> InnerGraphPlugin<'a> { } else { UsedByExports::Bool(false) }; + cb(self.dependencies, Some(used_by_exports)); } } diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_export_dependency_scanner.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_export_dependency_scanner.rs index 42c39fd48003..7b21a08517ad 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_export_dependency_scanner.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_export_dependency_scanner.rs @@ -2,8 +2,9 @@ use rspack_core::{ tree_shaking::symbol::DEFAULT_JS_WORD, BoxDependency, BoxDependencyTemplate, BuildInfo, ConstDependency, SpanExt, }; +use rustc_hash::FxHashMap as HashMap; use swc_core::{ - common::Spanned, + common::{Span, Spanned}, ecma::{ ast::{ ClassDecl, Decl, DefaultDecl, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, @@ -14,7 +15,7 @@ use swc_core::{ }, }; -use super::harmony_import_dependency_scanner::ImportMap; +use super::{harmony_import_dependency_scanner::ImportMap, ExtraSpanInfo}; use crate::dependency::{ AnonymousFunctionRangeInfo, HarmonyExportExpressionDependency, HarmonyExportHeaderDependency, HarmonyExportImportedSpecifierDependency, HarmonyExportSpecifierDependency, Specifier, @@ -26,6 +27,7 @@ pub struct HarmonyExportDependencyScanner<'a> { pub presentational_dependencies: &'a mut Vec, pub import_map: &'a mut ImportMap, pub build_info: &'a mut BuildInfo, + pub rewrite_usage_span: &'a mut HashMap, } impl<'a> HarmonyExportDependencyScanner<'a> { @@ -34,12 +36,14 @@ impl<'a> HarmonyExportDependencyScanner<'a> { presentational_dependencies: &'a mut Vec, import_map: &'a mut ImportMap, build_info: &'a mut BuildInfo, + rewrite_usage_span: &'a mut HashMap, ) -> Self { Self { dependencies, presentational_dependencies, import_map, build_info, + rewrite_usage_span, } } } @@ -60,6 +64,11 @@ impl Visit for HarmonyExportDependencyScanner<'_> { ident.sym.clone(), ident.sym.clone(), ))); + + self.rewrite_usage_span.insert( + export_decl.span(), + ExtraSpanInfo::AddVariableUsage(ident.sym.clone(), ident.sym.clone()), + ); self .build_info .harmony_named_exports @@ -75,6 +84,11 @@ impl Visit for HarmonyExportDependencyScanner<'_> { ident.sym.clone(), ident.sym.clone(), ))); + + self.rewrite_usage_span.insert( + export_decl.span(), + ExtraSpanInfo::AddVariableUsage(ident.sym.clone(), ident.sym.clone()), + ); self.build_info.harmony_named_exports.insert(ident.sym); }); } @@ -125,6 +139,11 @@ impl Visit for HarmonyExportDependencyScanner<'_> { export.clone(), orig.sym.clone(), ))); + + self.rewrite_usage_span.insert( + named.span(), + ExtraSpanInfo::AddVariableUsage(orig.sym.clone(), export.clone()), + ); self.build_info.harmony_named_exports.insert(export); } } @@ -144,6 +163,7 @@ impl Visit for HarmonyExportDependencyScanner<'_> { fn visit_export_default_expr(&mut self, export_default_expr: &'_ ExportDefaultExpr) { // TODO this should be at `HarmonyExportExpressionDependency` + // TODO: add variable usage self .dependencies .push(Box::new(HarmonyExportSpecifierDependency::new( @@ -169,6 +189,7 @@ impl Visit for HarmonyExportDependencyScanner<'_> { }; // TODO this should be at `HarmonyExportExpressionDependency` + // TODO: add variable usage self .dependencies .push(Box::new(HarmonyExportSpecifierDependency::new( diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_import_dependency_scanner.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_import_dependency_scanner.rs index 37015560e788..a6416341da7a 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_import_dependency_scanner.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/harmony_import_dependency_scanner.rs @@ -17,7 +17,7 @@ use swc_core::{ }, }; -use super::collect_destructuring_assignment_properties; +use super::{collect_destructuring_assignment_properties, ExtraSpanInfo}; use crate::dependency::{ HarmonyExportImportedSpecifierDependency, HarmonyImportSideEffectDependency, HarmonyImportSpecifierDependency, Specifier, @@ -73,7 +73,7 @@ pub struct HarmonyImportDependencyScanner<'a> { pub import_map: &'a mut ImportMap, pub imports: Imports, pub build_info: &'a mut BuildInfo, - pub rewrite_usage_span: &'a mut HashSet, + pub rewrite_usage_span: &'a mut HashMap, last_harmony_import_order: i32, } @@ -83,7 +83,7 @@ impl<'a> HarmonyImportDependencyScanner<'a> { presentational_dependencies: &'a mut Vec, import_map: &'a mut ImportMap, build_info: &'a mut BuildInfo, - rewrite_usage_span: &'a mut HashSet, + rewrite_usage_span: &'a mut HashMap, ) -> Self { Self { dependencies, @@ -341,15 +341,14 @@ pub struct HarmonyImportRefDependencyScanner<'a> { pub import_map: &'a ImportMap, pub dependencies: &'a mut Vec, pub properties_in_destructuring: HashMap>, - - pub rewrite_usage_span: &'a mut HashSet, + pub rewrite_usage_span: &'a mut HashMap, } impl<'a> HarmonyImportRefDependencyScanner<'a> { pub fn new( import_map: &'a ImportMap, dependencies: &'a mut Vec, - rewrite_usage_span: &'a mut HashSet, + rewrite_usage_span: &'a mut HashMap, ) -> Self { Self { import_map, @@ -379,7 +378,9 @@ impl Visit for HarmonyImportRefDependencyScanner<'_> { fn visit_prop(&mut self, n: &Prop) { match n { Prop::Shorthand(shorthand) => { - self.rewrite_usage_span.insert(shorthand.span); + self + .rewrite_usage_span + .insert(shorthand.span, ExtraSpanInfo::ReWriteUsedByExports); if let Some(reference) = self.import_map.get(&shorthand.to_id()) { self .dependencies @@ -403,7 +404,9 @@ impl Visit for HarmonyImportRefDependencyScanner<'_> { fn visit_ident(&mut self, ident: &Ident) { if let Some(reference) = self.import_map.get(&ident.to_id()) { - self.rewrite_usage_span.insert(ident.span); + self + .rewrite_usage_span + .insert(ident.span, ExtraSpanInfo::ReWriteUsedByExports); self .dependencies .push(Box::new(HarmonyImportSpecifierDependency::new( @@ -438,7 +441,9 @@ impl Visit for HarmonyImportRefDependencyScanner<'_> { if let Some(prop) = prop { let mut ids = reference.names.clone().map(|f| vec![f]).unwrap_or_default(); ids.push(prop); - self.rewrite_usage_span.insert(member_expr.span); + self + .rewrite_usage_span + .insert(member_expr.span, ExtraSpanInfo::ReWriteUsedByExports); self .dependencies .push(Box::new(HarmonyImportSpecifierDependency::new( diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs index bc3264146c2d..8bb66794d5af 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/mod.rs @@ -20,9 +20,10 @@ use rspack_core::{ ast::javascript::Program, BoxDependency, BoxDependencyTemplate, BuildInfo, BuildMeta, CompilerOptions, ModuleIdentifier, ModuleType, ResourceData, }; -use rustc_hash::FxHashSet as HashSet; +use rustc_hash::FxHashMap as HashMap; use swc_core::common::Span; use swc_core::common::{comments::Comments, Mark, SyntaxContext}; +use swc_core::ecma::atoms::JsWord; pub use util::*; use self::harmony_import_dependency_scanner::ImportMap; @@ -43,10 +44,18 @@ use self::{ pub struct ScanDependenciesResult { pub dependencies: Vec, pub presentational_dependencies: Vec, - pub rewrite_usage_span: HashSet, + // TODO: rename this name + pub rewrite_usage_span: HashMap, pub import_map: ImportMap, } +#[derive(Debug, Clone)] +pub enum ExtraSpanInfo { + ReWriteUsedByExports, + // (symbol, usage) + // (local, exported) refer https://github.com/webpack/webpack/blob/ac7e531436b0d47cd88451f497cdfd0dad41535d/lib/javascript/JavascriptParser.js#L2347-L2352 + AddVariableUsage(JsWord, JsWord), +} #[allow(clippy::too_many_arguments)] pub fn scan_dependencies( program: &Program, @@ -64,7 +73,7 @@ pub fn scan_dependencies( let comments = program.comments.clone(); let mut parser_exports_state = None; - let mut rewrite_usage_span = HashSet::default(); + let mut rewrite_usage_span = HashMap::default(); program.visit_with(&mut ApiScanner::new( &unresolved_ctxt, resource_data, @@ -133,6 +142,7 @@ pub fn scan_dependencies( &mut presentational_dependencies, &mut import_map, build_info, + &mut rewrite_usage_span, )); let mut worker_syntax_scanner = rspack_core::needs_refactor::WorkerSyntaxScanner::new( rspack_core::needs_refactor::DEFAULT_WORKER_SYNTAX,