I've encountered a race condition when using a lazy builder that renders an element with an attached script that includes dependencies.
In this case I'm using a library like this:
editor:
version: "1.0.0"
js:
js/editor.js: {}
dependencies:
- core/ckeditor
The issue is that dynamically added scripts are loaded asynchronously by default (see async). As a result in my example above it is possible for editor.js to be processed before ckeditor.js despite them being added to the page in the correct order resulting in a JS error.
This issue can be mitigated by attaching the libraries used by the lazy builder to the page after the lazy builder element so that it does not need to be added when replacing the placeholder.
$output['form'] = $lazy_builder;
$output['#attached']['library'][] = 'my_module/editor';
return $output;
Proposed Resolution
This should be preventable by adding an async="false" to all script tags loaded through the Drupal AJAX api from libraries.
Steps to Reproduce
I was able to reproduce this issue with and without JS aggregation, however with aggregation it was necessary to force my 2 JS files to load simultaneously by adding 10-20 image requests at the top of the page. CKEditor is a useful example dependency because of it's 550KB filesize.
Comments
Comment #2
Wim LeersThanks for reporting this! :)
Comment #3
malcolm_p CreditAttribution: malcolm_p commentedIt's actually not related to either big_pipe or quickedit, it also occurs using the AJAX api. The issue is that scripts added to a the page programmatically (ex AJAX api, big_pipe, quickedit) will be loaded asynchronously (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async). So if we are loading 2 scripts, the second of which depends on the first, a race condition can occur where the 2nd script finishes loading before the 1st.
This is hard to reproduce consistently as it depends on the specific load time of the scripts and what else is being loaded on the page before these scripts. I'll try and work on a test to reproduce it more consistently though.
Comment #4
Wim LeersThanks for clarifying!
We have an issue for that too: #1988968: Drupal.ajax does not guarantee that "add new JS file to page" commands have finished before calling said JS. Can you confirm that that issue (which has lots of prior discussion!) indeed covers the same problem?
Comment #5
malcolm_p CreditAttribution: malcolm_p commentedAh, interesting. Yes that's definitely related. Using a dependency manager will definitely be a more robust solution as well. I can't yet tell if the case of dependencies is currently handled though as I don't think dependency information is currently passed to the AddJsCommand.
Comment #7
Wim Leers