Support accessing a property of a library as a namespace itself


ClojureScript uses Google Closure conventions which is a relatively disciplined way to explicitly describe the library structure. In some sense `goog.provide` is a tag identifying which parts of a JavaScript object are being used as a namespace abstraction. However foreign JavaScript libraries do not really declare the structure of the library structure they export. ES6 export provides more discipline, but this represents only a portion of the cases we'll like to address.

In Clojure due to JVM munging, static inner classes in package use the `$` delimiter. ClojureScript itself adopted this convention for `foo$macros`. We could adopt a similar convention here.

This also gives us an idiomatic way to deal with `default` exports:

We don’t need to be too concerned about clashes - we can first check that the original thing exists. If not remove the suffix and check for the prefix.

There are common cases where nested access is necessary. For example React Native native modules. After the first $ we can return to . (suggested by Thomas Heller).




Thomas Heller
May 24, 2020, 7:59 PM

FWIW I implemented this in shadow-cljs. Unfortunately I can’t easily turn this into a patch given how different shadow-cljs handles ns forms. What I’m doing is pretty straightforward though, so it may apply to CLJS in some way.

A [react-native$NativeModules.SomeBridge :as woz] require will be turned into 2 virtual sources. One will become (and shared with any other react-native requires)

and the other will use that one

The sources will be treated as regular closure-js/goog sources and :advanced will make everything nice and short.

I made no changes to cljs.analyzer/resolve-var of any kind since the ns form setup all the necessary stuff so the consumer will have ns alias from woz to some.helper.module$react_native$NativeModules$SomeBridge and happily use the virtual sources this created. Nothing is done at the indivual ns level, everything is handled in the “resolve” stage which I believe has no distinct stage in CLJS but the parse-ns might be close enough.

is not handled yet. Waiting for the decision which prefix to use for that.

David Nolen
August 23, 2020, 5:43 PM

The non-global part is addressed in master as of . For the global bit I think we should just avoid picking new names for now.


David Nolen


David Nolen