Skip to content

Commit

Permalink
CLJS-1196: Assert failed on 3190+ while :require-ing .js file in :lib…
Browse files Browse the repository at this point in the history
…s directory

cljs.util
  - path
    can now take a string

cljs.js-deps
  - IJavaScript
    add new -closure-lib? to protocol
  - library-graph-node
    mark closure libs, record :libs path where found if given
  - load-library*
    pass :libs path to library-graph-node

cljs.closure
   - implement -closure-lib? on IJavaScript extended types
   - map->javascript-file
     merge :closure-lib info
   - rel-output-path
     Closure libraries need relative path treatment
   - lib-rel-path
     add helper to compute path relative to :libs dir where found
     to avoid name clashes
   - write-js?
     closure :libs also need to be written as JS
  • Loading branch information
swannodette committed May 9, 2015
1 parent d9feda1 commit 159fad2
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 37 deletions.
75 changes: 45 additions & 30 deletions src/main/clojure/cljs/closure.clj
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,15 @@

String
(-foreign? [this] false)
(-closure-lib? [this] false)
(-url [this] nil)
(-provides [this] (:provides (deps/parse-js-ns (string/split-lines this))))
(-requires [this] (:requires (deps/parse-js-ns (string/split-lines this))))
(-source [this] this)

clojure.lang.IPersistentMap
(-foreign? [this] (:foreign this))
(-closure-lib? [this] (:closure-lib this))
(-url [this] (or (:url this)
(deps/to-url (:file this))))
(-provides [this] (map name (:provides this)))
Expand All @@ -273,6 +275,7 @@
(defrecord JavaScriptFile [foreign ^URL url ^URL source-url provides requires lines source-map]
deps/IJavaScript
(-foreign? [this] foreign)
(-closure-lib? [this] (:closure-lib this))
(-url [this] url)
(-provides [this] provides)
(-requires [this] requires)
Expand All @@ -291,16 +294,19 @@
(JavaScriptFile. foreign url source-url (map name provides) (map name requires) lines source-map)))

(defn map->javascript-file [m]
(javascript-file
(:foreign m)
(when-let [f (:file m)]
(deps/to-url f))
(when-let [sf (:source-file m)]
(deps/to-url sf))
(:provides m)
(:requires m)
(:lines m)
(:source-map m)))
(merge
(javascript-file
(:foreign m)
(when-let [f (:file m)]
(deps/to-url f))
(when-let [sf (:source-file m)]
(deps/to-url sf))
(:provides m)
(:requires m)
(:lines m)
(:source-map m))
(when (:closure-lib m)
{:closure-lib true})))

(defn read-js
"Read a JavaScript file returning a map of file information."
Expand Down Expand Up @@ -1121,37 +1127,45 @@
(- (count (.split #"\r?\n" fdeps-str -1)) 1)
0)})))))))

(defn lib-rel-path [{:keys [lib-path url] :as ijs}]
(string/replace
(util/path url)
(str (io/file (System/getProperty "user.dir") lib-path) File/separator)
""))

(defn ^String rel-output-path
"Given an IJavaScript which is either in memory, in a jar file,
or is a foreign lib, return the path relative to the output
directory."
[js]
(let [url (deps/-url js)]
(cond
url
(if (deps/-foreign? js)
(util/get-name url)
(path-from-jarfile url))

(string? js)
(let [digest (MessageDigest/getInstance "SHA-1")]
(.reset digest)
(.update digest (.getBytes ^String js "utf8"))
(str
(->> (DatatypeConverter/printHexBinary (.digest digest))
(take 7)
(apply str))
".js"))

:else (str (random-string 5) ".js"))))
([js] (rel-output-path js nil))
([js opts]
(let [url (deps/-url js)]
(cond
url
(cond
(deps/-closure-lib? js) (lib-rel-path js)
(deps/-foreign? js) (util/get-name url)
:else (path-from-jarfile url))

(string? js)
(let [digest (MessageDigest/getInstance "SHA-1")]
(.reset digest)
(.update digest (.getBytes ^String js "utf8"))
(str
(->> (DatatypeConverter/printHexBinary (.digest digest))
(take 7)
(apply str))
".js"))

:else (str (random-string 5) ".js")))))

(defn write-javascript
"Write or copy a JavaScript file to output directory. Only write if the file
does not already exist. Return IJavaScript for the file on disk at the new
location."
[opts js]
(let [out-dir (io/file (util/output-directory opts))
out-name (rel-output-path js)
out-name (rel-output-path js opts)
out-file (io/file out-dir out-name)
ijs {:url (deps/to-url out-file)
:requires (deps/-requires js)
Expand All @@ -1171,6 +1185,7 @@
(let [url ^URL (deps/-url js)]
(or (not url)
(= (.getProtocol url) "jar")
(deps/-closure-lib? js)
(deps/-foreign? js))))

(defn source-on-disk
Expand Down
16 changes: 11 additions & 5 deletions src/main/clojure/cljs/js_deps.clj
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ case."
(defprotocol IJavaScript
(-foreign? [this] "Whether the Javascript represents a foreign
library (a js file that not have any goog.provide statement")
(-closure-lib? [this] "Whether the Javascript represents a Closure style
library")
(-url [this] "The URL where this JavaScript is located. Returns nil
when JavaScript exists in memory only.")
(-provides [this] "A list of namespaces that this JavaScript provides.")
Expand Down Expand Up @@ -205,18 +207,22 @@ case."
(defn- library-graph-node
"Returns a map of :provides, :requires, and :url given a URL to a goog-style
JavaScript library containing provide/require 'declarations'."
[url]
(with-open [reader (io/reader url)]
(-> reader line-seq parse-js-ns
(assoc :url url))))
([url] (library-graph-node url nil))
([url lib-path]
(with-open [reader (io/reader url)]
(-> reader line-seq parse-js-ns
(merge
{:url url :closure-lib true}
(when lib-path
{:lib-path lib-path}))))))

(defn load-library*
"Given a path to a JavaScript library, which is a directory
containing Javascript files, return a list of maps
containing :provides, :requires, :file and :url."
[path]
(->> (find-js-resources path)
(map library-graph-node)
(map #(library-graph-node % path))
(filter #(seq (:provides %)))))

(def load-library (memoize load-library*))
Expand Down
5 changes: 3 additions & 2 deletions src/main/clojure/cljs/util.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,11 @@
(.getName f))

(defn ^String path [x]
{:pre [(or (file? x) (url? x))]}
{:pre [(or (file? x) (url? x) (string? x))]}
(cond
(file? x) (.getAbsolutePath ^File x)
(url? x) (.getPath ^URL x)))
(url? x) (.getPath ^URL x)
(string? x) x))

(defn ^String ext
"Given a file, url or string return the file extension."
Expand Down

0 comments on commit 159fad2

Please sign in to comment.