Repository: vercel/next.js
Pull request: Revert "[turbopack] Fix some modification tracking bugs in TaskStorage"

Reverts vercel/next.js#89708

This is breaking the filesystem-caching-test https://github.com/vercel/next.js/actions/runs/22089976734/job/63836669063#step:35:3409

Changed files:
filename: turbopack/crates/turbo-tasks-macros/src/derive/task_storage_macro.rs
patch: @@ -1476,8 +1476,8 @@ fn generate_trait_accessor_methods(field: &FieldInfo) -> TokenStream {
                     #check_access
                     let current = self.typed().flags.#field_name();
                     if current != value {
-                        #track_modification
                         self.typed_mut().flags.#set_name(value);
+                        #track_modification
                     }
                 }
             }
@@ -1592,11 +1592,15 @@ fn generate_direct_accessors(field: &FieldInfo) -> TokenStream {
         }
 
         #[doc = "Take the field value, clearing it"]
+        #[doc = ""]
+        #[doc = "Only tracks modification if there was a value to take."]
         fn #take_name(&mut self) -> Option<#value_type> {
             #check_access
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            #take_expr
+            let value = #take_expr;
+            if value.is_some() {
+                #track_modification
+            }
+            value
         }
 
         #get_mut_accessor
@@ -1661,20 +1665,27 @@ fn generate_autoset_ops(field: &FieldInfo) -> TokenStream {
     };
 
     // Remove uses find_lazy_mut for lazy to avoid allocation.
-    // Track modification before mutating to ensure snapshot captures pre-mutation state.
     let remove_body = if is_option {
         let extractor = field.lazy_extractor_closure();
 
         quote! {
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            self.typed_mut().find_lazy_mut(#extractor).is_some_and(|set| set.remove(item))
+            let Some(set) = self.typed_mut().find_lazy_mut(#extractor) else {
+                return false;
+            };
+            let removed = set.remove(item);
+            if removed {
+                #track_modification
+            }
+            return removed;
+
         }
     } else {
         quote! {
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            #mut_expr.remove(item)
+            let removed = #mut_expr.remove(item);
+            if removed {
+                #track_modification
+            }
+            removed
         }
     };
 
@@ -1702,23 +1713,30 @@ fn generate_autoset_ops(field: &FieldInfo) -> TokenStream {
 
         #[doc = "Add an item to the set."]
         #[doc = "Returns true if the item was newly added, false if it already existed."]
-        #[doc = "Only tracks modification if the item is actually added."]
         #[must_use]
         fn #add_name(&mut self, item: #element_type) -> bool {
             #check_access
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            #mut_expr.insert(item)
+            let added = #mut_expr.insert(item);
+            if added {
+                #track_modification
+            }
+            added
         }
 
         #[doc = "Add multiple items to the set from an iterator."]
+        #[doc = "Only tracks modification if at least one item is actually added."]
         fn #extend_name(&mut self, items: impl IntoIterator<Item = #element_type>) {
             #check_access
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            // We can't easily check if any items will be new without iterating twice,
-            // so we track conservatively
-            #track_modification
-            #mut_expr.extend(items);
+            let set = #mut_expr;
+            let mut any_added = false;
+            for item in items {
+                if set.insert(item) {
+                    any_added = true;
+                }
+            }
+            if any_added {
+                #track_modification
+            }
         }
 
         #[doc = "Remove an item from the set."]
@@ -1826,17 +1844,25 @@ fn generate_countermap_ops(field: &FieldInfo) -> TokenStream {
 
     // Generate remove body - for lazy fields, we need to check if the map exists first
     // without allocating it. For inline fields, we can use the mut_expr directly.
-    // Track modification before mutating to ensure snapshot captures pre-mutation state.
     let remove_body = if is_option {
+        // Lazy: use find_lazy_mut to avoid allocating, only track modification if something was
         let extractor = field.lazy_extractor_closure();
         quote! {
-            #track_modification
-            self.typed_mut().find_lazy_mut(#extractor).map(|map| map.remove(key)).flatten()
+            let map = self.typed_mut().find_lazy_mut(#extractor)?;
+            let result = map.remove(key);
+            if result.is_some() {
+                #track_modification
+            }
+            result
         }
     } else {
+        // Inline: direct access, only track modification if something was removed
         quote! {
-            #track_modification
-            #mut_expr.remove(key)
+            let result = #mut_expr.remove(key);
+            if result.is_some() {
+                #track_modification
+            }
+            result
         }
     };
 
@@ -2029,23 +2055,28 @@ fn generate_automap_ops(field: &FieldInfo) -> TokenStream {
 
     let take_expression = {
         let take_name = field.take_ident();
-        quote! {self.typed_mut().#take_name()}
+        quote! {self.typed_mut().#take_name();}
     };
 
     // Generate remove body - for lazy fields, avoid allocation if map doesn't exist.
-    // Track modification before mutating to ensure snapshot captures pre-mutation state.
+    // Using ? operator to early-return None if map doesn't exist.
     let remove_body = if is_option {
         let extractor = field.lazy_extractor_closure();
         quote! {
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            self.typed_mut().find_lazy_mut(#extractor).map(|map| map.remove(key)).flatten()
+            let map = self.typed_mut().find_lazy_mut(#extractor)?;
+            let result = map.remove(key);
+            if result.is_some() {
+                #track_modification
+            }
+            result
         }
     } else {
         quote! {
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            #mut_expr.remove(key)
+            let result = #mut_expr.remove(key);
+            if result.is_some() {
+                #track_modification
+            }
+            result
         }
     };
 
@@ -2079,11 +2110,14 @@ fn generate_automap_ops(field: &FieldInfo) -> TokenStream {
 
 
         #[doc = "Remove the full map and return it"]
+        #[doc = "Only tracks modification if an entry was actually removed."]
         fn #take_name(&mut self) -> Option<#field_type> {
             #check_access
-            // Track before mutation to ensure snapshot captures pre-mutation state
-            #track_modification
-            #take_expression
+            let value = #take_expression;
+            if value.is_some() {
+                #track_modification
+            }
+            value
         }
 
         #[doc = "Iterate over all key-value pairs in the map"]