shadow-cljs

Ryan 2025-09-22T21:00:43.743099Z

Getting a new error when trying to build for release:

--- externs.shadow.js:17
Parse error. 'identifier' expected

Error while executing task: -compile
externs.shadow.js shows
/** @const {ShadowJS} */ var ArrayBuffer;
/** @const {ShadowJS} */ var Float64Array;
/** @const {ShadowJS} */ var JSJodaLocale;
/** @const {ShadowJS} */ var Uint32Array;
/** @const {ShadowJS} */ var Uint8Array;
/** @const {ShadowJS} */ var clearInterval;
/** @const {ShadowJS} */ var clearTimeout;
/** @const {ShadowJS} */ var decodeURIComponent;
/** @const {ShadowJS} */ var history;
/** @const {ShadowJS} */ var localStorage;
/** @const {ShadowJS} */ var location;
/** @const {ShadowJS} */ var module;
/** @const {ShadowJS} */ var navigator;
/** @const {ShadowJS} */ var sessionStorage;
/** @const {ShadowJS} */ var setDarkMode;
/** @const {ShadowJS} */ var setInterval;
/** @const {ShadowJS} */ var typeof;
ShadowJS.prototype.$$typeof;
ShadowJS.prototype.$_pfocustrap_firsthiddenfocusableelement;
ShadowJS.prototype.$_pfocustrap_lasthiddenfocusableelement;
ShadowJS.prototype.$attrs;
ShadowJS.prototype.A;
;
(abbreviated) .. any clues? watching build seems fine

thheller 2025-09-23T11:50:55.328749Z

only thing that looks suspicious to me is /** @const {ShadowJS} */ var typeof;

thheller 2025-09-23T11:52:04.392819Z

guessing for some reason it collected this as an extern it needs to generate. dunno how though.

Ryan 2025-09-23T12:21:53.944849Z

Hmmm.. is this a ‘figure out which node package is screwing me up’ sort of deal?

thheller 2025-09-23T13:48:34.690019Z

I wonder where it is coming from though. since the externs listed in that file are usually collected from CLJS files using JS, not the JS itself?

thheller 2025-09-23T13:50:03.916999Z

does any of your CLJS code contain a reference to typeof?

Ryan 2025-09-23T13:50:32.896859Z

A good question, let me check

Ryan 2025-09-23T13:53:36.793899Z

nothing in my code, but when I look at all cljs code in intellij, I get some results like:

(defn type-of [x]
                 
         (js* "typeof ~{}" x))
;;;;;;;;;;;; This file autogenerated from src/cljx/schema/utils.cljx

thheller 2025-09-23T13:54:16.869189Z

that wouldn't generate externs

thheller 2025-09-23T13:54:31.764929Z

try this at the CLJ REPL

(->> (shadow/compile* :your-build)
     (:compiler-env)
     (:cljs.analyzer/namespaces)
     (vals)
     (filter (fn [{:shadow/keys [js-access-globals] :as x}]
               (contains? js-access-globals "typeof"))))

thheller 2025-09-23T13:55:11.754159Z

that should have one hit

Ryan 2025-09-23T13:55:28.844479Z

Execution error (ArityException) at shadow.user/eval84850 (REPL:1). Wrong number of args (1) passed to: shadow.cljs.devtools.api/compile*

thheller 2025-09-23T13:55:32.676229Z

just change :your-build to whatever your build if is of course

thheller 2025-09-23T13:55:41.374399Z

oh right add a second {} arg there

Ryan 2025-09-23T13:56:50.056359Z

(->> (shadow/compile* :pnx {}) (:compiler-env) (:cljs.analyzer/namespaces) (vals) (filter (fn [{:shadow/keys [js-access-globals] :as x}] (contains? js-access-globals “typeof”)))) [null] Compiling ... Execution error (AssertionError) at shadow.build/configure (build.clj:314). Assert failed: (map? config)

thheller 2025-09-23T13:57:36.754589Z

(->> (shadow/compile* (shadow/get-config! :pnx) {})
     (:compiler-env)
     (:cljs.analyzer/namespaces)
     (vals)
     (filter (fn [{:shadow/keys [js-access-globals] :as x}]
               (contains? js-access-globals "typeof"))))

thheller 2025-09-23T13:58:29.489099Z

sorry I don't know my own APIs 😛

thheller 2025-09-23T13:58:48.503799Z

(->> (shadow/compile* (shadow/get-build-config :pnx) {})
     (:compiler-env)
     (:cljs.analyzer/namespaces)
     (vals)
     (filter (fn [{:shadow/keys [js-access-globals] :as x}]
               (contains? js-access-globals "typeof"))))

thheller 2025-09-23T13:58:49.495029Z

that one

Ryan 2025-09-23T13:58:55.144469Z

I can’t say I know them any better 😉

Ryan 2025-09-23T14:00:06.026069Z

… it built id just fine, no hits

Ryan 2025-09-23T14:01:29.812139Z

:builds            {:pnx          {:target            :browser
                                    :output-dir        "resources/public/js/compiled"
                                    :asset-path        "/js/compiled"
                                    :js-options        {:minimize-require false}
                                    :module-hash-names true
                                    :modules           {:pnx-web {:init-fn pnx-web.core/init}}
                                    :devtools          {:preloads [day8.re-frame-10x.preload]}
                                    :dev               {:compiler-options
                                                        {:optimizations   :none
                                                         :closure-defines {re-frame.trace.trace-enabled?        true
                                                                           day8.re-frame.tracing.trace-enabled? true}}}
                                    :release           {:output-dir    "dist/public/js/compiled"
                                                        :build-options {:ns-aliases {day8.re-frame.tracing day8.re-frame.tracing-stubs}}}}

Ryan 2025-09-23T14:01:40.036079Z

that’s the build config in case there’s something screwy with it

thheller 2025-09-23T14:02:04.196869Z

maybe just try deleting the .shadow-cljs/builds/pnx/release dir. maybe some bad cache for some reason

thheller 2025-09-23T14:02:11.198569Z

that looks fine

thheller 2025-09-23T14:03:21.608589Z

I mean it could be possible that its related to the :release tracing switch and thus not showing up for compile*

thheller 2025-09-23T14:03:32.570039Z

but the trick above won't work for release* if that doesn't build

thheller 2025-09-23T14:04:41.798949Z

I mean you can set :js-options {:generate-externs false} in the config and see if that fixes it

Ryan 2025-09-23T14:04:47.345419Z

yeah same issue

thheller 2025-09-23T14:05:06.510199Z

but it may then lack some externs and cause other issues

Ryan 2025-09-23T14:08:14.484709Z

sure

Ryan 2025-09-23T14:08:19.593079Z

gosh, same thing.

thheller 2025-09-23T14:09:07.269889Z

ah right no. that just turns off externs from JS files, not CLJS files

thheller 2025-09-23T14:09:42.245629Z

so yeah the only source this could be coming from technically is the CLJS source using js/typeof.foo

thheller 2025-09-23T14:10:40.258169Z

otherwise I really do not understand where this may be coming from

Ryan 2025-09-23T14:11:04.773519Z

Yeah me neither

thheller 2025-09-23T14:11:15.535829Z

ShadowJS.prototype.$$typeof; these things are possibly collected from npm JS sources

thheller 2025-09-23T14:11:22.947019Z

/** @const {ShadowJS} */ var typeof; but this is not

Ryan 2025-09-23T14:11:28.533829Z

aha ok

thheller 2025-09-23T14:11:40.330919Z

they normally only come from CLJS code using js/anything

Ryan 2025-09-23T14:11:45.527309Z

yeah there are heaps of them from the materialdesignicons npm module

thheller 2025-09-23T14:12:42.803189Z

do you have any simplified externs? https://shadow-cljs.github.io/docs/UsersGuide.html#_simplified_externs

thheller 2025-09-23T14:12:54.128869Z

I mean global:typeof would explain it too 😛

Ryan 2025-09-23T14:13:46.990339Z

no simplified externs

thheller 2025-09-23T14:14:00.664779Z

> yeah there are heaps of them from the materialdesignicons npm module

thheller 2025-09-23T14:14:03.210479Z

what does that mean? there aren't and js/anything references in npm code

thheller 2025-09-23T14:15:25.440589Z

that is the code where the /** @const {ShadowJS} */ things come from. thus it not showing up for yours is weird

Ryan 2025-09-23T14:15:53.154049Z

ShadowJS.prototype.mdiArrowRightCircleOutline;

thheller 2025-09-23T14:16:14.885729Z

thats the different kind and not global

Ryan 2025-09-23T14:16:21.568049Z

ah yeah, right

Ryan 2025-09-23T14:16:34.767139Z

only the top 17 or so are the global ones from the snipped

Ryan 2025-09-23T14:16:57.382989Z

I’ve searched for typeof in the whole repo and its only present on js side

thheller 2025-09-23T14:19:34.981499Z

only other thing I can think of is going into the CLJ repl

thheller 2025-09-23T14:19:50.191859Z

then (in-ns 'shaodw.build.closure)

thheller 2025-09-23T14:20:02.403679Z

then just redefining the function generating this stuff

thheller 2025-09-23T14:20:27.737179Z

(defn extern-globals-from-cljs [state]
  (->> (:build-sources state)
       (map #(get-in state [:sources %]))
       (filter #(= :cljs (:type %)))
       (map (fn [{:keys [ns file] :as src}]
              ;; we know those don't need externs
              (when (not= ns 'cljs.core)
                (let [{:shadow/keys [js-access-global]}
                      (get-in state [:compiler-env :cljs.analyzer/namespaces ns])]
                      (prn [:ext ns js-access-global])
                      js-access-global
                  ))))
       (reduce set/union #{})))

thheller 2025-09-23T14:20:58.583319Z

then just doing a release build, which should then print all the extern properties it collected before the build fails

thheller 2025-09-23T14:21:19.821249Z

(just added the prn there, might be easier if that already does the "typeof" check and only printing that)

Ryan 2025-09-23T14:23:16.841229Z

[:ext pnx.data.types #{“typeof”}]

Ryan 2025-09-23T14:23:29.662459Z

that looks like a problem!

Ryan 2025-09-23T14:24:36.404899Z

aha, it alluded me because its a cljc file

Ryan 2025-09-23T14:25:22.539389Z

:cljs [:fn #(= (js/typeof % "bigint"))])

thheller 2025-09-23T14:25:34.436789Z

aha. hmm that is totally legit

thheller 2025-09-23T14:27:21.142989Z

guess that just needs to be added to the filter so it doesn't try to turn it into externs

thheller 2025-09-23T14:29:20.497479Z

let me lookup one other thing and then I can make a new release to fix this

Ryan 2025-09-23T14:30:37.953359Z

awesome, thanks

thheller 2025-09-23T14:51:35.052709Z

I just pushed the 3.2.1 version with a fix for this

Ryan 2025-09-23T14:51:54.734069Z

Gosh thats fast! thanks!

Bryce Tichit 2025-09-22T22:31:09.515329Z

Hello ! I've got an issue with a package that is ESM only, obviously I can't import it from cjs code

[minisite-publish] error: Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/node_modules/react-markdown/index.js from /var/task/dist/minisite-ssr.js not supported.
Instead change the require of index.js in /var/task/dist/minisite-ssr.js to a dynamic import() which is available in all CommonJS modules.
    at /opt/rust/nodejs.js:2:13528
    at  (/opt/rust/nodejs.js:2:13906)
    at Le.e.<computed>.De._load (/opt/rust/nodejs.js:2:13498)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}
So I tried to use a dynamic import and use :target esm instead but now some browser code got included in the build
ReferenceError: document is not defined
    at shadow$provide.<computed> (file:///var/task/dist/minisite-ssr/main.mjs:122:314)
    at lh (file:///var/task/dist/minisite-ssr/main.mjs:680:472)
    at shadow$provide.<computed> (file:///var/task/dist/minisite-ssr/main.mjs:148:289)
    at lh (file:///var/task/dist/minisite-ssr/main.mjs:680:472)
    at shadow$provide.<computed> (file:///var/task/dist/minisite-ssr/main.mjs:281:46)
    at lh (file:///var/task/dist/minisite-ssr/main.mjs:680:472)
    at shadow$provide.<computed> (file:///var/task/dist/minisite-ssr/main.mjs:303:81)
    at lh (file:///var/task/dist/minisite-ssr/main.mjs:680:472)
    at shadow$provide.<computed> (file:///var/task/dist/minisite-ssr/main.mjs:304:175)
    at lh (file:///var/task/dist/minisite-ssr/main.mjs:680:472)
Any ideas how I could solve this? Can spin-up a github repo if needed, thanks !

borkdude 2025-09-24T10:54:35.515809Z

It works as long as libs don’t use top level await

thheller 2025-09-23T11:46:02.082639Z

:target :esm defaults to assuming a browser runtime. if not set :runtime :node in the build config

thheller 2025-09-23T11:47:24.490119Z

in my experience it is easier to just go with ESM if any ESM node packages are involved

thheller 2025-09-23T11:47:56.270249Z

it may work for a number of reasons, e.g. different versions of certain packages?

Bryce Tichit 2025-09-23T16:45:00.336329Z

Great thanks, I switched to a cJS equivalent library but I will try : runtime :node Again thanks for your amazing work on shadow-cljs, it's a beautiful piece of software it worked because nowadays modern Node.js allow requiring ESM modules from cJS but that feature is not guaranteed everywhere somehow (might be behind a feature flag)

thheller 2025-09-23T17:06:58.947199Z

oh really? didn't know that. that should solve some headaches

Bryce Tichit 2025-09-22T22:44:38.886109Z

Something really strange is that this happens only on Vercel (prod PaaS provider) not on my laptop locally, weird

Bryce Tichit 2025-09-22T23:05:28.376259Z

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = PropositionCaseStudy;
var _react = _interopRequireDefault(require("react"));
var _reactMarkdown = _interopRequireDefault(require("react-markdown"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
That's my compiled file with babel, the require("react-markdown") should fail here since it's CJS calling an ESM package but it's working great on my laptop. Is that magic? 😅

Bryce Tichit 2025-09-22T23:51:40.562239Z

Ok the reason it works on my local machine is that my Node version allows require of ESM modules but the one provided by Vercel does not

Bryce Tichit 2025-09-22T23:52:03.235399Z

I might simply drop using Vercel for my backend but curious to have your take here