shadow-cljs

mkarp 2025-04-29T13:02:49.201119Z

Hey there! We’re trying to upgrade shadow-cljs from 2.25.5 to a newer 2.x version and we’re hitting a pretty obscure issue: when running Cypress tests against a dev build, Cypress stalls at a particular point. The problem is that there are no errors or other messages in the browser console — the test runner is simply not proceeding, restarting the test doesn’t help, and the only way to run the tests again is to restart the Cypress test runner; browser seems to be fine and not frozen. We’ve tried to attack the problem as a blackbox (as there’s no useful reporting) from different angles, and so far couldn’t point it to anything specific. However, two symptoms are notable: • the issue starts to occur at either shadow-cljs 2.26.6 (our app fails to build) or 2.26.7 (builds and runs just fine, except the issue with the dev build in Cypress), 2.26.5 works, any version above it doesn’t work; • the issue starts to occur at some point when including a bit more code: we’re commenting out namespace requires, bringing them back one by one, and at some point the issue starts to occur again; however we couldn’t pin point it to a particular namespace; we could pin point it once to a fairly big static hashmap; it almost feels like there’s a threshold which Cypress test runner can handle, and once you reach it the runner stalls. So the question: were there any particular changes around shadow-cljs 2.26.6-2.26.7 that could at least remotely have caused this? I’ve been reading the changelogs but there’s nothing obvious from my point of view. Thanks!

thheller 2025-04-29T13:08:36.174889Z

https://github.com/thheller/shadow-cljs/commit/561d4990d4ee8bbdb50fad537b5e9c4cd32f96c4 this maybe? although I don't see how, unless you also changed your cypress version in this upgrade process?

thheller 2025-04-29T13:09:02.865089Z

basically that change was only relaxing requirements. as previously it would fail to compile

thheller 2025-04-29T13:09:53.053459Z

but I'm guessing if cypress does any kind of lazy loading via import() then it maybe goes async in a case where it didn't before?

thheller 2025-04-29T13:10:31.825859Z

my guess is in general would be async related. as in something goes async, but never fulfills its promise, calls a callback, etc?

mkarp 2025-04-29T13:12:58.950909Z

Sounds plausible 👍 Is there are a way to temporarily disable dynamic loading in shadow to try it out?

thheller 2025-04-29T13:13:41.403269Z

you misunderstand the purpose of this. there is no dynamic loading happening at all ever. the point was to remove it, well kind of

thheller 2025-04-29T13:15:22.013019Z

but no, there is no way to get back to old behavior. but the build wouldn't have worked before this change anyway, so I doubt this is really related?

thheller 2025-04-29T13:15:55.580289Z

meaning that if shadow-cljs ran into a npm dependency before that tried to use import() it would hard fail with an error

thheller 2025-04-29T13:16:00.373979Z

now it doesn't

thheller 2025-04-29T13:16:11.999109Z

you didn't run into a hard fail. so that doesn't seem to be it

thheller 2025-04-29T13:16:28.419879Z

> unless you also changed your cypress version in this upgrade process?

thheller 2025-04-29T13:16:29.928359Z

did you?

mkarp 2025-04-29T13:16:32.370749Z

Yes, that’s correct, we didn’t have failures prior

mkarp 2025-04-29T13:16:37.048269Z

No, Cypress is the same as before

mkarp 2025-04-29T13:17:41.365699Z

as in something goes async, but never fulfills its promise, calls a callback, etc?This looks almost like the problem I’m dealing with, now I need to figure out what’s causing it

thheller 2025-04-29T13:18:35.091639Z

does it always go to the same spot where it gets "stuck"?

mkarp 2025-04-29T13:20:13.981849Z

Yes, that’s where I’m looking now 👍

mkarp 2025-04-29T13:20:32.934919Z

Will keep this thread updated if I find anything specific

mkarp 2025-04-29T13:20:35.962179Z

Thanks!

thheller 2025-04-29T13:21:14.930649Z

FWIW there is a way to find if any dynamic imports are used, because it is a bit suspicious it starting to fail with that shadow-cljs version

thheller 2025-04-29T13:21:43.642989Z

could be shadow misidentifying a code pattern and changing code it shouldn't

👍 1
thheller 2025-04-29T13:27:43.782289Z

(->> (shadow/compile! :your-test-build {})
     (:sources)
     (vals)
     (filter #(= :shadow-js (:type %)))
     (filter #(seq (:js-dynamic-imports %)))
     (vec))

thheller 2025-04-29T13:27:54.464809Z

runs this over the REPL, e.g. npx shadow-cljs clj-repl. change :your-test-build to whatever your build id is

thheller 2025-04-29T13:28:44.833249Z

I'd expect that to return an empty vector, but maybe it doesn't?

mkarp 2025-04-29T13:38:13.140729Z

Yes, empty

thheller 2025-04-29T13:40:56.113809Z

I suppose you could try a local shadow-cljs checkout and use a more recent version with the commit above removed? however that works in git 😛

thheller 2025-04-29T13:41:44.125539Z

or take the .class file from an earlier jar and put it into your classpath 😛

thheller 2025-04-29T13:42:41.433129Z

kinda suspicious you reported a commit that I expected to cause a lot of breakage, but haven't heard of a single one until now

mkarp 2025-04-29T17:42:22.382039Z

I’ve spent a few more hours digging, and figured that Cypress’s cy.intercept() stalls network calls when combined with shadow-cljs 2.26.6+, js/fetch never gets resolved/rejected. I guess the next step would be to check how they have implemented cy.intercept() and why it clashes

thheller 2025-04-29T17:44:54.063789Z

not sure what that is, so can't say much

mkarp 2025-04-29T17:54:27.457589Z

Actually, scratch that. We might have done something weird in the way we’re intercepting loading of all resources. including js. Might be a user error in the end! Thanks for the support 🙏

thheller 2025-04-29T17:55:45.764209Z

still doesn't explain why it would break only when changing shadow-cljs version? 😛

mkarp 2025-04-29T18:09:29.695489Z

I’ll check again but I think all js urls were accidentally intercepted, and maybe this could have made loading to become very slow? I’ll have to look into the exact mechanism how network requests are intercepted there