Commit 1c9a250137c for woocommerce

commit 1c9a250137c4fc197a6751e587f992e2011d4639
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date:   Wed Oct 28 08:37:46 2026 +0100

    [Performance] Introduce request-level cache for wp_get_global_styles usages by blocks (#69698)

    While wp_get_global_styles has underlying caching in upstream components, its merging routines are heavily compounding during block initialization. This PR introduces a request-level caching wrapper to resolve this compounding behavior and migrates Woo core code to use it.

diff --git a/plugins/woocommerce/changelog/performance-69369-blocks-registration-global-styles b/plugins/woocommerce/changelog/performance-69369-blocks-registration-global-styles
new file mode 100644
index 00000000000..323b44d0548
--- /dev/null
+++ b/plugins/woocommerce/changelog/performance-69369-blocks-registration-global-styles
@@ -0,0 +1,4 @@
+Significance: patch
+Type: performance
+
+Introduced request-level cache for wp_get_global_styles usage by blocks.
diff --git a/plugins/woocommerce/includes/wc-conditional-functions.php b/plugins/woocommerce/includes/wc-conditional-functions.php
index 6d8133b521a..4c2539b9e0b 100644
--- a/plugins/woocommerce/includes/wc-conditional-functions.php
+++ b/plugins/woocommerce/includes/wc-conditional-functions.php
@@ -640,22 +640,11 @@ function wc_wp_theme_get_element_class_name( $element ) {
  * @return bool
  */
 function wc_block_theme_has_styles_for_element( $element ) {
-	if (
-		! wp_is_block_theme() ||
-		wc_wp_theme_get_element_class_name( $element ) === ''
-	) {
+	if ( ! wp_is_block_theme() || wc_wp_theme_get_element_class_name( $element ) === '' ) {
 		return false;
 	}

-	if ( function_exists( 'wp_get_global_styles' ) ) {
-		$global_styles = wp_get_global_styles();
-		if (
-			array_key_exists( 'elements', $global_styles ) &&
-			array_key_exists( $element, $global_styles['elements'] )
-		) {
-			return is_array( $global_styles['elements'][ $element ] );
-		}
-	}
+	$global_styles = \Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils::get_global_styles();

-	return false;
+	return is_array( $global_styles['elements'][ $element ] ?? null );
 }
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/Breadcrumbs.php b/plugins/woocommerce/src/Blocks/BlockTypes/Breadcrumbs.php
index 3b33961c63a..4d758bc5a24 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/Breadcrumbs.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/Breadcrumbs.php
@@ -127,9 +127,7 @@ class Breadcrumbs extends AbstractBlock {
 	 * @return array The font size classes and styles.
 	 */
 	private function get_theme_font_size_classes_and_styles() {
-		$theme_font_size = wp_get_global_styles(
-			array( 'blocks', 'woocommerce/breadcrumbs', 'typography', 'fontSize' )
-		);
+		$theme_font_size = StyleAttributesUtils::get_global_styles( array( 'blocks', 'woocommerce/breadcrumbs', 'typography', 'fontSize' ) );

 		if ( ! is_string( $theme_font_size ) || '' === $theme_font_size ) {
 			return array(
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/CustomerAccount.php b/plugins/woocommerce/src/Blocks/BlockTypes/CustomerAccount.php
index 960a6b6e783..2d5439896bd 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/CustomerAccount.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/CustomerAccount.php
@@ -65,11 +65,9 @@ class CustomerAccount extends AbstractBlock {
 		$parsed_hooked_block['attrs']['iconStyle']    = 'line';
 		$parsed_hooked_block['attrs']['iconClass']    = 'wc-block-customer-account__account-icon';

-		$customer_account_block_font_size = wp_get_global_styles( array( 'blocks', 'woocommerce/customer-account', 'typography', 'fontSize' ) );
-
+		$customer_account_block_font_size = StyleAttributesUtils::get_global_styles( array( 'blocks', 'woocommerce/customer-account', 'typography', 'fontSize' ) );
 		if ( ! is_string( $customer_account_block_font_size ) ) {
-			$navigation_block_font_size = wp_get_global_styles( array( 'blocks', 'core/navigation', 'typography', 'fontSize' ) );
-
+			$navigation_block_font_size = StyleAttributesUtils::get_global_styles( array( 'blocks', 'core/navigation', 'typography', 'fontSize' ) );
 			if ( is_string( $navigation_block_font_size ) ) {
 				$parsed_hooked_block['attrs']['style']['typography']['fontSize'] = $navigation_block_font_size;
 			}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
index c6cfb8cf48b..ccf63b461cd 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
@@ -138,11 +138,9 @@ class MiniCart extends AbstractBlock {
 	 * @return array|null
 	 */
 	public function modify_hooked_block_attributes( $parsed_hooked_block, $hooked_block_type, $relative_position, $parsed_anchor_block, $context ) {
-		$mini_cart_block_font_size = wp_get_global_styles( array( 'blocks', 'woocommerce/mini-cart', 'typography', 'fontSize' ) );
-
+		$mini_cart_block_font_size = StyleAttributesUtils::get_global_styles( array( 'blocks', 'woocommerce/mini-cart', 'typography', 'fontSize' ) );
 		if ( ! is_string( $mini_cart_block_font_size ) ) {
-			$navigation_block_font_size = wp_get_global_styles( array( 'blocks', 'core/navigation', 'typography', 'fontSize' ) );
-
+			$navigation_block_font_size = StyleAttributesUtils::get_global_styles( array( 'blocks', 'core/navigation', 'typography', 'fontSize' ) );
 			if ( is_string( $navigation_block_font_size ) ) {
 				$parsed_hooked_block['attrs']['style']['typography']['fontSize'] = $navigation_block_font_size;
 			}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterChips.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterChips.php
index ec75e3732b7..7dfeb4ab027 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterChips.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilterChips.php
@@ -3,6 +3,7 @@ declare( strict_types = 1 );

 namespace Automattic\WooCommerce\Blocks\BlockTypes;

+use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
 use Automattic\WooCommerce\Internal\ProductAttributes\VisualAttributeTermMeta;

 /**
@@ -31,7 +32,7 @@ final class ProductFilterChips extends AbstractBlock {
 		parent::enqueue_data( $attributes );

 		if ( is_admin() ) {
-			$this->asset_data_registry->add( 'globalStylesColors', wp_get_global_styles( array( 'color' ) ) );
+			$this->asset_data_registry->add( 'globalStylesColors', StyleAttributesUtils::get_global_styles( array( 'color' ) ) );
 		}
 	}

diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
index 0abb7b27a37..b90f7e94404 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductFilters.php
@@ -51,7 +51,7 @@ class ProductFilters extends AbstractBlock {
 		);

 		if ( is_admin() ) {
-			$this->asset_data_registry->add( 'globalStylesColors', wp_get_global_styles( array( 'color' ) ) );
+			$this->asset_data_registry->add( 'globalStylesColors', StyleAttributesUtils::get_global_styles( array( 'color' ) ) );
 		}

 		BlocksSharedState::load_store_config( 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WooCommerce' );
diff --git a/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php b/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
index 883481304b4..bf203c26f35 100644
--- a/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
+++ b/plugins/woocommerce/src/Blocks/Utils/StyleAttributesUtils.php
@@ -1,6 +1,8 @@
 <?php
 namespace Automattic\WooCommerce\Blocks\Utils;

+use Automattic\WooCommerce\Utilities\ArrayUtil;
+
 /**
  * StyleAttributesUtils class used for getting class and style from attributes.
  *
@@ -16,6 +18,13 @@ class StyleAttributesUtils {
 		'value' => '',
 	];

+	/**
+	 * Cached global styles.
+	 *
+	 * @var array<string,array>
+	 */
+	private static array $cached_global_styles = array();
+
 	/**
 	 * If color value is in preset format, convert it to a CSS var. Else return same value
 	 * For example:
@@ -789,4 +798,37 @@ class StyleAttributesUtils {
 			'styles'  => implode( ' ', $styles ),
 		);
 	}
+
+	/**
+	 * Request-level caching wrapper for wp_get_global_styles, which is pretty expensive in runtime.
+	 *
+	 * @since 11.4.0
+	 *
+	 * @param string[] $path Path to the desired global styles value.
+	 * @return mixed The resolved global styles value.
+	 */
+	public static function get_global_styles( array $path = array() ) {
+		if ( ! has_action( 'switch_theme', array( self::class, 'reset_global_styles_cache' ) ) ) {
+			add_action( 'switch_theme', array( self::class, 'reset_global_styles_cache' ) );
+			add_action( 'start_previewing_theme', array( self::class, 'reset_global_styles_cache' ) );
+		}
+
+		$cache_key                                = get_stylesheet() . '-' . get_current_blog_id();
+		self::$cached_global_styles[ $cache_key ] = self::$cached_global_styles[ $cache_key ] ?? wp_get_global_styles();
+		$resolved_style                           = self::$cached_global_styles[ $cache_key ];
+
+		return ArrayUtil::get_nested_value( $resolved_style, implode( '::', $path ), $resolved_style );
+	}
+
+	/**
+	 * Resets the global styles cache.
+	 *
+	 * @since 11.4.0
+	 * @internal
+	 *
+	 * @return void
+	 */
+	public static function reset_global_styles_cache(): void {
+		self::$cached_global_styles = array();
+	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BreadcrumbsTest.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BreadcrumbsTest.php
index 3cb51dfbc06..80a8ac39af1 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BreadcrumbsTest.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BreadcrumbsTest.php
@@ -4,6 +4,7 @@ declare( strict_types = 1 );

 namespace Automattic\WooCommerce\Tests\Blocks\BlockTypes;

+use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
 use WP_Theme_JSON_Data;
 use WP_UnitTestCase;

@@ -68,6 +69,7 @@ class BreadcrumbsTest extends WP_UnitTestCase {
 				return new WP_Theme_JSON_Data( $data, 'user' );
 			}
 		);
+		StyleAttributesUtils::reset_global_styles_cache();
 	}

 	/**