Skip to content

Commit 76ac6bf

Browse files
authoredOct 15, 2021
CLJS-3322: Upgrade to latest Closure Library - handle non-legacy GCL goog.module namespaces (#105)
* bump gcl * add goog.module handling case to analyzer * add goog.module handling case to compiler * add missing case to browser REPL bootstrap for goog.module * generalize munge-goog-module-lib * add resolve-import helper * fixup emission test * resolve goog.module imports in resolve-var * check that emission doesn't shadow import usage * wrap goog.module.get in goog.scope to avoid silly Closure warnings * remove dependency on goog.object from cljs.core macros file * add comment about goog.scope workaround * add docstrings to extern parsing ns * add Token/FUNCTION case * Token/NAME should check for simple name * handle goog.module case in parse-externs * make parsed->defs a multimethod * add resource->source-file helper * ^Node type hints * in NAME case stop if parent is OBJECTLIT * STRING_KEY case does not need split on "." * when parsing goog.modules, only provide ClojureScript defs for exported defs * remove unneeded condition * add internal reference to goog.math.Long (to allow self-parity tests to pass) * test cases
·
v1.12r1.10.891
1 parent 71c6f47 commit 76ac6bf

File tree

15 files changed

+269
-52
lines changed

15 files changed

+269
-52
lines changed
 

‎deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
org.clojure/clojure {:mvn/version "1.10.0"}
66
org.clojure/core.specs.alpha {:mvn/version "0.1.24"}
77
org.clojure/data.json {:mvn/version "0.2.6"}
8-
org.clojure/google-closure-library {:mvn/version "0.0-20201211-3e6c510d"}
8+
org.clojure/google-closure-library {:mvn/version "0.0-20211011-0726fdeb"}
99
org.clojure/spec.alpha {:mvn/version "0.1.143"}
1010
org.clojure/tools.reader {:mvn/version "1.3.3"}
1111
org.clojure/test.check {:mvn/version "0.10.0-alpha3"}}

‎pom.template.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<dependency>
3636
<groupId>org.clojure</groupId>
3737
<artifactId>google-closure-library</artifactId>
38-
<version>0.0-20201211-3e6c510d</version>
38+
<version>0.0-20210811-6da97fe1</version>
3939
</dependency>
4040
<dependency>
4141
<groupId>org.clojure</groupId>

‎project.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
[org.clojure/tools.reader "1.3.3"]
1616
[org.clojure/test.check "0.10.0-alpha3" :scope "test"]
1717
[com.cognitect/transit-clj "0.8.309"]
18-
[org.clojure/google-closure-library "0.0-20201211-3e6c510d"]
18+
[org.clojure/google-closure-library "0.0-20210811-6da97fe1"]
1919
[com.google.javascript/closure-compiler-unshaded "v20210808"]]
2020
:profiles {:1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}
2121
:uberjar {:aot :all :main cljs.main}

‎script/bootstrap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CORE_SPECS_ALPHA_RELEASE="0.1.24"
88
CLOSURE_RELEASE="20210808"
99
DJSON_RELEASE="0.2.6"
1010
TRANSIT_RELEASE="0.8.309"
11-
GCLOSURE_LIB_RELEASE="0.0-20201211-3e6c510d"
11+
GCLOSURE_LIB_RELEASE="0.0-20210811-6da97fe1"
1212
TREADER_RELEASE="1.3.3"
1313
TEST_CHECK_RELEASE="0.10.0-alpha3"
1414

‎src/main/cljs/cljs/core.cljs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,6 +2284,10 @@ reduces them without incurring seq initialization"
22842284
(not (identical? n js/Infinity))
22852285
(== (js/parseFloat n) (js/parseInt n 10))))
22862286

2287+
(def
2288+
^{:doc "INTERNAL: do not use"}
2289+
LongImpl goog.math.Long)
2290+
22872291
(defn int?
22882292
"Return true if x satisfies integer? or is an instance of goog.math.Integer
22892293
or goog.math.Long."

‎src/main/cljs/cljs/loader.cljs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
(ns cljs.loader
1010
(:require [goog.object :as gobj]
1111
[goog.html.legacyconversions :as legacy])
12-
(:import [goog.module ModuleLoader]
13-
[goog.module ModuleManager]))
12+
(:import [goog.module ModuleManager]
13+
[goog.module ModuleLoader]))
1414

1515
(def module-infos MODULE_INFOS) ;; set by compiler
1616
(def module-uris

‎src/main/cljs/clojure/browser/repl.cljs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,10 @@
227227
(let [ret (.require__ js/goog src)]
228228
(when (= reload "reload-all")
229229
(set! (.-cljsReloadAll_ js/goog) false))
230-
ret))))))
230+
;; handle requires from Closure Library goog.modules
231+
(if (js/goog.isInModuleLoader_)
232+
(js/goog.module.getInternal_ src)
233+
ret)))))))
231234

232235
(defn connect
233236
"Connects to a REPL server from an HTML document. After the

‎src/main/clojure/cljs/analyzer.cljc

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,12 @@
812812
(or (contains? global-exports (symbol module))
813813
(contains? global-exports (name module)))))
814814

815+
(defn goog-module-dep?
816+
[module]
817+
(let [[module _] (lib&sublib module)
818+
module-type (get-in @env/*compiler* [:js-dependency-index (str module) :module])]
819+
(= :goog module-type)))
820+
815821
(defn confirm-var-exists
816822
([env prefix suffix]
817823
(let [warn (confirm-var-exist-warning env prefix suffix)]
@@ -1010,6 +1016,12 @@
10101016
(str "node$module$" (munge (string/replace (str name) #"[.\/]" #?(:clj "\\$"
10111017
:cljs "$$")))))
10121018

1019+
(defn munge-goog-module-lib
1020+
([name]
1021+
(str "goog$module$" (munge (string/replace (str name) #"[.\/]" #?(:clj "\\$" :cljs "$$")))))
1022+
([ns name]
1023+
(str (munge ns) "." (munge-goog-module-lib name))))
1024+
10131025
(defn munge-global-export [name]
10141026
(str "global$module$" (munge (string/replace (str name) #"[.\/]" #?(:clj "\\$"
10151027
:cljs "$$")))))
@@ -1031,6 +1043,7 @@
10311043

10321044
(defn ns->module-type [ns]
10331045
(cond
1046+
(goog-module-dep? ns) :goog-module
10341047
(js-module-exists? ns) :js
10351048
(node-module-dep? ns) :node
10361049
(dep-has-global-exports? ns) :global))
@@ -1072,6 +1085,12 @@
10721085
:op :js-var
10731086
:foreign true}))
10741087

1088+
(defmethod resolve* :goog-module
1089+
[env sym full-ns current-ns]
1090+
{:name (symbol (str current-ns) (str (munge-goog-module-lib full-ns) "." (name sym)))
1091+
:ns current-ns
1092+
:op :var})
1093+
10751094
(defmethod resolve* :global
10761095
[env sym full-ns current-ns]
10771096
(let [pre (extern-pre sym current-ns)]
@@ -1135,6 +1154,15 @@
11351154
:op :js-var
11361155
:ns current-ns})))
11371156

1157+
(defn resolve-import
1158+
"goog.modules are deterministically assigned to a property of the namespace,
1159+
we cannot expect the reference will be globally available, so we resolve to
1160+
namespace local reference."
1161+
[env import]
1162+
(if (goog-module-dep? import)
1163+
(symbol (munge-goog-module-lib (-> env :ns :name) import))
1164+
import))
1165+
11381166
;; core.async calls `macroexpand-1` manually with an ill-formed
11391167
;; :locals map. Normally :locals maps symbols maps, but
11401168
;; core.async adds entries mapping symbols to symbols. We work
@@ -1207,7 +1235,13 @@
12071235
;; check if prefix is some existing def
12081236
(if-let [resolved (resolve-var env prefix nil false)]
12091237
(update resolved :name #(symbol (str % "." suffix)))
1210-
(let [idx (.lastIndexOf s ".")
1238+
;; glib imports (i.e. (:import [goog.module ModuleLoader])
1239+
;; are always just dotted symbols after the recursion
1240+
(let [s (str
1241+
(cond->> s
1242+
(goog-module-dep? sym)
1243+
(resolve-import env)))
1244+
idx (.lastIndexOf (str s) ".")
12111245
pre (subs s 0 idx)
12121246
suf (subs s (inc idx))]
12131247
{:op :var

‎src/main/clojure/cljs/compiler.cljc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,9 @@
12941294
(let [{node-libs true libs-to-load false} (group-by ana/node-module-dep? libs)]
12951295
[node-libs libs-to-load])
12961296
[nil libs]))
1297+
[goog-modules libs-to-load] (let [{goog-modules true libs-to-load false}
1298+
(group-by ana/goog-module-dep? libs-to-load)]
1299+
[goog-modules libs-to-load])
12971300
global-exports-libs (filter ana/dep-has-global-exports? libs-to-load)]
12981301
(when (-> libs meta :reload-all)
12991302
(emitln "if(!COMPILED) " loaded-libs-temp " = " loaded-libs " || cljs.core.set([\"cljs.core\"]);")
@@ -1336,11 +1339,26 @@
13361339
:else
13371340
(when-not (= lib 'goog)
13381341
(emitln "goog.require('" (munge lib) "');"))))
1342+
;; Node Libraries
13391343
(doseq [lib node-libs]
13401344
(let [[lib' sublib] (ana/lib&sublib lib)]
13411345
(emitln (munge ns-name) "."
13421346
(ana/munge-node-lib lib)
13431347
" = require('" lib' "')" (sublib-select sublib) ";")))
1348+
;; Google Closure Library Modules (i.e. goog.module(...))
1349+
;; these must be assigned to vars
1350+
(doseq [lib goog-modules]
1351+
(let [[lib' sublib] (ana/lib&sublib lib)]
1352+
(emitln "goog.require('" lib' "');")
1353+
;; we emit goog.scope here to suppress a Closure error about
1354+
;; goog.module.get when compiling - meant to discourage incorrect
1355+
;; usage by hand written code - not applicable here
1356+
(emitln "goog.scope(function(){")
1357+
(emitln (munge ns-name) "."
1358+
(ana/munge-goog-module-lib lib)
1359+
" = goog.module.get('" lib' "')" (sublib-select sublib) ";")
1360+
(emitln "});")))
1361+
;; Global Exports
13441362
(doseq [lib global-exports-libs]
13451363
(let [{:keys [global-exports]} (get js-dependency-index (name (-> lib ana/lib&sublib first)))]
13461364
(emit-global-export ns-name global-exports lib)))

‎src/main/clojure/cljs/core.cljc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,9 +1430,9 @@
14301430
(core/let [psym (resolve p)
14311431
pfn-prefix (subs (core/str psym) 0
14321432
(clojure.core/inc (.indexOf (core/str psym) "/")))]
1433-
(cons `(goog.object/set ~psym ~type true)
1433+
(cons `(unchecked-set ~psym ~type true)
14341434
(map (core/fn [[f & meths :as form]]
1435-
`(goog.object/set ~(symbol (core/str pfn-prefix f))
1435+
`(unchecked-set ~(symbol (core/str pfn-prefix f))
14361436
~type ~(with-meta `(fn ~@meths) (meta form))))
14371437
sigs))))
14381438

@@ -2672,8 +2672,8 @@
26722672
(js-obj* '())
26732673
`(let [~@(apply concat (clojure.set/map-invert expr->local))
26742674
~obj ~(js-obj* (filter-on-keys core/string? kvs))]
2675-
~@(map (core/fn [[k v]] `(goog.object/set ~obj ~k ~v)) sym-pairs)
2676-
~@(map (core/fn [[k v]] `(goog.object/set ~obj ~v ~(core/get kvs k))) expr->local)
2675+
~@(map (core/fn [[k v]] `(unchecked-set ~obj ~k ~v)) sym-pairs)
2676+
~@(map (core/fn [[k v]] `(unchecked-set ~obj ~v ~(core/get kvs k))) expr->local)
26772677
~obj))))
26782678

26792679
(core/defmacro alength [a]
@@ -2888,7 +2888,7 @@
28882888
(core/list 'js* "''+~{}" s))
28892889

28902890
(core/defmacro es6-iterable [ty]
2891-
`(goog.object/set (.-prototype ~ty) cljs.core/ITER_SYMBOL
2891+
`(unchecked-set (.-prototype ~ty) cljs.core/ITER_SYMBOL
28922892
(fn []
28932893
(this-as this#
28942894
(cljs.core/es6-iterator this#)))))

‎src/main/clojure/cljs/externs.clj

Lines changed: 98 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
[com.google.javascript.jscomp.parsing Config$JsDocParsing]
1717
[com.google.javascript.rhino
1818
Node Token JSTypeExpression JSDocInfo$Visibility]
19-
[java.nio.charset StandardCharsets]
2019
[java.util.logging Level]))
2120

2221
(def ^:dynamic *ignore-var* false)
@@ -26,7 +25,10 @@
2625
;; ------------------------------------------------------------------------------
2726
;; Externs Parsing
2827

29-
(defn annotate [props ty]
28+
(defn annotate
29+
"Given a sequential list of properties [foo core baz] representing segments
30+
of the namespace, annotate the last symbol with the type information."
31+
[props ty]
3032
(when (seq props)
3133
(conj
3234
(into [] (butlast props))
@@ -35,7 +37,8 @@
3537
(defn get-tag [^JSTypeExpression texpr]
3638
(when-let [root (.getRoot texpr)]
3739
(if (.isString root)
38-
(symbol (.getString root))(if-let [child (.. root getFirstChild)]
40+
(symbol (.getString root))
41+
(if-let [child (.. root getFirstChild)]
3942
(if (.isString child)
4043
(symbol (.. child getString)))))))
4144

@@ -97,17 +100,26 @@
97100
(fn [^Node node]
98101
(.getToken node)))
99102

100-
(defmethod parse-extern-node Token/VAR [node]
103+
;; handle named function case (i.e. goog.modules)
104+
;; function foo {}, the entire function is the node
105+
(defmethod parse-extern-node Token/FUNCTION [^Node node]
106+
(when (> (.getChildCount node) 0)
107+
(let [ty (get-var-info node)]
108+
(doto
109+
(cond-> (parse-extern-node (.getFirstChild node))
110+
ty (-> first (annotate ty) vector))))))
111+
112+
(defmethod parse-extern-node Token/VAR [^Node node]
101113
(when (> (.getChildCount node) 0)
102114
(let [ty (get-var-info node)]
103115
(cond-> (parse-extern-node (.getFirstChild node))
104116
ty (-> first (annotate ty) vector)))))
105117

106-
(defmethod parse-extern-node Token/EXPR_RESULT [node]
118+
(defmethod parse-extern-node Token/EXPR_RESULT [^Node node]
107119
(when (> (.getChildCount node) 0)
108120
(parse-extern-node (.getFirstChild node))))
109121

110-
(defmethod parse-extern-node Token/ASSIGN [node]
122+
(defmethod parse-extern-node Token/ASSIGN [^Node node]
111123
(when (> (.getChildCount node) 0)
112124
(let [ty (get-var-info node)
113125
lhs (cond-> (first (parse-extern-node (.getFirstChild node)))
@@ -120,13 +132,24 @@
120132
lhs))
121133
[lhs]))))
122134

123-
(defmethod parse-extern-node Token/NAME [node]
124-
(let [lhs (map symbol (string/split (.getQualifiedName node) #"\."))]
125-
(if (> (.getChildCount node) 0)
126-
(let [externs (parse-extern-node (.getFirstChild node))]
127-
(conj (map (fn [ext] (concat lhs ext)) externs)
128-
lhs))
129-
[lhs])))
135+
;; JavaScript name
136+
;; function foo {}, in this case the `foo` name node
137+
;; {"foo": bar}, in this case the `bar` name node
138+
(defmethod parse-extern-node Token/NAME [^Node node]
139+
(if (= Token/STRING_KEY (-> node .getParent .getToken))
140+
;; if we are inside an object literal we are done
141+
[]
142+
;; also check .getString - goog.module defs won't have qualified names
143+
(let [name (or (.getQualifiedName node) (.getString node))
144+
lhs (when-not (string/blank? name)
145+
(map symbol (string/split name #"\.")))]
146+
(if (seq lhs)
147+
(if (> (.getChildCount node) 0)
148+
(let [externs (parse-extern-node (.getFirstChild node))]
149+
(conj (map (fn [ext] (concat lhs ext)) externs)
150+
lhs))
151+
[lhs])
152+
[]))))
130153

131154
(defmethod parse-extern-node Token/GETPROP [node]
132155
(when-not *ignore-var*
@@ -135,6 +158,8 @@
135158
(annotate props ty)
136159
props)])))
137160

161+
;; JavaScript Object literal
162+
;; { ... }
138163
(defmethod parse-extern-node Token/OBJECTLIT [node]
139164
(when (> (.getChildCount node) 0)
140165
(loop [nodes (.children node)
@@ -144,8 +169,10 @@
144169
(recur (rest nodes)
145170
(concat externs (parse-extern-node (first nodes))))))))
146171

147-
(defmethod parse-extern-node Token/STRING_KEY [node]
148-
(let [lhs (map symbol (string/split (.getString node) #"\."))]
172+
;; Object literal string key node
173+
;; {"foo": bar} - the key and value together
174+
(defmethod parse-extern-node Token/STRING_KEY [^Node node]
175+
(let [lhs [(-> node .getString symbol)]]
149176
(if (> (.getChildCount node) 0)
150177
(let [externs (parse-extern-node (.getFirstChild node))]
151178
(conj (map (fn [ext] (concat lhs ext)) externs)
@@ -154,7 +181,17 @@
154181

155182
(defmethod parse-extern-node :default [node])
156183

157-
(defn parse-externs [^SourceFile source-file]
184+
(defn parse-externs
185+
"Returns a sequential collection of the form:
186+
187+
[[foo core first]
188+
[foo core next]
189+
[foo core baz last] ...]
190+
191+
Where the last symbol is annotated with var info via metadata. This simple
192+
structure captures the nested form of Closure namespaces and aids
193+
direct indexing."
194+
[^SourceFile source-file]
158195
(binding [*source-file* (.getName source-file)]
159196
(let [^CompilerOptions compiler-options
160197
(doto (CompilerOptions.)
@@ -167,8 +204,13 @@
167204
compiler)
168205
(.init (list source-file) '() compiler-options))
169206
js-ast (JsAst. source-file)
170-
^Node root (.getAstRoot js-ast closure-compiler)]
171-
(loop [nodes (.children root)
207+
^Node root (.getAstRoot js-ast closure-compiler)
208+
nodes (.children root)]
209+
(loop [nodes (cond-> nodes
210+
;; handle goog.modules which won't have top-levels
211+
;; need to look at internal children
212+
(= Token/MODULE_BODY (some-> nodes first .getToken))
213+
(-> first .children))
172214
externs []]
173215
(if (empty? nodes)
174216
externs
@@ -215,17 +257,42 @@
215257
(= (inc (count ns-segs)) (count var-segs))
216258
(= ns-segs (take (count ns-segs) var-segs)))))
217259

218-
(defn parsed->defs [externs]
219-
(let [ns-segs (into [] (map symbol (string/split (str *goog-ns*) #"\.")))]
220-
(reduce
221-
(fn [m xs]
222-
;; ignore definitions from other provided namespaces not under consideration
223-
(if (ns-match? ns-segs xs)
224-
(let [sym (last xs)]
225-
(cond-> m
226-
(seq xs) (assoc sym (merge (meta sym) {:ns *goog-ns* :name sym}))))
227-
m))
228-
{} externs)))
260+
(defmulti parsed->defs (fn [_ module-type] module-type))
261+
262+
(defmethod parsed->defs :goog
263+
([externs _]
264+
(let [grouped (group-by #(= 'exports (first %)) externs)
265+
exports (->> (get grouped true)
266+
(map (comp vec rest))
267+
(remove empty?)
268+
set)
269+
exported (filter exports (get grouped false))]
270+
(reduce
271+
(fn [m xs]
272+
(let [sym (last xs)]
273+
(cond-> m
274+
(seq xs) (assoc sym (merge (meta sym) {:ns *goog-ns* :name sym})))))
275+
{} exported))))
276+
277+
(defmethod parsed->defs :default
278+
([externs _]
279+
(let [ns-segs (into [] (map symbol (string/split (str *goog-ns*) #"\.")))]
280+
(reduce
281+
(fn [m xs]
282+
;; ignore definitions from other provided namespaces not under consideration
283+
(if (ns-match? ns-segs xs)
284+
(let [sym (last xs)]
285+
(cond-> m
286+
(seq xs) (assoc sym (merge (meta sym) {:ns *goog-ns* :name sym}))))
287+
m))
288+
{} externs))))
289+
290+
(defn resource->source-file
291+
[resource]
292+
(-> (SourceFile/builder)
293+
(.withPath (.toPath (io/file (.getPath resource))))
294+
(.withContent (io/input-stream resource))
295+
(.build)))
229296

230297
(defn analyze-goog-file
231298
([f]
@@ -237,11 +304,8 @@
237304
(binding [*goog-ns* ns]
238305
{:name ns
239306
:defs (parsed->defs
240-
(parse-externs
241-
(-> (SourceFile/builder)
242-
(.withPath (.toPath (io/file (.getPath rsrc))))
243-
(.withContent (io/input-stream rsrc))
244-
(.build))))}))))
307+
(parse-externs (resource->source-file rsrc))
308+
(:module desc))}))))
245309

246310
(comment
247311
(require '[clojure.java.io :as io]

‎src/test/cljs/cljs/predicates_test.cljs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
(ns cljs.predicates-test
1010
(:require [cljs.test :as test :refer-macros [deftest is]])
11-
(:import [goog.math Long Integer]))
11+
(:import [goog.math Integer]))
1212

1313
(def pred-val-table
1414
(let [uuid (uuid "00000000-0000-0000-0000-000000000000")]
@@ -41,9 +41,15 @@
4141
(let [posint 10e10
4242
negint -10e10
4343
neg0 (/ ##-Inf)
44-
natl (Long.getZero)
45-
posl (Long.fromNumber posint)
46-
negl (Long.fromNumber negint)
44+
;; NOTE: we must go through a var because in self-parity tests
45+
;; we cannot simply import goog.module namespaces if cljs.core
46+
;; depends on the type - that's because cljs.core was *separately
47+
;; compiled* already bundling goog.modules. In many cases this is
48+
;; not an issue, but it is an issue if internally we use the type
49+
;; to make instanceof assertions - which we do for Long
50+
natl (.getZero LongImpl)
51+
posl (.fromNumber LongImpl posint)
52+
negl (.fromNumber LongImpl negint)
4753
nati Integer.ZERO
4854
posi (Integer.fromNumber posint)
4955
negi (Integer.fromNumber negint)]
@@ -69,4 +75,4 @@
6975
(let [v (first row)]
7076
(dotimes [i (count row)]
7177
(is (= ((nth preds i) v) (nth row i))
72-
(pr-str (list (nth preds i) v))))))))
78+
(pr-str (list (nth preds i) v))))))))
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
(ns cljs.analyzer.glib-module-test
2+
(:require [cljs.analyzer :as ana]
3+
[cljs.analyzer-tests :as ana-tests]
4+
[clojure.test :as test :refer [deftest is testing]]
5+
[cljs.env :as env]))
6+
7+
(deftest glib-module-detect-test
8+
(testing "Basic glib module detection"
9+
(is (= :goog (get-in @ana-tests/test-cenv [:js-dependency-index (munge "goog.module.ModuleLoader") :module])))))
10+
11+
(deftest glib-module-predicate-test
12+
(testing "glib module detection predicate"
13+
(env/with-compiler-env ana-tests/test-cenv
14+
(is (ana/goog-module-dep? 'goog.module.ModuleLoader)))))
15+
16+
(deftest glib-module-classification-test
17+
(testing "glib module classification"
18+
(env/with-compiler-env ana-tests/test-cenv
19+
(is (= :goog-module (ana/ns->module-type 'goog.module.ModuleLoader))))))
20+
21+
(deftest glib-module-resolve-var-test
22+
(testing "glib module var resolution"
23+
(let [cenv (env/default-compiler-env)
24+
ns-ast (ana-tests/analyze-forms cenv
25+
'[(ns foo.core
26+
(:require [goog.module.ModuleLoader :as module-loader]))])
27+
aenv (assoc (ana/empty-env) :ns (ana/get-namespace cenv 'foo.core))]
28+
(is (= '{:name foo.core/goog$module$goog$module$ModuleLoader.EventType
29+
:ns foo.core
30+
:op :var}
31+
(env/with-compiler-env cenv
32+
(ana/resolve-var aenv 'module-loader/EventType)))))))
33+
34+
(deftest glib-module-resolve-import-test
35+
(testing "glib module resolve import helper test"
36+
(let [cenv (env/default-compiler-env)
37+
ns-ast (ana-tests/analyze-forms cenv
38+
'[(ns foo.core
39+
(:require [goog.module.ModuleLoader :as module-loader]))])
40+
aenv (assoc (ana/empty-env) :ns (ana/get-namespace cenv 'foo.core))]
41+
(is (= 'foo.core.goog$module$goog$module$ModuleLoader
42+
(env/with-compiler-env cenv
43+
(ana/resolve-import aenv 'goog.module.ModuleLoader)))))))
44+
45+
(deftest glib-module-resolve-import-var-test
46+
(testing "glib module :import var resolution"
47+
(let [cenv (env/default-compiler-env)
48+
ns-ast (ana-tests/analyze-forms cenv
49+
'[(ns foo.core
50+
(:import [goog.module ModuleLoader]))])
51+
aenv (assoc (ana/empty-env) :ns (ana/get-namespace cenv 'foo.core))]
52+
(is (= '{:name foo.core.goog$module$goog$module$ModuleLoader
53+
:ns goog.module ;; a bit odd, but doesn't matter, for emission we just :name
54+
:op :var}
55+
(env/with-compiler-env cenv
56+
(ana/resolve-var aenv 'ModuleLoader)))))))
57+
58+
(comment
59+
60+
(test/run-tests)
61+
62+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(ns cljs.compiler.glib-module-test
2+
(:require [cljs.compiler-tests :as comp-tests]
3+
[cljs.env :as env]
4+
[clojure.test :as test :refer [deftest is testing]]))
5+
6+
(deftest test-glib-module-compile
7+
(testing "glib modules compiled to Closure Compile expectations"
8+
(let [src (env/with-compiler-env (env/default-compiler-env)
9+
(comp-tests/compile-form-seq
10+
'[(ns test.foo
11+
(:import [goog.module ModuleLoader]))
12+
(def module-loader (ModuleLoader.))]))]
13+
(is (re-find #"goog\.require\('goog\.module\.ModuleLoader'\)" src))
14+
(is (re-find #"test\.foo\.goog\$module\$goog\$module\$ModuleLoader = goog\.module\.get\('goog.module.ModuleLoader'\)" src))
15+
(is (re-find #"test\.foo\.module_loader = \(new test\.foo\.goog\$module\$goog\$module\$ModuleLoader\(\)\)" src)))))
16+
17+
(comment
18+
19+
(test/run-tests)
20+
21+
)

‎src/test/clojure/cljs/externs_parsing_tests.clj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636

3737
(comment
3838

39+
(externs/parse-externs
40+
(externs/resource->source-file (io/resource "goog/object/object.js")))
41+
42+
(externs/analyze-goog-file "goog/object/object.js")
43+
3944
(test/run-tests)
4045

4146
(externs/analyze-goog-file "goog/date/date.js" 'goog.date.month)

0 commit comments

Comments
 (0)
Please sign in to comment.