Skip to content

Commit fc75264

Browse files
committed
Merge branch 'master' of github.com:clojure/clojurescript
2 parents afde265 + eb9478c commit fc75264

File tree

4 files changed

+100
-59
lines changed

4 files changed

+100
-59
lines changed

samples/repl/src/repl/foo.cljs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(ns repl.foo)
2+
3+
(defn bar [a b]
4+
(+ a b))

src/clj/cljs/analyzer.clj

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@
429429
(defn confirm-ns [env ns-sym]
430430
(when (and (nil? (get '#{cljs.core goog Math goog.string} ns-sym))
431431
(nil? (get (-> env :ns :requires) ns-sym))
432+
;; something else may have loaded the namespace, i.e. load-file
433+
(nil? (get-in @env/*compiler* [::namespaces ns-sym]))
432434
;; macros may refer to namespaces never explicitly required
433435
;; confirm that the library at least exists
434436
(nil? (io/resource (util/ns->relpath ns-sym))))
@@ -1473,6 +1475,7 @@
14731475
:import (partial parse-import-spec env deps)}
14741476
valid-forms (atom #{:use :use-macros :require :require-macros :import})
14751477
reload (atom {:use nil :require nil :use-macros nil :require-macros nil})
1478+
reloads (atom {})
14761479
{uses :use requires :require use-macros :use-macros require-macros :require-macros imports :import :as params}
14771480
(reduce
14781481
(fn [m [k & libs]]
@@ -1481,11 +1484,16 @@
14811484
(when-not (@valid-forms k)
14821485
(throw (error env (str "Only one " k " form is allowed per namespace definition"))))
14831486
(swap! valid-forms disj k)
1487+
;; check for spec type reloads
14841488
(when-not (= :import k)
14851489
(when (some #{:reload} libs)
14861490
(swap! reload assoc k :reload))
14871491
(when (some #{:reload-all} libs)
14881492
(swap! reload assoc k :reload-all)))
1493+
;; check for individual ns reloads from REPL interactions
1494+
(when-let [xs (seq (filter #(-> % meta :reload) libs))]
1495+
(swap! reloads assoc k
1496+
(zipmap (map first xs) (map #(-> % meta :reload) xs))))
14891497
(apply merge-with merge m
14901498
(map (spec-parsers k)
14911499
(remove #{:reload :reload-all} libs))))
@@ -1498,13 +1506,15 @@
14981506
(when *load-macros*
14991507
(load-core)
15001508
(doseq [nsym (vals use-macros)]
1501-
(let [k (:use-macros @reload)]
1509+
(let [k (or (:use-macros @reload)
1510+
(get-in @reloads [:use-macros nsym]))]
15021511
(if k
15031512
(clojure.core/require nsym k)
15041513
(clojure.core/require nsym))
15051514
(intern-macros nsym k)))
15061515
(doseq [nsym (vals require-macros)]
1507-
(let [k (:require-macros @reload)]
1516+
(let [k (or (:require-macros @reload)
1517+
(get-in @reloads [:require-macros nsym]))]
15081518
(if k
15091519
(clojure.core/require nsym k)
15101520
(clojure.core/require nsym))
@@ -1535,7 +1545,8 @@
15351545
ns-info))
15361546
ns-info)]
15371547
(swap! env/*compiler* update-in [::namespaces name] merge ns-info)
1538-
(merge {:env env :op :ns :form form}
1548+
(merge {:env env :op :ns :form form
1549+
:reloads @reloads}
15391550
(cond-> ns-info
15401551
(@reload :use)
15411552
(update-in [:uses]

src/clj/cljs/compiler.clj

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -839,46 +839,47 @@
839839
(emit-wrap env (emits target " = " val)))
840840

841841
(defn load-libs
842-
([libs] (load-libs libs nil))
843-
([libs seen]
844-
(let [loaded-libs (munge 'cljs.core.*loaded-libs*)
845-
loaded-libs-temp (munge (gensym 'cljs.core.*loaded-libs*))]
846-
(when (-> libs meta :reload-all)
847-
(emitln "if(!COMPILED) " loaded-libs-temp " = " loaded-libs " || cljs.core.set();")
848-
(emitln "if(!COMPILED) " loaded-libs " = cljs.core.set();"))
849-
(doseq [lib (remove (set (vals seen)) (distinct (vals libs)))]
850-
(cond
851-
(ana/foreign-dep? lib)
852-
(let [{:keys [target optimizations]} (get @env/*compiler* :options)]
853-
;; we only load foreign libraries under optimizations :none
854-
(when (= :none optimizations)
855-
(if (= :nodejs target)
856-
;; under node.js we load foreign libs globally
857-
(let [{:keys [js-dependency-index options]} @env/*compiler*
858-
ijs-url (get-in js-dependency-index [(name lib) :url])]
859-
(emitln "cljs.core.load_file(\""
860-
(str (io/file (util/output-directory options) (util/get-name ijs-url)))
861-
"\");"))
862-
(emitln "goog.require('" (munge lib) "');"))))
863-
864-
(-> libs meta :reload)
865-
(emitln "goog.require('" (munge lib) "', 'reload');")
866-
867-
(-> libs meta :reload-all)
868-
(emitln "goog.require('" (munge lib) "', 'reload-all');")
869-
870-
:else
871-
(emitln "goog.require('" (munge lib) "');")))
872-
(when (-> libs meta :reload-all)
873-
(emitln "if(!COMPILED) " loaded-libs " = cljs.core.into(" loaded-libs-temp ", " loaded-libs ");")))))
842+
[libs seen reloads]
843+
(let [loaded-libs (munge 'cljs.core.*loaded-libs*)
844+
loaded-libs-temp (munge (gensym 'cljs.core.*loaded-libs*))]
845+
(when (-> libs meta :reload-all)
846+
(emitln "if(!COMPILED) " loaded-libs-temp " = " loaded-libs " || cljs.core.set();")
847+
(emitln "if(!COMPILED) " loaded-libs " = cljs.core.set();"))
848+
(doseq [lib (remove (set (vals seen)) (distinct (vals libs)))]
849+
(cond
850+
(ana/foreign-dep? lib)
851+
(let [{:keys [target optimizations]} (get @env/*compiler* :options)]
852+
;; we only load foreign libraries under optimizations :none
853+
(when (= :none optimizations)
854+
(if (= :nodejs target)
855+
;; under node.js we load foreign libs globally
856+
(let [{:keys [js-dependency-index options]} @env/*compiler*
857+
ijs-url (get-in js-dependency-index [(name lib) :url])]
858+
(emitln "cljs.core.load_file(\""
859+
(str (io/file (util/output-directory options) (util/get-name ijs-url)))
860+
"\");"))
861+
(emitln "goog.require('" (munge lib) "');"))))
862+
863+
(or (-> libs meta :reload)
864+
(= (get reloads lib) :reload))
865+
(emitln "goog.require('" (munge lib) "', 'reload');")
866+
867+
(or (-> libs meta :reload-all)
868+
(= (get reloads lib) :reload-all))
869+
(emitln "goog.require('" (munge lib) "', 'reload-all');")
870+
871+
:else
872+
(emitln "goog.require('" (munge lib) "');")))
873+
(when (-> libs meta :reload-all)
874+
(emitln "if(!COMPILED) " loaded-libs " = cljs.core.into(" loaded-libs-temp ", " loaded-libs ");"))))
874875

875876
(defmethod emit* :ns
876-
[{:keys [name requires uses require-macros env]}]
877+
[{:keys [name requires uses require-macros reloads env]}]
877878
(emitln "goog.provide('" (munge name) "');")
878879
(when-not (= name 'cljs.core)
879880
(emitln "goog.require('cljs.core');"))
880-
(load-libs requires)
881-
(load-libs uses requires))
881+
(load-libs requires nil (:require reloads))
882+
(load-libs uses requires (:use reloads)))
882883

883884
(defmethod emit* :deftype*
884885
[{:keys [t fields pmasks body]}]

src/clj/cljs/repl.clj

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,12 @@
302302
:column column'}
303303
(when url
304304
{:url url}))))]
305-
;; take each non-nil :call and merge it into :function one-level up
306-
(map merge
305+
;; take each non-nil :call and optionally merge it into :function one-level up
306+
;; to avoid replacing with local symbols, we only replace munged name if we can munge call symbol back to it
307+
(map #(merge-with (fn [munged-fn-name unmunged-call-name]
308+
(if (= munged-fn-name (string/replace (cljs.compiler/munge unmunged-call-name) "." "$"))
309+
unmunged-call-name
310+
munged-fn-name)) %1 %2)
307311
(map #(dissoc % :call) with-calls)
308312
(concat (rest (map #(if (:call %)
309313
(hash-map :function (:call %))
@@ -467,14 +471,21 @@
467471
;; TODO: this should probably compile dependencies - David
468472

469473
(defn load-file
470-
([repl-env f] (load-file repl-env f nil))
474+
([repl-env f] (load-file repl-env f *repl-opts*))
471475
([repl-env f opts]
472476
(if (:output-dir opts)
473-
(let [src (if (util/url? f) f (io/resource f))
477+
(let [src (cond
478+
(util/url? f) f
479+
(.exists (io/file f)) (io/file f)
480+
:else (io/resource f))
474481
compiled (cljsc/compile src
475482
(assoc opts
476483
:output-file
477484
(cljsc/src-file->target-file src)))]
485+
;; make sure it's been analyzed, this is because if it's already compiled
486+
;; cljs.compiler/compile-file won't do anything, good for builds,
487+
;; but a bit annoying here
488+
(ana/analyze-file src opts)
478489
(-evaluate repl-env f 1 (cljsc/add-dep-string opts compiled))
479490
(-evaluate repl-env f 1 (cljsc/src-file->goog-require src)))
480491
(binding [ana/*cljs-ns* 'cljs.user]
@@ -515,6 +526,32 @@
515526
((or (:wrap opts) wrap-fn) form)
516527
opts)))
517528

529+
(defn canonicalize-specs [specs]
530+
(letfn [(canonicalize [quoted-spec-or-kw]
531+
(if (keyword? quoted-spec-or-kw)
532+
quoted-spec-or-kw
533+
(as-> (second quoted-spec-or-kw) spec
534+
(if (vector? spec) spec [spec]))))]
535+
(map canonicalize specs)))
536+
537+
(defn decorate-specs [specs]
538+
(if-let [k (some #{:reload :reload-all} specs)]
539+
(->> specs (remove #{k}) (map #(vary-meta % assoc :reload k)))
540+
specs))
541+
542+
(comment
543+
(canonicalize-specs
544+
'['foo.bar '[bar.core :as bar]])
545+
546+
(canonicalize-specs
547+
'['foo.bar '[bar.core :as bar] :reload])
548+
549+
(map meta
550+
(decorate-specs
551+
(canonicalize-specs
552+
'['foo.bar '[bar.core :as bar] :reload])))
553+
)
554+
518555
;; Special REPL fns, these provide compatiblity with Clojure functions
519556
;; that are not possible to reproduce given ClojureScript's compilation model
520557
;; All functions should have the following signature
@@ -574,43 +611,31 @@
574611
(evaluate-form repl-env env "<cljs repl>"
575612
(with-meta
576613
`(~'ns ~target-ns
577-
(:require
578-
~@(map
579-
(fn [quoted-spec-or-kw]
580-
(if (keyword? quoted-spec-or-kw)
581-
quoted-spec-or-kw
582-
(second quoted-spec-or-kw)))
583-
specs)))
614+
(:require ~@(-> specs canonicalize-specs decorate-specs)))
584615
{:merge true :line 1 :column 1})
585616
identity opts)
586617
(when is-self-require?
587618
(set! ana/*cljs-ns* restore-ns)))))
588-
'import
619+
'require-macros
589620
(fn self
590621
([repl-env env form]
591622
(self repl-env env form nil))
592623
([repl-env env [_ & specs :as form] opts]
593624
(evaluate-form repl-env env "<cljs repl>"
594625
(with-meta
595626
`(~'ns ~ana/*cljs-ns*
596-
(:import
597-
~@(map
598-
(fn [quoted-spec-or-kw]
599-
(if (keyword? quoted-spec-or-kw)
600-
quoted-spec-or-kw
601-
(second quoted-spec-or-kw)))
602-
specs)))
627+
(:require-macros ~@(-> specs canonicalize-specs decorate-specs)))
603628
{:merge true :line 1 :column 1})
604629
identity opts)))
605-
'require-macros
630+
'import
606631
(fn self
607632
([repl-env env form]
608633
(self repl-env env form nil))
609634
([repl-env env [_ & specs :as form] opts]
610635
(evaluate-form repl-env env "<cljs repl>"
611636
(with-meta
612637
`(~'ns ~ana/*cljs-ns*
613-
(:require-macros
638+
(:import
614639
~@(map
615640
(fn [quoted-spec-or-kw]
616641
(if (keyword? quoted-spec-or-kw)

0 commit comments

Comments
 (0)