From 805b05725d483521da9d5abb05527c932ac619a8 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Tue, 18 Mar 2025 22:18:13 +0000
Subject: [PATCH 1/4] Recursively get cached placeholders.

---
 .../Core/Render/Placeholder/CachedStrategy.php      | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
index 941c11ac27eb..f9c2d01facb9 100644
--- a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
+++ b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
@@ -21,7 +21,18 @@ public function __construct(
    * {@inheritdoc}
    */
   public function processPlaceholders(array $placeholders) {
-    return $this->renderCache->getMultiple($placeholders);
+    $return = $this->renderCache->getMultiple($placeholders);
+
+    foreach ($return as $key => $placeholder) {
+      if (!empty($placeholder['#attached']['placeholders'])) {
+        $cached = $this->renderCache->getMultiple($placeholder['#attached']['placeholders']);
+        foreach ($cached as $cache_key => $value) {
+          $return[$key]['#attached']['placeholders'][$cache_key] = $value;
+        }
+      }
+    }
+
+    return $return;
   }
 
 }
-- 
GitLab


From 50f1deb3da8c464257a7e29cf6d56a01be8edae2 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Mon, 31 Mar 2025 16:34:00 +0100
Subject: [PATCH 2/4] Private and improve docs.

---
 .../Render/Placeholder/CachedStrategy.php     | 30 +++++++++++++++----
 .../FunctionalJavascript/PerformanceTest.php  |  2 +-
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
index f9c2d01facb9..a02efe49fe40 100644
--- a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
+++ b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
@@ -22,17 +22,35 @@ public function __construct(
    */
   public function processPlaceholders(array $placeholders) {
     $return = $this->renderCache->getMultiple($placeholders);
+    if ($return) {
+      $return = $this->processNestedPlaceholders($return);
+    }
 
-    foreach ($return as $key => $placeholder) {
+    return $return;
+  }
+
+  /**
+   * Fetch any nested placeholders from cache.
+   */
+  private function processNestedPlaceholders(array $placeholders): array {
+    $sets = [];
+    foreach ($placeholders as $key => $placeholder) {
       if (!empty($placeholder['#attached']['placeholders'])) {
-        $cached = $this->renderCache->getMultiple($placeholder['#attached']['placeholders']);
-        foreach ($cached as $cache_key => $value) {
-          $return[$key]['#attached']['placeholders'][$cache_key] = $value;
+        $sets[] = $placeholder['#attached']['placeholders'];
+      }
+    }
+    if ($sets) {
+      $cached = $this->renderCache->getMultiple(...array_merge($sets));
+      if ($cached) {
+        $cached = $this->processNestedPlaceholders($cached);
+        foreach ($placeholders as $key => $placeholder) {
+          if (!empty($placeholder['#attached']['placeholders'])) {
+            $placeholders[$key]['#attached']['placeholders'] = array_replace($placeholder['#attached']['placeholders'], $cached);
+          }
         }
       }
     }
-
-    return $return;
+    return $placeholders;
   }
 
 }
diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
index 3264d769c195..c9d11689b73d 100644
--- a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
+++ b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
@@ -80,7 +80,7 @@ public function testLogin(): void {
         'discovery' => 10,
         'bootstrap' => 6,
         'dynamic_page_cache' => 1,
-        'render' => 16,
+        'render' => 14,
         'menu' => 1,
       ],
       'CacheSetCount' => 2,
-- 
GitLab


From f8ad4c8c83b6f56fe9d244ade640cc5e04324007 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Tue, 1 Apr 2025 14:01:41 +0100
Subject: [PATCH 3/4] Add explanatory comment.

---
 core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
index a02efe49fe40..757f647e5f0a 100644
--- a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
+++ b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php
@@ -31,6 +31,11 @@ public function processPlaceholders(array $placeholders) {
 
   /**
    * Fetch any nested placeholders from cache.
+   *
+   * Placeholders returned from cache may have placeholders in #attached, which
+   * can themselves be fetched from the cache. By recursively processing the
+   * placeholders here, we're able to use multiple cache get to fetch the cache
+   * items at each level of recursion.
    */
   private function processNestedPlaceholders(array $placeholders): array {
     $sets = [];
-- 
GitLab


From aed6b699ee66d030e9603dd5ec8cdf64f175a688 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Tue, 1 Apr 2025 14:09:31 +0100
Subject: [PATCH 4/4] Update assertions.

---
 .../tests/src/FunctionalJavascript/PerformanceTest.php        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
index c9d11689b73d..f1ca3242a2a8 100644
--- a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
+++ b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
@@ -73,14 +73,14 @@ public function testLogin(): void {
 
     $expected = [
       'QueryCount' => 4,
-      'CacheGetCount' => 49,
+      'CacheGetCount' => 48,
       'CacheGetCountByBin' => [
         'config' => 11,
         'data' => 4,
         'discovery' => 10,
         'bootstrap' => 6,
         'dynamic_page_cache' => 1,
-        'render' => 14,
+        'render' => 15,
         'menu' => 1,
       ],
       'CacheSetCount' => 2,
-- 
GitLab