This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-18
Channels
- # beginners (123)
- # boot (3)
- # cider (6)
- # clara (1)
- # cljs-dev (139)
- # cljsrn (9)
- # clojure (59)
- # clojure-italy (5)
- # clojure-uk (41)
- # clojured (10)
- # clojurescript (67)
- # community-development (1)
- # component (2)
- # core-async (7)
- # cursive (4)
- # datomic (4)
- # defnpodcast (2)
- # fulcro (23)
- # graphql (1)
- # jobs (2)
- # leiningen (4)
- # off-topic (32)
- # portkey (7)
- # protorepl (5)
- # re-frame (19)
- # reagent (5)
- # reitit (23)
- # shadow-cljs (29)
- # slack-help (1)
- # spacemacs (1)
- # tools-deps (21)
- # unrepl (18)
Is this where the cljs.core's aot existence is detected? https://github.com/clojure/clojurescript/blob/c9cf1a76b05b762fe0150b30e4230d56136035ff/src/main/clojure/cljs/closure.clj#L3056
no, maybe here: https://github.com/clojure/clojurescript/blob/1b22a53189e42a933043a759d8ee902a9ea93c40/src/main/clojure/cljs/compiler.cljc#L1308
I’m beginning to wonder if https://dev.clojure.org/jira/browse/CLJS-2646 is a valid ticket.
I’ve closed https://dev.clojure.org/jira/browse/CLJS-2646 with a note as to why I concluded I was wrong when I wrote it. I’m still curious about https://dev.clojure.org/jira/browse/CLJS-2671 which is likely unrelated.
Wow, since this ^ change eliminates double compilation of JAR code for a completely fresh build (including no ~/.cljs
), it drops my initial build from 35.6 s to 28.7 s for a React Native project that uses Om and other JAR deps.
Tested 1.10.191 with a project that uses code splitting and cljs.loader without success. Running into CLJS-2650 again. https://dev.clojure.org/jira/browse/CLJS-2650
Compilation fails here: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L611
It looks like the loaded.cljs doesn't get moved from the JAR to disk because requires-compilation?
returns false here: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L593
Where you’re pointing doesn’t make sense or do you mean requires-compilation is wrong generally?
I can repro, and get passed that by hacking the call to look like
(comp/requires-compilation? jar-file out-file (update opts :cache-key (fn [x] (or x :bogus))))
what I'm trying at the moment is to copy the cljs.loader from jar to disk just before the last compile-file
in compile-from-jar
.
so compile-from-jar
returns whatever compile-file
returns, but skips the cache. but not sure if that is even right?
(If you look at compile-from-jar
in 1.9.946 and now, you can see that the conditions have changed a little, but the :cache-key :bogus
hack makes it behave more like 1.9.946
@dnolen Isn't compile-from-jar responsible for moving files from jar to disk? this also seems only to happen when you actually use clojurescript from a JAR.
My hunch ws that, without the :bogus
hack, jar-file-to-disk
never gets called, and it jumps the gun, calling compile-file
requires-compilation?
has hard-coded logic to return false
for this namespace unless you use the hack
Yep, I'm just comparing the old and new behavior. Perhaps it was compiling it prematurely in 1.9.946? Dunno.
@dnolen yes, requires-compileation?
retuns false in compile-from-jar
. then the code to copy it from jar to disk doesn't get evaluated. but the last line ,`compile-file`, in compile-from-jar
fails.
Here is the 1.9.946 logic, for reference: https://github.com/clojure/clojurescript/blob/r1.9.946/src/main/clojure/cljs/closure.clj#L579-L597
The special case for cljs.loader in requires-compilation?
is to prevent cljs.loader from beeing cached, right?
The :cache-key :bogus
hack is not the right solution, but if useful, here is what happens with it in place: https://gist.github.com/mfikes/969939e06e830bcd2504fb58aa285101
@mfikes ah the guide is wrong. I run in to this previously as well, but thought I made a typo
(Even though I said, I got it running with the hack. I don't want to complain it is really successful. It brings up the browser, and it has a "Load Bar!" button, but I am unfamiliar with what is really supposed to happen at runtime at that point.)
any ideas for testing this? the current tests won't catch this, because loader.cljs is on the classpath/src path I think?
FWIW, this fixes the site https://github.com/clojure/clojurescript-site/pull/197
@mfikes ok, I thought about just checking the output files. and that it "jsut" compiles. 🙂
Yeah, there is a way to check output files in the script/test-cli
setup and make it fail if some arbitrary post-condition doesn't hold. A trick will be that it will block waiting for the browser to connect...
Here is an example of a disk-based post-condition https://github.com/clojure/clojurescript/blob/master/src/test/cljs_cli/cljs_cli/test.clj#L49
@r0man One idea to consider: The cljs-cli.test
namespace is really testing cljs.main
's core functionality.
But it seems that the ability to run some end-to-end tests using script/test-cli
might be useful going forward.
Thinking that perhaps for this one, there could be a code-splitting.test
namespace or somesuch that has a test or tests for this feature, and cljs-cli.test-runner
could be revised to require and run that namespace's tests as well.
(I'm just thinking that we might find the tests being run here will grow over time, as it is an easy way to exercise the system in an end-to-end way, and if that happens, perhaps separation of test namespaces might be useful.)
Also, @r0man if you look at the way the tests are run, the REPL environment is specified as an optional command line argument when the tests are run. Not sure if that framework needs to be revised to accommodate skipping certain tests if they don't apply to a given target or REPL environment. (So far, all tests are applicable to all environments.)
@dnolen @mfikes I just removed the cljs.loader check in requires-compilation? and it seems to work with my project as well.
now, I tried to test this with :aot-cache. I'm using :aot-cache true in my compiler options but ~/.cljs
stays empty. did the direcory change?
:closure-warnings
refresh now in the comprehensive 1.10.x doc list: https://gist.github.com/mfikes/bdbe214f03abac88ae384adb1ac26490
@dnolen @mfikes I added a patch to https://dev.clojure.org/jira/browse/CLJS-2650 It uses cljs.main to compile the code splitting guide in :none and :advanced. At the moment this test is in cljs-cli.test. Should I move it somewhere else?
@r0man I think it is fine... if we find that this namespace is getting crowded, we can spit it apart later.
@r0man Your patch tests the ability to pass two --compile
main opts simultaneously? I wasn't aware you can do that.
If I had to guess, the last one wins. (This is what happens if you pass two or more --re
options.
@mfikes That's the first time I'm using cljs.main. I tried it with only foo.core or only bar.core but I think only one of them ended up in the module info of cljs.loader.
No, I think you are probably right. I tried a couple of things to get this working and ended here. I'll remove the second one.
@dnolen So while trying to get a minimal test using only cljs.jar I realized that even the included test (https://github.com/clojure/clojurescript/blob/78b2395960767ea44b68ddd632d1dfe9a4957853/src/test/cljs_build/code-split/repl.clj) doesn't run with the latest versions. (Anything after r1.9.946 from what I can tell.)
Caused by: java.io.FileNotFoundException: The file out/cljs/loader.cljs does not exist.
at cljs.compiler$compile_file$fn__4145.invoke(compiler.cljc:1558)
at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1523)
at cljs.closure$compile_file.invokeStatic(closure.clj:556)
at cljs.closure$compile_from_jar.invokeStatic(closure.clj:626)
at cljs.closure$fn__5648.invokeStatic(closure.clj:647)
at cljs.closure$fn__5648.invoke(closure.clj:632)
at cljs.closure$fn__5571$G__5564__5578.invoke(closure.clj:511)
at cljs.closure$compile_sources$iter__5758__5762$fn__5763.invoke(closure.clj:983)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:706)
at clojure.core$next__5186.invokeStatic(core.clj:64)
at clojure.core$dorun.invokeStatic(core.clj:3134)
at clojure.core$doall.invokeStatic(core.clj:3140)
at cljs.closure$compile_sources.invokeStatic(closure.clj:980)
at cljs.closure$build.invokeStatic(closure.clj:2776)
at cljs.build.api$build.invokeStatic(api.clj:204)
at cljs.build.api$build.invoke(api.clj:189)
at cljs.build.api$build.invokeStatic(api.clj:192)
at cljs.build.api$build.invoke(api.clj:189)
at user$eval38.invokeStatic(repl.clj:25)
at user$eval38.invoke(repl.clj:25)
at clojure.lang.Compiler.eval(Compiler.java:7062)
at clojure.lang.Compiler.load(Compiler.java:7514)
... 9 more
@mfikes Sorry, I didn't see that. Though I did just now compile an uberjar from master. I'll try again—making sure I definitely have the latest.
@mfikes Works like a charm. I guess I didn't actually have the latest master. Thanks! 🙂
Great timing 🙂
Has anyone had issues with goog.module.ModuleLoader
being undefined in goog.module.ModuleLoader.prototype.evaluateCode_
? It's unable to dispatch an EvaluateCodeEvent
event, because ModuleLoader
is undefined.
I think it's because it's loading :cljs-base
which is redefining goog.module
.
Is it normal for cljs.loader/load
to also load :cljs-base
?
While loading, there's an error on goog.globalEval
for :cljs-base
: Error: Namespace "goog.string" already declared. at Object.goog.provide (eval at goog.globalEval (
So why is the loader trying to load :cljs-base
if that is already loaded by the script tag?
I'm really surprised that this seems to work. It makes me wonder if ClojureScript's persistent map avoids mutating itself at all when a revision based on it is made. Perhaps it does, and this code is skating on thin ice. Anyway, it bodes well if multthreading ever becomes a thing in JavaScript (in that ClojureScript might be within reach of supporting such a thing). https://gist.github.com/mfikes/9ef1908fff34c52a624f3dcf408d545f
You could mix aribtrary clojure and clojurescript code together, I guess, in the same context?
But does this make all nashorn threads reentrant? So js's run to completion semantics go away?
In addition to Rhino / Nashorn, this JavaScriptCore experiment is interesting https://webkit.org/blog/7846/concurrent-javascript-it-can-work/
Not that I was going to be able to build a slab allocator / garbage collector over SAB 🙂
you use a service worker. intercept synchronous xhr calls and hang the client webworker until some result is finished, then pass the result back in the response
Then you can build futures where you can do things like (await (anything-asynchronous blah
The wait is not reentrant though... run to completion for the worker context still holds
interestingly, in a cluster of web workers, I think Clojure's three main concurrency primitives can be mostly implemented in cljs
and with run to completion semantics, you can be sure that cljs threads can't be interrupted, so you get some concurrency protections that Clojure provides for free. Makes implementation a bit easier I believe