Fork me on GitHub
Mikko Koski07:09:49

How do I require a development library so that it will get dead code eliminated? Example: (ns foo (:require [dev-library])) (when goog.DEBUG (dev-library/do-something!) (println "Hello development!")) (println "Hello world!") AFAIK, dev-library will not be DCE'd. So how should I change the code? Some macro magic?


@rap1ds use :preloads build config

👍 2

I’d like to share something I’m working on. It’s a declarative web audio engine (think React for Web Audio API). In the spirit of data-oriented programming, the graph is just data. As a side-fx of it, it’s really easy to serialize/deserialize. Also, it’s extremely straightforward to extract part of a graph into a function, thus it is both generative and highly composable. It feels like a perfect “glue” for building non-trivial audio graphs.


Deployed example. Should work on mobiles too!


I'm getting: The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. <URL>


which browser?


and thanks for the feedback


got to polish the demo


wait… what happens if you click the page at least two times?


oh I had to click the page? this wasn't obvious to me since the page was entirely blank for me


I’ll update the example to make it clear

Chris McCormick10:09:35

I am running into a strange error under :advanced compilation using shadow-cljs. I am consuming this fork of Timidity using npm: It works well in dev mode. Under :advanced compilation I am seeing the following error:

app.js:598 Uncaught (in promise) ReferenceError: $jscomp is not defined
    at p.load (app.js:598)
    at rm (app.js:1394)
    at app.js:1395
    at app.js:1372
With that load function being defined here: The resulting compiled code ends up like this:
load(l) {
                            const f = this;
                            return $jscomp.asyncExecutePromiseGeneratorFunction(function*() {
                                V("load %o", l);
                                if (f.destroyed)
                                    throw Error("load() called after destroy()");
What should I do to diagnose the source of this missing $jscomp ?

Chris McCormick10:09:39

The calling code looks like this:

(-> (Timidity. timidity-base-url)
      (.load midi-data-uri)


@UUSQUGUF3 you can use :pseudo-names true to find out perhaps

Chris McCormick13:09:27

I tried with --debug and the result is the same, the error is still $jscomp is not defined. Maybe I should ask @thheller on #shadow-cljs

Chris McCormick13:09:31

It's late here but I will create a reproduceable case and follow up tomorrow.

Chris McCormick13:09:38

When I turn on :output-feature-set :es6 it fixes this, so it looks like some issue to do with closure compiler shims for this particular bit of code.


are you using :target :esm ?

Chris McCormick13:09:34

No I didn't know about this flag. Will try it tomorrow, thank you.


it's the same build target that nbb uses

Chris McCormick13:09:38

Oh it's currently :target :browser.


don't know if this has anything to do with it


but worth a try

👍 2

@UUSQUGUF3 :output-feature-set is the proper fix. $jscomp is about polyfills. would need more info to tell what exactly the problem there is. should be fine normally.

👍 4
Mikko Koski11:09:30

I'm using Browser REPL and what I'm seeing is that the first time I evaluate ns form in a namespace it takes quite a long time. Evaluating a single ns form causes a dozen of network requests, each taking close to 1 second. This means that the total time to eval is closer to 10 seconds. Sometimes this causes nREPL to time out. I'm seeing this same with and without Cider piggieback. The response of the repl xpc request is a bunch of goog.addDependency statements. What might be causing this? Is there any way to make this faster? Any ideas on how to debug this further? Screenshot attached.


we had this same issue with figwheel


the resolution was to make our backend server be on http/2 - that way the browser can request stuff in parallel

👍 2
Mikko Koski12:09:45

yeah I also have a figwheel setup in the same project and had the same issue there as well

Mikko Koski12:09:20

@U3JH98J4R But these requests are not going to my backend. I'm running my backend on port 8089, but these requests are going to the REPL server, 3449. I have a hunch that my own backend is already using http/2 (pedestal default).

Mikko Koski18:09:04

@U32ST9GR5 Did you find a solution for this? I can see that you posted a patch to the Jira issue but it hasn't gotten much attention

Mikko Harju13:09:55

Nope – actually we moved to Shadow-CLJS a bit after that and the problems were fixed. I also implemented a patch to the compiler that overcame that issue but it was abandoned after we did not really need it anymore. Don’t remember if I managed to implement it completely or not – at least I did something 🙂

👍 2

What does this error means Uncaught Error: No protocol method IDeref.-deref defined for type undefined:


Using @foo when foo is undefined/nil


But I have defined all reagent atom with default value


that doesn't matter, you are likely not deref'ing the actual atom


The subscription is returning nil, then it's calling deref on nil, probably


Probably not best to call @ on behalf of some other calling code automatically. You can do (when-let [derefable (sub [:blah])] @derefable) to protect against that


You're talking about subscriptions, but OP doesn't mention them - they can be using Reagent without re-frame. Also, it's never a good idea to use that pattern - a subscription must never return nil. If it does, it means it doesn't exist - means, the error is elsewhere.


hmm, maybe it'd say nil in the error? If so, maybe you're thing is actually not defined. But I've seen it a lot when a nil sub causes that problem


oh that's true, they might not be talking about subs


And yeah, subs should be defined before you call them, but sometimes folks typo or whatever. Then the above error doesn't help them sus it out much


The above error provides a stacktrace leading to the exact location of the subscription usage. The when-let pattern just hides the error.


okay so i should look at the subs definition ?


Yeah, there's sometimes cases where you want to make a component generic wrt a given sub, so you might pass in the sub path from the outside. Those situations are much more likely to cause issues with derefing. Depending on how you want the function to work, you may want it to not fail hard when a bad sub path is given.


@anshbenew If you use re-frame subscriptions, there should be a clear warning in the JS console saying which subscription ID is not found.


@john This is a very narrow, specialized, case. I would absolutely not recommend it to novices. A usage of a non-existent sub is an error, 100%. It should be fixed, that's it.


@p-himik it is just showing me this error


On a large enough code base, you might run into it though. Fair argument about trying to avoid it though


@anshbenew 1. I have no clue if you're using re-frame or not - you still haven't confirmed it 2. You don't have source maps enabled. Figure out how to enable them with the tooling that you use and you'll be able to see the relevant CLJS code 3. This is more #reagent related


Yes, I am using re-frame with reagent.


okay will try to enable source maps


I enabled source maps it is showing Uncaught ReferenceError: goog is not defined


goog.addDependency("base.js", ['goog'], []);