107a108,115
>     /**
>      * Cache for data-wp-each template blueprints.
>      *
>      * @since 6.7.0
>      * @var   array
>      */
>     private static $template_blueprints = array();
> 
1155,1174c1163,1172
< 	/**
< 	 * Processes the `data-wp-each` directive.
< 	 *
< 	 * This directive gets an array passed as reference and iterates over it
< 	 * generating new content for each item based on the inner markup of the
< 	 * `template` tag.
< 	 *
< 	 * @since 6.5.0
< 	 *
< 	 * @param WP_Interactivity_API_Directives_Processor $p               The directives processor instance.
< 	 * @param string                                    $mode            Whether the processing is entering or exiting the tag.
< 	 * @param array                                     $tag_stack       The reference to the tag stack.
< 	 */
< 	private function data_wp_each_processor( WP_Interactivity_API_Directives_Processor $p, string $mode, array &$tag_stack ) {
< 		if ( 'enter' === $mode && 'TEMPLATE' === $p->get_tag() ) {
< 			$attribute_name   = $p->get_attribute_names_with_prefix( 'data-wp-each' )[0];
< 			$extracted_suffix = $this->extract_prefix_and_suffix( $attribute_name );
< 			$item_name        = isset( $extracted_suffix[1] ) ? $this->kebab_to_camel_case( $extracted_suffix[1] ) : 'item';
< 			$attribute_value  = $p->get_attribute( $attribute_name );
< 			$result           = $this->evaluate( $attribute_value );
---
>     /**
>      * Processes the data-wp-each directive using a pre-computation and caching strategy.
>      *
>      * @param WP_HTML_Tag_Processor $p       The WP_HTML_Tag_Processor instance.
>      * @param array                 $context The context.
>      */
>     private function data_wp_each_processor( WP_HTML_Tag_Processor $p, array $context ) {
>         if ( 'TEMPLATE' !== $p->get_tag() ) {
>             return;
>         }
1176,1177c1174,1187
< 			// Gets the content between the template tags and leaves the cursor in the closer tag.
< 			$inner_content = $p->get_content_between_balanced_template_tags();
---
>         $directive_value = $p->get_attribute( 'data-wp-each' );
>         list( $item_name, $array_name ) = explode( ' in ', $directive_value );
>         $item_name  = trim( $item_name );
>         $array_name = trim( $array_name );
> 
>         $template_html = '';
>         if ( $p->next_tag(
>             array(
>                 'tag_closers' => 'visit',
>                 'tag_name'    => 'TEMPLATE',
>             )
>         ) ) {
>             $template_html = $p->get_content_between_balanced_tags();
>         }
1179,1211c1189,1194
< 			// Checks if there is a manual server-side directive processing.
< 			$template_end = 'data-wp-each: template end';
< 			$p->set_bookmark( $template_end );
< 			$p->next_tag();
< 			$manual_sdp = $p->get_attribute( 'data-wp-each-child' );
< 			$p->seek( $template_end ); // Rewinds to the template closer tag.
< 			$p->release_bookmark( $template_end );
< 
< 			/*
< 			 * It doesn't process in these situations:
< 			 * - Manual server-side directive processing.
< 			 * - Empty or non-array values.
< 			 * - Associative arrays because those are deserialized as objects in JS.
< 			 * - Templates that contain top-level texts because those texts can't be
< 			 *   identified and removed in the client.
< 			 */
< 			if (
< 				$manual_sdp ||
< 				empty( $result ) ||
< 				! is_array( $result ) ||
< 				! array_is_list( $result ) ||
< 				! str_starts_with( trim( $inner_content ), '<' ) ||
< 				! str_ends_with( trim( $inner_content ), '>' )
< 			) {
< 				array_pop( $tag_stack );
< 				return;
< 			}
< 
< 			// Extracts the namespace from the directive attribute value.
< 			$namespace_value         = end( $this->namespace_stack );
< 			list( $namespace_value ) = is_string( $attribute_value ) && ! empty( $attribute_value )
< 				? $this->extract_directive_value( $attribute_value, $namespace_value )
< 				: array( $namespace_value, null );
---
>         $p->next_tag(
>             array(
>                 'tag_name'    => 'TEMPLATE',
>                 'tag_closers' => 'visit',
>             )
>         );
1213,1220c1196
< 			// Processes the inner content for each item of the array.
< 			$processed_content = '';
< 			foreach ( $result as $item ) {
< 				// Creates a new context that includes the current item of the array.
< 				$this->context_stack[] = array_replace_recursive(
< 					end( $this->context_stack ) !== false ? end( $this->context_stack ) : array(),
< 					array( $namespace_value => array( $item_name => $item ) )
< 				);
---
>         $cache_key = md5( $template_html );
1222,1223c1198,1202
< 				// Processes the inner content with the new context.
< 				$processed_item = $this->_process_directives( $inner_content );
---
>         // 1. Pre-computation: Parse the template once and create a "blueprint" of bookmarks.
>         if ( ! isset( self::$template_blueprints[ $cache_key ] ) ) {
>             self::$template_blueprints[ $cache_key ] = array();
>             $blueprint_p                             = new WP_HTML_Tag_Processor( $template_html );
>             $bookmark_counter                        = 0;
1225,1229c1204,1212
< 				if ( null === $processed_item ) {
< 					// If the HTML is unbalanced, stop processing it.
< 					array_pop( $this->context_stack );
< 					return;
< 				}
---
>             while ( $blueprint_p->next_tag() ) {
>                 // Find any tag that has one or more `data-wp-` directives.
>                 if ( ! empty( $blueprint_p->get_attribute_names_with_prefix( 'data-wp-' ) ) ) {
>                     $bookmark_name = 'directive_tag_' . $bookmark_counter++;
>                     $blueprint_p->set_bookmark( $bookmark_name );
>                     self::$template_blueprints[ $cache_key ][] = $bookmark_name;
>                 }
>             }
>         }
1231,1237c1214,1215
< 				// Adds the `data-wp-each-child` to each top-level tag.
< 				$i = new WP_Interactivity_API_Directives_Processor( $processed_item );
< 				while ( $i->next_tag() ) {
< 					$i->set_attribute( 'data-wp-each-child', true );
< 					$i->next_balanced_tag_closer_tag();
< 				}
< 				$processed_content .= $i->get_updated_html();
---
>         $bookmarks = self::$template_blueprints[ $cache_key ];
>         $html      = '';
1239,1241c1217,1219
< 				// Removes the current context from the stack.
< 				array_pop( $this->context_stack );
< 			}
---
>         // 2. Optimized Loop: Jump directly to bookmarked tags and process them.
>         foreach ( $this->get_context_value( $array_name, $context ) as $item_context ) {
>             $item_p = new WP_HTML_Tag_Processor( $template_html );
1243,1244c1221,1226
< 			// Appends the processed content after the tag closer of the template.
< 			$p->append_content_after_template_tag_closer( $processed_content );
---
>             // Recreate the same inner context as the original function.
>             $inner_context = array(
>                 $item_name => $item_context,
>                 'context'  => $item_context,
>             );
>             $current_context = array_merge( $context, $inner_context );
1246,1249c1228,1239
< 			// Pops the last tag because it skipped the closing tag of the template tag.
< 			array_pop( $tag_stack );
< 		}
< 	}
---
>             // Instead of scanning all tags, iterate through our pre-computed bookmarks.
>             foreach ( $bookmarks as $bookmark_name ) {
>                 $item_p->seek( $bookmark_name );
>                 // Call the original, robust `process_directives` function on the targeted tag.
>                 $this->process_directives( $item_p, $current_context );
>             }
> 
>             $html .= $item_p->get_updated_html();
>         }
> 
>         $p->insert_before_closing_tag( $html );
>     }
