Expected: drupal_add_js('something.js', array('scope' => 'footer')) (or the library definition equivalent) is listed in drupalSettings.ajaxPageState.js.
Result: only the JS files that are in the 'header' scope are listed in drupalSettings.ajaxPageState.js.

Proposed resolution

diff --git a/core/includes/ b/core/includes/
index 10b09d6..70c0b81 100644
--- a/core/includes/
+++ b/core/includes/
@@ -3831,7 +3831,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS

       // Provide the page with information about the individual JavaScript files
       // used, information not otherwise available when aggregation is enabled.
-      $setting['ajaxPageState']['js'] = array_fill_keys(array_keys($items), 1);
+      $setting['ajaxPageState']['js'] = array_fill_keys(array_keys($javascript), 1);

       // Provide the page with information about the individual CSS files used,

This is analogous to how the CSS page state is stored. $items only contains the items for the current scope; and since settings on most pages are added when $scope == 'header', that explains why only JS files that are in the 'header' scope get added to the page state.

Remaining tasks

Get proper test coverage. In my initial testing it turned out to be impossible to reproduce the same problem in the tests, likely because WebTestBase does not actually execute JavaScript, it merely simulates the crucial aspects.

User interface changes


API changes


#1 1864944-1.patch732 bytesWim Leers
PASSED: [[SimpleTest]]: [MySQL] 49,300 pass(es).
[ View ]


Wim Leers’s picture

Status:Active» Needs review
Issue tags:+JavaScript
new732 bytes
PASSED: [[SimpleTest]]: [MySQL] 49,300 pass(es).
[ View ]
Wim Leers’s picture

Now that #1824500: In-place editing for Fields has landed, this is super easy to reproduce.

  1. Install D8 using the Standard install profile (which has Edit enabled).
  2. Go to the front page.
  3. Open your browser's console and type drupalSettings.ajaxPageState.js.
  4. Check whether edit.js is listed there (which has 'scope' => 'footer') . It's not. This is the bug.
nod_’s picture

Status:Needs review» Reviewed & tested by the community

Works well as a stop-gap measure. It's the whole API that needs to be worked on to avoid this kind of uglyness, see #1871596: Create a PartialResponse class to encapsulate html-level data [Moving to sandbox].

In the meanwhile, this works.

webchick’s picture

Status:Reviewed & tested by the community» Fixed

Hm. Unfortunately, doesn't sound like it's possible to work #2 into a test since it's JS-only. :(

Committed and pushed to 8.x. Thanks!

Wim Leers’s picture

It is in fact possible to add tests for this, similarly to how I'm doing tests over at #1875632: JS settings merging behavior: preserve integer keys (allow for array literals in drupalSettings): using json_decode().

However, all of this will change in the issue that nod_ pointed to in #3 so it's not clear if it's worth the effort. I personally believe it's worth it, even if only because that'll ensure tests in #1871596: Create a PartialResponse class to encapsulate html-level data [Moving to sandbox] will test this edge case too. Thoughts?

webchick’s picture

Title:ajaxPageState does not contain JS files that are in scopes other than 'header'» Tests for ajaxPageState does not contain JS files that are in scopes other than 'header'
Category:bug» task
Status:Fixed» Active
Issue tags:+Needs tests

Yeah, let's do it. That issue can always remove the test if it turns out to not be relevant.

Switching some metadata around.

Wim Leers’s picture

I'll likely get this done tomorrow.

lmeurs’s picture

The patch from #1 to set scripts paths to Drupal.settings.ajaxPageState.js scope independently has not been backported to Drupal 7, is this something that should be done? (sorry, am not very familiar with the backporting policy)

And sort of on the same subject (though D7): when the scope of the settings javascript has been altered to footer, on AJAX calls newly attached files are not being loaded. Explanation: When the scope of the settings variable is no longer header, drupal_get_js() does not add the Drupal.settings.ajaxPageState.js array, Drupal.settings.ajaxPageState.js is not defined on page load, ajax_render() does not receive $_POST['ajax_page_state']['js'] on AJAX calls, ajax_render() cannot determine which files are newly attached and thus none are appended to the head.

Is there a good reason for only adding Drupal.settings.ajaxPageState.js when the scope of the settings variable is set to header or should we create a new issue for this?

BTW: Workarounds are setting these variables for JS and CSS manually on hook_js_alter() or better to not change the scope of scripts but print the $scripts variable at the bottom of your page using this great little trick.