Skip to content

Commit 0febb0f

Browse files
committed
REPL options merging needs to be more disciplined
eliminate :default-*. Instead first merge -repl-options, then original options, then clojure.main style REPL options (with supplied defaults). Rhino error handling WIP. Default wrap-fn will not work as catching the JS error will swallow the stacktrace.
1 parent 74b2d71 commit 0febb0f

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

src/clj/cljs/repl.clj

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -467,13 +467,13 @@
467467
form, evaluate the form and return the result. The result is always the value
468468
represented as a string."
469469
([repl-env env form]
470-
(eval-cljs repl-env env form nil))
470+
(eval-cljs repl-env env form *repl-opts*))
471471
([repl-env env form opts]
472472
(evaluate-form repl-env
473473
(assoc env :ns (ana/get-namespace ana/*cljs-ns*))
474474
"<cljs repl>"
475475
form
476-
(wrap-fn form)
476+
((or (:wrap opts) wrap-fn) form)
477477
opts)))
478478

479479
;; Special REPL fns, these provide compatiblity with Clojure functions
@@ -620,7 +620,7 @@
620620
(.printStackTrace e))))
621621

622622
(defn repl*
623-
[repl-env {:keys [init need-prompt prompt flush read eval print caught reader print-no-newline source-map-inline]
623+
[repl-env {:keys [init need-prompt prompt flush read eval print caught reader print-no-newline source-map-inline wrap]
624624
:or {init #()
625625
need-prompt #(if (readers/indexing-reader? *in*)
626626
(== (readers/get-column-number *in*) 1)
@@ -643,20 +643,18 @@
643643
(merge
644644
{:cache-analysis true :source-map true}
645645
(cljsc/add-implicit-options
646-
(assoc (merge (-repl-options repl-env) opts)
647-
:init init
648-
:need-prompt prompt
649-
:flush flush
650-
:read read
651-
:print print
652-
:caught caught
653-
:reader reader
654-
:print-no-newline print-no-newline
655-
:source-map-inline source-map-inline
656-
:output-dir (or (:output-dir opts)
657-
(:default-output-dir repl-env))
658-
:target (or (:target opts)
659-
(:default-target repl-env)))))]
646+
(merge-with (fn [a b] (if (nil? b) a b))
647+
(-repl-options repl-env)
648+
opts
649+
{:init init
650+
:need-prompt prompt
651+
:flush flush
652+
:read read
653+
:print print
654+
:caught caught
655+
:reader reader
656+
:print-no-newline print-no-newline
657+
:source-map-inline source-map-inline})))]
660658
(env/with-compiler-env
661659
(or (::env/compiler repl-env) (env/default-compiler-env opts))
662660
(binding [ana/*cljs-ns* 'cljs.user

src/clj/cljs/repl/nashorn.clj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@
144144

145145
(defrecord NashornEnv [engine debug]
146146
repl/IReplEnvOptions
147-
(-repl-options [this] {})
147+
(-repl-options [this]
148+
{:output-dir ".cljs_nashorn_repl"})
148149
repl/IJavaScriptEnv
149150
(-setup [this {:keys [output-dir bootstrap output-to] :as opts}]
150151
(init-engine engine output-dir debug)
@@ -206,6 +207,6 @@
206207
Use a minimal bootstrapped cljs.core environment if not specified."
207208
[& {:keys [debug] :as opts}]
208209
(let [engine (create-engine)]
209-
(merge (NashornEnv. engine debug)
210-
{:default-output-dir ".cljs_nashorn_repl"}
210+
(merge
211+
(NashornEnv. engine debug)
211212
opts)))

src/clj/cljs/repl/node.clj

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@
169169
(aget (.. js/goog -dependencies_ -nameToPath) name))))))))))
170170

171171
(defrecord NodeEnv [host port socket proc]
172+
repl/IReplEnvOptions
173+
(-repl-options [this]
174+
{:output-dir ".cljs_node_repl"
175+
:target :nodejs})
172176
repl/IParseErrorMessage
173177
(-parse-error-message [_ _ _ _])
174178
repl/IJavaScriptEnv
@@ -188,9 +192,7 @@
188192
{:host "localhost"
189193
:port (+ 49000 (rand-int 10000))}
190194
options)]
191-
(merge (NodeEnv. host port (atom nil) (atom nil))
192-
{:default-output-dir ".cljs_node_repl"
193-
:default-target :nodejs})))
195+
(NodeEnv. host port (atom nil) (atom nil))))
194196

195197
(defn repl-env
196198
[& {:as options}]

src/clj/cljs/repl/rhino.clj

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,15 @@
6969
;; =============================================================================
7070

7171
(defn rhino-eval
72-
[repl-env filename line js]
72+
[{:keys [scope] :as repl-env} filename line js]
7373
(try
7474
(let [linenum (or line Integer/MIN_VALUE)]
7575
{:status :success
7676
:value (eval-result (-eval js repl-env filename linenum))})
7777
(catch Throwable ex
78+
;; manually set *e
79+
;; (ScriptableObject/putProperty scope "cljs.core._STAR_e"
80+
;; (Context/javaToJS ex scope))
7881
{:status :exception
7982
:value (.toString ex)
8083
:stacktrace (stacktrace ex)})))
@@ -145,10 +148,27 @@
145148
(js/CLOSURE_IMPORT_SCRIPT
146149
(aget (.. js/goog -dependencies_ -nameToPath) name)))))))))
147150

151+
;; Catching errors and rethrowing in Rhino swallows the original trace
152+
;; https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.rhino/inMyVKhPq6M/cY39hX20_z8J
153+
(defn wrap-fn [form]
154+
(cond
155+
(and (seq? form) (= 'ns (first form))) identity
156+
('#{*1 *2 *3 *e} form) (fn [x] `(cljs.core.pr-str ~x))
157+
:else
158+
(fn [x]
159+
`(cljs.core.pr-str
160+
(let [ret# ~x]
161+
(set! *3 *2)
162+
(set! *2 *1)
163+
(set! *1 ret#)
164+
ret#)))))
165+
148166
(defrecord RhinoEnv []
149167
repl/IReplEnvOptions
150168
(-repl-options [this]
151-
{:require-foreign true})
169+
{:require-foreign true
170+
:output-dir ".cljs_rhino_repl"
171+
:wrap wrap-fn})
152172
repl/IJavaScriptEnv
153173
(-setup [this opts]
154174
(rhino-setup this opts))
@@ -167,8 +187,7 @@
167187
;; Rhino is slow even with optimizations enabled
168188
(.setOptimizationLevel cx -1)
169189
(merge (RhinoEnv.)
170-
{:default-output-dir ".cljs_rhino_repl"
171-
:cx cx
190+
{:cx cx
172191
:scope (.initStandardObjects cx)})))
173192

174193
(comment

0 commit comments

Comments
 (0)