Issue #1664602 by quicksketch, Wim Leers, sun, webchick, nrussell: Fixed drupal_add_js() defer and async options break when aggregation is enabled (Replace with universal attributes array).

8.0.x
catch 2012-11-03 00:44:03 +00:00
parent 489c6f7579
commit 12eefe56c6
2 changed files with 35 additions and 40 deletions

View File

@ -3759,15 +3759,15 @@ function drupal_region_class($region) {
* else being the same, JavaScript added by a call to drupal_add_js() that
* happened later in the page request gets added to the page after one for
* which drupal_add_js() happened earlier in the page request.
* - defer: If set to TRUE, the defer attribute is set on the <script>
* tag. Defaults to FALSE.
* - async: If set to TRUE, the async attribute is set on the <script>
* tag. Defaults to FALSE.
* - cache: If set to FALSE, the JavaScript file is loaded anew on every page
* call; in other words, it is not cached. Used only when 'type' references
* a JavaScript file. Defaults to TRUE.
* - preprocess: If TRUE and JavaScript aggregation is enabled, the script
* file will be aggregated. Defaults to TRUE.
* - attributes: An associative array of attributes for the <script> tag. This
* may be used to add 'defer', 'async', or custom attributes. Note that
* setting any attributes will disable preprocessing as though the
* 'preprocess' option was set to FALSE.
* - browsers: An array containing information specifying which browsers
* should load the JavaScript item. See
* drupal_pre_render_conditional_comments() for details.
@ -3793,8 +3793,8 @@ function drupal_add_js($data = NULL, $options = NULL) {
}
$options += drupal_js_defaults($data);
// Preprocess can only be set if caching is enabled.
$options['preprocess'] = $options['cache'] ? $options['preprocess'] : FALSE;
// Preprocess can only be set if caching is enabled and no attributes are set.
$options['preprocess'] = $options['cache'] && empty($options['attributes']) ? $options['preprocess'] : FALSE;
// Tweak the weight so that files of the same weight are included in the
// order of the calls to drupal_add_js().
@ -3861,9 +3861,8 @@ function drupal_js_defaults($data = NULL) {
'weight' => 0,
'scope' => 'header',
'cache' => TRUE,
'defer' => FALSE,
'async' => FALSE,
'preprocess' => TRUE,
'attributes' => array(),
'version' => NULL,
'data' => $data,
'browsers' => array(),
@ -4090,16 +4089,9 @@ function drupal_pre_render_scripts($elements) {
break;
}
// The defer and async attributes must not be specified if the src
// attribute is not present.
if (!empty($element['#attributes']['src'])) {
// Both may be specified for legacy browser fallback purposes.
if (!empty($item['async'])) {
$element['#attributes']['async'] = 'async';
}
if (!empty($item['defer'])) {
$element['#attributes']['defer'] = 'defer';
}
// Attributes may only be set if this script is output independently.
if (!empty($element['#attributes']['src']) && !empty($item['attributes'])) {
$element['#attributes'] += $item['attributes'];
}
$elements[] = $element;

View File

@ -97,32 +97,14 @@ class JavaScriptTest extends WebTestBase {
}
/**
* Tests adding external JavaScript Files with the async attribute.
* Tests adding JavaScript files with additional attributes.
*/
function testAsyncAttribute() {
function testAttributes() {
$default_query_string = variable_get('css_js_query_string', '0');
drupal_add_library('system', 'drupal');
drupal_add_js('http://example.com/script.js', array('async' => TRUE));
drupal_add_js('core/misc/collapse.js', array('async' => TRUE));
$javascript = drupal_get_js();
$expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" async="async"></script>';
$expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" async="async"></script>';
$this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct async attribute.');
$this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered internal JavaScript with correct async attribute.');
}
/**
* Tests adding external JavaScript Files with the defer attribute.
*/
function testDeferAttribute() {
$default_query_string = variable_get('css_js_query_string', '0');
drupal_add_library('system', 'drupal');
drupal_add_js('http://example.com/script.js', array('defer' => TRUE));
drupal_add_js('core/misc/collapse.js', array('defer' => TRUE));
drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
$javascript = drupal_get_js();
$expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
@ -132,6 +114,27 @@ class JavaScriptTest extends WebTestBase {
$this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered internal JavaScript with correct defer attribute.');
}
/**
* Tests that attributes are maintained when JS aggregation is enabled.
*/
function testAggregatedAttributes() {
// Enable aggregation.
config('system.performance')->set('preprocess.js', 1)->save();
$default_query_string = variable_get('css_js_query_string', '0');
drupal_add_library('system', 'drupal');
drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
$javascript = drupal_get_js();
$expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
$expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
$this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute with aggregation enabled.');
$this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered internal JavaScript with correct defer attribute with aggregation enabled.');
}
/**
* Tests drupal_get_js() for JavaScript settings.
*/