Skip to content

Commit 3a29fa4

Browse files
author
dnolen
committed
avoid blocking on Node.js process doing I/O, tweak module_deps.js
1 parent c435427 commit 3a29fa4

File tree

2 files changed

+47
-23
lines changed

2 files changed

+47
-23
lines changed

src/main/cljs/cljs/module_deps.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/clojure/cljs/build/api.clj

+46-22
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
[cljs.compiler :as comp]
2222
[cljs.closure :as closure]
2323
[cljs.js-deps :as js-deps])
24-
(:import [java.io File]
25-
[java.lang ProcessBuilder Process]
26-
(java.util.concurrent TimeUnit)))
24+
(:import [java.io
25+
File StringWriter
26+
BufferedReader
27+
Writer InputStreamReader IOException]
28+
[java.lang ProcessBuilder]))
2729

2830
;; =============================================================================
2931
;; Useful Utilities
@@ -236,33 +238,55 @@
236238
ret)))
237239
[] deps)))
238240

241+
(defn- alive? [proc]
242+
(try (.exitValue proc) false (catch IllegalThreadStateException _ true)))
243+
244+
(defn- pipe [^Process proc in ^Writer out]
245+
;; we really do want system-default encoding here
246+
(with-open [^java.io.Reader in (-> in InputStreamReader. BufferedReader.)]
247+
(loop [buf (char-array 1024)]
248+
(when (alive? proc)
249+
(try
250+
(let [len (.read in buf)]
251+
(when-not (neg? len)
252+
(.write out buf 0 len)
253+
(.flush out)))
254+
(catch IOException e
255+
(when (and (alive? proc) (not (.contains (.getMessage e) "Stream closed")))
256+
(.printStackTrace e *err*))))
257+
(recur buf)))))
258+
239259
(defn node-module-deps
240260
"EXPERIMENTAL: return the foreign libs entries as computed by running
241261
the module-deps package on the supplied JavaScript entry point. Assumes
242262
that the module-deps & JSONStream NPM packages are either locally or
243263
globally installed."
244264
[{:keys [file]}]
245-
(let [code (string/replace
246-
(slurp (io/resource "cljs/module_deps.js"))
247-
"JS_FILE" file)
248-
proc (-> (ProcessBuilder.
249-
(into-array
250-
["node" "--eval" (str code)]))
251-
.start)
252-
timeout? (.waitFor proc 10 TimeUnit/SECONDS)]
253-
(when timeout?
254-
(println "Node.js process timed out"))
255-
(if (and (not (.isAlive proc))
256-
(zero? (.exitValue proc)))
257-
(let [is (.getInputStream proc)]
258-
(into []
259-
(map (fn [{:strs [file]}] file
260-
{:file file :module-type :commonjs}))
261-
(butlast (json/read-str (slurp is)))))
265+
(let [code (string/replace
266+
(slurp (io/resource "cljs/module_deps.js"))
267+
"JS_FILE" file)
268+
proc (-> (ProcessBuilder.
269+
["node" "--eval" code])
270+
.start)
271+
is (.getInputStream proc)
272+
iw (StringWriter. (* 16 1024 1024))
273+
es (.getErrorStream proc)
274+
ew (StringWriter. (* 1024 1024))
275+
_ (do (.start
276+
(Thread.
277+
(bound-fn [] (pipe proc is iw))))
278+
(.start
279+
(Thread.
280+
(bound-fn [] (pipe proc es ew)))))
281+
err (.waitFor proc)]
282+
(if (zero? err)
283+
(into []
284+
(map (fn [{:strs [file]}] file
285+
{:file file :module-type :commonjs}))
286+
(butlast (json/read-str (str iw))))
262287
(do
263288
(when-not (.isAlive proc)
264-
(let [es (.getErrorStream proc)]
265-
(println (slurp es))))
289+
(println (str ew)))
266290
[]))))
267291

268292
(comment

0 commit comments

Comments
 (0)