Fork me on GitHub
#clojurescript
<
2021-08-16
>
Artёm Alexeev09:08:04

Guys, hello! I got a little problem with cljs. I have a local/root dependency in my deps.edn. It works without any problems with shadow-clj, When I add the same dependency to deps.edn in figwheel project it crashes with the following stacktrace: https://paste.ofcode.org/3aTVdbtMzV3A6MC2vUdxcQ6 Does anyone have some ideas?

borkdude11:08:46

I want to write a test around flush-on-newline for SCI. First I want to make sure the behavior of the test works in CLJS itself:

(let [count-atm (atom 0)]
         (with-redefs [cljs.core/flush #(swap! count-atm inc)]
           (binding [*flush-on-newline* true]
             (prn) (prn)) #_(sci/eval-string (pr-str '(binding [*flush-on-newline* true]
                                       (prn) (prn)))))
         (prn @count-atm))
But when running this, @count-atm still yields 0. It seems the with-redefs doesn't really work. Any ideas?

borkdude11:08:52

Simple repro:

cljs.user=> (with-redefs [flush nil] (prn))

nil

borkdude12:08:51

cljs.user=> (source flush)
(defn flush [] ;stub
  nil)
hrm

dnolen12:08:43

yeah flush is not a thing I thought

dnolen12:08:56

you have to see how it's done internally

borkdude12:08:15

this is a no-op?

dnolen12:08:40

yes - but maybe not intentionally

dnolen12:08:54

-flush is a thing

borkdude12:08:02

does *flush-on-newline* make sense in CLJS at all?

dnolen12:08:20

you have to poke around - the big picture is already there

dnolen12:08:36

the protocol for writers, but it seems flush doesn't wrap -flush

dnolen12:08:45

because it's implementation specific

borkdude12:08:01

the only place I see it's being used in is newline where it appears to be a no-op.

dnolen12:08:23

look around for calls to -flush as I said

dnolen12:08:07

printing is more annoying than it appears because of oddities around JS logging

borkdude12:08:20

I don't see any -flush impls that look at *flush-on-newline*

borkdude12:08:17

wait sorry, that didn't make sense

borkdude12:08:26

it's the other way around

dnolen12:08:59

the printing stuff looks at the flag to determine whether to invoke it

borkdude12:08:25

correct, but that invokes flush (no-op), not -flush?

borkdude12:08:11

I'll make a repro with my own Writer impl

dnolen12:08:15

oh, sorry I confused this with *print-newline*

dnolen12:08:29

@borkdude so maybe it's not supported because there's no such thing as I/O

dnolen12:08:38

no standard thing

dnolen12:08:24

like there's literally no place for this stuff to go

dnolen12:08:31

and output in JS is not buffer oriented

dnolen12:08:39

you're just going straight to console.log

borkdude12:08:42

I actually don't care that it's not supported, I just cared about compatibility of SCI <-> CLJS, so all good.

dnolen12:08:22

@borkdude hrm why would change anything?

dnolen12:08:32

not necessary - because maybe it will be done later

borkdude12:08:59

because doing less is usually faster?

dnolen12:08:15

if the code does nothing VMs are pretty good at figuring that out

dnolen12:08:18

not meaningful

dnolen12:08:39

Closure is also good at figuring it out too

borkdude12:08:54

I would be surprised if the map lookup would be compiled away

dnolen12:08:57

if anything is missing - it's fixing the docstrings about the state of things

borkdude12:08:21

but I won't die on this hill

dnolen12:08:37

the cost of a map look on something that's supposed to be I/O bound is not something to spend time on 🙂

dnolen12:08:31

the golden rule is to change nothing - unless we're adding something or fixing a bug

borkdude12:08:42

either way is fine with me. I think it could be a minor win, if the code was removed, that at least it wouldn't confuse people as much as it did me

Rina12:08:24

I have a function with this line code: (js/Number.isFinite value) When I try to perform some unit tests on this function (using cljs.test) I get the error TypeError TypeError: 'undefined' is not a function (evaluating 'Number.isFinite(G__47385_47386)') Do native JS functions run on the testing environment?

dnolen12:08:58

@borkdude that's why I suggested fixing the docstring / adding a couple of comments about the state - I agree it's confusing when you start to look at it - and I didn't remember either

dnolen12:08:19

@rinam https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite - it's been around for a while now - but always possible it's not available in the JS environment you are using

dnolen12:08:23

what environment?

Rina12:08:20

When I run the function that used js/Number.isFinite the code works as expected. But when I perform the unit tests on this function I get the error TypeError TypeError: 'undefined' is not a function (evaluating 'Number.isFinite(G__47385_47386)')

Rina12:08:26

This error is only thrown on the unit tests

Rina13:08:51

Any idea?

dnolen13:08:49

@rinam does that mean your testing environment is the same as your program environment?

Rina13:08:01

Maybe the term environment is wrong. I'll try to make it more simple. I have a foo function

(defn foo [volume]
  (if (js/Number.isFinite volume) 
    volume
    0))
When I run this code using the repl it works as expected. When I wrote unit tests for this function and ran the tests there is an error TypeError TypeError: 'undefined' is not a function (evaluating 'Number.isFinite(G__47385_47386)') . Is that clear?

dnolen13:08:04

Because what does "ran the tests" mean?

dnolen13:08:15

ClojureScript doesn't have any runners built in

Rina13:08:44

I use cljs.test

dnolen13:08:24

that is not a runner

dnolen13:08:33

do you mean you are running the test via the REPL too?

Rina13:08:09

I use phantomjs

dnolen13:08:18

so that's the problem

dnolen13:08:37

phantomjs JS environment doesn't have this functionality

dnolen13:08:44

not a ClojureScript issue

Rina13:08:51

I understand. Thank you for your help and patience.

dnolen13:08:15

phantomjs is a pretty old runner

dnolen13:08:25

I would probably look at puppeteer

dnolen13:08:56

it's probably not turnkey - but there should be examples in the wild about how to use it for testing

👍 3
Matsu15:08:05

Are there people working with Web Components with ClojureScript or is it mostly used for React through Reagent?

dnolen15:08:20

ClojureScript existed long before React

dnolen15:08:39

ClojureScript is for delivering Clojure where the JVM is not available

dnolen15:08:55

it does not assume anything about where you are going except JS runtime is required

dnolen15:08:37

you can use Web Components from JS - so that means you can use Web Components w/ ClojureScript

lilactown16:08:49

I remember that hot reloading web components is a PITA

dnolen16:08:13

but important to conceptually decouple hot reloading UIs from ClojureScript

dnolen16:08:43

yes ClojureScript makes it easy to do - but it is not a requirement - many contexts still exist where that property might not be interesting

lilactown16:08:04

sure. I didn't take the question to be, "can we develop web components with ClojureScript?" but rather, "is this path well paved?" which I would say the web components + clojurescript DX is not well paved at all compared to using something like React. that's just a function of how much time, money, and people are trying to do that.

dnolen16:08:27

but is the DX any different from JS? If not - probably not a big deal

lilactown16:08:45

no idea, never done anything serious with WC

dnolen16:08:48

i.e. you still get a REPL etc.

dnolen16:08:39

just pointing out the baseline - if you can do it JS then you can do it in ClojureScript

dnolen16:08:03

and plenty of things exist now to make it frictionless (no externs, Webpack etc. works) - and the REPL still there

lilactown16:08:35

remembering now that web components really need class support

dnolen16:08:13

do Web Components actually break the old prototype patterns?

dnolen16:08:28

(if so we should capture that, if we didn't already)

lilactown16:08:15

IIRC it requires that special behavior w/ calling super() in the constructor that can't be shimmed via prototypes

lilactown16:08:30

ah yeah the Reflect.construct seems to be a way around that now

dnolen16:08:57

but only if people are using private fields above

dnolen16:08:04

which probably isn't true for extending native stuff

lilactown16:08:40

gotcha, it works for HTMLElement but not for all cases of user-land classes

dnolen16:08:41

right but even here there is no real problem - the thing about class is always the ever growing list of things it supposed to do

dnolen16:08:05

you can write JS WebComponents and use them and let JS tools sort it out