clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Nazral 2021-01-11T09:43:01.253600Z

Hi, I am trying to use https://github.com/vasturiano/force-graph from shadow-cljs and am having a problem. I install the library all right with npm, but when I try to reproduce

import ForceGraph from 'force-graph';
with (:require ["force-graph" :as fg]) then fg/ForceGraph is nil (same if I use :refer)

Nazral 2021-01-11T09:43:32.254200Z

(it works fine if I use it from a <script> tag)

Nazral 2021-01-11T09:45:24.255100Z

The error I get is shadow-cljs - [reload failed] module$node_modules$force_graph$dist$force_graph_common.ForceGraph is not a constructor which makes sense given that force_graph.common does not contain ForceGraph

p-himik 2021-01-11T09:52:14.255300Z

When you use (:require ["force-graph" :as fg]), what's the output of (js/console.log fg)?

Nazral 2021-01-11T09:53:28.255500Z

A function object that seems to be quite empty

p-himik 2021-01-11T09:54:37.255700Z

So it's a function. Maybe just (:require ["force-graph" :as ForceGraph]) then?

p-himik 2021-01-11T09:55:38.255900Z

Alternatively, if that doesn't work, (:require ["force-graph" :default ForceGraph]) (but in this case I would've expected that fg object from before to have the default key).

p-himik 2021-01-11T09:56:41.256100Z

For future reference, this is the relevant imports translation table: https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages Note that in a few odd cases it doesn't work, so js/console.log is still useful.

Nazral 2021-01-11T09:56:59.256300Z

It worked, thanks ! It's also that I was calling it wrongly 😅

Nazral 2021-01-11T09:57:09.256500Z

(fg) indeed outputs what I wanted

p-himik 2021-01-11T09:57:31.256700Z

So was it :as or :default?

Nazral 2021-01-11T10:07:51.257100Z

:as

👍 1
lambduhhh 2021-01-11T14:33:15.259500Z

Starting a mini series on my channel focusing on Clojurescript. Tune in for some laughing and learning you some lisp languages.. That's what I'm all about! 😜✌️ Also open to any requests for tutorials ^~^ https://youtu.be/ZMB-M_XDotE

Volodymyr Huzar 2021-01-11T15:00:30.261200Z

Hi, I am trying to migrate ClojureScript tests from “Chrome Headless” to jsdom using Karma and shadow-cljs as test runners. The regular tests which require access to DOM or browser API work fine. But async test where cljs.core.async/go is used doesn’t work. Basically, nothing inside go is executed. Does anyone have some idea what could be wrong? Did I miss some configuration? Is it only jsdom issue or maybe it is cljs.core.async interoperability issue? I have put a simple test example below

(ns async-tests
  (:require [cljs.test :refer [deftest async]]
            [cljs.core.async :refer [go <! timeout]]))

(deftest async-go-test
  (async done
    (.log js/console "Before go is printed")
    (go
      (.log js/console "After go is never printed")
      (<! (timeout 1))
      (done))))
The result I get in console is
LOG: 'Testing async-tests'
LOG: 'Before go is printed'
WebKit 537.36 (undefined 0.0.0): Executed 159 of 185 SUCCESS (0 secs / 0.589 secs)
WebKit 537.36 (undefined 0.0.0) ERROR
Disconnected, because no message in 30000 ms.
I have create a StackOverflow issue with few more details https://stackoverflow.com/questions/65669171/clojurescript-cljs-core-async-go-doesnt-work-inside-jsdom

Volodymyr Huzar 2021-01-12T08:42:16.276100Z

js/setTimeout works fine, it is the first thing I have tried to replace in tests, but later realised that it will not be so good to abandon cljs.core.async because of jsdom

thheller 2021-01-12T10:27:50.276500Z

you could just override whatever the nextTick detection logic does and make it either use setImmediate from node or Promise microtasks or setTimeout. it is the detection that is the problem I think

Volodymyr Huzar 2021-01-12T11:55:08.276700Z

Thanks, I’ll try that. I think it could be good enough to unblock using of jsdom with cljs.async but probably it would be nice if the problem is fixed in one of the parts of this issue (jsdom or goog.async)

Volodymyr Huzar 2021-01-13T11:25:42.305700Z

(set! (.. js/window -goog -async -nextTick) js/setTimeout) does it job and makes cljs.core.async/go to work

Volodymyr Huzar 2021-01-13T14:28:21.311900Z

@thheller looking back on workaround you have proposed and which works what is you opinion about this defect. Is it more related to clojure/goog/async or jsdom or is it just colliding of tools and it would be hard to fix it inside any of them?

thheller 2021-01-13T15:53:02.312100Z

I don't know. I haven't looked at the code of nextTick in detail. I'd put the blame on jsdom in case it "pretends" to emulate something when it doesn't

👍 1
Volodymyr Huzar 2021-01-14T11:09:27.002Z

I have created a small Node demo where only jsdom and google-closure-library are used https://github.com/Valdermeyder/jsdom-google-closure-library and they work fine together (unless I did some terrible mistake). My next assumptions that it could be either karma connector for jsdom or something related to the clojurescript ecosystem. I’ll try to create a simple clojurescript demo some time later to check that

2021-01-11T15:05:30.264600Z

Does (or should) require (the function, not the ns declaration arg) work differently in cljs than cj? When I do something like (require '[clojure.pprint :as pprint]) and then invoke (pprint/pprint "test") I get a warning in my repl along the lines of:

------ WARNING - :undeclared-ns ------------------------------------------------
 Resource: <eval>:1:2
 No such namespace: pprint, could not locate pprint.cljs, pprint.cljc, or JavaScript source providing "pprint"
--------------------------------------------------------------------------------

------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:2
 Use of undeclared Var pprint/pprint
--------------------------------------------------------------------------------
This seems to happen with any dynamically required ns. If I add the required namespace to my ns in the :require block it works. Is this expected behavior?

thheller 2021-01-11T15:17:48.265200Z

@markbastian "dynamic require" in CLJS is not supported

👍 1
🙏 1
thheller 2021-01-11T15:20:48.265500Z

I'm guessing that the async mechanism used by core.async is either somehow affected by jsdom and doesn't execute at all

thheller 2021-01-11T15:22:36.265700Z

https://github.com/google/closure-library/blob/master/closure/goog/async/nexttick.js this is the underlying code doing a bunch of browser detection stuff

thheller 2021-01-11T15:23:03.266100Z

maybe jsdom "pretends" that something is there but doesn't actually do anything

GHvW 2021-01-11T16:00:07.268600Z

is there any way around the dynamic imports issue in a browser context? If a npm dependency is a hard requirement, is there any way to isolate that and work with it in javascript but still have your application primarily built in clojurescript?

Volodymyr Huzar 2021-01-11T16:21:05.268700Z

thank you for the response. I’ll create an issue for “jsdom”, maybe they can help as well to find the exact reason from their side. I also thought about order of .js files which are loaded by karma but I’m not sure if it makes sense at all

GHvW 2021-01-11T16:45:14.269400Z

thank you so much!!!

Volodymyr Huzar 2021-01-11T17:34:25.269800Z

The ticket to jsdom wouldn’t be so easy. I have to figure out how to reproduce the behaviour without karma and other tools. I’ll see what I can do with that

thheller 2021-01-11T17:41:27.270Z

you could first try to isolate whether it actually is core.async or the nexttick stuff

thheller 2021-01-11T17:42:43.270200Z

try

(ns async-tests
  (:require [cljs.test :refer [deftest async]]
            [goog.async.nextTick]))

(deftest async-go-test
  (async done
    (.log js/console "Before go is printed")
    (js/goog.async.nextTick
      (fn []
        (.log js/console "After go is never printed")
        (done)))))

Volodymyr Huzar 2021-01-11T17:53:42.270400Z

seems like it is nextTick I got the same error as before with go

Volodymyr Huzar 2021-01-11T17:57:08.270600Z

Thanks for pointing that. With nextTick it should be easier to create a reproducible example as it is js and should run in node environment without all other tools I have right now.

thheller 2021-01-11T18:21:57.270800Z

also try with js/setTimeout just to be sure

grounded_sage 2021-01-11T22:32:08.274700Z

Is there a good way to capture the name of a function or it’s namespace when you throw an error inside a go block and propagate it?