This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-04
Channels
- # aleph (2)
- # beginners (80)
- # boot (18)
- # cider (6)
- # cljs-dev (14)
- # cljsrn (5)
- # clojure (114)
- # clojure-android (5)
- # clojure-dev (8)
- # clojure-greece (6)
- # clojure-italy (9)
- # clojure-russia (108)
- # clojure-uk (82)
- # clojurescript (158)
- # css (1)
- # cursive (21)
- # data-science (1)
- # datomic (66)
- # emacs (9)
- # ethereum (3)
- # fulcro (26)
- # graphql (7)
- # hoplon (25)
- # juxt (2)
- # keechma (34)
- # lein-figwheel (4)
- # leiningen (2)
- # off-topic (4)
- # om (5)
- # onyx (14)
- # parinfer (2)
- # pedestal (17)
- # planck (3)
- # portkey (14)
- # re-frame (23)
- # reagent (12)
- # ring (8)
- # rum (1)
- # shadow-cljs (506)
- # spacemacs (2)
- # vim (11)
- # yada (6)
@mhuebert do you know if the CLJS compiler will read macro files with :clj
or :cljs
conditionals?
you do have 4 seperate react
versions in your page at https://www.maria.cloud/intro
@thheller :-). I don't mind at all. I noticed the duplicates a couple days ago and was one reason why I was trying to switch to your js system. (The duplicates between the two frames is another story though. One frame has to be advanced compiled, the other can't be, and they load from different domains for security reasons. I would need to load React separately, from the same domain in both frames, & only once. The only way I know how to do that is deps.clj with an empty js file 'providing' react with a :global-exports option. I have encountered so many troubles with this stuff)
yeah not saying that my stuff would fix all your issues, just that :foreign-libs
is bad š
I believe that if we AOT compile macros then it must take the :clj branch because it is java doing the compiling, but if you run macros from self-host it takes the :cljs branch
but at least in my version you can tell the compiler :js-options {:resolve {"react" {:target :global :global "React"}}}
in config š
@thheller: that is exactly what I want to be able to specify with one of these fake empty js files
Plus it is a huge pain now that cljs will just magically decide whether to take my js from what i specify in deps.clj or go read from node_modules
(ns demo.selfhost
(:require [cljs.js :as self]))
(defn compile-it []
(js/console.log
(self/compile-str
(self/empty-state)
"(ns my.user) (map inc [1 2 3])"
""
{:eval self/js-eval}
identity)))
only weird thing I need to figure out is loading order since cljs.js
has this weird hack for goog.require
my current thinking is to do a normal compile for your ābuildā, then do a second pass that just adds everything you want for self host
{:build-id :selfhost
:target :browser
:output-dir "out/demo-selfhost/public/js"
:asset-path "/js"
:build-options
{:self-host
{:module :base
:macros [cljs.core
cljs.spec.alpha]}}
:modules
{:base
{:entries [demo.selfhost]}}}
problem I have currently is that cljs.js
does not really require cljs.core$macros
when loading
Yes, there is just one network request per bundle, organized as json file with classpath-like 'paths' as keys
Eg with Maria I want things to load on-demand because otherwise start time is too slow
ie. the goog loader will ensure that the deps were actually loaded BEFORE loading the actual file
is it just a normal build and then a bunch of tooling to provide the self-host things you need?
say if I just modify shadow-cljs
to properly compile macro namespaces you could work with that?
here is my cljs-live config where i package stuff to use for self-host: https://github.com/mhuebert/maria/blob/master/editor/live-deps.clj#L8
so, if you added this ability to AOT compile macros, I would (attempt to) modify cljs-live to use shadow-cljs, and it would remove one step (manually doing a 2nd pass with self-host compiler).
so what I can do for you: a) compile a list of macro namespaces, dump them in a location of your choosing
re: dependencies, that would relate to this problem: https://github.com/braintripping/cljs-live/blob/master/src/cljs_live/compiler.cljs#L15
the compile process in shadow-cljs is quite different so I actually donāt know how the cljs compiler does it š
ie. if you want to compile-str (ns my.demo (:require [something.foo :as x]))
but something.foo
is not yet loaded. what happens?
mine is here: https://github.com/braintripping/cljs-live/blob/master/src/cljs_live/compiler.cljs#L93
cljs-live bundles include a āname-to-pathā key which maps namespaces to file-paths
there is the readme but i am not sure it goes into that level of detail: https://github.com/braintripping/cljs-live
so i think load-fn
is always called when you (require) something. it is up to load-fn
to (a) know if it has already been loaded or not, and if not, (b) provide a source file and analysis cache. the source file can be compiled js or uncompiled clj*
load-fn
gets namespaces as input and must map that to source. so we need to know which names map to which āfilesā
and an important thing, certainly in my case but I think generally, is that these secondary builds, you might want to have a number of them and be able to load them independently / at a time of your choosing. Because they are quite large. cljs.core
analysis cache + cljs.core$macros
w/ cache is 900kb. the maria bundle is 1.5mb, clojure spec + deps is 1.8mb
it is important that the self-host compiler / bootstrap loader does not re-evaluate stuff that was already loaded by the āappā build
@mhuebert so far I create a ābootstrap.index.jsonā (transit) which contains infos like this
{:type :cljs,
:provides #{cljs.compiler},
:requires
#{cljs.tools.reader goog.string cljs.core goog cljs.env
goog.string.StringBuffer clojure.set cljs.analyzer cljs.source-map
clojure.string},
:resource-name "cljs/compiler.cljc",
:output-name "cljs.compiler.js"}
{:type :cljs,
:provides #{cljs.core$macros},
:requires
#{cljs.compiler cljs.core cljs.env clojure.set cljs.analyzer
clojure.string clojure.walk},
:resource-name "cljs/core$macros.cljc",
:output-name "cljs.core$macros.js"}
{:type :cljs,
:provides #{cljs.analyzer.api},
:requires #{cljs.core goog cljs.env cljs.analyzer},
:resource-name "cljs/analyzer/api.cljc",
:output-name "cljs.analyzer.api.js"}
{:type :cljs,
:provides #{cljs.spec.gen.alpha},
:requires #{cljs.core goog},
:resource-name "cljs/spec/gen/alpha.cljs",
:output-name "cljs.spec.gen.alpha.js"}
{:type :cljs,
:provides #{cljs.spec.alpha$macros},
:requires
#{cljs.core goog cljs.analyzer.api cljs.env cljs.analyzer
clojure.string clojure.walk cljs.spec.gen.alpha},
:resource-name "cljs/spec/alpha$macros.cljc",
:output-name "cljs.spec.alpha$macros.js"}
the idea is to load this index on startup, build a runtime index out of the :requires/:provides
then either load the compiled :output-name files in :load
or the :resource-name
file and compile that
'{:build-id :selfhost
:target :browser
:output-dir "out/demo-selfhost/public/js"
:asset-path "/js"
:bootstrap-options
{:entries []
:macros [cljs.spec.alpha]}
:modules
{:base
{:entries [demo.selfhost]}}}
does it follow macro dependencies? ie. if you require namespace x
which requires x$macros
not sure if it needs to pre-compile everything or just use :entries
to copy the requires sources so cljs.js
can compile it
compiling is super slow in the browser, if things arenāt precompiled it can be multiple-second wait times
I think I have the basics now, Iāll try to put together something that actually works
i remember encountering subtle issues with macros. normally if i wanted to use a namespace, i wanted to include the macros it uses as well. but some macros are not self-host compatible, so i added :entry/exclude and :entry/no-follow.
in your example - we specify explicitly which macro namespaces we want, and then shadow would ensure that those macro namespaces & their dependencies are loaded
(ns demo.selfhost
(:require [cljs.js :as cljs]
[shadow.bootstrap :as boot]))
(boot/init
(fn []
(cljs/compile-str
(cljs/empty-state)
"(ns my.user) (map inc [1 2 3])"
""
{:eval cljs/js-eval
:load boot/load}
identity)))
would it be reasonable to ask that the original source + compiled source are both copied into this dir
my own use case is source lookups from the editor. but since bootstrap is used commonly for tooling i probably wouldnāt be the only one
i am liking this a lot. for Maria I could put one big long list of things into :bootstrap-options
and the only constant cost is a larger bootstrap.index.json
. then users can require any of those namespaces and they will be loaded on demand.
is it necessary for the app that runs shadow.bootstrap/init
(& /load
) to be compiled together with all the stuff in :bootstrap-options
, or could it āconsumeā any bootstrap.index.json
file, provided with a prefix path of where to load the files from?
and the app that uses bootstrap/init or bootstrap/load knowing what has already been loaded (by itself)
[zilence@zpro ~/code/shadow-cljs/out/demo-selfhost/public/js/bootstrap]$ find .
.
./ana
./ana/cljs.analyzer.api.cljc.ana.transit.json
./ana/cljs.analyzer.cljc.ana.transit.json
./ana/cljs.compiler.cljc.ana.transit.json
./ana/cljs.core$macros.cljc.ana.transit.json
./ana/cljs.core.cljs.ana.transit.json
./ana/cljs.env.cljc.ana.transit.json
./ana/cljs.reader.cljs.ana.transit.json
./ana/cljs.source_map.base64.cljs.ana.transit.json
./ana/cljs.source_map.base64_vlq.cljs.ana.transit.json
./ana/cljs.source_map.cljs.ana.transit.json
./ana/cljs.spec.alpha$macros.cljc.ana.transit.json
./ana/cljs.spec.gen.alpha.cljs.ana.transit.json
./ana/cljs.tagged_literals.cljc.ana.transit.json
./ana/cljs.tools.reader.cljs.ana.transit.json
./ana/cljs.tools.reader.edn.cljs.ana.transit.json
./ana/cljs.tools.reader.impl.commons.cljs.ana.transit.json
./ana/cljs.tools.reader.impl.errors.cljs.ana.transit.json
./ana/cljs.tools.reader.impl.inspect.cljs.ana.transit.json
./ana/cljs.tools.reader.impl.utils.cljs.ana.transit.json
./ana/cljs.tools.reader.reader_types.cljs.ana.transit.json
./ana/clojure.set.cljs.ana.transit.json
./ana/clojure.string.cljs.ana.transit.json
./ana/clojure.walk.cljs.ana.transit.json
./index.transit.json
./js
./js/cljs.analyzer.api.js
./js/cljs.analyzer.js
./js/cljs.compiler.js
./js/cljs.core$macros.js
./js/cljs.core.js
./js/cljs.env.js
./js/cljs.reader.js
./js/cljs.source_map.base64.js
./js/cljs.source_map.base64_vlq.js
./js/cljs.source_map.js
./js/cljs.spec.alpha$macros.js
./js/cljs.spec.gen.alpha.js
./js/cljs.tagged_literals.js
./js/cljs.tools.reader.edn.js
./js/cljs.tools.reader.impl.commons.js
./js/cljs.tools.reader.impl.errors.js
./js/cljs.tools.reader.impl.inspect.js
./js/cljs.tools.reader.impl.utils.js
./js/cljs.tools.reader.js
./js/cljs.tools.reader.reader_types.js
./js/clojure.set.js
./js/clojure.string.js
./js/clojure.walk.js
./js/goog.array.array.js
./js/goog.asserts.asserts.js
./js/goog.base.js
./js/goog.debug.error.js
./js/goog.dom.nodetype.js
./js/goog.functions.functions.js
./js/goog.iter.iter.js
./js/goog.math.integer.js
./js/goog.math.long.js
./js/goog.math.math.js
./js/goog.object.object.js
./js/goog.reflect.reflect.js
./js/goog.string.string.js
./js/goog.string.stringbuffer.js
./js/goog.structs.map.js
./js/goog.structs.structs.js
./js/goog.uri.uri.js
./js/goog.uri.utils.js
./src
./src/cljs.analyzer.api.cljc
./src/cljs.analyzer.cljc
./src/cljs.compiler.cljc
./src/cljs.core$macros.cljc
./src/cljs.core.cljs
./src/cljs.env.cljc
./src/cljs.reader.cljs
./src/cljs.source_map.base64.cljs
./src/cljs.source_map.base64_vlq.cljs
./src/cljs.source_map.cljs
./src/cljs.spec.alpha$macros.cljc
./src/cljs.spec.gen.alpha.cljs
./src/cljs.tagged_literals.cljc
./src/cljs.tools.reader.cljs
./src/cljs.tools.reader.edn.cljs
./src/cljs.tools.reader.impl.commons.cljs
./src/cljs.tools.reader.impl.errors.cljs
./src/cljs.tools.reader.impl.inspect.cljs
./src/cljs.tools.reader.impl.utils.cljs
./src/cljs.tools.reader.reader_types.cljs
./src/clojure.set.cljs
./src/clojure.string.cljs
./src/clojure.walk.cljs
./src/goog.array.array.js
./src/goog.asserts.asserts.js
./src/goog.base.js
./src/goog.debug.error.js
./src/goog.dom.nodetype.js
./src/goog.functions.functions.js
./src/goog.iter.iter.js
./src/goog.math.integer.js
./src/goog.math.long.js
./src/goog.math.math.js
./src/goog.object.object.js
./src/goog.reflect.reflect.js
./src/goog.string.string.js
./src/goog.string.stringbuffer.js
./src/goog.structs.map.js
./src/goog.structs.structs.js
./src/goog.uri.uri.js
./src/goog.uri.utils.js
well, you get the idea /src
are the actual sources. /js
is the compiled code, /ana
is analyzer data
so if you app is in /js/foo.js
the index will be in /js/bootstrap/index.transit.json
eg. say you include quil.core
under :bootstrap-options :entries, but you donāt have quil.core
in your app itself
and then quil.core
requires some goog namespaces that arenāt required anywhere else in your app
the nice thing if you include everything is that this becomes decoupled from the app
it might have issues already since shadow-cljs may sometimes compile things slightly different
ok. IIRC the cljs.analyzer/parse-ns
didnāt follow macro dependencies (because it was never including them in cljs builds) so i had to make my own modified version for that.
woho twbs/bootstrap
should finally become usuable https://github.com/twbs/bootstrap/issues/24167 š
if you want to try master
the new :bootstrap-options
config entry controls everything
it does not yet properly follow the macros so it will only compile the macros you specify
shadow.bootstrap.loaded-libs
is an atom
which is a set of symbols matching all goog.provide
d names that have been loaded
noob question, iāve been using shadow-cljs via npm, what would the simplest way to run master be?
INFO: duplicate resource cljs/js.cljs on classpath, using jar:file:/Users/MattPro/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/js.cljs over jar:file:/Users/MattPro/.m2/repository/thheller/shadow-cljs/2.0.7/shadow-cljs-2.0.7.jar!/cljs/js.cljs
now, The required namespace "react" is not available, it was required by "re_view/render_loop.cljs".
this still throws from cljs.js:
live.js:680 goog.require could not find: cljs.core$macros
goog.logToConsole_ @ live.js:680
live.js:714 Uncaught Error: goog.require could not find: cljs.core$macros
at Object.goog.require (live.js:714)
at cljs.js.js:15
is there a way to prefer shadowās copy over clojureās? (it would appear that shadowās is being ignored?)
thats why I put mine there but forgot that .jar loading rules load clojurescript before shadow-cljs so that version wins over mine
if I have this in shadow-cljs.edn:
:js-options {:resolve {"react" {:target :global
:global "React"}
"react-dom" {:target :global
:global "ReactDOM"}
"codemirror" {:target :global
:global "CodeMirror"}}}
then should i be able to just put react, react-dom and codemirror in separate script tags and (:require [codemirror :as CM])
?i prefer it, i am just trying to get something that can work with both shadow-cljs and cljsbuild
Uncaught TypeError: Cannot read property 'provide' of undefined
in `shadow.js.provide(āmodule$codemirrorā, function(require,module,exports) {
module.exports=(CodeMirror);
});`
:modules {:main {:entries [shadow.js your.ns]}}
should ensure its loaded before the codemirror include
I struggle with my test-build specifically chosen for this without any other stuff going on š
ok, one last thing. one of my dependencies (which i control) has a javascript file that i want to include. currently i do that via deps.cljs/foreign-lib. any idea how i can get that to work?
in the future it will just be (:require ["/path/to/file" :as x])
with relative path support
currently its (:require ["some-name" :as x])
and then in :resolve {"some-name" {:target :file :file "path/to/file.js"}}
being able to include arbitrary js file x
as a dep is something iāve done a few times
the JS deps stuff is all based on files, since npm uses all files and doesnāt have a classpath
i have a prosemirror package which has cljs code which is an interface on top of a slew of ProseMirror stuff which i have bundled up with webpack
so I have a deps.cljs:
{:foreign-libs [{:file "js/pm.pack.js"
:provides ["pack.prosemirror"]}
{:file "js/pmMarkdown.pack.js"
:requires ["pack.prosemirror" "cljsjs.markdown-it"]
:provides ["pack.prosemirror-markdown"]}]
:npm-deps {:prosemirror-markdown "^0.22.0"}}
now at some point I can get rid of the in-between step and just require this stuff directly from npm, however, i havenāt yet & am fairly certain that at least the non-shadow cljs stuff canāt support all the modules required by prosemirror
https://github.com/braintripping/re-view/blob/master/re_view_prosemirror/webpack.config.js
the file is just a bunch of es6 exports:
export {EditorView, Decoration, DecorationSet} from "prosemirror-view"
export {EditorState, Selection, SelectionRange, TextSelection, NodeSelection, AllSelection, Transaction, Plugin, PluginKey} from "prosemirror-state"
export {keymap} from "prosemirror-keymap"
export {findWrapping, liftTarget, canSplit, canJoin, ReplaceAroundStep, ReplaceStep} from "prosemirror-transform"
export {wrapInList, splitListItem, liftListItem, sinkListItem} from "prosemirror-schema-list"
export {InputRule, wrappingInputRule, textblockTypeInputRule, inputRules, undoInputRule, allInputRules} from "prosemirror-inputrules"
export {Schema, Node, Mark, ResolvedPos, NodeRange, Fragment, Slice, MarkType, NodeType} from "prosemirror-model"
import * as commandsObj from "prosemirror-commands"
export const commands = commandsObj;
import * as historyObj from "prosemirror-history"
export const history = historyObj;
import * as modelObj from "prosemirror-model"
export const model = modelObj;
itās just a lot to rewrite right now š. maybe i can just manually copy the compiled files and link with script tags for now
(:require ["prosemirror-transform" :refer (findWrapping, liftTarget, canSplit, canJoin, ReplaceAroundStep, ReplaceStep)])
I just had to create a namespace like so:
(ns shadow-init.init
(:require shadow.js
shadow.bootstrap))
by not including the macros in the build, itās ~900kb lighter. of course we have to load that anyway, but that can happen after the page is visible & first things have started to work.
it could be smarter and collect everything it needs to load by looking at the index data
maybe with http2 it is not a big deal to be fetching each dependency independently, since we have the index and can fetch all transitive deps in parallel.
a naĆÆve load-fn loads each dep, parses requires, then loads the next, takes forever
(defonce
^{:doc "Each runtime environment provides a different way to load a library.
Whatever function *load-fn* is bound to will be passed two arguments - a
map and a callback function: The map will have the following keys:
:name - the name of the library (a symbol)
:macros - modifier signaling a macros namespace load
:path - munged relative library path (a string)
It is up to the implementor to correctly resolve the corresponding .cljs,
.cljc, or .js resource (the order must be respected). If :macros is true
resolution should only consider .clj or .cljc resources (the order must be
respected). Upon resolution the callback should be invoked with a map
containing the following keys:
:lang - the language, :clj or :js
:source - the source of the library (a string)
:file - optional, the file path, it will be added to AST's :file keyword
(but not in :meta)
:cache - optional, if a :clj namespace has been precompiled to :js, can
give an analysis cache for faster loads.
:source-map - optional, if a :clj namespace has been precompiled to :js, can
give a V3 source map JSON
If the resource could not be resolved, the callback should be invoked with
nil."
:dynamic true}
*load-fn*
(fn [m cb]
(throw (js/Error. "No *load-fn* set"))))
load-fn should load the source of something, parse it to load the deps, then load all deps (recursively), then finally call the callback
ah wait .. if you have the source I suppose you can call eval-str
which will call back into the load-fn
Iām so glad that everything is sync in shadow-cljs, doing stuff like this async hurts my brain
the append-source-map
function includes the original source along with the source map, which all needs to be encoded/decoded/shipped. i have source-maps disabled for cljs-live, if we enable them here it would be worth seeing what the effect on speed and file size is with the source file left out
so, I think in that case load-fn does not have to parse deps, it can just return the thing for itself, but will then be called repeatedly as more calls to require() are evaluated in the source
you just return that map, then cljs takes it from there. a file wonāt actually be evaluated until its deps have been.
yeah there is absolutely no urgency on source maps, just wanted to mention that small thing
(defn compile-it []
(cljs/compile-str
boot/compile-state-ref
"(ns my.user (:require [reagent.core :as r])) (map inc [1 2 3])"
""
{:eval cljs/js-eval
:load boot/load}
print-result))
that part is a bit of a hack:
(cond-> bundle
(or (string/starts-with? v "goog")
(string/starts-with? k "goog")
(and (string/ends-with? k ".js")
;; for a JS file, see if a goog.provide statement shows up
;; in teh first 300 characters.
(some-> v (> (.indexOf (subs v 0 300) "goog.provide") -1))))
;;
;; parse google provide statements to enable dependency resolution
;; for arbitrary google closure modules.
;; this is a slow operation so we don't want to do it on all files.
(update "name-to-path" merge (let [provides (parse-goog-provides v)]
(when (empty? provides)
(log k ": " provides "\n"))
(apply hash-map (interleave provides (repeat k))))))
that parsing of goog.provide
statements happens just when i download/load a ābundleā, nothing is evalād there yet
š the bright side is that these problems are far__ better solved with full access to the build/compile system, eg. shadow, than trying to peck at it from the outside like cljs-live
(defn load [{:keys [name path macros] :as rc} cb]
;; check index build by init
;; find all dependencies
;; load js and ana data via xhr
;; maybe eval?
;; call cb
;; FIXME: needs to ensure that deps are loaded first
(go (let [ana (<! (load-analyzer-data name))
js (<! (load-js name))]
(js/console.log "boot/load" name macros ana (count js))
(cb {:lang :js :source js :cache ana}))
))
i put this in for :eval
during debugging:
(fn [{:keys [source cache lang name]}]
(println "Eval" {:name name
:lang lang
:cache (some-> cache (str) (subs 0 20))
:source (some-> source (subs 0 150))})
(js/eval source))
(defn compile-it []
(cljs/compile-str
boot/compile-state-ref
"(ns my.user (:require [reagent.core :as r])) (map inc [1 2 3])"
""
{:eval
(fn [{:keys [source cache lang name]}]
(js/console.log "Eval" name lang {:cache (some-> cache (str) (subs 0 20))
:source (some-> source (subs 0 150))})
(js/eval source))
:load boot/load}
print-result))
The required namespace "react" is not available, it was required by "reagent/core.cljs".
ok. would be great if that error message could indicate if the missing thing is a javascript namespace
https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/js.cljs#L427-L482
:macros
is true, but we keep returning reagent.core, which then requests reagent.core$macros again?
but now it tries to load cljs.core
endlessly. damn I wish I could just say āits taken care of, just continue compilationā
maybe this gets into the thing, where we need to know which namespaces are loaded in the app__, ie. javascript exists on the window.namespace.variable, and return a blank map for those
true strife awaits those who eval an existing namespace twice. more than one late night because of that.
(defn set-loaded [namespaces]
(let [loaded (into #{} (map symbol) namespaces)]
(swap! loaded-ref set/union loaded)
(swap! cljs/*loaded* set/union loaded)))
which canāt work since I do something totally different than what the self-host compiler knows and expects
itās so great that you can change build settings and not have to restart the build tool
silent loading, when you have full knowledge of the deps tree, I think should be the path forward for all types once we get the basics working
so eg. the call to :load-fn with reagent.core
will result in calculating all the transitive deps, downloading in parallel, evalāing + putting into analysis cache, then returning; or, calculating + downloading all transitive deps, put in cache somewhere, then return to cljs, which will then recurse the :load-fn through all the transitive deps, but not downloading them sequentially
in the shadow-cljs bootstrap demo, there were also :ns errors because the macros ns wasnāt being loaded in init
, I tried adding that:
(let [idx (build-index data)
ana-core (<! (load-analyzer-data 'cljs.core))
ana-core$macros (<! (load-analyzer-data 'cljs.core$macros))]
(cljs/load-analysis-cache! compile-state-ref 'cljs.core ana-core)
(cljs/load-analysis-cache! compile-state-ref 'cljs.core$macros ana-core$macros)
(js/eval (<! (load-macro-js 'cljs.core$macros)))
(init-cb)
)
then I remembered that the first thing we do in Maria, before evaluating anything, is run `(require ā[cljs.core :include-macros true]). Then our :load function takes care of all that ^^ stuff, without us doing it manually. https://github.com/mhuebert/maria/blob/master/editor/src/maria/eval.cljs#L66