Skip to content

Commit c5a06c8

Browse files
committed
CLJS-3332: Cannot require @firebase/auth
Handle libraries that declare exports. Previously we only looked at top-level package.json. Expand this so that if top-level package.json declares exports, then we consider those package.json files as well. This leads to computing correct :provides with the exist logic which has worked suitably for some time. Add tests. Add some comments and docstrings to aid readability in the future.
1 parent 89b4c19 commit c5a06c8

File tree

4 files changed

+87
-19
lines changed

4 files changed

+87
-19
lines changed

src/main/clojure/cljs/closure.clj

+55-15
Original file line numberDiff line numberDiff line change
@@ -2766,27 +2766,67 @@
27662766
[]))))
27672767

27682768
(defn- node-file-seq->libs-spec*
2769+
"Given a sequence of non-nested node_module paths where the extension ends in
2770+
`.js/.json`, return lib-spec maps for each path containing at least :file,
2771+
:module-type, and :provides."
27692772
[module-fseq opts]
27702773
(letfn [(package-json? [path]
2771-
(boolean (re-find #"node_modules[/\\](@[^/\\]+?[/\\])?[^/\\]+?[/\\]package\.json$" path)))]
2772-
(let [pkg-jsons (into {}
2773-
(comp
2774-
(map #(.getAbsolutePath %))
2775-
(filter package-json?)
2776-
(map (fn [path]
2777-
[path (json/read-str (slurp path))])))
2778-
module-fseq)
2779-
trim-package-json (fn [s]
2780-
(if (string/ends-with? s "package.json")
2781-
(subs s 0 (- (count s) 12))
2782-
s))]
2774+
(= "package.json" (.getName (io/file path))))
2775+
2776+
(top-level-package-json? [path]
2777+
(boolean (re-find #"node_modules[/\\](@[^/\\]+?[/\\])?[^/\\]+?[/\\]package\.json$" path)))
2778+
2779+
;; the path sans the package.json part
2780+
;; i.e. some_lib/package.json -> some_lib
2781+
(trim-package-json [s]
2782+
(if (string/ends-with? s "package.json")
2783+
(subs s 0 (- (count s) 12))
2784+
s))
2785+
2786+
(trim-relative [path]
2787+
(cond-> path
2788+
(string/starts-with? path "./")
2789+
(subs 2)))
2790+
2791+
(add-exports [pkg-jsons]
2792+
(reduce-kv
2793+
(fn [pkg-jsons path {:strs [exports] :as pkg-json}]
2794+
(reduce-kv
2795+
(fn [pkg-jsons export _]
2796+
;; NOTE: ignore "." exports for now
2797+
(if (= "." export)
2798+
pkg-jsons
2799+
(let [export-pkg-json
2800+
(io/file
2801+
(.getCanonicalPath (io/file (trim-package-json path) export))
2802+
"package.json")]
2803+
(cond-> pkg-jsons
2804+
(.exists export-pkg-json)
2805+
(assoc
2806+
(.getAbsolutePath export-pkg-json)
2807+
(json/read-str (slurp export-pkg-json)))))))
2808+
pkg-jsons exports))
2809+
pkg-jsons pkg-jsons))]
2810+
(let [
2811+
;; a map of all the *top-level* package.json paths and their exports
2812+
;; to the package.json contents as EDN
2813+
pkg-jsons (add-exports
2814+
(into {}
2815+
(comp
2816+
(map #(.getAbsolutePath %))
2817+
(filter top-level-package-json?)
2818+
(map (fn [path]
2819+
[path (json/read-str (slurp path))])))
2820+
module-fseq))]
27832821
(into []
27842822
(comp
27852823
(map #(.getAbsolutePath %))
27862824
(map (fn [path]
27872825
(merge
27882826
{:file path
27892827
:module-type :es6}
2828+
;; if the file is *not* a package.json, then compute what
2829+
;; namespaces it :provides to ClojureScript
27902830
(when-not (package-json? path)
27912831
(let [pkg-json-main (some
27922832
(fn [[pkg-json-path {:as pkg-json :strs [name]}]]
@@ -2795,13 +2835,13 @@
27952835
(when-not (nil? entry)
27962836
;; should be the only edge case in
27972837
;; the package.json main field - Antonio
2798-
(let [entry (cond-> entry
2799-
(string/starts-with? entry "./")
2800-
(subs 2))
2838+
(let [entry (trim-relative entry)
28012839
entry-path (-> pkg-json-path
28022840
(string/replace \\ \/)
28032841
trim-package-json
28042842
(str entry))]
2843+
;; find a package.json entry point that matches
2844+
;; the `path`
28052845
(some (fn [candidate]
28062846
(when (= candidate (string/replace path \\ \/))
28072847
name))

src/main/clojure/cljs/util.cljc

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
(if (== n Integer/MIN_VALUE)
4141
0
4242
(Math/abs n)))]
43-
(str synthethetic-version-prefix
43+
(str synthethetic-version-prefix
4444
(qualifier (reduce unchecked-add-int (map file-hash (file-seq (main-src-directory)))))))))
4545

4646
(defn ^String clojurescript-version
@@ -390,14 +390,18 @@
390390
(str (string/join ", " (pop xs)) " and " (peek xs)))))
391391

392392
(defn module-file-seq
393+
"Return a seq of all files in `node_modules` ending in `.js` or `.json` that are
394+
not in an internally nested `node_modules` dir."
393395
([] (module-file-seq (io/file "node_modules")))
394396
([dir]
395397
(let [fseq (tree-seq
396398
(fn [^File f]
399+
;; ignore embedded node_modules, the user did not install
400+
;; these
397401
(and (. f (isDirectory))
398-
(not (boolean
399-
(re-find #"node_modules[\\\/].*[\\\/]node_modules"
400-
(.getPath f))))))
402+
(not (boolean
403+
(re-find #"node_modules[\\\/].*[\\\/]node_modules"
404+
(.getPath f))))))
401405
(fn [^File d]
402406
(seq (. d (listFiles))))
403407
dir)]
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(ns firebase.core
2+
(:require ["firebase/auth" :as auth]))
3+

src/test/clojure/cljs/build_api_tests.clj

+21
Original file line numberDiff line numberDiff line change
@@ -796,3 +796,24 @@
796796
(ana/with-warning-handlers [(collecting-warning-handler ws)]
797797
(build/build (build/inputs (io/file inputs "cljs_3311_regress/core.cljs")) opts cenv))
798798
(is (empty? @ws)))))
799+
800+
(deftest test-cljs-3332
801+
(testing "Test that package.json w/ exports work, Firebase as example"
802+
(let [out (.getPath (io/file (test/tmp-dir) "npm-deps-test-out"))]
803+
(test/delete-out-files out)
804+
(test/delete-node-modules)
805+
(spit (io/file "package.json") "{}")
806+
(let [{:keys [inputs opts]} {:inputs (str (io/file "src" "test" "cljs_build"))
807+
:opts {:main 'firebase.core
808+
:output-dir out
809+
:optimizations :none
810+
:install-deps true
811+
:npm-deps {:firebase "9.3.0"}
812+
:closure-warnings {:check-types :off}
813+
:target :bundle}}
814+
cenv (env/default-compiler-env)]
815+
(build/build (build/inputs (io/file inputs "firebase/core.cljs")) opts cenv)
816+
(is (= #{"firebase/auth"} (:node-module-index @cenv))))
817+
(.delete (io/file "package.json"))
818+
(test/delete-node-modules)
819+
(test/delete-out-files out))))

0 commit comments

Comments
 (0)