This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-20
Channels
- # announcements (1)
- # architecture (14)
- # asami (21)
- # babashka (1)
- # beginners (44)
- # biff (6)
- # calva (24)
- # clojure (16)
- # clojure-europe (12)
- # clojurescript (32)
- # cursive (23)
- # datascript (5)
- # honeysql (8)
- # hyperfiddle (1)
- # malli (1)
- # nextjournal (34)
- # nrepl (4)
- # off-topic (64)
- # re-frame (12)
- # reagent (1)
- # releases (2)
- # reveal (41)
- # shadow-cljs (137)
- # spacemacs (4)
- # xtdb (5)
I’ve run into a bug (quite some months back) with macros in self-host where syntax-quoted symbols aren’t always expanded. Found some time today… I came across this bit here where we build up an alias-map and bind that to reader/**alias-map*
,* but then override `reader/resolve-symbol` to ana/resolve-symbol
which doesn’t appear to have access to those aliases directly (though the analyzer is building up aliases in its own way, i presume) https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/compiler.clj#L312
there is a repro here: https://github.com/mhuebert/shadow-bootstrap-example/blob/shadow-syntax-quote/src/shadow_eval/core.cljs#L16
now, weirdly, this only happens if there is both a macros.cljs
and macros.cljc
file. if I delete the .cljs
file and use only .cljc
with the self-require there, the symbol expands as expected.
maybe it’s because with the cljs
file present, in the first “pass” there are no :require
’s found by the analyzer
whereas with a self-requiring cljc
file, it finds the sub-macros
namespace on the first (non-macros) pass
so I guess that is my theory, that the read-loop in shadow’s compiler builds up an alias map which is not visible to the analyzer namespace, but is required for syntax-quote expansion. however sometimes it “works anyway” if the analyzer has already “seen” the same namespace in a prior pass, and the namespace-alias was also visible to that pass.
does this include the .cljs
file or the .cljc
file? it is technically speaking in a :cljs
branch of the .cljc
file but loading in CLJ mode since it is a macro
If it's not behind a reader conditional then I'd expect it to load / be a available in all passes
Something related to this behaviour changed several months ago (or more) and I haven't been able to update Maria.cloud’s dependencies since then because it breaks a lot of macros
Eg Reagent.core/with-let used to work but doesn't anymore because it uses an ns alias in a macro to delegate to a macro in another namespace
In this case I know that shadows compile loop is aware of the alias from logging at that point
The code is compiled and available, it's just the syntax quote expansion that doesn't work
as far as I can tell you are in undefined territory and macros cannot be included this way
so if I diagnose this correctly the problem is that requires in CLJ files are not followed
ie. add
(ns bootstrap-test.macros
(:require-macros bootstrap-test.macros)
(:require [bootstrap-test.sub-macros]))
self-host is mind bending enough already, if you add CLJC to the mix it all becomes even worse
But isn't it the case that these requires are being followed? Because it works if I change the symbol to be fully qualified. It is only the read phase where the syntax quote doesn't work
And it seems weird to be building up a map of ns-aliases but then overriding resolve-sym so that it can't see them
They are bound in the reader ns, not ana?Ana is only seeing stuff from previous passes? If I log the ns-aliases I see one for sub
but that's not being seen or used by ana/resolve-symbol
I can log there that we encounter a syntax quote sub/wrap
symbol, sub is found in ns-aliases but resolve-symbol doesn't find it
bootstrap-test.macros
does a self :require-macros but in a cljs file separate from the cljc file
but isn't this because it is self-host compiling with this reference context.
(ns bootstrap-test.macros
(:require-macros bootstrap-test.macros))
so there is no sub alias?IIRC I thought these issues were shadow specific, couldn't repro in the cljs test suite
yeah, so it’s not related to cljc - if i rename that to clj, same error https://github.com/mhuebert/shadow-bootstrap-example/commit/6ec1810758357011acf85b59750fc682d1a03825
but to me this all looks like it is working as intended? this issue with using fully qualified names for macros has been there since forever (and even exists in non-self-hosted code)
something definitely changed with this several months ago though because this broke a bunch of things with Maria
that is possible since I added support for :as-alias
a couple months ago. maybe that messed something up?
i know there are many cases where one needs to use fully qualified symbols in macros but this I think is different - these are symbols for macros, from macro namespaces that are required by a macro namespace. eg https://github.com/reagent-project/reagent/blob/master/src/reagent/core.clj#L10 this works as expected
of course one has always had to use fully qualified namespaces for stuff that is calling at runtime
but this makes me think, maybe im wrong about the main issue being syntax quote expansion
is this do-analyze-cljs-string
supposed to expand macros https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/compiler.clj#L278
this is expanding macros https://github.com/thheller/shadow-cljs/blob/9b1f5295db8458d5d06890b4761e1ecf71c3a7a0/src/main/shadow/build/compiler.clj#L264
ach now i remember how hard it was to bisect this, i can’t even run the old version anymore because of java incompatibilities
[:failed-to-compare "^1.2.0" "1.2.2" #error {
:cause "Cannot invoke \"Object.getClass()\" because \"target\" is null"
:via
[{:type java.lang.NullPointerException
:message "Cannot invoke \"Object.getClass()\" because \"target\" is null"
:at [clojure.lang.Reflector invokeInstanceMethod "Reflector.java" 97]}]
well, looks like reagent has other reasons why its not selfhost-compatible so that’s not a good goal. I will see again how many macros broke that we were actually using in maria
so as far as I can tell your repro also breaks in 2.8.36, so this issue isn't the one affecting maria I guess?
well I apologize for this rabbit trail. When I made those original repro’s I think I assumed that since shadow and cljs appeared to diverge here it was also a bug that was probably contributing. However, I’ve finally fixed all the other things that had broken in the meantime and all our curriculum runs fine without any changes needed to this macro-syntax-quote stuff.
I think I have still run into this issue elsewhere when trying to write selfhost-compatible macros. But I’ve mostly given up on that because it’s so hard.
I did verify that a :refer in a .cljs
file makes an alias available during the macro pass of a .cljc
file - as you described above
I found requiring Hero Icons like this also includes the Hero icons not referred:
(:require ["@heroicons/react/solid" :refer [CheckIcon ChatIcon]])
While the following does not:
(:require ["@heroicons/react/solid/CheckIcon" :as CheckIcon]
["@heroicons/react/solid/ChatIcon" :as ChatIcon])
Is there any way to require without repeating "@heroicons/react/solid"
over and over?
I tried with:
(:require ["@heroicons/react/solid" ["CheckIcon" :as CheckIcon]
["ChatIcon" :as ChatIcon]])
Which causes: Invalid namespace declaration
Is it something that is impossible to do with how such things work or is it just something not important enough to get any attention?
changing :require
to allow the nested stuff is not an option since that would break compatibility with standard CLJS
changing that :refer
only actually imports what was referred is a substantial amount of work, which I simply don't have time for currently. it is also non-standard behavior and basically something webpack invented.
Thanks for the insight. I'm just curious 😄
JS tooling is something I've successfully managed to dodge for a very long time... exactly because examples like "non-standard behavior and basically something webpack invented".
Hey thheller - general question for you. Is it possible to read the metadata for clojurescript functions from build hooks (which are in clojure)? Or is it generally possible to parse the namespace and get publics ~ trying to figure out the best way to inspect a clojurescript file from the build and determine some general information about it
[:compiler-env :cljs.analyzer/namespaces 'your.ns :defs 'foo :meta]
in the build state
Hello, I'm getting an error in a release build (works in dev mode): $.clearTimeout is not a function
the corresponding call is here:
goog.functions.debounce = function(f, interval, opt_scope) {
'use strict';
let timeout = 0;
return /** @type {function(...?)} */ (function(var_args) {
'use strict';
goog.global.clearTimeout(timeout);
const args = arguments;
timeout = goog.global.setTimeout(function() {
'use strict';
f.apply(opt_scope, args);
}, interval);
});
};
I'm using npx shadow-cljs release main --debug
for :target = :browser
my deps.edn is:
{:paths ["src/main" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
com.fulcrologic/fulcro {:mvn/version "3.5.9"}}
:aliases {:dev {:extra-paths ["src/dev"]
:extra-deps {org.clojure/clojurescript {:mvn/version "1.10.914"}
thheller/shadow-cljs {:mvn/version "2.16.9"}
binaryage/devtools {:mvn/version "1.0.4"}
cider/cider-nrepl {:mvn/version "0.27.4"}}}}}
I pulled it from the fulcro guide
it's webpack-ed though
I'll try to release a version without webpack
isn't it a good practive?
I mean does it have a reason you are doing it? is there something missing otherwise?
I thought it would reduce the loading times
I need the bundle at least for css files though, is that fine?
why not?
I mean you can run webpack separately. that is fine as long as it doesn't try to process the shadow-cljs output
yeah, it should be fine just for css then
I'd like to avoid having to manually add copy css files from node_modules/ to my public directory]
Hi there! I'm trying to import a npm dependency, and I'm getting the error IllegalArgumentException No matching field found: getAbsolutePath for class clojure.lang.PersistentHashMap
. I know it's probably an error with the way I'm importing the lib, but is there something else I can do to debug this issue?
@mauricio.szabo which npm dependency would this be? you can also provide the full stacktrace and shadow-cljs version please. that would already telling me about 95% of what I need to know
It's the monaco-editor,
the full require is ["monaco-editor/esm/vs/editor/editor.api" :as monaco]
.
This is the stacktrace on the shadow-cljs console:
IllegalArgumentException No matching field found: getAbsolutePath for class clojure.lang.PersistentHashMap
clojure.lang.Reflector.getInstanceField (Reflector.java:397)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:440)
shadow.cljs.devtools.errors/fn--13467 (errors.clj:228)
shadow.cljs.devtools.errors/fn--13467 (errors.clj:222)
clojure.lang.MultiFn.invoke (MultiFn.java:239)
shadow.cljs.devtools.errors/error-format (errors.clj:449)
shadow.cljs.devtools.errors/error-format (errors.clj:440)
shadow.cljs.devtools.errors/error-format (errors.clj:443)
shadow.cljs.devtools.errors/error-format (errors.clj:440)
shadow.cljs.devtools.server.worker.impl/build-failure/fn--14276 (impl.clj:133)
shadow.cljs.devtools.server.worker.impl/build-failure (impl.clj:132)
shadow.cljs.devtools.server.worker.impl/build-failure (impl.clj:128)
Is an import
from a css
file even valid? Why does Monaco is trying to import it?
@U05224H0W is there a way to ignore these CSS files when I compile my code with Shadow-CLJS?
what's the best way to import css files from node_modules into the shadow-cljs build in the browser? I tried webpack but it's not working
have you looked into postcss? I'm currently using tailwind with postcss, and importing tailiwind CSS modules directly from node_modules.
Thanks for your answer. Does it also import other assets (like fonts) like react does natively?
It's been a while since I touched anything front-end related, and I've never before worked with Tailwind. Also, it's been a long time since I used postcss. I'm sorry I can't give you a detailed answer. afaik tailwind has its own way of dealing with fonts. https://tailwindcss.com/docs/font-family and postcss has plugins https://www.postcss.parts/tag/fonts?searchTerm=font