log

July 2020

July 2nd

Hello! Long time no see. First log of 2020! Coronavirus, amiright? Hey, let’s fix the Athens production build.

Pulled in latest changes and dev build seems to be working fine. Production build time. shadow-cljs release app gives us:

shadow-cljs - config: /home/tom/git/athens/shadow-cljs.edn  cli version: 2.8.83  node: v12.13.1
shadow-cljs - socket connect failed, server process dead?
shadow-cljs - running: lein run -m shadow.cljs.devtools.cli --npm release app
[:app] Compiling ...
------ WARNING #1 -  -----------------------------------------------------------
 Resource: com/cognitect/transit.js:649:8
 variable module is undeclared
--------------------------------------------------------------------------------
------ WARNING #2 -  -----------------------------------------------------------
 Resource: com/cognitect/transit/impl/writer.js:256:8
 variable isObject is undeclared
--------------------------------------------------------------------------------
------ WARNING #3 -  -----------------------------------------------------------
 File: ~/.m2/repository/thheller/shadow-cljs/2.8.83/shadow-cljs-2.8.83.jar!/shadow/cljs/devtools/client/env.cljs:203:51
--------------------------------------------------------------------------------
 200 | (defn make-task-fn [{:keys [log-missing-fn log-call-async log-call]} {:keys [fn-sym fn-str async]}]
 201 |   (fn [next]
 202 |     (try
 203 |       (let [fn-obj (js/goog.getObjectByName fn-str js/$CLJS)]
---------------------------------------------------------^----------------------
 variable $CLJS is undeclared
--------------------------------------------------------------------------------
 204 |         (cond
 205 |           (nil? fn-obj)
 206 |           (do (when log-missing-fn
 207 |                 (log-missing-fn fn-sym))
--------------------------------------------------------------------------------
------ WARNING #4 -  -----------------------------------------------------------
 File: ~/.m2/repository/tick/tick/0.4.26-alpha/tick-0.4.26-alpha.jar!/tick/locale_en_us.cljc:5:31
--------------------------------------------------------------------------------
   2 |   #?(:cljs (:require ["@js-joda/locale_en-us" :as js-joda-locale])))
   3 |
   4 | ; doing this for the one-arity tick.format/formatter. (npm users don't get js/JSJodaLocale global automatically)
   5 | #?(:cljs (set! js/JSJodaLocale js-joda-locale))
-------------------------------------^------------------------------------------
 constant JSJodaLocale assigned a value more than once.
Original definition at externs.shadow.js:4
--------------------------------------------------------------------------------
   6 |
   7 |
   8 |
--------------------------------------------------------------------------------
nil
[:app] Build completed. (6056 files, 5941 compiled, 1 warnings, 186.53s)

------ WARNING #1 - :undeclared-var --------------------------------------------
 Resource: stylefy/impl/conversion.cljc:110:69
--------------------------------------------------------------------------------
 107 |     (let [css-parent-selector (or custom-selector (class-selector hash))
 108 |           css-manual-styles (map
 109 |                              (fn [manual-style]
 110 |                                (let [manual-selector-and-css-props (clojure.walk/walk #(if (map? %)
---------------------------------------------------------------------------^----
 Use of undeclared Var clojure.walk/walk
--------------------------------------------------------------------------------
 111 |                                                                                         (utils/remove-special-keywords %)
 112 |                                                                                         %)
 113 |                                                                                      identity
 114 |                                                                                      manual-style)
--------------------------------------------------------------------------------

What does release app actually do? Better head to the shadow-cljs user guide.

July 3rd

Let’s turn off advanced optimizations for the Athens build. Seems to work!

Looks like we’ve got source maps back again.

Why is shadow-cljs’s runtime browser code still in there?

So after stripping out the :preloads and changing to :simple optimizations I get:

shadow-cljs release app --verbose
shadow-cljs - config: /home/tom/git/athens/shadow-cljs.edn  cli version: 2.8.83  node: v12.13.1
shadow-cljs - socket connect failed, server process dead?
shadow-cljs - running: lein run -m shadow.cljs.devtools.cli --npm release app --verbose
[:app] Compiling ...
-> build target: :browser stage: :configure
<- build target: :browser stage: :configure (4 ms)
-> Resolving Module: :app
<- Resolving Module: :app (7191 ms)
-> build target: :browser stage: :compile-prepare
<- build target: :browser stage: :compile-prepare (1 ms)
-> Shadow JS Cache read: 5707 JS files
<- Shadow JS Cache read: 5707 JS files (1104 ms)
-> Cache read: cljs/core.cljs
<- Cache read: cljs/core.cljs (59 ms)
-> Cache read: athens/config.cljs

(... etc etc lots of "Cache read"s ...)

compilation failed
{:tag :shadow.build.compiler/fail-many, :resource-ids ([:shadow.build.classpath/resource "cljs_http/client.cljs"] [:shadow.build.classpath/resource "cljs_http/core.cljs"]), :errors {[:shadow.build.classpath/resource "cljs_http/client.cljs"] #error {
 :cause "aborted par-compile, [:shadow.build.classpath/resource \"cljs_http/client.cljs\"] still waiting for #{cljs-http.core cljs.core.async}"
 :data {:aborted [:shadow.build.classpath/resource "cljs_http/client.cljs"], :pending #{cljs-http.core cljs.core.async}}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "aborted par-compile, [:shadow.build.classpath/resource \"cljs_http/client.cljs\"] still waiting for #{cljs-http.core cljs.core.async}"
   :data {:aborted [:shadow.build.classpath/resource "cljs_http/client.cljs"], :pending #{cljs-http.core cljs.core.async}}
   :at [shadow.build.compiler$par_compile_one invokeStatic "compiler.clj" 955]}]
 :trace
 [[shadow.build.compiler$par_compile_one invokeStatic "compiler.clj" 955]
  [shadow.build.compiler$par_compile_one invoke "compiler.clj" 920]
  [shadow.build.compiler$par_compile_cljs_sources$fn__13607$iter__13629__13633$fn__13634$fn__13635$fn__13636 invoke "compiler.clj" 1038]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 665]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.lang.AFn applyToHelper "AFn.java" 156]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$bound_fn_STAR_$fn__5749 doInvoke "core.clj" 2003]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn call "AFn.java" 18]
  [java.util.concurrent.FutureTask run "FutureTask.java" 266]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1149]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 624]
  [java.lang.Thread run "Thread.java" 748]]}, [:shadow.build.classpath/resource "cljs_http/core.cljs"] #error {
 :cause "aborted par-compile, [:shadow.build.classpath/resource \"cljs_http/core.cljs\"] still waiting for #{cljs.core.async}"
 :data {:aborted [:shadow.build.classpath/resource "cljs_http/core.cljs"], :pending #{cljs.core.async}}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "aborted par-compile, [:shadow.build.classpath/resource \"cljs_http/core.cljs\"] still waiting for #{cljs.core.async}"
   :data {:aborted [:shadow.build.classpath/resource "cljs_http/core.cljs"], :pending #{cljs.core.async}}
   :at [shadow.build.compiler$par_compile_one invokeStatic "compiler.clj" 955]}]
 :trace
 [[shadow.build.compiler$par_compile_one invokeStatic "compiler.clj" 955]
  [shadow.build.compiler$par_compile_one invoke "compiler.clj" 920]
  [shadow.build.compiler$par_compile_cljs_sources$fn__13607$iter__13629__13633$fn__13634$fn__13635$fn__13636 invoke "compiler.clj" 1038]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 665]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.lang.AFn applyToHelper "AFn.java" 156]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$bound_fn_STAR_$fn__5749 doInvoke "core.clj" 2003]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn call "AFn.java" 18]
  [java.util.concurrent.FutureTask run "FutureTask.java" 266]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1149]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 624]
  [java.lang.Thread run "Thread.java" 748]]}}}
ExceptionInfo: compilation failed
	shadow.build.compiler/par-compile-cljs-sources/fn--13607 (compiler.clj:1051)
	shadow.build.compiler/par-compile-cljs-sources (compiler.clj:985)
	shadow.build.compiler/par-compile-cljs-sources (compiler.clj:978)
	shadow.build.compiler/compile-cljs-sources (compiler.clj:1094)
	shadow.build.compiler/compile-cljs-sources (compiler.clj:1084)
	shadow.build.compiler/compile-all (compiler.clj:1372)
	shadow.build.compiler/compile-all (compiler.clj:1229)
	shadow.build.api/compile-sources (api.clj:255)
	shadow.build.api/compile-sources (api.clj:247)
	shadow.build/compile (build.clj:406)
	shadow.build/compile (build.clj:397)
	shadow.cljs.devtools.api/release* (api.clj:353)
	shadow.cljs.devtools.api/release* (api.clj:340)
	shadow.cljs.devtools.cli/do-build-command (cli.clj:29)
	shadow.cljs.devtools.cli/do-build-command (cli.clj:26)
	shadow.cljs.devtools.cli/do-build-commands (cli.clj:51)
	shadow.cljs.devtools.cli/do-build-commands (cli.clj:40)
	shadow.cljs.devtools.cli/main/body-fn--16982--auto----17573 (cli.clj:168)
	shadow.cljs.devtools.cli/main (cli.clj:167)
	shadow.cljs.devtools.cli/main (cli.clj:134)
	clojure.core/apply (core.clj:669)
	clojure.core/apply (core.clj:660)
	shadow.cljs.devtools.cli/-main (cli.clj:221)
	shadow.cljs.devtools.cli/-main (cli.clj:219)
	clojure.lang.Var.invoke (Var.java:399)
	user/eval152 (form-init8604438828613587683.clj:1)
	user/eval152 (form-init8604438828613587683.clj:1)
	clojure.lang.Compiler.eval (Compiler.java:7177)
	clojure.lang.Compiler.eval (Compiler.java:7167)
	clojure.lang.Compiler.load (Compiler.java:7636)
	clojure.lang.Compiler.loadFile (Compiler.java:7574)
	clojure.main/load-script (main.clj:475)
	clojure.main/init-opt (main.clj:477)
	clojure.main/init-opt (main.clj:477)
	clojure.main/initialize (main.clj:508)
	clojure.main/null-opt (main.clj:542)
	clojure.main/null-opt (main.clj:539)
	clojure.main/main (main.clj:664)
	clojure.main/main (main.clj:616)
	clojure.lang.Var.applyTo (Var.java:705)
	clojure.main.main (main.java:40)

Yikes, looks like we ran out of RAM or something. After freeing up some memory we get a successful compile! Here’s what’s inside:

-> Shadow JS Cache read: 5707 JS files
<- Shadow JS Cache read: 5707 JS files (1083 ms)
-> Cache read: cljs/core.cljs
<- Cache read: cljs/core.cljs (45 ms)
-> Cache read: clojure/string.cljs
-> Cache read: athens/coeffects.cljs
-> Cache read: athens/config.cljs
<- Cache read: athens/coeffects.cljs (27 ms)
<- Cache read: athens/config.cljs (27 ms)
<- Cache read: clojure/string.cljs (27 ms)
-> Cache read: cljs/tools/reader/impl/inspect.cljs
-> Cache read: cljs/tools/reader/impl/utils.cljs
<- Cache read: cljs/tools/reader/impl/inspect.cljs (6 ms)
<- Cache read: cljs/tools/reader/impl/utils.cljs (6 ms)
-> Cache read: cljs/tools/reader/reader_types.cljs
<- Cache read: cljs/tools/reader/reader_types.cljs (5 ms)
-> Cache read: cljs/tools/reader/impl/errors.cljs
<- Cache read: cljs/tools/reader/impl/errors.cljs (6 ms)
-> Cache read: cljs/tools/reader/impl/commons.cljs
<- Cache read: cljs/tools/reader/impl/commons.cljs (5 ms)
-> Cache read: cljs/tools/reader.cljs
<- Cache read: cljs/tools/reader.cljs (18 ms)
-> Cache read: clojure/walk.cljs
-> Cache read: cljs/tools/reader/edn.cljs
<- Cache read: clojure/walk.cljs (5 ms)
-> Cache read: clojure/set.cljs
<- Cache read: cljs/tools/reader/edn.cljs (6 ms)
<- Cache read: clojure/set.cljs (5 ms)
-> Cache read: me/tonsky/persistent_sorted_set/arrays.cljc
-> Cache read: cljs/reader.cljs
-> Cache read: clojure/data.cljs
<- Cache read: clojure/data.cljs (43 ms)
<- Cache read: me/tonsky/persistent_sorted_set/arrays.cljc (47 ms)
-> Cache read: me/tonsky/persistent_sorted_set.cljs
<- Cache read: cljs/reader.cljs (59 ms)
<- Cache read: me/tonsky/persistent_sorted_set.cljs (9 ms)
-> Cache read: clojure/edn.cljs
-> Cache read: datascript/db.cljc
<- Cache read: clojure/edn.cljs (6 ms)
-> Cache read: datascript/lru.cljc
<- Cache read: datascript/lru.cljc (377 ms)
<- Cache read: datascript/db.cljc (383 ms)
-> Cache read: datascript/parser.cljc
-> Cache read: datascript/pull_parser.cljc
-> Cache read: datascript/impl/entity.cljc
<- Cache read: datascript/pull_parser.cljc (9 ms)
<- Cache read: datascript/impl/entity.cljc (7 ms)
-> Cache read: datascript/pull_api.cljc
<- Cache read: datascript/pull_api.cljc (562 ms)
<- Cache read: datascript/parser.cljc (576 ms)
-> Cache read: posh/lib/datom_matcher.cljc
-> Cache read: posh/lib/util.cljc
-> Cache read: datascript/query.cljc
<- Cache read: posh/lib/datom_matcher.cljc (4 ms)
<- Cache read: posh/lib/util.cljc (6 ms)
-> Cache read: cljs/core/match.cljs
-> Cache read: posh/lib/pull_analyze.cljc
<- Cache read: posh/lib/pull_analyze.cljc (589 ms)
<- Cache read: datascript/query.cljc (598 ms)
-> Cache read: posh/lib/db.cljc
<- Cache read: cljs/core/match.cljs (593 ms)
-> Cache read: datascript/core.cljc
-> Cache read: posh/lib/q_analyze.cljc
<- Cache read: posh/lib/db.cljc (6 ms)
-> Cache read: posh/lib/graph.cljc
<- Cache read: posh/lib/graph.cljc (4 ms)
<- Cache read: datascript/core.cljc (10 ms)
<- Cache read: posh/lib/q_analyze.cljc (9 ms)
-> Cache read: posh/lib/update.cljc
<- Cache read: posh/lib/update.cljc (5 ms)
-> Cache read: reagent/debug.cljs
-> Cache read: posh/core.cljc
<- Cache read: posh/core.cljc (41 ms)
<- Cache read: reagent/debug.cljs (47 ms)
-> Cache read: posh/stateful.cljc
-> Cache read: reagent/impl/util.cljs
<- Cache read: reagent/impl/util.cljs (5 ms)
<- Cache read: posh/stateful.cljc (6 ms)
-> Cache read: reagent/impl/batching.cljs
-> Cache read: posh/plugin_base.cljc
<- Cache read: reagent/impl/batching.cljs (6 ms)
-> Cache read: reagent/ratom.cljs
<- Cache read: posh/plugin_base.cljc (7 ms)
<- Cache read: reagent/ratom.cljs (37 ms)
-> Cache read: reagent/impl/component.cljs
<- Cache read: reagent/impl/component.cljs (7 ms)
-> Cache read: reagent/impl/template.cljs
<- Cache read: reagent/impl/template.cljs (6 ms)
-> Cache read: reagent/dom.cljs
<- Cache read: reagent/dom.cljs (6 ms)
-> Cache read: cognitect/transit.cljs
-> Cache read: reagent/core.cljs
<- Cache read: cognitect/transit.cljs (9 ms)
-> Cache read: no/en/core.cljc
<- Cache read: no/en/core.cljc (13 ms)
<- Cache read: reagent/core.cljs (18 ms)
-> Cache read: cljs_http/util.cljs
-> Cache read: cljs/core/async/impl/protocols.cljs
-> Cache read: posh/reagent.cljc
<- Cache read: cljs/core/async/impl/protocols.cljs (4 ms)
-> Cache read: cljs/core/async/impl/buffers.cljs
<- Cache read: cljs_http/util.cljs (9 ms)
<- Cache read: cljs/core/async/impl/buffers.cljs (7 ms)
-> Cache read: cljs/core/async/impl/dispatch.cljs
<- Cache read: cljs/core/async/impl/dispatch.cljs (503 ms)
<- Cache read: posh/reagent.cljc (515 ms)
-> Cache read: cljs/core/async/impl/ioc_helpers.cljs
-> Cache read: athens/db.cljs
-> Cache read: cljs/core/async/impl/channels.cljs
<- Cache read: cljs/core/async/impl/ioc_helpers.cljs (379 ms)
<- Cache read: cljs/core/async/impl/channels.cljs (377 ms)
<- Cache read: athens/db.cljs (377 ms)
-> Cache read: cljs/core/async/impl/timers.cljs
<- Cache read: cljs/core/async/impl/timers.cljs (6 ms)
-> Cache read: cljs/pprint.cljs
-> Cache read: cljs/core/async.cljs
<- Cache read: cljs/core/async.cljs (41 ms)
-> Cache read: datascript/transit.cljs
-> Cache read: cljs_http/core.cljs
<- Cache read: cljs/pprint.cljs (95 ms)
-> Cache read: re_frame/interop.cljs
<- Cache read: cljs_http/core.cljs (64 ms)
<- Cache read: datascript/transit.cljs (65 ms)
<- Cache read: re_frame/interop.cljs (14 ms)
-> Cache read: re_frame/loggers.cljc
-> Cache read: cljs_http/client.cljs
<- Cache read: re_frame/loggers.cljc (4 ms)
-> Cache read: re_frame/registrar.cljc
-> Cache read: re_frame/db.cljc
-> Cache read: re_frame/utils.cljc
<- Cache read: re_frame/registrar.cljc (9 ms)
<- Cache read: re_frame/utils.cljc (9 ms)
-> Cache read: re_frame/trace.cljc
<- Cache read: re_frame/db.cljc (11 ms)
<- Cache read: cljs_http/client.cljs (16 ms)
<- Cache read: re_frame/trace.cljc (244 ms)
-> Cache read: re_frame/interceptor.cljc
-> Cache read: re_frame/subs.cljc
<- Cache read: re_frame/interceptor.cljc (61 ms)
-> Cache read: re_frame/events.cljc
<- Cache read: re_frame/subs.cljc (63 ms)
-> Cache read: re_frame/cofx.cljc
<- Cache read: re_frame/events.cljc (8 ms)
<- Cache read: re_frame/cofx.cljc (8 ms)
-> Cache read: re_frame/router.cljc
-> Cache read: re_frame/std_interceptors.cljc
<- Cache read: re_frame/router.cljc (13 ms)
-> Cache read: re_frame/fx.cljc
<- Cache read: re_frame/std_interceptors.cljc (11 ms)
<- Cache read: re_frame/fx.cljc (10 ms)
-> Cache read: re_frame/core.cljc
<- Cache read: re_frame/core.cljc (9 ms)
-> Cache read: athens/util.cljc
<- Cache read: athens/util.cljc (5 ms)
-> Cache read: clojure/zip.cljs
-> Cache read: day8/re_frame/forward_events_fx.cljs
<- Cache read: clojure/zip.cljs (5 ms)
-> Cache read: cljs/env.cljc
<- Cache read: cljs/env.cljc (5 ms)
<- Cache read: day8/re_frame/forward_events_fx.cljs (11 ms)
-> Cache read: cljs/tagged_literals.cljc
-> Cache read: day8/re_frame/async_flow_fx.cljs
<- Cache read: cljs/tagged_literals.cljc (5 ms)
-> Cache read: cljs/analyzer.cljc
<- Cache read: day8/re_frame/async_flow_fx.cljs (9 ms)
-> Cache read: cljs/spec/gen/alpha.cljs
-> Cache read: athens/effects.cljs
<- Cache read: cljs/spec/gen/alpha.cljs (12 ms)
-> Cache read: cljs/spec/alpha.cljs
<- Cache read: cljs/analyzer.cljc (67 ms)
<- Cache read: athens/effects.cljs (63 ms)
<- Cache read: cljs/spec/alpha.cljs (54 ms)
-> Cache read: debux/common/macro_specs.cljc
-> Cache read: cljs/analyzer/api.cljc
-> Cache read: cljs/repl.cljs
<- Cache read: debux/common/macro_specs.cljc (6 ms)
<- Cache read: cljs/analyzer/api.cljc (10 ms)
<- Cache read: cljs/repl.cljs (9 ms)
-> Cache read: cljsjs/react.cljs
-> Cache read: debux/common/util.cljc
<- Cache read: cljsjs/react.cljs (5 ms)
-> Cache read: cljsjs/react/dom.cljs
<- Cache read: cljsjs/react/dom.cljs (7 ms)
-> Cache read: athens/listeners.cljs
<- Cache read: debux/common/util.cljc (16 ms)
-> Cache read: spec_tools/form.cljc
-> Cache read: day8/re_frame/tracing.cljc
<- Cache read: spec_tools/form.cljc (7 ms)
-> Cache read: spec_tools/impl.cljc
<- Cache read: athens/listeners.cljs (16 ms)
<- Cache read: spec_tools/impl.cljc (146 ms)
-> Cache read: spec_tools/parse.cljc
<- Cache read: day8/re_frame/tracing.cljc (420 ms)
<- Cache read: spec_tools/parse.cljc (270 ms)
-> Cache read: athens/events.cljs
-> Cache read: spec_tools/transform.cljc
<- Cache read: spec_tools/transform.cljc (7 ms)
-> Cache read: spec_tools/core.cljc
<- Cache read: athens/events.cljs (53 ms)
<- Cache read: spec_tools/core.cljc (325 ms)
-> Cache read: spec_tools/data_spec.cljc
-> Cache read: spec_tools/visitor.cljc
<- Cache read: spec_tools/data_spec.cljc (7 ms)
-> Cache read: meta_merge/core.cljc
<- Cache read: spec_tools/visitor.cljc (7 ms)
-> Cache read: reitit/exception.cljc
-> Cache read: spec_tools/json_schema.cljc
<- Cache read: meta_merge/core.cljc (5 ms)
<- Cache read: reitit/exception.cljc (5 ms)
<- Cache read: spec_tools/json_schema.cljc (8 ms)
-> Cache read: reitit/trie.cljc
-> Cache read: spec_tools/swagger/core.cljc
<- Cache read: reitit/trie.cljc (7 ms)
<- Cache read: spec_tools/swagger/core.cljc (10 ms)
-> Cache read: reitit/impl.cljc
<- Cache read: reitit/impl.cljc (308 ms)
-> Cache read: reitit/coercion.cljc
-> Cache read: reitit/core.cljc
<- Cache read: reitit/coercion.cljc (7 ms)
-> Cache read: reitit/frontend/controllers.cljs
-> Cache read: reitit/coercion/spec.cljc
<- Cache read: reitit/core.cljc (6 ms)
<- Cache read: reitit/frontend/controllers.cljs (5 ms)
-> Cache read: reitit/frontend.cljs
<- Cache read: reitit/coercion/spec.cljc (9 ms)
<- Cache read: reitit/frontend.cljs (5 ms)
-> Cache read: garden/types.cljc
-> Cache read: reitit/frontend/history.cljs
<- Cache read: garden/types.cljc (5 ms)
-> Cache read: garden/util.cljc
<- Cache read: reitit/frontend/history.cljs (7 ms)
-> Cache read: reitit/frontend/easy.cljs
<- Cache read: garden/util.cljc (6 ms)
-> Cache read: garden/compression.cljc
-> Cache read: garden/color.cljc
<- Cache read: reitit/frontend/easy.cljs (9 ms)
-> Cache read: garden/selectors.cljc
<- Cache read: garden/compression.cljc (7 ms)
-> Cache read: garden/units.cljc
-> Cache read: athens/router.cljs
<- Cache read: athens/router.cljs (222 ms)
<- Cache read: garden/color.cljc (229 ms)
<- Cache read: garden/units.cljc (276 ms)
-> Cache read: garden/stylesheet.cljc
<- Cache read: garden/stylesheet.cljc (121 ms)
<- Cache read: garden/selectors.cljc (399 ms)
-> Cache read: stylefy/impl/log.cljc
<- Cache read: stylefy/impl/log.cljc (5 ms)
-> Cache read: garden/compiler.cljc
<- Cache read: garden/compiler.cljc (177 ms)
-> Cache read: dommy/utils.cljs
-> Cache read: garden/core.cljc
<- Cache read: dommy/utils.cljs (6 ms)
-> Cache read: dommy/core.cljs
<- Cache read: garden/core.cljc (8 ms)
-> Cache read: stylefy/impl/cache.cljs
-> Cache read: stylefy/impl/utils.cljc
<- Cache read: stylefy/impl/cache.cljs (6 ms)
-> Cache read: stylefy/impl/state.cljc
<- Cache read: stylefy/impl/state.cljc (46 ms)
<- Cache read: stylefy/impl/utils.cljc (50 ms)
<- Cache read: dommy/core.cljs (56 ms)
-> Cache read: stylefy/impl/hashing.cljc
-> Cache read: stylefy/impl/conversion.cljc
<- Cache read: stylefy/impl/hashing.cljc (9 ms)
<- Cache read: stylefy/impl/conversion.cljc (9 ms)
-> Cache read: stylefy/impl/dom.cljs
<- Cache read: stylefy/impl/dom.cljs (11 ms)
-> Cache read: athens/subs.cljs
-> Cache read: stylefy/impl/styles.cljc
<- Cache read: athens/subs.cljs (12 ms)
-> Cache read: sablono/util.cljc
<- Cache read: stylefy/impl/styles.cljc (12 ms)
<- Cache read: sablono/util.cljc (6 ms)
-> Cache read: stylefy/core.cljc
-> Cache read: sablono/normalize.cljc
<- Cache read: sablono/normalize.cljc (7 ms)
<- Cache read: stylefy/core.cljc (13 ms)
-> Cache read: devcards/util/utils.cljs
-> Cache read: sablono/interpreter.cljc
-> Cache read: athens/style.cljs
<- Cache read: sablono/interpreter.cljc (25 ms)
<- Cache read: athens/style.cljs (24 ms)
<- Cache read: devcards/util/utils.cljs (27 ms)
-> Cache read: cljsjs/marked.cljs
-> Cache read: sablono/core.cljs
<- Cache read: cljsjs/marked.cljs (7 ms)
-> Cache read: devcards/util/markdown.cljs
<- Cache read: devcards/util/markdown.cljs (841 ms)
<- Cache read: sablono/core.cljs (848 ms)
-> Cache read: cljs/test.cljs
-> Cache read: devcards/util/edn_renderer.cljs
<- Cache read: devcards/util/edn_renderer.cljs (9 ms)
-> Cache read: devcards/system.cljs
<- Cache read: cljs/test.cljs (11 ms)
<- Cache read: devcards/system.cljs (23 ms)
-> Cache read: athens/lib/dom/attributes.cljc
-> Cache read: devcards/core.cljs
<- Cache read: athens/lib/dom/attributes.cljc (5 ms)
-> Cache read: java/time.cljs
<- Cache read: java/time.cljs (5 ms)
-> Cache read: time_literals/read_write.cljc
<- Cache read: time_literals/read_write.cljc (6 ms)
-> Cache read: cljs/java_time/interop.cljc
<- Cache read: devcards/core.cljs (105 ms)
-> Cache read: athens/devcards/buttons.cljs
<- Cache read: cljs/java_time/interop.cljc (108 ms)
-> Cache read: cljc/java_time/local_date_time.cljc
-> Cache read: cljc/java_time/local_date.cljc
<- Cache read: cljc/java_time/local_date_time.cljc (9 ms)
<- Cache read: cljc/java_time/local_date.cljc (6 ms)
-> Cache read: cljc/java_time/local_time.cljc
-> Cache read: cljc/java_time/clock.cljc
<- Cache read: cljc/java_time/clock.cljc (7 ms)
-> Cache read: cljc/java_time/instant.cljc
<- Cache read: cljc/java_time/local_time.cljc (9 ms)
-> Cache read: cljc/java_time/zone_id.cljc
<- Cache read: cljc/java_time/instant.cljc (5 ms)
-> Cache read: cljc/java_time/zone_offset.cljc
<- Cache read: cljc/java_time/zone_id.cljc (7 ms)
-> Cache read: cljc/java_time/zoned_date_time.cljc
<- Cache read: cljc/java_time/zone_offset.cljc (5 ms)
-> Cache read: cljc/java_time/offset_date_time.cljc
<- Cache read: cljc/java_time/offset_date_time.cljc (6 ms)
-> Cache read: cljc/java_time/duration.cljc
<- Cache read: cljc/java_time/zoned_date_time.cljc (10 ms)
-> Cache read: cljc/java_time/year_month.cljc
<- Cache read: cljc/java_time/duration.cljc (5 ms)
-> Cache read: cljc/java_time/month.cljc
<- Cache read: cljc/java_time/year_month.cljc (8 ms)
-> Cache read: cljc/java_time/year.cljc
<- Cache read: cljc/java_time/month.cljc (6 ms)
-> Cache read: cljc/java_time/day_of_week.cljc
<- Cache read: cljc/java_time/day_of_week.cljc (5 ms)
-> Cache read: cljc/java_time/period.cljc
<- Cache read: cljc/java_time/year.cljc (8 ms)
-> Cache read: java/time/temporal.cljs
<- Cache read: cljc/java_time/period.cljc (6 ms)
<- Cache read: java/time/temporal.cljs (6 ms)
-> Cache read: cljc/java_time/temporal/temporal_adjusters.cljc
-> Cache read: cljc/java_time/temporal/temporal_amount.cljc
<- Cache read: cljc/java_time/temporal/temporal_adjusters.cljc (7 ms)
-> Cache read: cljc/java_time/temporal/chrono_field.cljc
<- Cache read: cljc/java_time/temporal/temporal_amount.cljc (4 ms)
-> Cache read: cljc/java_time/temporal/chrono_unit.cljc
<- Cache read: cljc/java_time/temporal/chrono_field.cljc (7 ms)
<- Cache read: cljc/java_time/temporal/chrono_unit.cljc (5 ms)
-> Cache read: cljs/java_time/extend_eq_and_compare.cljs
<- Cache read: cljs/java_time/extend_eq_and_compare.cljs (7 ms)
-> Cache read: java/time/format.cljs
-> Cache read: tick/core.cljc
<- Cache read: java/time/format.cljs (6 ms)
-> Cache read: tick/format.cljc
<- Cache read: tick/format.cljc (6 ms)
<- Cache read: tick/core.cljc (109 ms)
-> Cache read: tick/interval.cljc
<- Cache read: tick/interval.cljc (10 ms)
-> Cache read: tick/locale_en_us.cljc
-> Cache read: tick/alpha/api.cljc
<- Cache read: tick/locale_en_us.cljc (7 ms)
<- Cache read: athens/devcards/buttons.cljs (2903 ms)
<- Cache read: tick/alpha/api.cljc (2679 ms)
-> Cache read: instaparse/auto_flatten_seq.cljc
-> Cache read: athens/devcards/db.cljs
<- Cache read: instaparse/auto_flatten_seq.cljc (7 ms)
-> Cache read: instaparse/print.cljc
<- Cache read: instaparse/print.cljc (7 ms)
-> Cache read: instaparse/failure.cljc
<- Cache read: instaparse/failure.cljc (7 ms)
-> Cache read: instaparse/util.cljc
<- Cache read: instaparse/util.cljc (6 ms)
-> Cache read: instaparse/reduction.cljc
<- Cache read: instaparse/reduction.cljc (7 ms)
-> Cache read: instaparse/combinators_source.cljc
<- Cache read: instaparse/combinators_source.cljc (8 ms)
-> Cache read: instaparse/gll.cljc
<- Cache read: instaparse/gll.cljc (506 ms)
-> Cache read: instaparse/cfg.cljc
<- Cache read: instaparse/cfg.cljc (7 ms)
-> Cache read: instaparse/transform.cljc
<- Cache read: instaparse/transform.cljc (5 ms)
-> Cache read: instaparse/abnf.cljc
<- Cache read: athens/devcards/db.cljs (863 ms)
-> Cache read: instaparse/viz.cljs
<- Cache read: instaparse/abnf.cljc (302 ms)
-> Cache read: athens/devcards/all_pages.cljs
-> Cache read: athens/devcards/athena.cljs
<- Cache read: instaparse/viz.cljs (7 ms)
-> Cache read: instaparse/line_col.cljc
-> Cache read: instaparse/repeat.cljc
<- Cache read: instaparse/line_col.cljc (62 ms)
<- Cache read: instaparse/repeat.cljc (63 ms)
-> Cache read: instaparse/core.cljc
<- Cache read: instaparse/core.cljc (34 ms)
-> Cache read: athens/parser.cljc
<- Cache read: athens/parser.cljc (274 ms)
-> Cache read: komponentit/autosize.cljs
-> Cache read: athens/parse_renderer.cljs
<- Cache read: komponentit/autosize.cljs (9 ms)
<- Cache read: athens/parse_renderer.cljs (36 ms)
-> Cache read: athens/devcards/blocks.cljs
<- Cache read: athens/devcards/athena.cljs (687 ms)
-> Cache read: athens/devcards/breadcrumbs.cljs
<- Cache read: athens/devcards/breadcrumbs.cljs (18 ms)
-> Cache read: athens/patterns.cljc
<- Cache read: athens/patterns.cljc (5 ms)
<- Cache read: athens/devcards/all_pages.cljs (924 ms)
<- Cache read: athens/devcards/blocks.cljs (753 ms)
-> Cache read: athens/devcards/textinput.cljs
-> Cache read: athens/devcards/block_page.cljs
-> Cache read: athens/devcards/node_page.cljs
<- Cache read: athens/devcards/block_page.cljs (681 ms)
-> Cache read: clojure/core/protocols.cljs
<- Cache read: clojure/core/protocols.cljs (4 ms)
-> Cache read: clojure/datafy.cljs
<- Cache read: clojure/datafy.cljs (5 ms)
-> Cache read: sci/impl/types.cljc
<- Cache read: sci/impl/types.cljc (5 ms)
-> Cache read: sci/impl/macros.cljc
<- Cache read: sci/impl/macros.cljc (12 ms)
-> Cache read: sci/impl/unrestrict.cljc
<- Cache read: sci/impl/unrestrict.cljc (4 ms)
-> Cache read: sci/impl/vars.cljc
<- Cache read: sci/impl/vars.cljc (73 ms)
-> Cache read: sci/impl/utils.cljc
<- Cache read: sci/impl/utils.cljc (7 ms)
-> Cache read: sci/impl/destructure.cljc
<- Cache read: sci/impl/destructure.cljc (6 ms)
-> Cache read: sci/impl/doseq_macro.cljc
<- Cache read: sci/impl/doseq_macro.cljc (7 ms)
-> Cache read: sci/impl/for_macro.cljc
<- Cache read: sci/impl/for_macro.cljc (7 ms)
-> Cache read: sci/impl/interop.cljc
<- Cache read: sci/impl/interop.cljc (8 ms)
-> Cache read: sci/impl/analyzer.cljc
<- Cache read: sci/impl/analyzer.cljc (10 ms)
-> Cache read: sci/impl/fns.cljc
<- Cache read: sci/impl/fns.cljc (7 ms)
-> Cache read: sci/impl/max_or_throw.cljc
<- Cache read: sci/impl/max_or_throw.cljc (6 ms)
-> Cache read: sci/impl/hierarchies.cljc
<- Cache read: athens/devcards/node_page.cljs (852 ms)
<- Cache read: sci/impl/hierarchies.cljc (8 ms)
-> Cache read: sci/impl/io.cljc
-> Cache read: sci/impl/multimethods.cljc
-> Cache read: athens/devcards/daily_notes.cljs
<- Cache read: sci/impl/io.cljc (5 ms)
-> Cache read: edamame/impl/read_fn.cljc
<- Cache read: edamame/impl/read_fn.cljc (5 ms)
-> Cache read: edamame/impl/syntax_quote.cljc
<- Cache read: edamame/impl/syntax_quote.cljc (5 ms)
-> Cache read: edamame/impl/parser.cljc
<- Cache read: sci/impl/multimethods.cljc (19 ms)
<- Cache read: edamame/impl/parser.cljc (8 ms)
-> Cache read: sci/impl/parser.cljc
<- Cache read: sci/impl/parser.cljc (11 ms)
-> Cache read: sci/impl/namespaces.cljc
<- Cache read: athens/devcards/textinput.cljs (909 ms)
<- Cache read: sci/impl/namespaces.cljc (464 ms)
-> Cache read: sci/impl/opts.cljc
<- Cache read: sci/impl/opts.cljc (11 ms)
-> Cache read: shadow/cljs/devtools/client/env.cljs
-> Cache read: sci/impl/interpreter.cljc
<- Cache read: shadow/cljs/devtools/client/env.cljs (9 ms)
-> Cache read: shadow/remote/runtime/api.cljc
<- Cache read: shadow/remote/runtime/api.cljc (54 ms)
-> Cache read: shadow/remote/runtime/writer.cljs
<- Cache read: sci/impl/interpreter.cljc (64 ms)
-> Cache read: sci/core.cljc
<- Cache read: shadow/remote/runtime/writer.cljs (4 ms)
-> Cache read: shadow/remote/runtime/cljs/env.cljs
-> Cache read: shadow/remote/runtime/shared.cljc
<- Cache read: shadow/remote/runtime/cljs/env.cljs (5 ms)
-> Cache read: shadow/remote/runtime/cljs/js_builtins.cljs
<- Cache read: shadow/remote/runtime/shared.cljc (7 ms)
-> Cache read: shadow/remote/runtime/obj_support.cljc
<- Cache read: shadow/remote/runtime/cljs/js_builtins.cljs (6 ms)
<- Cache read: shadow/remote/runtime/obj_support.cljc (25 ms)
-> Cache read: shadow/remote/runtime/eval_support.cljs
<- Cache read: sci/core.cljc (37 ms)
-> Cache read: shadow/remote/runtime/tap_support.cljc
<- Cache read: shadow/remote/runtime/eval_support.cljs (5 ms)
<- Cache read: shadow/remote/runtime/tap_support.cljc (38 ms)
-> Cache read: athens/devcards/left_sidebar.cljs
-> Cache read: shadow/remote/runtime/cljs/browser.cljs
<- Cache read: shadow/remote/runtime/cljs/browser.cljs (18 ms)
-> Cache read: athens/devcards/right_sidebar.cljs
-> Cache read: athens/devcards/devtool.cljs
<- Cache read: athens/devcards/daily_notes.cljs (699 ms)
-> Cache read: athens/devcards/spinner.cljs
<- Cache read: athens/devcards/spinner.cljs (29 ms)
<- Cache read: athens/devcards/right_sidebar.cljs (616 ms)
<- Cache read: athens/devcards/left_sidebar.cljs (841 ms)
<- Cache read: athens/devcards/devtool.cljs (841 ms)
-> Cache read: athens/views.cljs
<- Cache read: athens/views.cljs (574 ms)
-> Cache read: athens/core.cljs
<- Cache read: athens/core.cljs (616 ms)

We still need to strip out:

Then try :advanced again.

July 6th

To remove the devcards dependencies I split out the Athens view code out of the devcards files and into a new folder (https://github.com/athensresearch/athens/commit/df157ee2e610fc9fc92c0db7abf8832be5883523). It was the devtool devcards that was including the shadow-cljs stuff! Build seems to be working fine under :simple optimizations now.

July 10th

RemNote has recently added a feature called “Power-Up Rem” where referencing special Rems (like Athens/Roam blocks) modify the behaviour of the referencing block. This feels like a missing piece to building user composable views! Let’s make a demo.

What kind of functionality do we want to try out?

The first thing we need to decide: should the demo use the existing datascript app components or should it be a self-contained demo like sci-boxes? With the amount of changes that are happening to the codebase at the moment I’m leaning towards self-contained. On the flip side, using the existing components could mean a more quickly usable feature…

Why not both? I’ll pull from the more stable existing components where possible and try to build up to a demo-able functionality.

SO. If I embed a block and it’s a ‘special’ block then I want to to modify the behaviour of the referencing block. What is a ‘special’ block? Let’s say it’s a block that starts with “:sci”. Then we want to treat the rest of the block’s string content as SCI code to be run when the block is rendered. Referring to the referencing block as ‘parent’, in order to implement TODOs the special block will need to:

So in the “TODO” case we’re happy to have full control of the resulting render, as we know we want the checkbox first and then the rest of the content. Meaning it doesn’t matter where the ‘embed’ (e.g. “((TODO))”) is within the parent. But in the normal case, where we’re just embedding one block in another, the position matters: we want to embed in a certain place within the block.

Here’s our current method of parsing a block’s content:

(defn parse-and-render
  "Converts a string of block syntax to Hiccup, with fallback formatting if it can’t be parsed."
  [string]
  (let [result (parser/parse-to-ast string)]
    (if (insta/failure? result)
      [:span
       {:title (pr-str (insta/get-failure result))
        :style {:color "red"}}
       string]
      [vec (transform result)])))

The important part is transform, which wraps instaparse’s fn of the same name. From their docs:

insta/transform takes a map from tree tags to transform functions. A transform function is defined as a function which takes the children of the tree node as inputs and returns a replacement node.

Here’s the wrapper with everything removed but our :block-ref transform fn:

(defn transform
  "Transforms Instaparse output to Hiccup."
  [tree]
  (insta/transform
    {:block-ref (fn [uid]
                  (let [block (pull db/dsdb '[*] [:block/uid uid])]
                    [:span (use-style block-ref {:class "block-ref"})
                     [:span {:class "contents" :on-click #(navigate-uid uid)} (parse-and-render (:block/string @block))]]))
    tree))

So our current parsing method involves turning a block’s string into a tree, then running a replacement fn on each node in the tree. The replacement fn for block embeds recursively calls parse again. This works great for normal block embedding but how could we step out and make modifications to other parts of the tree?

July 11th

I took a step back last night and realised I was thinking about the problem in the wrong way. In our parse step it doesn’t make sense to run code and manipulate the tree (at least not to solve this current issue?), the parse step should fetch and embed the code just like any other block, then in another step we want to walk the tree and execute the code. This seems like an excuse to use zippers!

Let’s try these steps:

  1. In the parsers ‘transform’ step, if a block embed using ‘(())’ referenences a block that begins with “:sci”, treat it as a ‘modifier’ and mark it as ‘:athens/sci-modifier’ inside the returned hiccup
  2. In an extra step, use a zipper to traverse the hiccup and when we hit “modifier” code strip it out and run it, passing in the containing block and replacing it with the code’s return value!

This seems super hacky and the API is garbage (should we use “{{}}” like Roam?) but.. it works? Here’s the zipper code:

(defn modify [tree]
  (loop [loc (hiccup-zip tree)]
    (if (zip/end? loc)
      (zip/node loc)
      (recur (let [node (zip/node loc)]
               (if (= :athens/sci-modifier (first node))
                 (let [code (subs (second node) 4)
                       context {:block (-> loc zip/remove zip/root)}
                       result (eval-sci-modifier code context)]
                   (hiccup-zip result))
                 (zip/next loc)))))))

When we pass it a hiccup tree like this:

[:span {:class "block" :style {:white-space "pre-line"}}
 [:athens/sci-modifier
  ":sci (let [{:keys [block]} *1]
          [:div [:input {:type "checkbox"}]
           [:span {:style {:margin-left 10}} block]])"]
 " collect eggs"]

We get this:

[:div [:input {:type "checkbox"}]
 [:span {:style {:margin-left 10 }}
  [:span {:class "block" :style {:white-space "pre-line"}}
   " collect eggs"]]]

Two questions that spring to mind:

  1. What are the security implications of allowing ebedded code (possibly other people’s code) access to parts of your graph? How can we minimise that access via the Principle of Least Authority?
  2. What do we need to pass into the modifier block so that it can mark the TODO as DONE?