diff --git a/core/modules/big_pipe/js/big_pipe.js b/core/modules/big_pipe/js/big_pipe.js index 2deefec3437d14611bcc2181adfc710399e13a6e..986cf476e792e13e5f73329482319b09da336e5e 100644 --- a/core/modules/big_pipe/js/big_pipe.js +++ b/core/modules/big_pipe/js/big_pipe.js @@ -8,7 +8,7 @@ 'use strict'; /** - * Executes Ajax commands in <script type="application/json"> tag. + * Executes Ajax commands in <script type="application/vnd.drupal-ajax"> tag. * * These Ajax commands replace placeholders with HTML and load missing CSS/JS. * @@ -52,8 +52,8 @@ * Processes a streamed HTML document receiving placeholder replacements. * * @param {HTMLDocument} context - * The HTML document containing <script type="application/json"> tags - * generated by BigPipe. + * The HTML document containing <script type="application/vnd.drupal-ajax"> + * tags generated by BigPipe. * * @return {bool} * Returns true when processing has been finished and a stop signal has been diff --git a/core/modules/big_pipe/src/Render/BigPipe.php b/core/modules/big_pipe/src/Render/BigPipe.php index cb30d2a2dde05595a1885a25ec4d4fb9cbc372fd..95fe7851d893d401dcda21aff77b547118294354 100644 --- a/core/modules/big_pipe/src/Render/BigPipe.php +++ b/core/modules/big_pipe/src/Render/BigPipe.php @@ -29,6 +29,20 @@ */ class BigPipe implements BigPipeInterface { + /** + * The BigPipe placeholder replacements start signal. + * + * @var string + */ + const START_SIGNAL = '<script type="application/vnd.drupal-ajax" data-big-pipe-event="start"></script>'; + + /** + * The BigPipe placeholder replacements stop signal. + * + * @var string + */ + const STOP_SIGNAL = '<script type="application/vnd.drupal-ajax" data-big-pipe-event="stop"></script>'; + /** * The renderer. * @@ -285,7 +299,8 @@ protected function sendPlaceholders(array $placeholders, array $placeholder_orde // Send the start signal. print "\n"; - print '<script type="application/json" data-big-pipe-event="start"></script>' . "\n"; + print static::START_SIGNAL; + print "\n"; flush(); // A BigPipe response consists of a HTML response plus multiple embedded @@ -296,7 +311,7 @@ protected function sendPlaceholders(array $placeholders, array $placeholder_orde // to be returned. // @see \Drupal\Core\EventSubscriber\AjaxResponseSubscriber::onResponse() $fake_request = $this->requestStack->getMasterRequest()->duplicate(); - $fake_request->headers->set('Accept', 'application/json'); + $fake_request->headers->set('Accept', 'application/vnd.drupal-ajax'); foreach ($placeholder_order as $placeholder_id) { if (!isset($placeholders[$placeholder_id])) { @@ -332,7 +347,7 @@ protected function sendPlaceholders(array $placeholders, array $placeholder_orde // Send this embedded AJAX response. $json = $ajax_response->getContent(); $output = <<<EOF - <script type="application/json" data-big-pipe-replacement-for-placeholder-with-id="$placeholder_id"> + <script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="$placeholder_id"> $json </script> EOF; @@ -348,7 +363,9 @@ protected function sendPlaceholders(array $placeholders, array $placeholder_orde } // Send the stop signal. - print '<script type="application/json" data-big-pipe-event="stop"></script>' . "\n"; + print "\n"; + print static::STOP_SIGNAL; + print "\n"; flush(); } diff --git a/core/modules/big_pipe/src/Render/BigPipeInterface.php b/core/modules/big_pipe/src/Render/BigPipeInterface.php index 55a5a3d2e71963c6ef650410031a7904961fa186..f526f54893c9a9852f7abfca0dc56fef3daa02ef 100644 --- a/core/modules/big_pipe/src/Render/BigPipeInterface.php +++ b/core/modules/big_pipe/src/Render/BigPipeInterface.php @@ -71,15 +71,15 @@ * sent first, the closing </body> tag is not yet sent, and the connection * is kept open. Whenever another BigPipe Placeholder is rendered, Drupal * sends (and so actually appends to the already-sent HTML) something like - * <script type="application/json">[{"command":"settings","settings":{…}}, {"command":…}. + * <script type="application/vnd.drupal-ajax">[{"command":"settings","settings":{…}}, {"command":…}. * - So, for every BigPipe placeholder, we send such a <script - * type="application/json"> tag. And the contents of that tag is exactly - * like an AJAX response. The BigPipe module has JavaScript that listens for - * these and applies them. Let's call it an Embedded AJAX Response (since it - * is embedded in the HTML response). Now for the interesting bit: each of - * those Embedded AJAX Responses must also take into account the cumulative - * AJAX page state of the HTML document and all preceding Embedded AJAX - * responses. + * type="application/vnd.drupal-ajax"> tag. And the contents of that tag is + * exactly like an AJAX response. The BigPipe module has JavaScript that + * listens for these and applies them. Let's call it an Embedded AJAX + * Response (since it is embedded in the HTML response). Now for the + * interesting bit: each of those Embedded AJAX Responses must also take + * into account the cumulative AJAX page state of the HTML document and all + * preceding Embedded AJAX responses. * 2. No-JS BigPipe placeholders: 1 HtmlResponse + N embedded HtmlResponses. * - Before a BigPipe response is sent, it is just a HTML response that * contains no-JS BigPipe placeholders. Those placeholders can take two @@ -125,8 +125,8 @@ * 6. [… repeat until all no-JS placeholder replacements are sent …] * 7. Send content after last no-JS placeholder. * 8. Send script_bottom (markup to load bottom i.e. non-critical JS). - * 9. 1st placeholder replacement: <script type="application/json">[{"command":"settings","settings":{…}}, {"command":…} - * 10. 2nd placeholder replacement: <script type="application/json">[{"command":"settings","settings":{…}}, {"command":…} + * 9. 1st placeholder replacement: <script type="application/vnd.drupal-ajax">[{"command":"settings","settings":{…}}, {"command":…} + * 10. 2nd placeholder replacement: <script type="application/vnd.drupal-ajax">[{"command":"settings","settings":{…}}, {"command":…} * 11. [… repeat until all placeholder replacements are sent …] * 12. Send </body> and everything after it. * 13. Terminate request/response cycle. diff --git a/core/modules/big_pipe/src/Tests/BigPipeTest.php b/core/modules/big_pipe/src/Tests/BigPipeTest.php index 931ef9f9e16c3374c713f3651cac19a0b1c05580..b3f4912d12a754169bb8049165a2f46e26a1beb8 100644 --- a/core/modules/big_pipe/src/Tests/BigPipeTest.php +++ b/core/modules/big_pipe/src/Tests/BigPipeTest.php @@ -8,6 +8,7 @@ namespace Drupal\big_pipe\Tests; use Drupal\big_pipe\Render\Placeholder\BigPipeStrategy; +use Drupal\big_pipe\Render\BigPipe; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\Html; use Drupal\Core\Url; @@ -26,9 +27,6 @@ */ class BigPipeTest extends WebTestBase { - const START_SIGNAL= '<script type="application/json" data-big-pipe-event="start"></script>'; - const STOP_SIGNAL= '<script type="application/json" data-big-pipe-event="stop"></script>'; - /** * Modules to enable. * @@ -218,8 +216,8 @@ public function testBigPipeNoJs() { $this->pass('Verifying there are no BigPipe placeholders & replacements…', 'Debug'); $this->assertEqual('<none>', $this->drupalGetHeader('BigPipe-Test-Placeholders')); $this->pass('Verifying BigPipe start/stop signals are absent…', 'Debug'); - $this->assertNoRaw(static::START_SIGNAL, 'BigPipe start signal absent.'); - $this->assertNoRaw(static::STOP_SIGNAL, 'BigPipe stop signal absent.'); + $this->assertNoRaw(BigPipe::START_SIGNAL, 'BigPipe start signal absent.'); + $this->assertNoRaw(BigPipe::STOP_SIGNAL, 'BigPipe stop signal absent.'); $this->pass('Verifying BigPipe assets are absent…', 'Debug'); $this->assertFalse(empty($this->getDrupalSettings()), 'drupalSettings and BigPipe asset library absent.'); @@ -273,7 +271,7 @@ protected function assertBigPipePlaceholders(array $expected_big_pipe_placeholde // Verify expected placeholder replacement. $result = $this->xpath('//script[@data-big-pipe-replacement-for-placeholder-with-id=:id]', [':id' => Html::decodeEntities($big_pipe_placeholder_id)]); $this->assertEqual($expected_ajax_response, trim((string) $result[0])); - $expected_placeholder_replacement = '<script type="application/json" data-big-pipe-replacement-for-placeholder-with-id="' . $big_pipe_placeholder_id . '">'; + $expected_placeholder_replacement = '<script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="' . $big_pipe_placeholder_id . '">'; $this->assertRaw($expected_placeholder_replacement); $pos = strpos($this->getRawContent(), $expected_placeholder_replacement); $placeholder_replacement_positions[$pos] = $big_pipe_placeholder_id; @@ -282,22 +280,22 @@ protected function assertBigPipePlaceholders(array $expected_big_pipe_placeholde $this->assertEqual(array_keys($expected_big_pipe_placeholders), array_values($placeholder_positions)); $this->assertEqual(count($expected_big_pipe_placeholders), preg_match_all('/' . preg_quote('<div data-big-pipe-placeholder-id="', '/') . '/', $this->getRawContent())); $this->assertEqual(array_keys($expected_big_pipe_placeholders), array_values($placeholder_replacement_positions)); - $this->assertEqual(count($expected_big_pipe_placeholders), preg_match_all('/' . preg_quote('<script type="application/json" data-big-pipe-replacement-for-placeholder-with-id="', '/') . '/', $this->getRawContent())); + $this->assertEqual(count($expected_big_pipe_placeholders), preg_match_all('/' . preg_quote('<script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="', '/') . '/', $this->getRawContent())); $this->pass('Verifying BigPipe start/stop signals…', 'Debug'); - $this->assertRaw(static::START_SIGNAL, 'BigPipe start signal present.'); - $this->assertRaw(static::STOP_SIGNAL, 'BigPipe stop signal present.'); - $start_signal_position = strpos($this->getRawContent(), static::START_SIGNAL); - $stop_signal_position = strpos($this->getRawContent(), static::STOP_SIGNAL); + $this->assertRaw(BigPipe::START_SIGNAL, 'BigPipe start signal present.'); + $this->assertRaw(BigPipe::STOP_SIGNAL, 'BigPipe stop signal present.'); + $start_signal_position = strpos($this->getRawContent(), BigPipe::START_SIGNAL); + $stop_signal_position = strpos($this->getRawContent(), BigPipe::STOP_SIGNAL); $this->assertTrue($start_signal_position < $stop_signal_position, 'BigPipe start signal appears before stop signal.'); $this->pass('Verifying BigPipe placeholder replacements and start/stop signals were streamed in the correct order…', 'Debug'); $expected_stream_order = array_keys($expected_big_pipe_placeholders); - array_unshift($expected_stream_order, static::START_SIGNAL); - array_push($expected_stream_order, static::STOP_SIGNAL); + array_unshift($expected_stream_order, BigPipe::START_SIGNAL); + array_push($expected_stream_order, BigPipe::STOP_SIGNAL); $actual_stream_order = $placeholder_replacement_positions + [ - $start_signal_position => static::START_SIGNAL, - $stop_signal_position => static::STOP_SIGNAL, + $start_signal_position => BigPipe::START_SIGNAL, + $stop_signal_position => BigPipe::STOP_SIGNAL, ]; ksort($actual_stream_order, SORT_NUMERIC); $this->assertEqual($expected_stream_order, array_values($actual_stream_order));