This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-27
Channels
- # aws (8)
- # beginners (172)
- # boot-dev (4)
- # cider (16)
- # cljs-dev (123)
- # cljsjs (4)
- # clojure (90)
- # clojure-brasil (3)
- # clojure-dev (7)
- # clojure-dusseldorf (1)
- # clojure-finland (1)
- # clojure-italy (59)
- # clojure-russia (3)
- # clojure-seattle (2)
- # clojure-seattle-old (1)
- # clojure-spec (40)
- # clojure-uk (28)
- # clojurescript (327)
- # clojurewerkz (3)
- # code-reviews (8)
- # cursive (4)
- # datomic (24)
- # editors (1)
- # emacs (19)
- # fulcro (147)
- # funcool (1)
- # graphql (1)
- # hoplon (34)
- # jobs-rus (1)
- # lein-figwheel (5)
- # leiningen (20)
- # luminus (14)
- # midje (1)
- # off-topic (8)
- # onyx (7)
- # parinfer (47)
- # pedestal (1)
- # perun (1)
- # portkey (46)
- # re-frame (25)
- # reagent (9)
- # remote-jobs (4)
- # ring-swagger (5)
- # rum (1)
- # shadow-cljs (113)
- # slack-help (8)
- # spacemacs (7)
- # sql (9)
- # tools-deps (23)
- # uncomplicate (3)
- # unrepl (3)
- # yada (6)
I’ve been thinking about how to create JS generators and async functions in ClojureScript
(they are heavily used in https://observablehq.com notebooks, and I eventually want to see if it would be possible to use ClojureScript there)
I wonder if it would be a good idea to add :js-generator
and :js-async
metadata to functions so they can compile to function*
and async function
, respectively
and js-yield
,`js-yield*`,`js-await` for emitting => yield
,`yield*`,`await`
js interop mainly, it’d be pretty ugly to use existing js generators and async functions inside cljs
i thought i could just reach for core.async instead, but I didn’t really understand generators/async functions until I saw them combined, which are now implemented in most browsers today: https://github.com/tc39/proposal-async-iteration#async-generator-functions
and they’re more or less like core.async - nobody uses that stuff unless they have to because callbacks are the baseline
they’re even less meaningful for React code (>70% of what ClojureScript users are doing) where async patterns are just callbacks
I’d like to see more compelling cases where they are solving some actual problem for end users before we start looking at adding more JS primitives
@shaunlebron ES await
\`async` is just sugar over functions that return Promise
. You can always use the Promise
API on the result of async function
. If you need to provide async function
in your cljs public API, just return Promise
. Generators are sugar for generating stateful Iterator
s and way to add some kind of laziness to JS. Cljs structures are lazy and implement Iterator
for long time. Cljs is ahead in this.
thanks for replying. it would just be nice to drop down to JS things since clojure is about embracing the host (if I’m interpreting that goal correctly)
also, generators are pausable/cancelable coroutines that can send and receive values at yield points. not sure a lazy sequence can do that
as for just using the Promise API, the synchronous style of async/await is nicer, similar to why core.async was created
@U050B88UR my feeling is that it’s more important than we realize, so I’ll do the work to make a case for it. already drafting a notebook that is essentially describing how it makes cancelable “goblocks” possible
Are the tests passing on Windows CI? One report on Reagent mentioned problems with the change I made to module_deps.js
It is expected with the new release that this code breaks: https://github.com/frankiesardo/linked/blob/master/src/linked/map.cljc#L257-L259 (because the map-entry created by this custom type is not MapEntry or doesn't implement IMapEntry) ?
Is the correct solution to call (MapEntry. k v nil)
there? The hash__
parameter is different compared to Clojure
@juhoteperi I've shut off Windows CI on the ClojureScript clone I maintain in my GitHub account. The two issues with it currently (IIRC): It fails silently, so you don't know if a unit test failed. It started failing incessantly due to something else that I couldn't figure out, so I turned it off.
I'll see if I can find an old Windows CI (AppVeyor) run, but I think it was failing fast with something related to certificates and lein.
@juhoteperi Well, good news is that the fail-fast certificate thing has now been resolved (whatever it was), and Windows CI runs again 🙂 We can see failures https://ci.appveyor.com/project/mfikes/clojurescript
I think (apart from fixing any unit test failures there), the only other bit to be addressed is to make it cause the the AppVeyor build to fail if the unit tests fail (otherwise you have to manually look at them)
Okay, that was the issue that was reported on Reagent / https://dev.clojure.org/jira/browse/CLJS-2708
Quite strange, does Node on Windows read this JS code differently: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/module_deps.js#L84-L85 ?
@juhoteperi I have access to Node on Windows. Let me know if there is a specific expression you’d like evaluated. I tried this, with the very last form (not involving a string) hanging for more intput I suppose.
> "abc".startsWith("a");
true
> "abc".startsWith("goog:");
false
> "abc".startsWith(goog:);
...
Could it be due to expression being split to two lines? And the file probably uses Unix Line-endings
Or hmm, could it be the quotation marks are lost for some reason
Yeah, it appears that, from the Windows CI errors, it thinks the call is syntactically intended to be id.startsWith(goog)
with goog
being a variable, but it sees a :
and indicates a syntax error
This shouldn't fix it, but trying to see if we can get more data: https://github.com/mfikes/clojurescript/commit/859bac595c76fc325bef65701b9f77360bc95952
@juhoteperi I have no clue why, but the above might be fixing it (using single quotes), and perhaps we are on to other errors that were masked by that one: https://ci.appveyor.com/project/mfikes/clojurescript/build/1.0.2
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L2358 maybe quotation marks aren't correctly passed here on Windows
really strange
maybe they would need to be escaped or something
Perhaps it is exhibiting something like
C:\Users\mfikes>node --eval console.log("goog:")
SyntaxError: Expected ')'
at exports.runInThisContext (vm.js:53:3)
at Anonymous function ([eval]-wrapper:6:1)
at Module.prototype._compile (module.js:423:3)
at Anonymous function (node.js:613:7)
at nextTickCallbackWith0Args (node.js:452:9)
at _tickCallback (node.js:381:13)
@juhoteperi This is probably equivalent to the theory you have:
user=> (shell/sh "node" "--eval" "console.log('goog:')")
{:exit 0, :out "goog:\n", :err ""}
user=> (shell/sh "node" "--eval" "console.log(\"goog:\")")
{:exit 1, :out "", :err "SyntaxError: Expected ')'\r\n at exports.runInThisContext (vm.js:53:3)\r\n at Anonymous function ([eval]-wrapper:6:1)\r\n at Module.prototype._compile (module.js:423:3)\r\n at Anonymous function (node.js:613:7)\r\n at nextTickCallbackWith0Args (node.js:452:9)\r\n at _tickCallback (node.js:381:13)\r\n"}
I’ll try actually using ProcessBuilder
, but this is probably what shell/sh
does anyway,.
Yeah, confirmed that you can repro directly with ProcessBuilder
as you would expect:
user=> (let [proc (-> (ProcessBuilder. ["node" "--eval" "console.log(\"goog:\")"])
.start)
is (.getInputStream proc)
iw (StringWriter. (* 16 1024 1024))
es (.getErrorStream proc)
ew (StringWriter. (* 1024 1024))
_ (do (.start
(Thread.
(bound-fn [] (pipe proc is iw))))
(.start
(Thread.
(bound-fn [] (pipe proc es ew)))))
err (.waitFor proc)]
[err (str iw) (str ew)])
[1 "" "SyntaxError: Expected ')'\r\n at exports.runInThisContext (vm.js:53:3)\r\n at Anonymous function ([eval]-wrapper:6:1)\r\n at Module.prototype._compile (module.js:423:3)\r\n at Anonymous function (node.js:613:7)\r\n at nextTickCallbackWith0Args (node.js:452:9)\r\n at _tickCallback (node.js:381:13)\r\n"]
So, if we somehow can ensure all literal strings use single quotes, that would work around the issue.
user=> (let [proc (-> (ProcessBuilder. ["node" "--eval" "console.log('goog:')"])
.start)
is (.getInputStream proc)
iw (StringWriter. (* 16 1024 1024))
es (.getErrorStream proc)
ew (StringWriter. (* 1024 1024))
_ (do (.start
(Thread.
(bound-fn [] (pipe proc is iw))))
(.start
(Thread.
(bound-fn [] (pipe proc es ew)))))
err (.waitFor proc)]
[err (str iw) (str ew)])
[0 "goog:\n" ""]
Those two double quotes I added are only ones in the file. Change those to single quites + add comment on the file about only using single quotes should be good enough.
Cool. I can add a JIRA patch. Then we can perhaps sort out the subsequent failures that occur even with that fix.
mainFields problems is probably very similar
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L2352 it generates "
here, it could generate strings with '
instead
@shaunlebron sure, but I think making a case for has to be grounded in the reality of the existing user base
this request comes up very infrequently and never with a actual use case that relates at all to how people are actually using ClojureScript
and I haven’t seen anything happen in the JavaScript world that makes me think it’s delivering enough value to take it on
also the fact that we can process ES6 in build means you can do what you need in JS if it’s really a problem
just like Clojure there’s no reason to import all the primitives of the host, it’s not meaningful
yeah, that’s compelling
yeah, and that ES6 code can call cljs functions fine too
this may be the direction that I end up agreeing with
If using ES6 with foreign-libs + :module-type :es6
there are some limitations currently calling cljs <-> es6 <-> cljs
would age and increased use of generators and async/await functions merit their inclusion eventually?
Not sure if ES6 is usable with Closure JS (`:libs`)
@juhoteperi it should be since i worked on that
If es6 module is only module using a Cljs namespace, the namespace is not included in build
I think there is same problem with :libs
It is due to how build
finds the necessary Cljs files to include in build
Oh, and this works with :none
but not with optimizations
@shaunlebron of course if people start clamoring for this feature because it’s a common requirement I don’t see why not
@juhoteperi right I think the issue is when you want to require a ClojureScript namespace
Yes, ES6 can import CLjs using import * from "goog:foo.cljs.namespace";
but this only works if this cljs ns is used by another cljs namespace
I'll open issue about this
@juhoteperi wouldn’t be so hard to fix, I guess we need to check ES6 modules for cljs imports as an earlier pass
I think it is related to build pipeline ordering here: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/closure.clj#L2809-L2819
I think add-js-sources
adds files from :libs
(including module processed files)
But add-dependency-sources
is called before that
In :none
mode all sources inside build source
are compiled (if source
is directory) but if optimization and :main
is used, only that single file is used as entrypoint
(in fact I think maybe we should starting warning about the file system way of doing things)
Point is that this happens even without optimizations if source is single file
I’ve attached a patch to https://dev.clojure.org/jira/browse/CLJS-2708, tried confirming that it works, but honestly can’t figure out Node and Windows issues to even repro the original ticket description, so I’ve asked the original reporter to help see if the patch resolves it.
Though with :optimization :none
there is no error about the missing namespace (because JS modules don't validate if required modules exist)
I fear add-dependencies
step should somehow be recursive
Because we use intitial js-sources
to find the used JS modules, and then those JS modules could add new Cljs namespaces, which use different JS modules etc.
fix point meaning, we keep applying the source finding passes until the set of discovered things stops changing
I think it would have to also keep applying handle-js-modules
(or we need to split / move this) so that new added JS modules get processed
handle-js-modules
could be split into once function that can be called multiple times to add new JS modules to build, and then another function which will process files once all modules are found
looks like I missed classpath libs REPL support - fixed in master - will probably do a spot release on Friday
thanks for the transit-cljs
fix as well
heh took a long time to really hit this one https://dev.clojure.org/jira/browse/CLJS-2710