Repository: vercel/next.js
Pull request: Turbopack: cleanup Effect::MemberCall

Probably marginally faster to do a single link step here than 3 `link` calls. And certainly cleaner

Closes PACK-5346

Changed files:
filename: turbopack/crates/turbopack-ecmascript/src/analyzer/mod.rs
patch: @@ -1810,7 +1810,19 @@ impl JsValue {
             }
             JsValue::WellKnownFunction(func) => {
                 let (name, explainer) = match func {
-                   WellKnownFunctionKind::ObjectAssign => (
+                    WellKnownFunctionKind::ArrayFilter => (
+                      "Array.prototype.filter".to_string(),
+                      "The standard Array.prototype.filter method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter"
+                    ),
+                    WellKnownFunctionKind::ArrayForEach => (
+                      "Array.prototype.forEach".to_string(),
+                      "The standard Array.prototype.forEach method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"
+                    ),
+                    WellKnownFunctionKind::ArrayMap => (
+                      "Array.prototype.map".to_string(),
+                      "The standard Array.prototype.map method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"
+                    ),
+                    WellKnownFunctionKind::ObjectAssign => (
                         "Object.assign".to_string(),
                         "Object.assign method: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign",
                     ),
@@ -3533,6 +3545,9 @@ impl Hash for RequireContextValue {
 /// A list of well-known functions that have special meaning in the analysis.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum WellKnownFunctionKind {
+    ArrayFilter,
+    ArrayForEach,
+    ArrayMap,
     ObjectAssign,
     PathJoin,
     PathDirname,

filename: turbopack/crates/turbopack-ecmascript/src/analyzer/well_known.rs
patch: @@ -43,6 +43,21 @@ pub async fn replace_well_known(
         JsValue::Member(_, box JsValue::WellKnownFunction(kind), box prop) => {
             well_known_function_member(kind, prop)
         }
+        JsValue::Member(_, box JsValue::Array { .. }, box ref prop) => match prop.as_str() {
+            Some("filter") => (
+                JsValue::WellKnownFunction(WellKnownFunctionKind::ArrayFilter),
+                true,
+            ),
+            Some("forEach") => (
+                JsValue::WellKnownFunction(WellKnownFunctionKind::ArrayForEach),
+                true,
+            ),
+            Some("map") => (
+                JsValue::WellKnownFunction(WellKnownFunctionKind::ArrayMap),
+                true,
+            ),
+            _ => (value, false),
+        },
         _ => (value, false),
     })
 }

filename: turbopack/crates/turbopack-ecmascript/src/references/mod.rs
patch: @@ -1218,7 +1218,6 @@ pub(crate) async fn analyse_ecmascript_module_internal(
                         &ast_path,
                         span,
                         func,
-                        JsValue::unknown_empty(false, "no this provided"),
                         args,
                         &analysis_state,
                         &add_effects,
@@ -1242,21 +1241,31 @@ pub(crate) async fn analyse_ecmascript_module_internal(
                     {
                         continue;
                     }
-                    let mut obj = analysis_state
-                        .link_value(*obj, ImportAttributes::empty_ref())
-                        .await?;
-                    let prop = analysis_state
-                        .link_value(*prop, ImportAttributes::empty_ref())
+
+                    let func = analysis_state
+                        .link_value(
+                            JsValue::member(obj.clone(), prop),
+                            eval_context.imports.get_attributes(span),
+                        )
                         .await?;
 
                     if !new
+                        && matches!(
+                            func,
+                            JsValue::WellKnownFunction(
+                                WellKnownFunctionKind::ArrayFilter
+                                    | WellKnownFunctionKind::ArrayForEach
+                                    | WellKnownFunctionKind::ArrayMap
+                            )
+                        )
+                        && let [EffectArg::Closure(value, block)] = &mut args[..]
                         && let JsValue::Array {
                             items: ref mut values,
                             mutable,
                             ..
-                        } = obj
-                        && matches!(prop.as_str(), Some("map" | "forEach" | "filter"))
-                        && let [EffectArg::Closure(value, block)] = &mut args[..]
+                        } = analysis_state
+                            .link_value(*obj, eval_context.imports.get_attributes(span))
+                            .await?
                     {
                         *value = analysis_state
                             .link_value(take(value), ImportAttributes::empty_ref())
@@ -1281,18 +1290,10 @@ pub(crate) async fn analyse_ecmascript_module_internal(
                         }
                     }
 
-                    let func = analysis_state
-                        .link_value(
-                            JsValue::member(Box::new(obj.clone()), Box::new(prop)),
-                            eval_context.imports.get_attributes(span),
-                        )
-                        .await?;
-
                     handle_call(
                         &ast_path,
                         span,
                         func,
-                        obj,
                         args,
                         &analysis_state,
                         &add_effects,
@@ -1564,7 +1565,6 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
     ast_path: &[AstParentKind],
     span: Span,
     func: JsValue,
-    this: JsValue,
     args: Vec<EffectArg>,
     state: &AnalysisState<'_>,
     add_effects: &G,
@@ -1706,7 +1706,6 @@ async fn handle_call<G: Fn(Vec<Effect>) + Send + Sync>(
                     ast_path,
                     span,
                     alt,
-                    this.clone(),
                     args.clone(),
                     state,
                     add_effects,