3 * Renders BigPipe placeholders using Drupal's Ajax system.
6 (function ($, Drupal, drupalSettings) {
11 * Executes Ajax commands in <script type="application/vnd.drupal-ajax"> tag.
13 * These Ajax commands replace placeholders with HTML and load missing CSS/JS.
15 * @param {number} index
17 * @param {HTMLScriptElement} placeholderReplacement
18 * Script tag created by BigPipe.
20 function bigPipeProcessPlaceholderReplacement(index, placeholderReplacement) {
21 var placeholderId = placeholderReplacement.getAttribute('data-big-pipe-replacement-for-placeholder-with-id');
22 var content = this.textContent.trim();
23 // Ignore any placeholders that are not in the known placeholder list. Used
24 // to avoid someone trying to XSS the site via the placeholdering mechanism.
25 if (typeof drupalSettings.bigPipePlaceholderIds[placeholderId] !== 'undefined') {
26 // If we try to parse the content too early (when the JSON containing Ajax
27 // commands is still arriving), textContent will be empty which will cause
28 // JSON.parse() to fail. Remove once so that it can be processed again
30 // @see bigPipeProcessDocument()
32 $(this).removeOnce('big-pipe');
35 var response = JSON.parse(content);
36 // Create a Drupal.Ajax object without associating an element, a
37 // progress indicator or a URL.
38 var ajaxObject = Drupal.ajax({
44 // Then, simulate an AJAX response having arrived, and let the Ajax
46 ajaxObject.success(response, 'success');
52 * Processes a streamed HTML document receiving placeholder replacements.
54 * @param {HTMLDocument} context
55 * The HTML document containing <script type="application/vnd.drupal-ajax">
56 * tags generated by BigPipe.
59 * Returns true when processing has been finished and a stop signal has been
62 function bigPipeProcessDocument(context) {
63 // Make sure we have BigPipe-related scripts before processing further.
64 if (!context.querySelector('script[data-big-pipe-event="start"]')) {
68 $(context).find('script[data-big-pipe-replacement-for-placeholder-with-id]')
70 .each(bigPipeProcessPlaceholderReplacement);
72 // If we see the stop signal, clear the timeout: all placeholder
73 // replacements are guaranteed to be received and processed.
74 if (context.querySelector('script[data-big-pipe-event="stop"]')) {
76 clearTimeout(timeoutID);
84 function bigPipeProcess() {
85 timeoutID = setTimeout(function () {
86 if (!bigPipeProcessDocument(document)) {
92 // The frequency with which to check for newly arrived BigPipe placeholders.
93 // Hence 50 ms means we check 20 times per second. Setting this to 100 ms or
94 // more would cause the user to see content appear noticeably slower.
95 var interval = drupalSettings.bigPipeInterval || 50;
96 // The internal ID to contain the watcher service.
101 // If something goes wrong, make sure everything is cleaned up and has had a
102 // chance to be processed with everything loaded.
103 $(window).on('load', function () {
105 clearTimeout(timeoutID);
107 bigPipeProcessDocument(document);
110 })(jQuery, Drupal, drupalSettings);