goog.module.ModuleManager questions

Skip to first unread message

Thomas Heller

Feb 21, 2019, 6:12:35 PM2/21/19
to Closure Library Discuss
Hey there,

we use goog.module.ModuleManager and associated classes via ClojureScript. We kinda lagged behind a bit and were using a quite old version of the Closure Library. When updating to a newer release I ran into a couple of issues due to some changes in how the loader operates. I adapted the changes easily but I'm a bit curious how this is handled at Google or how the API is intended to be used.

a) ModuleManager.beforeLoadModuleCode(id)

This either wasn't used before or was called automatically. Why does this need to be called manually when the Loader knows exactly when it starts loading the code? The tests only call this by creating custom ModuleLoader implementations. Is the intent to subclass ModuleLoader?

b) ModuleManager.setModuleTrustedUris(obj)

I get why the TrustedResourceUrl is used but how do you get those into a build in a "trusted" fashion without resorting to hacks that use the unchecked conversion [1]? In my builds the actual URIs use unique filenames with a hash value to allow permanent caching. Since I only know the hashes after compilation I used to prepend the moduleUris via a simple "global" variable that be used as input to setModuleUris. How do I deal with URIs that aren't known at compile time (eg. dependent on some CDN info)? If everything is relying on unchecked conversions the whole "trusted" setup seems kinda pointless?

I got this working fine but it all seems rather hacky and I wonder if there is a cleaner way? Maybe there is something in the Closure Compiler that I missed which actually generates the modules to be loaded?


[1] goog.html.uncheckedconversions.trustedResourceUrlFromStringKnownToSatisfyTypeContract

Steve Hicks

Apr 9, 2019, 6:35:10 PM4/9/19
to Closure Library Discuss, Kevin Irish (please note: this is an external mailing list)

Sorry for the slow response.  We're currently working on our procedures to try to ensure we don't let things lapse so long in the future.

The short answer is that most of the module manager code is owned external to the Closure Library team, so we don't have as much insight as we'd like into this.  I've copied the person who made many of the most recent substantive changes to ModuleManager to see if he can shed some light on this.

In terms of trusted URLs, there are typically various factories to build them.  Internally we have several, which I believe use the scary one under the hood, but provide very specific points that can be audited and scrutinized to make sure all proper escaping and whatever else is happening.  Dropping patterns into a CDN seems like something that should be doable.  A lot of enforcement I believe is around goog.string.Const (e.g. TrustedResourceUrl.fromConstant), which can be made from a goog.define that can be populated by a --define flag in the compiler - so if you can just generate the entire URL offline, that would be one path.


You received this message because you are subscribed to the Google Groups "Closure Library Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
For more options, visit

Stephen Hicks

Apr 9, 2019, 8:36:57 PM4/9/19
to Closure Library Discuss
Forwarded response from kirish:

I am certainly not an expert on the history here, but I can do my best to answer.

a) If I understand the question - Our modules are bundled together with several of them in the same download, so beforeLoadModuleCode() / setLoaded() are used to keep track of which one is currently being initialized. This is actually done outside of Closure Compiler as you had theorized, but it can be basically interpreted as a late bundling pass of the compiler. The term "load" here should really be "initialized", because it doesn't correspond to the network load in any way; it refers to when the JS defining that module is parsed and executed. I'm curious how old the version of Closure you are migrating off of is, since it looks like this setup has been around since 2009!

b) We don't typically use goog.module.ModuleLoader internally, so we don't actually use the functionality provided by goog.module.ModuleInfo#uris_ or goog.module.ModuleManager#setModuleTrustedUris(). Our trick with our custom module loaders is to implement goog.module.AbstractModuleLoader#loadModules such that it is able to construct the download URL just from the passed module ids (either ignoring the moduleInfoMap, or using it just to calculate dependencies). The construction of the URL itself can be done with goog.html.TrustedResourceUrl.format or the other related "safe" constructors. it sounds like this approach may be applicable for your situation, I hope it helps!
To unsubscribe from this group and stop receiving emails from it, send an email to

Thomas Heller

Apr 10, 2019, 3:38:32 AM4/10/19
to Closure Library Discuss
Thanks for the reply.

The split into beforeLoadModuleCode(id)/setLoaded is what got me, older versions were content with only setLoaded(id). Thanks for confirming the intent of those.

I missed the goog.html.TrustedResourceUrl.format so that makes things a little less "hacky". I'll might adopt a custom ModuleLoader as well.

Reply all
Reply to author
0 new messages