Fork me on GitHub
Stevy B04:02:42

Hi all ! Beginner here. I am trying to compile my app with

shadow-cljs watch dev-ui
But I am getting this error :
shadow-cljs - config: .../shadow-cljs.edn
shadow-cljs - HTTP server available at 
shadow-cljs - server version: 2.11.4 running at 
shadow-cljs - nREPL server started on port 54872
shadow-cljs - watching build :dev-ui
[:dev-ui] Configuring build.
[:dev-ui] Compiling ...
[:dev-ui] Build failure:
The required namespace "react" is not available, it was required by "reagent/core.cljs".
I have installed react with
npm install react react-dom create-react-class 
but the issue is still there. Let me know if I am doing everything right ? Thanks for the help.


did you install it in the correct directory? there should be a <project>/node_modules/react directory. if you don't have a package.json in your project dir it might install somewhere else.

Stevy B09:02:07

I didnt install npm in the right folder that was the issue

Stevy B09:02:10

now all good thanks !

Peter Muys08:02:47

Hello, I have a problem when doint a release with shadow-cljs, I get the following error: [:app] Compiling ... [2021-02-05 09:20:43.012 - INFO] - {:resource-name "node_modules/moment-mini/moment.min.js", :requires [{:line 1, :column 4095}]} Closure compilation failed with 1 errors --- externs.shadow.js:13 Parse error. 'identifier' expected

Peter Muys08:02:46

The js-invalid-requires also comes up when watching (shadow-cljs watch app), but everything seems to work fine


@peter085 don't know that package. it might try to do a dynamic import() which is not supported

Peter Muys10:02:55

When looking at the moment.min.js file ate columnn 4095 i see a function with 'return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0'

Peter Muys10:02:39

When i look at externs.shadow.js:13 i see ShadowJS.prototype.;

Peter Muys10:02:33

the package moment-mini is a dependency of (I think) mermaid npm module.


hmm odd. seems like shadow-cljs collected some kind of empty externs property. no clue how.

Peter Muys11:02:55

The description of moment-mini: This package exposes as an npm module so you can import/require the minified version of moment into your projects without the bloat of the locales. This package will follow the

Peter Muys11:02:48

How could I solve this problem? It stops me from deploying my app.


@peter085 I don't know. I tried the moment-mini and mermaid packages and they compile fine. something must confuse the externs generator but I don't know how or what.

Peter Muys14:02:58

Ok, thanks for looking. BTW I otherwise love shadow-cljs (never had a problem like this before)


it is a very odd issue. can you check if the line ShadowJS.prototype.; is actually ShadowJS.prototype.; and not maybe some unicode char or so behind inbetween the .;?


its not supposed to generate empty externs and I don't know how it would

Peter Muys15:02:36

@thheller This is a copy with lines before and after, it doesn't show any other chars. / @const {ShadowJS} */ var location; / @const {ShadowJS} */ var module$node_modules$codemirror$lib$codemirror; ShadowJS.prototype.; ShadowJS.prototype.$; ShadowJS.prototype.$$typeof;


hmm yeah would be interested to find out how it gets to generate an empty externs entry

Peter Muys15:02:04

Do you need any other info, like package.json or something else?


trying to think of a good way to debug this


@peter085 can you create an empty CLJ ns like (ns debug) and put this in it

(defn find-it
  { :flush}
  [{:keys [output] :as build-state}]
  (->> output
       (filter #(contains? (:properties %) ""))
       (map :resource-id)


then in your build-config set :build-hooks [(debug/find-it)]


that should then at least tell us which of the files is causing the empty externs

Peter Muys15:02:43

ok,let my try


oh wait it doesn't get to flush, use this instead

(defn find-it
  { :optimize-prepare}
  [{:keys [output] :as build-state}]

  (->> (vals output)
       (filter #(contains? (:properties %) ""))
       (map :resource-id)



you can define it entirely in the REPL too


doesn't need to be in a file just shadow-cljs clj-repl is fine


oh wait. its missing a (vals)


(vals output)


forgot its a map 😉

Peter Muys15:02:22

I got the following: shadow-cljs - starting via "clojure" WARNING: When invoking clojure.main, use -M enabling instrumentation [:app] Compiling ... [2021-02-05 16:48:35.711 - INFO] - {:resource-name "node_modules/moment-mini/moment.min.js", :requires [{:line 1, :column 4095}]} () Closure compilation failed with 1 errors --- externs.shadow.js:13 Parse error. 'identifier' expected The only difference is the () in de output, 'enabling instrumentations' is something from my code

Peter Muys15:02:01

oeps, missed some messages


updated the code snippet


yeah the () would be the empty sequence from the prn if it didn't find what it was looking for

Peter Muys15:02:07

Same output with vals


maybe try

(defn find-it
  { :optimize-prepare}
  [{:keys [output] :as build-state}]

  (doseq [{:keys [resource-id properties]} (vals output)
          prop properties
          :when (< (count prop) 2)]
    (prn [:prop resource-id prop]))



that should at least log something. maybe too much though


can ignore anything thats not empty, just need to find the one that "looks" empty

Peter Muys15:02:31

[:prop [ "node_modules/d3-force/dist/d3-force.js"] "x"]
[:prop [ "node_modules/d3-force/dist/d3-force.js"] "r"]
[:prop [ "node_modules/d3-force/dist/d3-force.js"] "y"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "L"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "x"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "R"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "C"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "_"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "P"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "U"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "y"]
[:prop [ "node_modules/d3-voronoi/dist/d3-voronoi.js"] "N"]
[:prop [ "node_modules/d3-shape/dist/d3-shape.js"] "x"]
[:prop [ "node_modules/d3-shape/dist/d3-shape.js"] "y"]
[:prop [ "node_modules/dagre-d3/lib/shapes.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/shapes.js"] "y"]
[:prop [ "node_modules/codemirror/mode/perl/perl.js"] "s"]
[:prop [ "node_modules/codemirror/mode/perl/perl.js"] "q"]
[:prop [ "node_modules/codemirror/mode/perl/perl.js"] "y"]
[:prop [ "node_modules/codemirror/mode/perl/perl.js"] "m"]
[:prop [ "node_modules/dagre/lib/coordinate-system.js"] "x"]
[:prop [ "node_modules/dagre/lib/coordinate-system.js"] "y"]
[:prop [ "node_modules/codemirror/lib/codemirror.js"] "f"]
[:prop [ "node_modules/codemirror/lib/codemirror.js"] "x"]
[:prop [ "node_modules/codemirror/lib/codemirror.js"] "y"]


yeah those are all fine

Peter Muys15:02:47

[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-polygon.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-polygon.js"] "y"]
[:prop [ "node_modules/d3-contour/dist/d3-contour.js"] "x"]
[:prop [ "node_modules/d3-contour/dist/d3-contour.js"] "y"]
[:prop [ "node_modules/d3-path/dist/d3-path.js"] "_"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "n"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "z"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "s"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "e"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "p"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "x"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "v"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "t"]
[:prop [ "node_modules/d3-geo/dist/d3-geo.js"] "o"]
[:prop [ "node_modules/graphlib/lib/graph.js"] "w"]
[:prop [ "node_modules/graphlib/lib/graph.js"] "v"]
[:prop [ "node_modules/khroma/dist/color/rgb.js"] "a"]
[:prop [ "node_modules/khroma/dist/color/rgb.js"] "b"]
[:prop [ "node_modules/khroma/dist/color/rgb.js"] "r"]
[:prop [ "node_modules/khroma/dist/color/rgb.js"] "g"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-ellipse.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-ellipse.js"] "y"]
[:prop [ "node_modules/dagre/lib/normalize.js"] "x"]
[:prop [ "node_modules/dagre/lib/normalize.js"] "y"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-rect.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-rect.js"] "y"]
[:prop [ "node_modules/khroma/dist/methods/hsla.js"] "s"]
[:prop [ "node_modules/khroma/dist/methods/hsla.js"] "a"]
[:prop [ "node_modules/khroma/dist/methods/hsla.js"] "l"]
[:prop [ "node_modules/khroma/dist/methods/hsla.js"] "h"]
[:prop [ "node_modules/d3-dispatch/dist/d3-dispatch.js"] "_"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "d"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "n"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "s"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "p"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "x"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "t"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "i"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "r"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "y"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "l"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "h"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "m"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "$"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "o"]
[:prop [ "node_modules/mermaid/dist/mermaid.core.js"] "c"]
[:prop [ "node_modules/dagre-d3/lib/create-edge-paths.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/create-edge-paths.js"] "y"]
[:prop [ "node_modules/khroma/dist/methods/grayscale.js"] "s"]
[:prop [ "node_modules/d3-drag/dist/d3-drag.js"] "x"]
[:prop [ "node_modules/d3-drag/dist/d3-drag.js"] "_"]
[:prop [ "node_modules/d3-drag/dist/d3-drag.js"] "y"]
[:prop [ "node_modules/khroma/dist/methods/rgba.js"] "a"]
[:prop [ "node_modules/khroma/dist/methods/rgba.js"] "b"]
[:prop [ "node_modules/khroma/dist/methods/rgba.js"] "r"]
[:prop [ "node_modules/khroma/dist/methods/rgba.js"] "g"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "d"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "w"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "s"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "Q"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "q"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "L"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "p"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "x"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "M"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "S"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "Z"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "H"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "V"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "U"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "y"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "X"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "u"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "m"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "W"]
[:prop [ "node_modules/d3-time-format/dist/d3-time-format.js"] "c"]
[:prop [ "node_modules/dagre/lib/util.js"] "x"]
[:prop [ "node_modules/dagre/lib/util.js"] "y"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "s"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "x"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "a"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "i"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "b"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "r"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "g"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "l"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "h"]
[:prop [ "node_modules/d3-interpolate/dist/d3-interpolate.js"] "c"]


don't need those

Peter Muys15:02:56

[:prop [ "node_modules/d3-brush/dist/d3-brush.js"] "n"]
[:prop [ "node_modules/d3-brush/dist/d3-brush.js"] "w"]
[:prop [ "node_modules/d3-brush/dist/d3-brush.js"] "s"]
[:prop [ "node_modules/d3-brush/dist/d3-brush.js"] "e"]
[:prop [ "node_modules/dagre/lib/order/barycenter.js"] "v"]
[:prop [ "node_modules/d3-zoom/dist/d3-zoom.js"] "x"]
[:prop [ "node_modules/d3-zoom/dist/d3-zoom.js"] "k"]
[:prop [ "node_modules/d3-zoom/dist/d3-zoom.js"] "y"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "s"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "a"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "b"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "r"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "g"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "l"]
[:prop [ "node_modules/khroma/dist/channels/index.js"] "h"]
[:prop [ "node_modules/codemirror/mode/elm/elm.js"] "f"]
[:prop [ "node_modules/graphlib/lib/json.js"] "w"]
[:prop [ "node_modules/graphlib/lib/json.js"] "v"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-line.js"] "x"]
[:prop [ "node_modules/dagre-d3/lib/intersect/intersect-line.js"] "y"]
[:prop [ "node_modules/dagre/lib/greedy-fas.js"] "w"]
[:prop [ "node_modules/dagre/lib/greedy-fas.js"] "v"]
[:prop [ "node_modules/khroma/dist/channels/reusable.js"] "a"]
[:prop [ "node_modules/khroma/dist/channels/reusable.js"] "b"]
[:prop [ "node_modules/khroma/dist/channels/reusable.js"] "r"]
[:prop [ "node_modules/khroma/dist/channels/reusable.js"] "g"]
[:prop [ "node_modules/dagre/lib/position/index.js"] "x"]
[:prop [ "node_modules/dagre/lib/position/index.js"] "y"]
[:prop [ "node_modules/dagre/lib/layout.js"] "e"]
[:prop [ "node_modules/dagre/lib/layout.js"] "x"]
[:prop [ "node_modules/dagre/lib/layout.js"] "y"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "d"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "w"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "s"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "L"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "M"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "y"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "h"]
[:prop [ "node_modules/moment-mini/moment.min.js"] "m"]
[:prop [ "node_modules/khroma/dist/color/hsl.js"] "s"]
[:prop [ "node_modules/khroma/dist/color/hsl.js"] "a"]
[:prop [ "node_modules/khroma/dist/color/hsl.js"] "l"]
[:prop [ "node_modules/khroma/dist/color/hsl.js"] "h"]
[:prop [ "node_modules/codemirror/mode/haskell/haskell.js"] "f"]
[:prop [ "node_modules/d3-quadtree/dist/d3-quadtree.js"] "x"]
[:prop [ "node_modules/d3-quadtree/dist/d3-quadtree.js"] "y"]
[:prop [ "node_modules/d3-selection/dist/d3-selection.js"] "x"]
[:prop [ "node_modules/d3-selection/dist/d3-selection.js"] "_"]
[:prop [ "node_modules/d3-selection/dist/d3-selection.js"] "y"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "s"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "b"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "r"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "g"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "l"]
[:prop [ "node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.js"] "h"]
[:prop [ "node_modules/khroma/dist/color/hex.js"] "a"]
[:prop [ "node_modules/khroma/dist/color/hex.js"] "b"]
[:prop [ "node_modules/khroma/dist/color/hex.js"] "r"]
[:prop [ "node_modules/khroma/dist/color/hex.js"] "g"]
[:prop [ "node_modules/dagre/lib/order/resolve-conflicts.js"] "i"]
[:prop [ "node_modules/khroma/dist/methods/invert.js"] "b"]
[:prop [ "node_modules/khroma/dist/methods/invert.js"] "r"]
[:prop [ "node_modules/khroma/dist/methods/invert.js"] "g"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "z"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "s"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "x"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "a"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "_"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "t"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "i"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "r"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "y"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "A"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "m"]
[:prop [ "node_modules/d3-hierarchy/dist/d3-hierarchy.js"] "c"]
[:prop [ "node_modules/d3-chord/dist/d3-chord.js"] "_"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "s"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "a"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "b"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "r"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "g"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "l"]
[:prop [ "node_modules/khroma/dist/utils/channel.js"] "h"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "s"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "a"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "b"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "r"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "g"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "l"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "h"]
[:prop [ "node_modules/d3-color/dist/d3-color.js"] "c"]

Peter Muys16:02:05

nothing empty


yeah those are all fine



(defn find-it
  { :optimize-prepare}

  (prn ( build-state))



if that contains "" then it is somehow coming from CLJS not JS

Peter Muys16:02:30

[2021-02-05 17:19:55.794 - INFO] - {:resource-name "node_modules/moment-mini/moment.min.js", :requires [{:line 1, :column 4095}]}
#{"" "_run" "NaN" "flush-after-render" "getMode" "unbounded-unshift" "_peek-at" "_update-watching" "fromCharCode" "onChange" "_queued-run" "add-after-render" "flush-render" "_set-opts" "_peek" "isScrolling" "floorEntry" "autoLoadMode" "ceilingEntry" "createElement" "Fragment" "PersistentVector" "copyState" "POSITIVE_INFINITY" "findModeByName" "Children.toArray" "queue-render" "schedule" "startState" "_set-state" "hasNext" "findDOMNode" "flush-queues" "_handle-change" "getLength" "PersistentArrayMap" "Doc" "render" "_try-capture" "flush-before-flush" "cljsIsDirty" "unmountComponentAtNode" "NEGATIVE_INFINITY" "Component" "add-before-flush" "run-queues" "core" "equiv"}
Closure compilation failed with 1 errors
--- externs.shadow.js:13
Parse error. 'identifier' expected


ah ok, let me get the function to find it


(defn find-it
  { :optimize-prepare}

  (doseq [{:keys [ns file] :as src}
          :let [{:shadow/keys [js-access-properties]}
                (get-in state [:compiler-env :cljs.analyzer/namespaces ns])] 
          :when (contains? js-access-properties "")]
    (prn [:found ns js-access-properties]))


this should do it


oh oops delete something

Peter Muys16:02:54

something wrong in find-it

[2021-02-05 17:23:40.074 - WARNING] - {:hook-idx 0, :hook-sym debug/find-it, :build-id :app}
Note: The following stack trace applies to the reader or compiler, your code was not executed.
CompilerException Syntax error macroexpanding doseq at (debug.clj:15:13). #:clojure.error{:phase :macro-syntax-check, :line 15, :column 13, :source "debug.clj", :symbol doseq}


(defn find-it
  { :optimize-prepare}

  (doseq [src-id (:build-sources state)
          :let [{:keys [ns file] :as src}
                (get-in state [:sources src-id])
                {:shadow/keys [js-access-properties]}
                (get-in state [:compiler-env :cljs.analyzer/namespaces ns])]
          :when (contains? js-access-properties "")]
    (prn [:found ns js-access-properties]))



should state and build-state be the same var?


(defn find-it
  { :optimize-prepare}

  (doseq [src-id (:build-sources state)
          :let [{:keys [ns file] :as src}
                (get-in state [:sources src-id])
                {:shadow/keys [js-access-properties]}
                (get-in state [:compiler-env :cljs.analyzer/namespaces ns])]
          :when (contains? js-access-properties "")]
    (prn [:found ns js-access-properties]))


Peter Muys16:02:26

Got [:found glas-editor.plugin-paste #{""}]

Peter Muys16:02:46

Looks like my code


would be curious to see what that does and how ends up adding an empty property

Peter Muys16:02:44

This is the function

(defn plugin-paste []
			{:on-cm-init (fn [editor config state]
											 (cm/on-paste editor (fn [editor event]
																							 (on-paste-event editor event))))})


its the entire ns, not the function


none of the would generate any externs

Peter Muys16:02:57

if i change it to 
(defn plugin-paste []

Peter Muys16:02:02

i still get the error


this is the ns glas-editor.plugin-paste


whatever else is in that file matters

Peter Muys16:02:58

I removed the require for the  plugin name space, now i get
[:app] Compiling ... [2021-02-05 17:35:32.949 - INFO] - {:resource-name "node_modules/moment-mini/moment.min.js", :requires [{:line 1, :column 4095}]} ------ WARNING #1 - ----------------------------------------------------------- Resource: node_modules/codemirror/lib/codemirror.js:2 constant module$node_modules$codemirror$lib$codemirror assigned a value more than once. Original definition at externs.shadow.js:11 --------------------------------------------------------------------------------

Peter Muys16:02:43

/** @const {ShadowJS} */ var location;
/** @const {ShadowJS} */ var module$node_modules$codemirror$lib$codemirror;   <-- ln 11


thats just a warning, you can ignore that


dunno how that happens either but for now it doesn't matter

Peter Muys16:02:07

It did generate a main.js

Peter Muys16:02:01

Ok, I will try removing code bit by bit in glas-editor and let you know what i found. Ok for you?

Peter Muys16:02:19

Found the following code that generates the error:

(ns glas-editor.plugin-paste  
  \["turndown" :as td\]  
 \["turndown-plugin-gfm" :as tdgfm\]  
 (def td-service (td/. (bean/->js {"headingStyle" "atx"  
 "codeBlockStyle" "fenced"})))

td/. is the cause.


how does that even work? thats not a valid JS function name?


@peter085 is that supposed to be (td. ...) without the /?

Peter Muys17:02:50

Doesn't explain the moment-mini error, but does explain the externs problem i think


this is not an error. it is a warning.


just search for require in the code. anything that is not just a plain require call with a string argument is "invalid"


Hi, I'm trying to run-tests using @testing-library/react-native npm module. But I'm getting this error

undefined is not an object (evaluating 'shadow.js.shim.module$$testing_library$react_native.render')
Here is my test file (I think I'm importing it correct, see the js example
(ns limeray.component-test
  (:require [clojure.test :refer [deftest run-tests run-all-tests]]
            ["@testing-library/react-native" :refer [render]]
            [reagent.core :as r]
            [limeray.component :as ui]))

(def jaime (render (r/as-element [ui/button {:title "My Title"}])))

(deftest render-button-with-title
  (as-> (render (r/as-element [ui/button {:title "My Title"}])) $view
    (.getByText $view "My Title")))

Is this something related to externs?


no. there just doesn't seem to be a render function. looks correct otherwise but I don't know the setup. is this running in node or how does it work?


:thinking_face: I'm running shadow-cljs watch app , then using cursive I connected to the repl, then switched to cljs by calling (shadow.cljs.devtools.api/repl :app) The connected client is an android emulator. What I'm doing is to send the run-tests in repl.


yeah that doesn't work. you cannot add requires dynamically in a react-native env. so if you regular app doesn't have this require then adding it via the REPL won't work


but I really don't know anything about how react-native testing works or what kind of setup it requires


Oh ok. Maybe I can try testing it in node-repl and see if it will work. Looking at the library, it is just a wrapper for react-test-renderer which I think deals only with js objects (vdom)


that won't work if your code requires react-native anywhere. since that package needs to be built by metro


I see. looks like I have to do some research how testing works in react-native. Thanks a lot for clarifying. Btw, out of curiosity, you cannot add requires dynamically in a react-native env. In the context of browser env, what does it mean by requiring dynamically? Maybe this will help me understand why its not possible in react-native


Or I would say, what is happening when doing require dynamically.


dynamically as in anything done in the REPL and not at build-time


shadow-cljs just generates some JS for your build but does not provide any JS dependencies


metro will then process that generated JS and actually fill in those dependencies such as react-native itself


this output you then load and all requires that were provided are available


however if you now connect the REPL metro is out of the equation and as such cannot provide JS dependencies anymore


Does that mean if I require lets say the @testing-library/react-native in my production code. Metro will be able to provide it as deps? EDIT: I've just tried it, looks like lib is now being loaded


yes, if you get it into the build somehow it'll be available


Cool. I think I can do this a temp fix for now. Thanks a lot. appreciate your help and explaining in detail 😄