diff --git a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php
index e0160d1..d77ce4d 100644
--- a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php
+++ b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php
@@ -141,9 +141,10 @@ public function processAttachments(AttachmentsInterface $response) {
$attached = $response->getAttachments();
// Send a message back if the render array has unsupported #attached types.
+ // @todo This needs to be configurable somehow.
$unsupported_types = array_diff(
array_keys($attached),
- ['html_head', 'feed', 'html_head_link', 'http_header', 'library', 'html_response_attachment_placeholders', 'placeholders', 'drupalSettings']
+ ['html_head', 'feed', 'html_head_link', 'http_header', 'library', 'html_response_attachment_placeholders', 'placeholders', 'drupalSettings', 'big_pipe_placeholders']
);
if (!empty($unsupported_types)) {
throw new \LogicException(sprintf('You are not allowed to use %s in #attached.', implode(', ', $unsupported_types)));
diff --git a/core/lib/Drupal/Core/Render/PlaceholderGenerator.php b/core/lib/Drupal/Core/Render/PlaceholderGenerator.php
index e0940bf..51d7c77 100644
--- a/core/lib/Drupal/Core/Render/PlaceholderGenerator.php
+++ b/core/lib/Drupal/Core/Render/PlaceholderGenerator.php
@@ -80,6 +80,8 @@ public function createPlaceholder(array $element) {
// The cacheability metadata for the placeholder. The rendered result of
// the placeholder may itself be cached, if [#cache][keys] are specified.
'#cache' => TRUE,
+ // The options for creating the placeholder. (optional)
+ '#create_placeholder_options' => TRUE,
]);
// Generate placeholder markup. Note that the only requirement is that this
diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php
index b1f7c2a..c1cbc0a 100644
--- a/core/lib/Drupal/Core/Render/Renderer.php
+++ b/core/lib/Drupal/Core/Render/Renderer.php
@@ -158,24 +158,9 @@ public function renderPlain(&$elements) {
}
/**
- * Renders final HTML for a placeholder.
- *
- * Renders the placeholder in isolation.
- *
- * @param string $placeholder
- * An attached placeholder to render. (This must be a key of one of the
- * values of $elements['#attached']['placeholders'].)
- * @param array $elements
- * The structured array describing the data to be rendered.
- *
- * @return array
- * The updated $elements.
- *
- * @see ::replacePlaceholders()
- *
- * @todo Make public as part of https://www.drupal.org/node/2469431
+ * {@inheritdoc}
*/
- protected function renderPlaceholder($placeholder, array $elements) {
+ public function renderPlaceholder($placeholder, array $elements) {
// Get the render array for the given placeholder
$placeholder_elements = $elements['#attached']['placeholders'][$placeholder];
@@ -196,7 +181,6 @@ protected function renderPlaceholder($placeholder, array $elements) {
return $elements;
}
-
/**
* {@inheritdoc}
*/
@@ -341,6 +325,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
'#lazy_builder',
'#cache',
'#create_placeholder',
+ '#create_placeholder_options',
// These keys are not actually supported, but they are added automatically
// by the Renderer, so we don't crash on them; them being missing when
// their #lazy_builder callback is invoked won't surprise the developer.
@@ -647,6 +632,8 @@ protected function setCurrentRenderContext(RenderContext $context = NULL) {
*
* @returns bool
* Whether placeholders were replaced.
+ *
+ * @see ::renderPlaceholder()
*/
protected function replacePlaceholders(array &$elements) {
if (!isset($elements['#attached']['placeholders']) || empty($elements['#attached']['placeholders'])) {
diff --git a/core/lib/Drupal/Core/Render/RendererInterface.php b/core/lib/Drupal/Core/Render/RendererInterface.php
index ff04d86..ccbe2d5 100644
--- a/core/lib/Drupal/Core/Render/RendererInterface.php
+++ b/core/lib/Drupal/Core/Render/RendererInterface.php
@@ -67,6 +67,24 @@ public function renderRoot(&$elements);
public function renderPlain(&$elements);
/**
+ * Renders final HTML for a placeholder.
+ *
+ * Renders the placeholder in isolation.
+ *
+ * @param string $placeholder
+ * An attached placeholder to render. (This must be a key of one of the
+ * values of $elements['#attached']['placeholders'].)
+ * @param array $elements
+ * The structured array describing the data to be rendered.
+ *
+ * @return array
+ * The updated $elements.
+ *
+ * @see ::render()
+ */
+ public function renderPlaceholder($placeholder, array $elements);
+
+ /**
* Renders HTML given a structured array tree.
*
* Renderable arrays have two kinds of key/value pairs: properties and
diff --git a/core/modules/big_pipe/big_pipe.info.yml b/core/modules/big_pipe/big_pipe.info.yml
new file mode 100644
index 0000000..b0f6e91
--- /dev/null
+++ b/core/modules/big_pipe/big_pipe.info.yml
@@ -0,0 +1,6 @@
+name: BigPipe
+type: module
+description: 'Enables BigPipe for authenticated users; first send+render the cheap parts of the page, then the expensive parts.'
+package: Core
+version: VERSION
+core: 8.x
diff --git a/core/modules/big_pipe/big_pipe.libraries.yml b/core/modules/big_pipe/big_pipe.libraries.yml
new file mode 100644
index 0000000..88ecff6
--- /dev/null
+++ b/core/modules/big_pipe/big_pipe.libraries.yml
@@ -0,0 +1,11 @@
+big_pipe:
+ version: VERSION
+ js:
+ js/big_pipe.js: {}
+ drupalSettings:
+ bigPipePlaceholders: []
+ dependencies:
+ - core/jquery
+ - core/drupal
+ - core/drupal.ajax
+ - core/drupalSettings
diff --git a/core/modules/big_pipe/big_pipe.module b/core/modules/big_pipe/big_pipe.module
new file mode 100644
index 0000000..f25b2a3
--- /dev/null
+++ b/core/modules/big_pipe/big_pipe.module
@@ -0,0 +1,80 @@
+setAjaxPageState(isset($settings['ajaxPageState']) ? $settings['ajaxPageState'] : NULL);
+ }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function big_pipe_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+ // Check if the user has JavaScript enabled without adding JavaScript.
+ $form['big_pipe_has_js'] = array(
+ '#type' => 'hidden',
+ '#default_value' => '1',
+ );
+
+ $form['#after_build'][] = 'big_pipe_form_after_build';
+ $form['#submit'][] = 'big_pipe_form_set_js_check';
+}
+
+/**
+ * After build handler for user_login_form().
+ */
+function big_pipe_form_after_build($form, FormStateInterface $form_state) {
+ // This is tricky: We want Form API to default big_pipe_has_js to 1 in
+ // case it gets not send. We also want to set the value of the HTML element
+ // to 0 and add