diff --git a/core/.eslintrc.json b/core/.eslintrc.json index 218d84f937..81ed0cccb5 100644 --- a/core/.eslintrc.json +++ b/core/.eslintrc.json @@ -12,6 +12,7 @@ "domready": true, "jQuery": true, "_": true, + "loadjs": true, "matchMedia": true, "Backbone": true, "Modernizr": true, diff --git a/core/assets/vendor/loadjs/loadjs.min.js b/core/assets/vendor/loadjs/loadjs.min.js new file mode 100644 index 0000000000..24f62cadc9 --- /dev/null +++ b/core/assets/vendor/loadjs/loadjs.min.js @@ -0,0 +1 @@ +loadjs=function(){function e(e,n){e=e.push?e:[e];var t,r,i,c,o=[],f=e.length,a=f;for(t=function(e,t){t.length&&o.push(e),--a||n(o)};f--;)r=e[f],i=s[r],i?t(r,i):(c=u[r]=u[r]||[],c.push(t))}function n(e,n){if(e){var t=u[e];if(s[e]=n,t)for(;t.length;)t[0](e,n),t.splice(0,1)}}function t(e,n,r,i){var o,s,u=document,f=r.async,a=(r.numRetries||0)+1,h=r.before||c;i=i||0,/(^css!|\.css$)/.test(e)?(o=!0,s=u.createElement("link"),s.rel="stylesheet",s.href=e.replace(/^css!/,"")):(s=u.createElement("script"),s.src=e,s.async=void 0===f||f),s.onload=s.onerror=s.onbeforeload=function(c){var u=c.type[0];if(o&&"hideFocus"in s)try{s.sheet.cssText.length||(u="e")}catch(e){u="e"}if("e"==u&&(i+=1)styles = $scripts; + } + + /** + * {@inheritdoc} + */ + public function render() { + + return [ + 'command' => 'add_js', + 'data' => $this->styles, + ]; + } + +} diff --git a/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php b/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php index ee5208b078..0418527e71 100644 --- a/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php +++ b/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php @@ -174,11 +174,13 @@ protected function buildAttachmentsCommands(AjaxResponse $response, Request $req } if ($js_assets_header) { $js_header_render_array = $this->jsCollectionRenderer->render($js_assets_header); - $resource_commands[] = new PrependCommand('head', $this->renderer->renderPlain($js_header_render_array)); + $scripts_attributes = array_map(function ($render_array) { return $render_array['#attributes']; }, $js_header_render_array); + $resource_commands[] = new AddJsCommand($scripts_attributes); } if ($js_assets_footer) { $js_footer_render_array = $this->jsCollectionRenderer->render($js_assets_footer); - $resource_commands[] = new AppendCommand('body', $this->renderer->renderPlain($js_footer_render_array)); + $scripts_attributes = array_map(function ($render_array) { return $render_array['#attributes']; }, $js_footer_render_array); + $resource_commands[] = new AddJsCommand($scripts_attributes); } foreach (array_reverse($resource_commands) as $resource_command) { $response->addCommand($resource_command, TRUE); diff --git a/core/misc/ajax.js b/core/misc/ajax.js index fefe9f3031..8425768ce5 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -11,7 +11,7 @@ * included to provide Ajax capabilities. */ -(function ($, window, Drupal, drupalSettings) { +(function ($, window, Drupal, drupalSettings, loadjs) { 'use strict'; @@ -859,14 +859,26 @@ // Track if any command is altering the focus so we can avoid changing the // focus set by the Ajax command. var focusChanged = false; - for (var i in response) { - if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) { - this.commands[response[i].command](this, response[i], status); - if (response[i].command === 'invoke' && response[i].method === 'focus') { - focusChanged = true; + + var that = this; + Object.keys(response).reduce(function (deferredCommand, i) { + return deferredCommand.then(function () { + var command = response[i].command; + + if (command && that.commands[command]) { + if (command === 'invoke' && response[i].method === 'focus') { + focusChanged = true; + } + + if (command === 'add_js') { + return that.commands[command](that, response[i], status); + } + else { + that.commands[command](that, response[i], status); + } } - } - } + }); + }, $.Deferred().resolve()); // If the focus hasn't be changed by the ajax commands, try to refocus the // triggering element or one of its parents if that element does not exist @@ -1338,7 +1350,24 @@ document.styleSheets[0].addImport(match[1]); } while (match); } + }, + + add_js: function (ajax, response) { + var deferred = $.Deferred(); + + // @todo: simplify JSON response and remove mapping? + var scriptsSrc = response.data.map(function (script) { + return script.src; + }); + + loadjs(scriptsSrc, { + success: function () { + deferred.resolve(); + } + }); + + return deferred.promise(); } }; -})(jQuery, window, Drupal, drupalSettings); +})(jQuery, window, Drupal, drupalSettings, loadjs); diff --git a/core/tests/Drupal/Tests/Listeners/ProfilingTestListener.php b/core/tests/Drupal/Tests/Listeners/ProfilingTestListener.php new file mode 100644 index 0000000000..bea78cacb8 --- /dev/null +++ b/core/tests/Drupal/Tests/Listeners/ProfilingTestListener.php @@ -0,0 +1,18 @@ +toString(), 50), + number_format($test->getTestResultObject()->time(), 3), + number_format($time, 3) + ); + } +}