|
4668 | 4668 |
|
4669 | 4669 | (defonce |
4670 | 4670 | ^{:private true |
4671 | | - :doc "the set of paths currently being loaded by this thread"} |
4672 | | - *pending-paths* #{}) |
| 4671 | + :doc "A stack of paths currently being loaded by this thread"} |
| 4672 | + *pending-paths* ()) |
4673 | 4673 |
|
4674 | 4674 | (defonce |
4675 | 4675 | ^{:private true :doc |
|
4803 | 4803 | (doseq [arg args] |
4804 | 4804 | (apply load-lib prefix (prependss arg opts)))))))) |
4805 | 4805 |
|
4806 | | -;; Public |
| 4806 | +(defn- check-cyclic-dependency |
| 4807 | + "Detects and rejects non-trivial cyclic load dependencies. The |
| 4808 | + exception message shows the dependency chain with the cycle |
| 4809 | + highlighted. Ignores the trivial case of a file attempting to load |
| 4810 | + itself because that can occur when a gen-class'd class loads its |
| 4811 | + implementation." |
| 4812 | + [path] |
| 4813 | + (when (some #{path} (rest *pending-paths*)) |
| 4814 | + (let [pending (map #(if (= % path) (str "[ " % " ]") %) |
| 4815 | + (cons path *pending-paths*)) |
| 4816 | + chain (apply str (interpose "->" pending))] |
| 4817 | + (throw (Exception. (str "Cyclic load dependency: " chain)))))) |
4807 | 4818 |
|
| 4819 | +;; Public |
4808 | 4820 |
|
4809 | 4821 | (defn require |
4810 | 4822 | "Loads libs, skipping any that are already loaded. Each argument is |
|
4897 | 4909 | (when *loading-verbosely* |
4898 | 4910 | (printf "(clojure.core/load \"%s\")\n" path) |
4899 | 4911 | (flush)) |
4900 | | -; (throw-if (*pending-paths* path) |
4901 | | -; "cannot load '%s' again while it is loading" |
4902 | | -; path) |
4903 | | - (when-not (*pending-paths* path) |
| 4912 | + (check-cyclic-dependency path) |
| 4913 | + (when-not (= path (first *pending-paths*)) |
4904 | 4914 | (binding [*pending-paths* (conj *pending-paths* path)] |
4905 | | - (clojure.lang.RT/load (.substring path 1))))))) |
| 4915 | + (clojure.lang.RT/load (.substring path 1))))))) |
4906 | 4916 |
|
4907 | 4917 | (defn compile |
4908 | 4918 | "Compiles the namespace named by the symbol lib into a set of |
|
0 commit comments