How do I get the direct result of a simple clojurescript compilation?

I want to be able to inject javascript code into my app while testing. Following this line of reasoning, I do the following in a repl.

=> (cljs.closure/build '(swap! my-project.my-namespace.my-atom inc) {})
<= "goog.addDependency(\"base.js\", ['goog'], []);\ngoog.addDependency(\"../x8LL7.js\", [], []);"

После, я

=> more out/x8LL7.js 
<= cljs.core.swap_BANG_.call(null,my_project.my_namespace.my_atom,cljs.core.inc);

Да, похоже, это то, что я хочу. Я могу ошибаться, но я не думаю, что мне нужна зависимость "base.js", так как она уже включена в тестируемое работающее приложение (которое использует:simple:optimizations).

У меня вопрос, как я могу получить содержимое файла out/x8LL7.js? Я просто хочу строку, которая написана out/x8LL7.js так как я не использую строку файла deps, которая возвращается из cljs.closure/build,

Если это не так просто, то, я думаю, я могу просто проанализировать возвращенную строку deps, открыть файл самостоятельно и затем использовать содержимое; не так уж и важно. Тем не менее, я надеялся, что есть более прямой путь.

3 ответа

Решение

В основном, просто записка для себя, но в случае, если кому-то нужно знать, вот как я быстро это исправил.

(def cljs-to-js-dir "_cljs_to_js_out")

(def js-options { :output-dir cljs-to-js-dir})

(defn js-compile [quoted-expr]
  (let [ result (cljs.closure/build quoted-expr js-options)
         file-name  ((re-find #"(/.+\.js)" result) 0)]
    (slurp (str  cljs-to-js-dir "/" file-name))))

(defmacro to-js [expr]
  (js-compile `((fn [] ~expr))))

Используя этот код, вы можете (из repl) набрать:

=> (to-js (swap! my-project.my-namespace.my-atom inc))
<= "(function (){\nreturn cljs.core.swap_BANG_.call(null,my_project.my_namespace.my_atom,cljs.core.inc);\n}).call(null);\n"

Могу поспорить, что вам любопытно, почему я обернул expr(ession) в немедленно вызываемую функцию без аргументов. Это потому, что cljs.closure/build оптимизирует код, если он на самом деле не используется. Например:

=> (js-compile '(fn [a b] (+ a b))) 
<= ""

тем не мение

=> (js-compile '((fn [a b] (+ a b)) 2 3))
<= "(function (a,b){\nreturn (a + b);\n}).call(null,2,3);\n"

Детали в стороне, (to-js) кажется делает то, что я хочу.

Вы можете попробовать онлайн REPL для cljs-in-cljs на http://clojurescript.net/:

Сначала включите режим отладки:

cljs.user=> (set! webrepl/*debug* true)

Теперь, когда вы оцениваете форму, вы получите результат чтения, анализа (только полученную форму) и отправленный JS:

cljs.user=> (def myatom (atom 1))
...
cljs.user=> (swap! myatom inc)
READ: (swap! myatom inc)
ANALYZED: (swap! myatom inc)
EMITTED: "cljs.core.swap_BANG_.call(null,cljs.user.myatom,cljs.core.inc)"
2

Отказ от ответственности: я создатель cljs-in-cljs/clojurescript.net

Более прямым способом было бы внедрить код js (например, 'var DEBUG=true;'), а затем сослаться на него из clojurescript. Внедрение clojurescript рискованно, потому что нет никакого договора на то, какой код js будет скомпилирован clojurescript - вы могли бы иметь совершенно другой код с другими настройками оптимизации или версией clojurescript.

Другие вопросы по тегам