-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debug loader returns null
when loading an ES module if goog.bootstrap
called from a <script type=module>
#1152
Comments
Move the calls to goog.bootstrap from blockly.mjs to prepare.mjs. This is needed to work around a bug in the Cosure Library debug loader (google/closure-library#1152). This gets a bit ugly because most of the code has to go in a <script> (because it needs goog.bootstrap, which was loaded by an earlier <script> tag).
Move the calls to goog.bootstrap from blockly.mjs to prepare.mjs. This is needed to work around a bug in the Cosure Library debug loader (google/closure-library#1152). This gets a bit ugly because most of the code has to go in a <script> (because it needs goog.bootstrap, which was loaded by an earlier <script> tag).
…playground (#5931) * chore(deps): Update closure/goog/base.js, add goog.js * Update base.js from the latest version (20220104.0.0). * Also copy over goog.js, which provides access to asuitable subset of goog.* via an importable module). * refactor(tests): Have playground.html load Blockly as a module N.B.: * We still need a preparation step, in order to load base.js and deps.js via <script> tags in uncompiled mode; in compiled mode it will instead load all the *_compressed.js files via <script> tags. Acess to the Blockly object is via: import Blockly from './playgrounds/blockly.mjs'; (N.B: no "* as", since blockly.mjs has only a default export.) * There remain two serious defects when running in uncompiled mode: * It does not attempt to load msg/messages.js, causing startup to fail. * Module loading only works if there are no ES Modules; if there are, something goes wrong with base.js's attempt to sequence module loads causing goog.modules that import ES modules to get a null exports object for that import. X-( * fix(tests): Have playground.html load messages.js before generators This fixes the issue caused by missing messages when loading the generators. * fix(tests): Move bootsrap calls to prepare.js Move the calls to goog.bootstrap from blockly.mjs to prepare.mjs. This is needed to work around a bug in the Cosure Library debug loader (google/closure-library#1152). This gets a bit ugly because most of the code has to go in a <script> (because it needs goog.bootstrap, which was loaded by an earlier <script> tag). * fix(documentation): Minor comment corrections for PR #5931
High level response: the person who wrote all this code left Google a while back, and we don't really use ES modules internally at the moment, so this is pretty poorly covered. Is there a reason the Going deeper - I'm stepping through the debug loader and it looks like the difference is that when it's loading the googModule dependency, I've got to step away for a bit, but the next step would be to figure out what's setting |
When the esModule is written, there's a check for I tried to fix this by also checking if there are any ES modules pending and then setting This seems like a fundamental issue with Firefox. The rationale behind using a separate "after" script is that if the loaded module fails to load, we still want to reset the state, so we really do depend on the browser getting the order right here. Here's a minimal repro to see the problematic Firefox behavior: // file: a.js
console.log('inside'); <script type="module">
function s(src, body) {
const script = document.createElement('script');
if (src) script.src = src;
if (body) script.innerHTML = body;
script.type = 'module';
script.defer = true;
document.head.appendChild(script);
}
s('', `console.log('before');`);
s('a.js');
s('', `console.log('after');`);
</script> In Chrome, this logs (before, inside, after), while in Firefox, it logs (before, after, inside). I suspect this is a Firefox bug? I don't understand why this works when the bootstrap command is not in a module (the only difference seems to be the |
Okay, and now that repro is also printing (before, after, inside) in Chrome. So now I really have no idea what's going on. I wonder if this use case is just fundamentally broken? |
Understood—though I was mildly surprised that this hadn't been noticed by other teams doing a
We have an app that was basically a single .html` page:
<!-- index.html -->
<script src="closure/goog/base.js"></script>
<script src="build/deps.js"></script>
<script type=module>
import myModule from 'wrapper.mjs';
myModule.doSomething();
</script> // wrapper.mjs
await new Promise((resolve, reject) => {
goog.bootstrap([/* modules to bootstrap */], resolve)
});
// N.B. top-level module still contains a goog.module.declareLegacyNamespace.
export default globalThis.myModule; which was nice because it kept the code in Unfortunately as noted this did not work as expected, so for now I have changed it to: <!-- index.html -->
<script src="closure/goog/base.js"></script>
<script src="build/deps.js"></script>
<script>
window.loaded = new Promise((resolve, reject) => {
goog.bootstrap([/* modules to bootstrap */], resolve)
});
</script>
<script type=module>
await window.loaded;
myModule.doSomething();
</script> which feels a little kludgy but works fine. Thanks for looking in to this issue. It sounds like it may not be easy to fix properly, but I hope that at least having a report open will help anyone else who encounters it. |
I see. Thanks for reporting this, and expanding on what you're doing. Unfortunately, Your workaround is indeed kludgy, and I'm sorry that that's what it takes, but as you've gathered, it's unlikely we'll be able to fix this "the right way". If anybody can figure out how to adjust the debug loader to make it work in all ES-module-supporting browsers, we'd welcome a contribution, but it's not something we're going to be able to prioritize. |
Consider an ES module using
declareModuleId
:which is required by a
goog.module
:If this is loaded as follows:
then all is well.
If, however, the final
<script>
tag is changed to a<script type=module>
, then this fails with…and indeed, this is because
goog.DebugLoader_.prototype.load_
has returnednull
; this appears to be because thegoog.require
call in the dependant module has happened before its dependency has finished loading.This problem does not occur if the dependant module is converted to also be an ES module:
The text was updated successfully, but these errors were encountered: