Fork me on GitHub
#cljs-dev
<
2019-11-04
>
Filipe Silva08:11:55

I cleaned up the windows logs for the failing and successful run and diffed them

Filipe Silva08:11:44

the only real difference is that the failing run didn't have a cache hit I think? It has all these extra lines

Filipe Silva08:11:24

then some of the file copy and compilation logs are in different order, but the total number is the same

thheller08:11:03

would maybe help to try get it to fail with :pseudo-names true and/or source maps

thheller08:11:10

to at least get a clue where it fails

Filipe Silva08:11:43

then it's interesting enough that both the failed run and successful run actually fail in the same place... but one fails with a TypeError and the other one fails with a ReferenceError

Filipe Silva08:11:30

failed run error

WARNING: 0 error(s), 65 warning(s)
Optimizing with Google Closure Compiler, elapsed time: 50287.5409 msecs
Optimizing 373 sources, elapsed time: 50927.9967 msecs
builds/out-adv/core-advanced-test.js:1130:94 TypeError: (intermediate value).Fi is not a function
Stack:
  @builds/out-adv/core-advanced-test.js:1130:94
  @builds/out-adv/core-advanced-test.js:7201:3
TypeError: Object doesn't support property or method 'Fi'
   at Anonymous function (C:\projects\clojurescript\builds\out-adv\core-advanced-test.js:1130:90)
   at Global code (C:\projects\clojurescript\builds\out-adv\core-advanced-test.js:14:3)
type test-out.txt
V8_HOME not set, skipping V8 tests
Testing with SpiderMonkey

(no "Testing ..." messages)

Filipe Silva08:11:55

successful run error

WARNING: 0 error(s), 65 warning(s)
Optimizing with Google Closure Compiler, elapsed time: 51853.3191 msecs
Optimizing 373 sources, elapsed time: 52504.6602 msecs
builds/out-adv/core-advanced-test.js:7196:879 ReferenceError: test is not defined
Stack:
  @builds/out-adv/core-advanced-test.js:7196:879
  @builds/out-adv/core-advanced-test.js:7201:3
ReferenceError: 'test' is not defined
   at Anonymous function (C:\projects\clojurescript\builds\out-adv\core-advanced-test.js:7196:847)
   at Global code (C:\projects\clojurescript\builds\out-adv\core-advanced-test.js:14:3)
type test-out.txt
V8_HOME not set, skipping V8 tests
Testing with SpiderMonkey

(lots of "Testing ..." messages)

Filipe Silva09:11:26

oh, there's another difference... the downloaded version of seems to have a difference file size

Filipe Silva14:11:22

heya, following up on that discussion about core.async.interop last thursday on #clojurescript

Filipe Silva14:11:47

I put up a repo with the <p! macro along with a guide in https://github.com/filipesilva/async-interop

Filipe Silva14:11:01

cc @dnolen @thheller @lilactown @didibus (as you were the most involved in this discussion)

Filipe Silva14:11:10

the guide is in .adoc and structured so that it could go on https://clojurescript.org/, in the guides section

Filipe Silva14:11:26

meanwhile it's also published to clojars as async-interop

Filipe Silva14:11:07

is this a good way to put forward a proposal?

Filipe Silva15:11:57

I copied that code almost verbatim from David post in https://clojurians.slack.com/archives/C03S1L9DN/p1572541632221300 (but changed the exception to throw the original error)

Filipe Silva15:11:49

will have to read up on promise-chan, I don't know anything about it

dnolen15:11:11

@filipematossilva I would argue that you don't want to throw the original error

dnolen15:11:39

though it is a matter of taste - if you annotate the thing then you know it was in fact a promise error immediately and not some other kind of issue

dnolen15:11:54

one problem with promises is that you can call reject with any kind of value you like

dnolen15:11:50

it doesn't need to be a instance of error

Filipe Silva15:11:21

I think I see what you mean

Filipe Silva15:11:32

adding a new test for a value shows the problem

Filipe Silva15:11:37

(deftest interop-catch-non-error
  (async done
         (let [err "Rejected"]
           (go
             (is (= err
                    (is (thrown?
                         js/Object
                         (<p! (js/Promise.reject err))))))
             (done)))))

Filipe Silva15:11:49

D:\sandbox\async-interop\.shadow-cljs\builds\test\dev\out\cljs-runtime\cljs.core.async.impl.ioc_helpers.js:106
throw e29069;
^
Rejected

Filipe Silva15:11:00

so the gotcha here is that the macro should throw the ex-info and the consumer should do ex-cause themselves

Filipe Silva16:11:57

@darwin I'm trying to figure if promise-chan would improve anything or fix any broken semantics, but I don't think it does?

Filipe Silva16:11:18

as long as <p! itself is called with a promise, the promise semantics stand

Filipe Silva16:11:21

e.g. this works

Filipe Silva16:11:27

(deftest interop-consumer-semantics
  (async done
         (go
          (let [p (js/Promise.resolve 42)]
            (is (= (<p! p) 42))
            (is (= (<p! p) 42))
            (done)))))

Filipe Silva16:11:58

because the p->c function is calling .then on the promise itself

Filipe Silva16:11:34

the resulting channel itself doesn't have promise semantics however, but I'm not sure it should either

Filipe Silva16:11:46

I'm not sure if it's correct for the p->c function to not close the channel itself after a value though...

darwin16:11:06

I looked again and <p! has correct semantics, it does not expose internal channel and each usage is creating a new channel, but if someone was using async-interop.interop/p->c directly, he could run into the issue that only one consumer wins taking result value

darwin16:11:53

this should not work, I believe

Filipe Silva16:11:34

correct, that hangs

darwin16:11:54

with promise-chan it should work

Filipe Silva16:11:43

I guess the question then is, should it hang or not? or rather, should p->c offer chan or promise-chan semantics?

dnolen16:11:02

that's a good point - promise-chan is better

darwin16:11:04

depends if you want to make p->c public, people might want to do something further with the channel, e.g. alts! or pipelines or something

darwin16:11:35

but in that case they might want to implement their own p->c and not rely on your code, don’t know

dnolen16:11:12

this is just about interop

dnolen16:11:20

you don't need lots of options in my opinion

Filipe Silva16:11:21

tbh I don't have a very good POV on what should be the canonical usage... I just wanted to get the ball rolling on David's proposal of some official interop, and if both of you think promise-chain is better, then better it is

dnolen16:11:56

if you want to trivially translate async/await code promise-chan is better

dnolen16:11:01

fewer suprises

darwin16:11:52

another argument might be that promise-chan might be also more lightweight, I have this feeling that normal channel must support “queues”, but promise-chan can just remember one value, so it is potentially lighter, but I don’t know exact impl

Filipe Silva16:11:02

yes that was the original intention

Filipe Silva16:11:20

pushed and released

Filipe Silva16:11:24

what should be my next steps to move the proposal along? maybe open a JIRA issue with the patches to core.async and a PR to clojurescript-site?

dnolen16:11:34

just make a JIRA issue to core.async

Roman Liutikov16:11:32

I was playing lately with compiler extension to emit async/await hoping that Closure can take care of compiling it down to whatever needed. But then realized that because of scoping rules and the fact that await can't be used outside of async function, even if JS gets do {} expressions it's still has to be compiled into IIFE, when targeting older browsers.

Roman Liutikov16:11:34

do expressions proposal also discusses 'async do {}' blocks, but that's just too much :D

dnolen16:11:30

I've also been looking over core.async

dnolen16:11:56

updating ClojureScript core.async to match Clojure looks a like a pretty boring exercise - it could have been done long ago by anyone

dnolen16:11:54

after that's done I don't think it would be very hard for someone to limit the scope of the transformation to compete w/ existing state machine compilation support for async/await