Вопрос

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\", [], []);"

I then

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

Yes, it appears that this is what I want. I could be mistaken, but I do not think I need the "base.js" dependency, as it is already included in the running app under test (which is using :simple :optimizations).

My question is, how can I get the content of file out/x8LL7.js? I just want the string that is written to out/x8LL7.js as I have no use for the deps file string that is returned from cljs.closure/build.

If it isn't easy, then I guess I can just parse the returned deps string, open the file myself and then use the content; not a big deal. Still, I was hoping there was a more direct way.

Это было полезно?

Решение 2

Mostly just a note to myself, but in case someone needs to know, here is how I quick fixed it.

(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))))

Using this code, you can then (from the repl) type:

=> (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"

I bet you are curious as to why I wrapped the expr(ession) in a immediately called no argument function. It is because cljs.closure/build will optimize away code if it is not actually used. For instance:

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

however

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

Details aside, (to-js) seems to do what I want.

Другие советы

The more direct way would be injecting js code(like 'var DEBUG=true;') and then referring to it from clojurescript. Injecting clojurescript is risky, because there is no contract to what js code clojurescript would be compiled - you could have completely different code with other optimization setting or clojurescript version.

You can try the online REPL for cljs-in-cljs at clojurescript.net:

First enable debug mode:

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

Now when you eval a form you will get the result of read, analysis (just the resulting form) and the emitted 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

Disclaimer: I'm the creator of cljs-in-cljs/clojurescript.net

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top