cljs.repl.node/setup

functionsince v0.0-2629Edit
(setup repl-env)
(setup {:keys [host port socket state], :as repl-env} opts)

Source code @ clojurescript:src/main/clojure/cljs/repl/node.clj
(defn setup
  ([repl-env] (setup repl-env nil))
  ([{:keys [host port socket state] :as repl-env} opts]
   (let [tname (thread-name)]
     (.put results tname (LinkedBlockingQueue.))
     (.put outs tname *out*)
     (.put errs tname *err*))
   (locking lock
     (when-not @socket
       (let [output-dir   (io/file (util/output-directory opts))
             _            (.mkdirs output-dir)
             of           (io/file output-dir "node_repl.js")
             _            (spit of
                            (string/replace (slurp (io/resource "cljs/repl/node_repl.js"))
                              "var PORT = 5001;"
                              (str "var PORT = " (:port repl-env) ";")))
             proc         (.start (build-process opts repl-env of))
             env          (ana/empty-env)
             core         (io/resource "cljs/core.cljs")
             ;; represent paths as vectors so we can emit JS arrays, this is to
             ;; paper over Windows issues with minimum hassle - David
             path         (.getPath (.getCanonicalFile output-dir))
             [fc & cs]    (rest (util/path-seq path)) ;; remove leading empty string
             root         (.substring path 0 (+ (.indexOf path fc) (count fc)))
             root-path    (vec (cons root cs))
             rewrite-path (conj root-path "goog")]
         (reset! (:proc repl-env) proc)
         (loop [r nil]
           (when-not (= r "ready")
             (Thread/sleep 50)
             (try
               (reset! socket (create-socket host port))
               (catch Exception e))
             (if @socket
               (recur (read-response (:in @socket)))
               (recur nil))))
         (.start (Thread. (bound-fn [] (event-loop proc (:in @socket)))))
         ;; compile cljs.core & its dependencies, goog/base.js must be available
         ;; for bootstrap to load, use new closure/compile as it can handle
         ;; resources in JARs
         (let [core-js (closure/compile core
                         (assoc opts :output-file
                                     (closure/src-file->target-file
                                       core (dissoc opts :output-dir))))
               deps    (closure/add-dependencies opts core-js)]
           ;; output unoptimized code and only the deps file for all compiled
           ;; namespaces, we don't need the bootstrap target file
           (apply closure/output-unoptimized
             (assoc (assoc opts :target :none)
               :output-to (.getPath (io/file output-dir "node_repl_deps.js")))
             deps))
         ;; bootstrap, replace __dirname as __dirname won't be set
         ;; properly due to how we are running it - David
         (node-eval repl-env
           (-> (slurp (io/resource "cljs/bootstrap_nodejs.js"))
             (string/replace "path.resolve(__dirname, \"..\", \"base.js\")"
               (platform-path (conj rewrite-path "bootstrap" ".." "base.js")))
             (string/replace
               "path.join(\".\", \"..\", src)"
               (str "path.join(" (platform-path rewrite-path) ", src)"))
             (string/replace "path.resolve(__dirname, \"..\", src)"
               (str "path.join(" (platform-path rewrite-path) ", src)"))
             (string/replace
               "var CLJS_ROOT = \".\";"
               (str "var CLJS_ROOT = " (platform-path root-path) ";"))))
         ;; load the deps file so we can goog.require cljs.core etc.
         (node-eval repl-env
           (str "require("
             (platform-path (conj root-path "node_repl_deps.js"))
             ")"))
         ;; load cljs.core, setup printing
         (repl/evaluate-form repl-env env ""
           '(do
              (.require js/goog "cljs.core")
              (enable-console-print!)))
         (bootstrap/install-repl-goog-require repl-env env)
         (node-eval repl-env
           (str "goog.global.CLOSURE_UNCOMPILED_DEFINES = "
             (json/write-str (:closure-defines opts)) ";")))))
   (swap! state update :listeners inc)))