Fork me on GitHub
code star 803:05:20

Has anyone run into problems using node mjs files on Clojure Script?

code star 803:05:57

I keep hitting this ecma6 import vs require... And I feel like I keep crashing into a wall

hipster coder05:05:59

ok, heads up… there’s an issue with the latest node 14, typescript, not recognizing .ts files when you enable Ecma6 modules… I have the intuition this will affect clojurescript being able to load npm modules, until they fix it…

hipster coder05:05:33

so don’t get your hopes up about using the latest node version, ts, and ecma6 together


Quick tip for new users of the :target :bundle feature: Some JS libraries may require certain objects to be available in global scope. Some CLJSJS libs have done that for you. With bundle target, depending only on package.json you no longer get globals. You can solve that with the following webpack config, where reactstrap is a plain NPM module from your package.json . It makes the global GlobalReactstrap available to all other modules.

const webpack = require('webpack');

module.exports = {
   plugins: [
     new webpack.ProvidePlugin({      
       GlobalReactstrap: 'reactstrap'

👍 4
Karol Wójcik08:05:23

How define new var in library. In clojure I would do:

(in-ns 'some-library) 
(def new-symbol-in-library "X")
, but in clojurescript for obvious reasons is not possible


you can't really do that

Karol Wójcik08:05:55

Ok good to know


Hello, mongodb can run javascript code for map reduce,or in filter using javascript using $where, is it possible to use Clojurescript instead? thank you

Eric Scott17:05:26

So I have a custom literal tag defined in a data_readers.cljc:

 lstr ont-app.vocabulary.lstr/read-LangStr
Said function works like this:
> (def x (read-LangStr "[email protected]"))
> x
#lstr "[email protected]"
> (type x)
The read-LangStr function itself works fine in both clj and cljs. The tag always works in clj. However, under certain circumstances the cljs reader will barf on #lstr with this message:
Attempting to call unbound fn: #'ont-app.vocabulary.lstr/read-LangStr
As I understand it, this means that the cljs.reader/tag-table somehow registers the association between the tag and the function, but at some critical point in the compilation process, that function is pointing at a bunch of nothing. This problem arises when I try to write a test function in the vocabulary library that uses the tag directly. I can fix it if I use cljs.reader/read-string on the string equivalent. It also goes away when I read the tag in a test within in a module that uses the vocabulary library as a dependency. It also arises when I use say rhino-repl. Can someone help me wrap my head around what's going on here? Thanks.


you need to ensure that the ont-app.vocabulary.lstr namespace is loaded before whatever namespace that uses the reader tag


the CLJS compiler does not guarantee this by default

Eric Scott17:05:32

I'm including this namespace in the require section of the testing module, and requiring it in the repls. Is that not enough?


the requires are pulled in in order, so the one asking for the implementation of the tag must be before all the ones that use it


alternatively, you could require the implementation ns for the reader function in every ns that uses that tag

Eric Scott17:05:33

I thought I was doing that. My require within my test module contains [ont-app.vocabulary.lstr].

Eric Scott17:05:54

Is there a way in lein/cljsbuild to specify that the lstr module is fully loaded before evaluating the data_readers.cljc file?


clojure never does parallel loading


well, I guess you could do something weird and force it to, but it won't do it via normal require forms


the next require never happens until the previous succeeds


it’s hard for us to infer exactly what you mean by > my require within my test module the idea is that in your dependency graph, ont-app.vocabulary.lstr must be loaded before any code that uses it so if you do e.g.:

(ns module.a
  (:require [ont-app.vocabulary.lstr]
(ns module.b)

#lstr "foo"
you do not have a guarantee that module.b will be loaded after ont-app.vocabulary.lstr . your graph essentially looks like:


this directly contradicts what I thought I knew about require


do you have citation that there's some parallel path?


I didn’t mean to infer parallelization


it will be some order - but module.b will be loaded before module.a


what I mean is that require processes args in order, and to completion, so the args do impose ordering


yes, that's true... I must have misread


I was probably unclear


I didn’t know it was guaranteed to run in order


shadow-cljs does do parallel compilation IIRC


oh, I find that surprising


the clj version literally processes the clauses via doseq without any parallelization, and I am failing to find a precise source but I recall someone saying that parallel require was an unlikely feature


it’s different in CLJS because there’s two phases


oh, right - I don't know as much about cljs, and I can see how the phases (and the model of compiling namespaces "in isolation") would break assumptions that work in clj


because of course, if shadow-cljs supports hot-reloading, it will load an ns standalone and I can't make many assumptions about what other cljs code has been loaded in the context where that happens

Eric Scott17:05:10

No, the problem is happening here:

Eric Scott17:05:31

(ns ont-app.vocabulary.core-test
   [ont-app.vocabulary.lstr :as lstr]

Eric Scott17:05:00

(test yadda yadda #lstr "[email protected]")


that’s surprising

Eric Scott17:05:40

(read-string "#lstr \"[email protected]\"")]

Eric Scott17:05:40

where read-string is cljs.reader/read-string

Eric Scott17:05:44

So it appears that the tag-table that informs the execution env uses a tag table with fully resolved function, but the compiler of the source only knows about the mapping, but not the definition of the function.


@eric.d.scott Not sure if this helps, but if I'm understanding you, I've solved that problem in this example by using -i to cause the definitions to be available to the ClojureScript compiler before the compiler runs: (see the use of clj -i)

Eric Scott17:05:09

Am I correct in the impression that I'd need to switch from lein to deps to do this?


Perhaps there is a way to do the same with lein

Eric Scott17:05:54

Thanks @mfikes, I'll poke around a bit with this idea.


What's the meaning of this error?:

router.cljc:204 Uncaught Error: [object Promise] is not ISeqable
    at Object.cljs$core$seq [as seq] (core.cljs:1226)
    at re_frame$fx$do_fx_after (fx.cljc:74)
    at Object.re_frame$interceptor$invoke_interceptor_fn [as invoke_interceptor_fn] (interceptor.cljc:71)
    at Object.re_frame$interceptor$invoke_interceptors [as invoke_interceptors] (interceptor.cljc:109)
    at Object.re_frame$interceptor$execute [as execute] (interceptor.cljc:204)
    at Object.re_frame$events$handle [as handle] (events.cljc:65)
    at Object.eval [as re_frame$router$IEventQueue$_process_1st_event_in_queue$arity$1] (router.cljc:179)
    at Object.eval [as re_frame$router$IEventQueue$_run_queue$arity$1] (router.cljc:198)
    at eval (router.cljc:146)
    at Object.eval [as re_frame$router$IEventQueue$_fsm_trigger$arity$3] (router.cljc:169)


happening for these lines:

(let [create-token (.createToken stripe card-element)]
            (.then create-token
                   (fn [result]
                     (prn "result is" (.-token result)))))


I see you are using re-frame, if these lines are inside an event handler, for example, you are returning a Promise to re-frame


that could be the cause of the error


"Promise to re-frame". I don't understand what that means. How to fix the error?


the code you posted, is it inside a re-frame event handler?


you could return a {} and the error will probably go away

(let [create-token (.createToken stripe card-element)]
            (.then create-token
                   (fn [result]
                     (prn "result is" (.-token result))))
  {} ;; <- here


still giving me:

scheduler.development.js:108 Uncaught TypeError: lastCallbackNode is not a function
    at flushFirstCallback (scheduler.development.js:108)
    at flushWork (scheduler.development.js:220)
    at MessagePort.globalValue.port1.onmessage (scheduler.development.js:612)
flushFirstCallback @ scheduler.development.js:108
flushWork @ scheduler.development.js:220
globalValue.port1.onmessage @ scheduler.development.js:612


I think you put the {} as an argument to .then , didn’t you?


it should be the last expression of let


( re-frame.core/reg-event-fx 
( clojure.core/fn 
[ { :keys [ db ] } [ ___68384__auto__ stripe card-element ] ] ( prn "setting stripe token" ) ( let [ create-token ( .createToken stripe card-element ) ] ( prn "create token is " create-token ) ( .then create-token ( fn [ result ] ( prn "result is" ( .-token result ) ) ) ) {} ) ) )


alternatively you can return the same db or coeffects you received as parameters


that's not good obviously


the code you posted last still doesn’t work?


you are passing a Promise to something that expects a CLJS seq


.then expects a cljs seq?


any cljs collection. vector probably.


what does this error mean:

react-dom.development.js:11366 Uncaught TypeError: lastCallbackNode is not a function
    at flushFirstCallback (scheduler.development.js:108)
    at flushImmediateWork (scheduler.development.js:170)
    at exports.unstable_runWithPriority (scheduler.development.js:262)
    at runWithPriority$2 (react-dom.development.js:11306)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11350)
    at flushSyncCallbackQueue (react-dom.development.js:11339)
    at scheduleWork (react-dom.development.js:21432)
    at Object.enqueueForceUpdate (react-dom.development.js:13146)
    at cmp.Component.forceUpdate (react.development.js:354)
    at Object.reagent$impl$batching$run_queue [as run_queue] (batching.cljs:38)


you are passing something that is not a function to something that expects a function


how do I find which line this is happening?


reagent$impl$batching$run_queue so something you passed to reagent at some point I guess. if you use chrome you can use "pause on uncaught exception" and look at the value in lastCallbackNode. maybe that has a clue for what you passed.


@thheller that lands me to:

try {
    continuationCallback = callback();
  } finally {
    currentPriorityLevel = previousPriorityLevel;
    currentExpirationTime = previousExpirationTime;
in scheduler.development.js


I'm pretty sure the error is in my events.cljs, but not about which line


don't look at the code, that doesn't matter.


look at the variables on the side


what are the variables supposed to tell me and which ones do I look at?

Shako Farhad00:05:55

Remember that on-click properties of reagent components want an anonymous function. To make an anonymous function you need to do like this: :on-click #(my-function) OR :on-click (fn [] my-function)


yeah that's what I have in reality. Regular :div works but :>div needs re-focus or click in the browser


I have no clue. lastCallbackNode is the name you are looking for. sorry I can't really explain how to use the debugger in more detail. bottom line is that you are probably passing an incorrect value into something somewhere


can't help more than that, going to bed now. good luck 😛