Fork me on GitHub
#shadow-cljs
<
2022-11-01
>
pez14:11:29

What am I missing here? I have a file util.cljc :

(ns util
  #?(:clj (:refer-clojure :exclude [slurp]))
  #?(:cljs (:require-macros [util])))

#?(:clj
   (defmacro slurp [file]
     (clojure.core/slurp file)))
And a file parse.cljs:
(ns parse
  (:require [util :refer [slurp]]))

(comment
  (slurp "shadow-cljs.edn")
  )
Then I need to load parse.cljs twice to use the macro:
% npx shadow-cljs node-repl
shadow-cljs - config: /Users/pez/Projects/sass2garden/shadow-cljs.edn
shadow-cljs - updating dependencies
shadow-cljs - dependencies updated
[2022-11-01 15:10:18.802 - WARNING] TCP Port 9630 in use.
[2022-11-01 15:10:18.805 - WARNING] TCP Port 9631 in use.
shadow-cljs - server version: 2.20.7 running at 
shadow-cljs - nREPL server started on port 54616
cljs.user=> shadow-cljs - #4 ready!
(load-file "src/main/parse.cljs")
[]
cljs.user=> (in-ns 'parse) 
nil
parse=> (slurp "shadow-cljs.edn")

Execution error (TypeError) at (<cljs repl>:1).
Cannot read properties of undefined (reading 'call')
:repl/exception!
parse=> (load-file "src/main/parse.cljs")
[]
parse=> (slurp "shadow-cljs.edn")
";; shadow-cljs configuration\n{:source-paths\n [\"src/dev\"\n  \"src/main\"\n  \"src/test\"]\n\n :dependencies\n []\n\n :builds\n {}}\n"
parse=> 

localshred16:11:16

In clojurescript you have to require macros separately using :require-macros in the ns form https://clojurescript.org/guides/ns-forms#_macros

localshred16:11:10

You're using :require-macros in util ns but not in the parse ns. My guess is you just need to tweak that to use your slurp macro

pez16:11:43

Hmmm, since I am using :require-macros from util.cljc, things should be good, right? It's equivalent to, util.cljs:

(ns parse
  (:require [util :refer [slurp]]))

(comment
  (slurp "shadow-cljs.edn"))
+ util.clj:
(ns util
  (:refer-clojure :exclude [slurp]))

(defmacro slurp [file]
  (clojure.core/slurp file))
And I get the same strange behaviour if I do it like that. Loading parse.cljs twice makes it work.

thheller17:11:56

might be a bug. does (require 'parse) (parse/slurp ...) work?

pez19:11:36

I'll try the shadow.resource way. Doesn't matter much for my current use case, but seems like something that I should be using generally.

pez19:11:42

As for the macro problem. It is quite strange. I get different results with require, but it doesn't quite work as I expect.

cljs.user=> shadow-cljs - #4 ready!
(require 'parse) 
nil
cljs.user=> (parse/slurp "shadow-cljs.edn")
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:2
 Use of undeclared Var parse/slurp
--------------------------------------------------------------------------------

cljs.user=> (in-ns 'parse)
nil
parse=> (parse/slurp "shadow-cljs.edn")
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:2
 Use of undeclared Var parse/slurp
--------------------------------------------------------------------------------

parse=> (slurp "shadow-cljs.edn")
";; shadow-cljs configuration\n{:source-paths\n [\"src/dev\"\n  \"src/main\"\n  \"src/test\"]\n\n :dependencies\n []\n\n :builds\n {}}\n"

pez19:11:56

And trying with both qualified and non-qualified with load-file:

cljs.user=> shadow-cljs - #4 ready!
(load-file "src/main/parse.cljs")
[]
cljs.user=> (parse/slurp "shadow-cljs.edn")
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:2
 Use of undeclared Var parse/slurp
--------------------------------------------------------------------------------

cljs.user=> (in-ns 'parse)
nil
parse=> (parse/slurp "shadow-cljs.edn")
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:2
 Use of undeclared Var parse/slurp
--------------------------------------------------------------------------------

parse=> (slurp "shadow-cljs.edn")

Execution error (TypeError) at (<cljs repl>:1).
Cannot read properties of undefined (reading 'call')
:repl/exception!
parse=> (load-file "src/main/parse.cljs")
[]
parse=> (slurp "shadow-cljs.edn")
";; shadow-cljs configuration\n{:source-paths\n [\"src/dev\"\n  \"src/main\"\n  \"src/test\"]\n\n :dependencies\n []\n\n :builds\n {}}\n"

thheller20:11:39

could be that the REPL just forgets to load the macros

thheller20:11:01

too tired to check now. feel free to open an issue, so I don't forget to check

pez22:11:12

When writing the issue and trying to minimize it further, I notice that my repro with require was crap. It does work with require, it is with load-file it doesn't work. I also found out another interesting detail <- click-bait https://github.com/thheller/shadow-cljs/issues/1059

Raymond Ko18:11:14

If you are targeting a :node-library and have to use :js-provider :require (for mariadb since it has syntax the Closure compiler does not understand right now), is there anyway to get shadow-cljs to import a ESM module? I tried the "https://shadow-cljs.github.io/docs/UsersGuide.html#_dynamic_module_import" section in the User Guide, but I got ReferenceError: shadow_esm_import is not defined

thheller18:11:41

Currently only :target :esm adds the proper code to make that work

thheller18:11:13

maybe you can use :target :esm instead?

thheller18:11:23

I guess you can also sort of make it work by adding :prepend "global.shadow_esm_import = function(s) { return import(s); };" to your build config

Raymond Ko18:11:16

I tried it, but I would have to change a quite a few things since it is a big project and I'm doing non-standard things. Many errors.

Raymond Ko18:11:36

I'll try your suggestion

Raymond Ko20:11:59

That worked. I added it to :target-defaults :node-library :prepend . Thank you for your help.

alex21:11:41

Just upgraded to shadow-cljs 2.20.7 in both deps.edn and package.json. Tried to run a build report via

npx shadow-cljs run shadow.cljs.build-report client js-provider-import-report.html
and ran into the following error
File: /Users/alex/code/icebreaker/src/icebreaker/config.cljc
failed to require macro-ns "icebreaker.macros", it was required by "icebreaker.config"
Error in phase :execution

FileNotFoundException: Could not locate digest__init.class, digest.clj or digest.cljc on classpath.

thheller07:11:56

so it can't find the digest ns. This is a CLJ error, it is not from shadow-cljs. So I'm guessing you maybe don't have a deps.edn alias activated or something like that

thheller07:11:18

also note that :js-provider :import will cause shadow-cljs to not bundle any npm dependencies. so your build report will shrink, depending on how many you used. it'll only contain cljs code after that. don't get mislead by that. the build will only work if something else provides those dependencies, so be sure to compare the final size. not the build reports.

alex14:11:48

Thanks, I'll look into the alias stuff. Our aliases haven't changed recently so I wonder if there was an underlying CLJ change that is now incompatible with our current setup Also appreciate the tip with :js-provider :import - that makes sense

Drew Verlee23:11:00

I have cljs devtools installed with my shadow build > Installing CLJS DevTools 1.0.6 and enabling features :formatters :hints :async > But I still dont get the cljs encoded/formatted structures when i do console log. Any idea's on what i can try to get it to work?

MegaMatt15:11:32

have you enabled this?