From 880a94195bba36488d36b0aec3a58be8ec9b54a3 Mon Sep 17 00:00:00 2001 From: Mike Fikes Date: Fri, 14 Jun 2019 14:32:31 -0400 Subject: [PATCH] Dynamically add gen-path to classloader Fixes #30 --- README.md | 12 ------------ src/cljs_test_runner/main.clj | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 327aab8..5b9ae21 100644 --- a/README.md +++ b/README.md @@ -83,18 +83,6 @@ To use Closure Compiler advanced optimisation levels you will need to create an {:optimizations :advanced} ``` -The Closure Compiler then requires the generated test runner to be on the path so you'll need to add this to your `:paths` key in your `deps.edn`: - -```edn -:paths ["src" "test" "cljs-test-runner-out/gen"] -``` - -It will fail the first time you run this, that's because that directory doesn't exist yet so it'll be removed from the path on startup. To fix this you can run the following before executing your tests: - -```bash -mkdir -p cljs-test-runner-out/gen -``` - Now when you run the following, your tests will be executed with advanced compilation: ```bash diff --git a/src/cljs_test_runner/main.clj b/src/cljs_test_runner/main.clj index 4e0547a..d01ab61 100644 --- a/src/cljs_test_runner/main.clj +++ b/src/cljs_test_runner/main.clj @@ -6,7 +6,8 @@ [clojure.edn :as edn] [clojure.tools.cli :as cli] [cljs.build.api :as cljs] - [doo.core :as doo])) + [doo.core :as doo]) + (:import (clojure.lang DynamicClassLoader))) (def ns-filter-cljs "Namespace filtering code from cognitect-labs/test-runner but modified and as a string. Inserted into the test runner ClojureScript code when it's rendered. Forgive me performing string based meta programming." @@ -102,6 +103,19 @@ (edn/read-string (slurp path)) {})) +(defn add-loader-url + "Add url string or URL to the highest level DynamicClassLoader url set." + [url] + (let [u (if (string? url) (java.net.URL. url) url) + loader (loop [loader (.getContextClassLoader (Thread/currentThread))] + (let [parent (.getParent loader)] + (if (instance? DynamicClassLoader parent) + (recur parent) + loader)))] + (if (instance? DynamicClassLoader loader) + (.addURL ^DynamicClassLoader loader u) + (throw (IllegalAccessError. "Context classloader is not a DynamicClassLoader"))))) + (defn test-cljs-namespaces-in-dir "Execute all ClojureScript tests in a directory." [{:keys [env dir out watch ns-symbols ns-regexs var include exclude verbose compile-opts doo-opts]}] @@ -124,6 +138,7 @@ :doo-env :chrome-headless})] (io/make-parents src-path) (spit src-path test-runner-cljs) + (add-loader-url (io/as-url (io/file gen-path))) (try (let [build-opts (merge {:output-to out-path :output-dir out @@ -196,6 +211,8 @@ (defn -main "Creates a ClojureScript test runner and executes it with node (by default)." [& args] + (let [cl (.getContextClassLoader (Thread/currentThread))] + (.setContextClassLoader (Thread/currentThread) (clojure.lang.DynamicClassLoader. cl))) (let [{:keys [options errors summary]} (cli/parse-opts args cli-options)] (cond (:help options) (exit 0 summary)