squint

Chris McCormick 2025-10-05T00:49:37.037959Z

Eucalyptus is what makes koala bears sleepy all the time. 🐨 Be careful, nobody wants a slow-down in the Borkdude productivity machine. 🙀

borkdude 2025-10-06T07:31:12.441189Z

ok hopefully we can discover a minimal repro

Chris McCormick 2025-10-06T12:44:14.795539Z

It seems to be something to do with the way SVG elements are being appended to an existing SVG element. I can only get the bug to manifest in the browser, not in a test, because the there's no way in the happy-dom environment to check if it's actually visible. I think I know how to fix it though.

Chris McCormick 2025-10-06T13:22:17.365489Z

Hooray, I managed to get a repro test case failing: https://github.com/chr15m/eucalypt/pull/9/files

borkdude 2025-10-06T13:25:20.420999Z

Awesome!

Chris McCormick 2025-10-06T14:22:48.078579Z

Fixed. I linked to the games page from the main demo page now. If you update your snake demo in the squint playground to Eucalypt 0.0.8 it works.

borkdude 2025-10-06T14:23:58.117839Z

What was the issue?

2025-10-06T15:49:32.196119Z

I wonder if it intended to use rswap! which is intended for recursive reactive atom swappage?

2025-10-06T15:50:16.153729Z

and by intended I mean slept walk to the piano and played the first few notes of a song it once heard on the radio

Chris McCormick 2025-10-07T11:03:15.403569Z

The issue was the SVG namespace handling. Basically the LLM's initial logic for deciding which namespace to use during createElementNS was broken. I replaced it with something leaner that doesn't require state outside the patcher.

borkdude 2025-10-07T12:50:37.064779Z

👍 🙏

borkdude 2025-10-05T08:10:28.012239Z

I must say it smells ok, but the taste...

😅 1
borkdude 2025-10-05T08:14:40.092629Z

According to LLM eucalypt isn't sedative for humans nor koalas 😅

borkdude 2025-10-05T08:17:12.444729Z

Btw this open issue about the games page, is that still relevant? I couldn't find the games branch

Chris McCormick 2025-10-05T12:21:05.969519Z

Oh it's actually merged into main now. You can got to localhost:8000/games.html to see the bug.

Chris McCormick 2025-10-05T12:21:27.937159Z

Click a tab and then another tab and the buttons disappear or double up, depending on the order you click tabs.

Chris McCormick 2025-10-05T12:21:38.341979Z

I've been trying to understand the bug today but not getting very far.

Chris McCormick 2025-10-05T12:27:29.745759Z

I did manage to get a failing test case working though so that's progress: https://github.com/chr15m/eucalypt/actions/runs/18258701125/job/51983658743 https://github.com/chr15m/eucalypt/commit/b05b2ffa80221d73728a6c3c80439a25aa56b338

Chris McCormick 2025-10-05T13:34:31.046079Z

Ok I figured out why this bug is happening and it's really silly. The LLM used r/atom instead of a regular atom when setting up timers. So there's some deeply nested recursive re-rendering happening. So the bug is in the test really, however I did run it against real Reagent which handles it fine. So I need to figure out what to do there. But in the meantime I can upload the games page which now works.

Chris McCormick 2025-10-05T13:37:25.745629Z

I think it comes down to swap! in ClojureScript being atomic, whereas in Eucalypt the swap! is on a fake atom and so two of them run at the same time and overlap.

Chris McCormick 2025-10-05T13:37:35.701729Z

Because the second one is happening off a timer. 🤔

Chris McCormick 2025-10-05T13:50:07.317579Z

Actually Eucalypt defers swap! to the Squint implementation, and I think it's not atomic. So a swap! on a timer that causes a re-render breaks things if it's already in the middle of a render. I guess I'd have to implement some locking mechanism in the render loop. 😵‍💫

borkdude 2025-10-05T14:43:00.503789Z

what do you mean with swap! in squint not being atomic?

borkdude 2025-10-05T18:22:18.434419Z

CLJS's swap! is just the same as (reset! foo (f @foo)) . Since JS has no threads, this will always happen "atomically", since this code is synchronous

borkdude 2025-10-05T18:39:07.925009Z

So this remark doesn't make sense. Squint's swap! is just as "atomic" as CLJS's. https://github.com/chr15m/eucalypt/commit/0ba0b9777ea1f84ce2fd7f1156447fcc64f6c614 Also the remark before it you can remove now

borkdude 2025-10-05T18:46:58.922739Z

atoms in clojurescript are just mutable boxes, there is nothing special to them, no locking mechanisms whatsoever - because it is JS there are no threads and there is no locking. It's implemented in squint the same way

1
Chris McCormick 2025-10-06T00:43:01.509359Z

Ah yes true. Thanks, I have removed those two statements from the README.

Chris McCormick 2025-10-06T00:43:58.527319Z

There must be something else going on which is causing a re-render during the initial render. The problem went away when I changed from Eucalypt's r/atom to a regular atom in the timers in https://github.com/chr15m/eucalypt/blob/main/src/test/src/timers_and_buttons.test.cljs#L24. So Eucalypt is doing something to trigger a re-render when the timer atoms are created, which is different to Reagent. Maybe :ref is called too early. 🤔 I'll create a new failing test and see if I can get to the bottom of it.

👍 1
Chris McCormick 2025-10-06T00:48:10.512019Z

I also realized in the Snake demo the "Game Over!" does not appear unless I force re-render, but clicking 'compile!' in the sandbox, or navigating between tabs in the demo page shows it up.

👍 1
Chris McCormick 2025-10-05T00:51:16.046779Z

Wait never mind, I asked the LLMs and they said humans hallucinated this.

🥴 2
Chris McCormick 2025-10-05T13:05:21.569329Z

TIL: https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone - available in browser & Node. I imagine this would be fast.

borkdude 2025-10-05T13:34:29.134169Z

Is there also structuredEquals?

Chris McCormick 2025-10-05T13:35:16.228519Z

I wish. I guess if it existed the isEqual function wouldn't be needed.

2025-10-06T02:06:23.176239Z

I tried to use this once but was disappointed. I can't remember what the limitation was, I think it doesn't support the symbol type In the end I had to write my own recursive function

Chris McCormick 2025-10-06T02:13:52.077169Z

Ah ok so if there's a js/Symbol in there it might fail.