Skip to content

Commit

Permalink
fix: amd define in function params (#9088)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk authored Jan 22, 2025
1 parent 060ab07 commit 28b9a96
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use swc_core::{
},
};

use super::JavascriptParserPlugin;
use crate::{
dependency::{
amd_define_dependency::AmdDefineDependency,
Expand All @@ -22,6 +21,7 @@ use crate::{
},
utils::eval::BasicEvaluatedExpression,
visitors::{scope_info::FreeName, JavascriptParser, Statement},
JavascriptParserPlugin,
};

pub struct AMDDefineDependencyParserPlugin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use rspack_core::{ConstDependency, RuntimeGlobals, SpanExt};
use swc_core::ecma::ast::{CallExpr, Expr, MemberExpr};
use swc_core::{common::Spanned, ecma::ast::UnaryExpr};

use super::JavascriptParserPlugin;
use crate::utils::eval::{evaluate_to_identifier, evaluate_to_string, BasicEvaluatedExpression};
use crate::visitors::{expr_matcher, JavascriptParser};
use crate::visitors::JavascriptParser;
use crate::JavascriptParserPlugin;

pub struct RequireJsStuffPlugin;
pub struct AMDParserPlugin;

const DEFINE: &str = "define";
const REQUIRE: &str = "require";
const DEFINE_AMD: &str = "define.amd";
const REQUIRE_AMD: &str = "require.amd";

impl JavascriptParserPlugin for RequireJsStuffPlugin {
impl JavascriptParserPlugin for AMDParserPlugin {
fn call(
&self,
parser: &mut JavascriptParser,
Expand All @@ -29,19 +29,18 @@ impl JavascriptParserPlugin for RequireJsStuffPlugin {
"undefined".into(),
None,
)));
Some(true)
} else {
None
return Some(true);
}
None
}

fn member(
&self,
parser: &mut JavascriptParser,
expr: &MemberExpr,
_for_name: &str,
for_name: &str,
) -> Option<bool> {
if expr_matcher::is_require_version(expr) {
if for_name == "require.version" {
parser
.presentational_dependencies
.push(Box::new(ConstDependency::new(
Expand All @@ -52,8 +51,7 @@ impl JavascriptParserPlugin for RequireJsStuffPlugin {
)));
return Some(true);
}

if expr_matcher::is_require_onerror(expr) || expr_matcher::is_requirejs_onerror(expr) {
if for_name == "requirejs.onError" {
parser
.presentational_dependencies
.push(Box::new(ConstDependency::new(
Expand All @@ -65,8 +63,8 @@ impl JavascriptParserPlugin for RequireJsStuffPlugin {
return Some(true);
}

// AMDPlugin
if expr_matcher::is_define_amd(expr) || expr_matcher::is_require_amd(expr) {
// AMD
if for_name == "define.amd" || for_name == "require.amd" {
parser
.presentational_dependencies
.push(Box::new(ConstDependency::new(
Expand All @@ -77,7 +75,6 @@ impl JavascriptParserPlugin for RequireJsStuffPlugin {
)));
return Some(true);
}

None
}

Expand Down Expand Up @@ -191,7 +188,7 @@ impl JavascriptParserPlugin for RequireJsStuffPlugin {
RuntimeGlobals::AMD_DEFINE.name().into(),
Some(RuntimeGlobals::AMD_DEFINE),
)));
return Some(true);
return Some(false);
}
None
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ use swc_core::{
ecma::ast::{BlockStmtOrExpr, CallExpr, ExprOrSpread, Pat},
};

use super::{
require_ensure_dependencies_block_parse_plugin::GetFunctionExpression, JavascriptParserPlugin,
};
use crate::{
dependency::{
amd_require_dependency::AMDRequireDependency,
amd_require_item_dependency::AMDRequireItemDependency,
local_module_dependency::LocalModuleDependency, unsupported_dependency::UnsupportedDependency,
},
parser_plugin::require_ensure_dependencies_block_parse_plugin::GetFunctionExpression,
utils::eval::BasicEvaluatedExpression,
visitors::{create_traceable_error, JavascriptParser, Statement},
JavascriptParserPlugin,
};

fn is_reserved_param(pat: &Pat) -> bool {
Expand Down
7 changes: 7 additions & 0 deletions crates/rspack_plugin_javascript/src/parser_plugin/amd/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod amd_define_dependency_parser_plugin;
mod amd_plugin;
mod amd_require_dependencies_block_parser_plugin;

pub use amd_define_dependency_parser_plugin::AMDDefineDependencyParserPlugin;
pub use amd_plugin::AMDParserPlugin;
pub use amd_require_dependencies_block_parser_plugin::AMDRequireDependenciesBlockParserPlugin;
10 changes: 4 additions & 6 deletions crates/rspack_plugin_javascript/src/parser_plugin/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod amd;
mod api_plugin;
mod check_var_decl;
mod common_js_exports_parse_plugin;
Expand Down Expand Up @@ -27,15 +28,13 @@ mod use_strict_plugin;
mod webpack_included_plugin;
mod worker_plugin;

pub mod amd_define_dependency_parser_plugin;
pub mod amd_require_dependencies_block_parser_plugin;
pub mod define_plugin;
pub mod hot_module_replacement_plugin;
pub mod provide_plugin;
pub mod require_js_stuff_plugin;

pub(crate) use self::amd_define_dependency_parser_plugin::AMDDefineDependencyParserPlugin;
pub(crate) use self::amd_require_dependencies_block_parser_plugin::AMDRequireDependenciesBlockParserPlugin;
pub(crate) use self::amd::AMDDefineDependencyParserPlugin;
pub(crate) use self::amd::AMDParserPlugin;
pub(crate) use self::amd::AMDRequireDependenciesBlockParserPlugin;
pub(crate) use self::api_plugin::APIPlugin;
pub(crate) use self::check_var_decl::CheckVarDeclaratorIdent;
pub(crate) use self::common_js_exports_parse_plugin::CommonJsExportsParserPlugin;
Expand All @@ -60,7 +59,6 @@ pub(crate) use self::r#const::{is_logic_op, ConstPlugin};
pub use self::r#trait::{BoxJavascriptParserPlugin, JavascriptParserPlugin};
pub(crate) use self::require_context_dependency_parser_plugin::RequireContextDependencyParserPlugin;
pub(crate) use self::require_ensure_dependencies_block_parse_plugin::RequireEnsureDependenciesBlockParserPlugin;
pub(crate) use self::require_js_stuff_plugin::RequireJsStuffPlugin;
pub(crate) use self::url_plugin::URLPlugin;
pub(crate) use self::use_strict_plugin::UseStrictPlugin;
pub(crate) use self::webpack_included_plugin::WebpackIsIncludedPlugin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ impl<'parser> JavascriptParser<'parser> {
parser_plugin::AMDRequireDependenciesBlockParserPlugin,
));
plugins.push(Box::new(parser_plugin::AMDDefineDependencyParserPlugin));
plugins.push(Box::new(parser_plugin::RequireJsStuffPlugin));
plugins.push(Box::new(parser_plugin::AMDParserPlugin));
}

if module_type.is_js_auto() || module_type.is_js_dynamic() {
Expand Down
144 changes: 73 additions & 71 deletions crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use super::{
TopLevelScope,
};
use crate::parser_plugin::{is_logic_op, JavascriptParserPlugin};
use crate::visitors::scope_info::{FreeName, VariableInfo};
use crate::visitors::scope_info::FreeName;

fn warp_ident_to_pat(ident: Ident) -> Pat {
Pat::Ident(ident.into())
Expand Down Expand Up @@ -791,31 +791,70 @@ impl JavascriptParser<'_> {
fn _walk_iife<'a>(
&mut self,
expr: &'a Expr,
params: impl Iterator<Item = &'a Expr>,
args: impl Iterator<Item = &'a Expr>,
current_this: Option<&'a Expr>,
) {
let mut fn_params = vec![];
fn get_var_name(parser: &mut JavascriptParser, expr: &Expr) -> Option<String> {
if let Some(rename_identifier) = parser.get_rename_identifier(expr)
&& let drive = parser.plugin_drive.clone()
&& rename_identifier
.call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name))
.unwrap_or_default()
&& !rename_identifier
.call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name))
.unwrap_or_default()
{
let variable = parser
.get_variable_info(&rename_identifier)
.map(|info| info.free_name.as_ref())
.and_then(|free_name| free_name)
.and_then(|free_name| match free_name {
FreeName::String(s) => Some(s.to_string()),
FreeName::True => None,
})
.unwrap_or(rename_identifier);
return Some(variable);
}
parser.walk_expression(expr);
None
}

let rename_this = current_this.and_then(|this| get_var_name(self, this));
let variable_info_for_args = args
.map(|param| get_var_name(self, param))
.collect::<Vec<_>>();

let mut params = vec![];
let mut scope_params = vec![];
if let Some(expr) = expr.as_fn_expr() {
for param in &expr.function.params {
let ident = param.pat.as_ident().expect("should be a `BindingIdent`");
fn_params.push(ident);
if get_variable_info(self, &Expr::Ident(ident.id.clone())).is_none() {
scope_params.push(Cow::Borrowed(&param.pat));
if let Some(fn_expr) = expr.as_fn_expr() {
for (i, pat) in fn_expr.function.params.iter().map(|p| &p.pat).enumerate() {
// SAFETY: is_simple_function will ensure pat is always a BindingIdent.
let ident = pat.as_ident().expect("should be a `BindingIdent`");
params.push(ident);
if variable_info_for_args
.get(i)
.and_then(|i| i.as_deref())
.is_none()
{
scope_params.push(Cow::Borrowed(pat));
}
}
} else if let Some(expr) = expr.as_arrow() {
for param in &expr.params {
let ident = param.as_ident().expect("should be a `BindingIdent`");
fn_params.push(ident);
if get_variable_info(self, &Expr::Ident(ident.id.clone())).is_none() {
scope_params.push(Cow::Borrowed(param));
} else if let Some(arrow_expr) = expr.as_arrow() {
for (i, pat) in arrow_expr.params.iter().enumerate() {
// SAFETY: is_simple_function will ensure pat is always a BindingIdent.
let ident = pat.as_ident().expect("should be a `BindingIdent`");
params.push(ident);
if variable_info_for_args
.get(i)
.and_then(|i| i.as_deref())
.is_none()
{
scope_params.push(Cow::Borrowed(pat));
}
}
};
let variable_info_for_args = params
.map(|param| get_variable_name(self, param))
.collect::<Vec<_>>();
}

// Add function name in scope for recursive calls
if let Some(expr) = expr.as_fn_expr() {
if let Some(ident) = &expr.ident {
scope_params.push(Cow::Owned(Pat::Ident(ident.clone().into())));
Expand All @@ -824,24 +863,24 @@ impl JavascriptParser<'_> {

let was_top_level_scope = self.top_level_scope;
self.top_level_scope =
if !matches!(was_top_level_scope, TopLevelScope::False) && expr.as_arrow().is_some() {
if !matches!(was_top_level_scope, TopLevelScope::False) && expr.is_arrow() {
TopLevelScope::ArrowFunction
} else {
TopLevelScope::False
};

let rename_this = current_this.and_then(|this| get_variable_name(self, this));
self.in_function_scope(true, scope_params.into_iter(), |parser| {
if let Some(this) = rename_this
&& matches!(expr, Expr::Fn(_))
&& !expr.is_arrow()
{
parser.set_variable("this".to_string(), this)
}
for (variable_info, param) in variable_info_for_args.into_iter().zip(fn_params) {
let Some(variable_info) = variable_info else {
continue;
};
parser.set_variable(param.sym.to_string(), variable_info);
for (i, var_info) in variable_info_for_args.into_iter().enumerate() {
if let Some(var_info) = var_info
&& let Some(param) = params.get(i)
{
parser.set_variable(param.sym.to_string(), var_info);
}
}

if let Some(expr) = expr.as_fn_expr() {
Expand Down Expand Up @@ -989,6 +1028,7 @@ impl JavascriptParser<'_> {
} else {
self.walk_expression(callee);
}
self.walk_expr_or_spread(&expr.args);
}
}
Callee::Import(_) => {
Expand All @@ -1002,11 +1042,15 @@ impl JavascriptParser<'_> {
self.enter_call -= 1;
return;
}

self.walk_expr_or_spread(&expr.args);
}
Callee::Super(_) => {
// Do nothing about super, same as webpack
self.walk_expr_or_spread(&expr.args);
}
Callee::Super(_) => {} // Do nothing about super, same as webpack
}

self.walk_expr_or_spread(&expr.args);
self.enter_call -= 1;
}

Expand Down Expand Up @@ -1481,45 +1525,3 @@ fn member_prop_len(member_prop: &MemberProp) -> Option<usize> {
MemberProp::Computed(_) => None,
}
}

fn get_variable_info<'p>(
parser: &'p mut JavascriptParser,
expr: &Expr,
) -> Option<&'p VariableInfo> {
if let Some(rename_identifier) = parser.get_rename_identifier(expr)
&& let drive = parser.plugin_drive.clone()
&& rename_identifier
.call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name))
.unwrap_or_default()
&& !rename_identifier
.call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name))
.unwrap_or_default()
{
return parser.get_variable_info(&rename_identifier);
}
None
}

fn get_variable_name(parser: &mut JavascriptParser, expr: &Expr) -> Option<String> {
if let Some(rename_identifier) = parser.get_rename_identifier(expr)
&& let drive = parser.plugin_drive.clone()
&& rename_identifier
.call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name))
.unwrap_or_default()
&& !rename_identifier
.call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name))
.unwrap_or_default()
{
let variable = parser
.get_variable_info(&rename_identifier)
.map(|info| info.free_name.as_ref())
.and_then(|free_name| free_name)
.and_then(|free_name| match free_name {
FreeName::String(s) => Some(s.to_string()),
FreeName::True => None,
})
.unwrap_or(rename_identifier);
return Some(variable);
}
None
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,7 @@ pub(crate) mod expr_matcher {
is_object_define_property: "Object.defineProperty",
is_require_ensure: "require.ensure",
is_require_version: "require.version",
is_require_amd: "require.amd",
is_require_onerror: "require.onError",
is_requirejs_onerror: "requirejs.onError",
is_define_amd: "define.amd",
// unsupported
is_require_extensions: "require.extensions",
is_require_config: "require.config",
Expand Down
Loading

2 comments on commit 28b9a96

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on 28b9a96 Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ecosystem CI detail: Open

suite result
modernjs ❌ failure
rspress ✅ success
rslib ✅ success
rsbuild ✅ success
rsdoctor ✅ success
examples ✅ success
devserver ✅ success
nuxt ✅ success

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on 28b9a96 Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2025-01-21 c06787b) Current Change
10000_big_production-mode_disable-minimize + exec 36.7 s ± 515 ms 37.9 s ± 1.13 s +3.33 %
10000_development-mode + exec 1.86 s ± 52 ms 1.82 s ± 24 ms -2.33 %
10000_development-mode_hmr + exec 681 ms ± 9.8 ms 684 ms ± 6.1 ms +0.41 %
10000_production-mode + exec 2.45 s ± 138 ms 2.36 s ± 50 ms -3.63 %
10000_production-mode_persistent-cold + exec 2.61 s ± 155 ms 2.55 s ± 182 ms -2.26 %
10000_production-mode_persistent-hot + exec 1.77 s ± 116 ms 1.73 s ± 44 ms -2.11 %
arco-pro_development-mode + exec 1.76 s ± 98 ms 1.74 s ± 123 ms -1.00 %
arco-pro_development-mode_hmr + exec 388 ms ± 2.3 ms 388 ms ± 1.8 ms +0.11 %
arco-pro_production-mode + exec 3.64 s ± 257 ms 3.68 s ± 152 ms +1.03 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.75 s ± 314 ms 3.78 s ± 147 ms +0.61 %
arco-pro_production-mode_persistent-cold + exec 3.8 s ± 165 ms 3.85 s ± 191 ms +1.38 %
arco-pro_production-mode_persistent-hot + exec 2.34 s ± 79 ms 2.48 s ± 200 ms +6.11 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.67 s ± 99 ms 3.64 s ± 200 ms -0.75 %
large-dyn-imports_development-mode + exec 2.11 s ± 29 ms 2.09 s ± 73 ms -0.99 %
large-dyn-imports_production-mode + exec 2.16 s ± 40 ms 2.13 s ± 32 ms -1.62 %
threejs_development-mode_10x + exec 1.53 s ± 22 ms 1.53 s ± 48 ms -0.08 %
threejs_development-mode_10x_hmr + exec 788 ms ± 39 ms 785 ms ± 16 ms -0.39 %
threejs_production-mode_10x + exec 5.25 s ± 61 ms 5.44 s ± 412 ms +3.60 %
threejs_production-mode_10x_persistent-cold + exec 5.35 s ± 65 ms 5.5 s ± 408 ms +2.84 %
threejs_production-mode_10x_persistent-hot + exec 4.5 s ± 44 ms 4.59 s ± 238 ms +2.05 %
10000_big_production-mode_disable-minimize + rss memory 8680 MiB ± 34.2 MiB 8699 MiB ± 75.2 MiB +0.22 %
10000_development-mode + rss memory 656 MiB ± 19.6 MiB 672 MiB ± 29 MiB +2.49 %
10000_development-mode_hmr + rss memory 1264 MiB ± 163 MiB 1281 MiB ± 137 MiB +1.38 %
10000_production-mode + rss memory 639 MiB ± 31 MiB 674 MiB ± 27.3 MiB +5.35 %
10000_production-mode_persistent-cold + rss memory 744 MiB ± 15.6 MiB 770 MiB ± 36.9 MiB +3.49 %
10000_production-mode_persistent-hot + rss memory 723 MiB ± 37.7 MiB 754 MiB ± 22 MiB +4.25 %
arco-pro_development-mode + rss memory 553 MiB ± 38.1 MiB 597 MiB ± 22.9 MiB +7.99 %
arco-pro_development-mode_hmr + rss memory 631 MiB ± 36 MiB 673 MiB ± 98.8 MiB +6.62 %
arco-pro_production-mode + rss memory 738 MiB ± 66.3 MiB 754 MiB ± 36.8 MiB +2.16 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 730 MiB ± 23.1 MiB 755 MiB ± 37.4 MiB +3.49 %
arco-pro_production-mode_persistent-cold + rss memory 844 MiB ± 36.6 MiB 882 MiB ± 16.5 MiB +4.56 %
arco-pro_production-mode_persistent-hot + rss memory 695 MiB ± 19.9 MiB 773 MiB ± 30.5 MiB +11.23 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 727 MiB ± 32.5 MiB 761 MiB ± 22.2 MiB +4.68 %
large-dyn-imports_development-mode + rss memory 642 MiB ± 4.5 MiB 668 MiB ± 6.31 MiB +4.07 %
large-dyn-imports_production-mode + rss memory 523 MiB ± 4.79 MiB 538 MiB ± 15.6 MiB +2.80 %
threejs_development-mode_10x + rss memory 551 MiB ± 32.9 MiB 552 MiB ± 15.6 MiB +0.16 %
threejs_development-mode_10x_hmr + rss memory 1145 MiB ± 125 MiB 1049 MiB ± 150 MiB -8.33 %
threejs_production-mode_10x + rss memory 865 MiB ± 36.9 MiB 860 MiB ± 36.7 MiB -0.62 %
threejs_production-mode_10x_persistent-cold + rss memory 968 MiB ± 136 MiB 929 MiB ± 144 MiB -4.04 %
threejs_production-mode_10x_persistent-hot + rss memory 870 MiB ± 25.8 MiB 881 MiB ± 19.9 MiB +1.25 %

Threshold exceeded: ["arco-pro_production-mode_persistent-hot + exec"]

Please sign in to comment.