Verified Commit 041a12b5 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3441137 by catch, mherchel: BigPipe injecting Local Actions block...

Issue #3441137 by catch, mherchel: BigPipe injecting Local Actions block creates large janky layout shift in Claro

(cherry picked from commit 3203676d)
parent 66faba3a
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -355,6 +355,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
    $pre_bubbling_elements = array_intersect_key($elements, [
      '#cache' => TRUE,
      '#lazy_builder' => TRUE,
      '#lazy_builder_preview' => TRUE,
      '#create_placeholder' => TRUE,
    ]);

+20 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
use Drupal\Core\Url;
use Drupal\language\ConfigurableLanguageInterface;
use Drupal\system\Entity\Menu;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\block\Entity\Block;

/**
@@ -316,3 +317,22 @@ function block_configurable_language_delete(ConfigurableLanguageInterface $langu
    }
  }
}

/**
 * Implements hook_block_build_BASE_BLOCK_ID_alter().
 */
function block_block_build_local_actions_block_alter(array &$build, BlockPluginInterface $block) {
  $build['#lazy_builder_preview'] = [
    '#type' => 'container',
    '#attributes' => [
      'class' => ['invisible'],
    ],
    'actions' => [
      '#theme' => 'menu_local_action',
      '#link' => [
        'title' => t('Add'),
        'url' => Url::fromUserInput('#'),
      ],
    ],
  ];
}
+61 −0
Original line number Diff line number Diff line
@@ -9,7 +9,9 @@
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\PlaceholderingRenderCache;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\Renderer;
use Drupal\Core\Security\TrustedCallbackInterface;

/**
@@ -1047,6 +1049,50 @@ public function testRenderChildrenPlaceholdersDifferentArguments() {
    $this->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the ones added by each #lazy_builder callback exist.');
  }

  /**
   * Tests the creation of an element with a lazy_builder_preview.
   *
   * @covers ::render
   * @covers ::doRender
   * @covers \Drupal\Core\Render\RenderCache::get
   * @covers ::replacePlaceholders
   */
  public function testRenderLazyBuilderPreview() {
    $this->setUpRequest();
    $this->setupMemoryCache();
    $this->renderCache = new TestPlaceholderingRenderCache($this->requestStack, $this->cacheFactory, $this->cacheContextsManager, $this->placeholderGenerator);
    $this->renderer = new Renderer($this->callableResolver, $this->themeManager, $this->elementInfo, $this->placeholderGenerator, $this->renderCache, $this->requestStack, $this->rendererConfig);

    $this->cacheContextsManager->expects($this->any())
      ->method('convertTokensToKeys')
      ->willReturnArgument(0);
    $this->callableResolver->expects($this->any())
      ->method('getCallableFromDefinition')
      ->willReturnArgument(0);

    $test_element = $this->generatePlaceholderWithLazyBuilderPreview();

    $element1 = $element2 = $test_element;
    // Render the element twice so that it is in the render cache.
    $result = $this->renderer->renderRoot($element1);
    $result = $this->renderer->renderRoot($element2);
    $placeholder_string = (string) $this->renderCache->placeholderElements[0]['#markup'];
    $this->assertSame($this->renderCache->placeholderElements[0]['#attached']['placeholders'][$placeholder_string]['#preview'], ['#markup' => 'Lazy Builder Preview']);
  }

  /**
   * Generates an element with a lazy builder and preview.
   */
  public function generatePlaceholderWithLazyBuilderPreview(): array {
    return [
      '#cache' => [
        'keys' => ['test_render'],
      ],
      '#lazy_builder' => [__namespace__ . '\\PlaceholdersTest::callbackPerUser', ['foo']],
      '#lazy_builder_preview' => ['#markup' => 'Lazy Builder Preview'],
    ];
  }

  /**
   * Generates an element with placeholders at 3 levels.
   *
@@ -1156,3 +1202,18 @@ public static function trustedCallbacks() {
  }

}

class TestPlaceholderingRenderCache extends PlaceholderingRenderCache {

  /**
   * The placeholder elements created during rendering.
   */
  public array $placeholderElements = [];

  protected function createPlaceholderAndRemember(array $rendered_elements, array $pre_bubbling_elements) {
    $placeholder_element = parent::createPlaceholderAndRemember($rendered_elements, $pre_bubbling_elements);
    $this->placeholderElements[] = $placeholder_element;
    return $placeholder_element;
  }

}