Repository navigation
Conversation
Alpine.morph() clones every element it patches. On the clone, x-modelable still queued its entangle microtask, which ran after cloneNode() had returned and so registered a real effect against the live component's data. That effect copied the outer value back over any inner change made in the meantime, and since the clone is thrown away without cleanup, one entanglement leaked per morph. Wrap the directive in skipDuringClone() like x-init, x-effect and x-on. Fixes alpinejs#4928
|
Thanks for adding the regression tests. I checked The pagination case completed 11 real attribute-observer updates and retained every selected ID. Unchecking and rechecking a row, disabling automatic selection, keeping the notes and focus, and removing and recreating the component also worked. The nested-array case kept two model reads after 0, 1, 5, 10 and 20 morphs. The source files were checked against the base and PR Git blob hashes before compilation. These checks cover standalone Alpine and Morph; the original Livewire application remains untested here. |
|
Thanks for testing it so thoroughly, especially the morph-count and component re-creation cases. |
Fixes #4928.
Alpine.morph()clones every element it patches withAlpine.cloneNode(). On the clone,x-modelalready skips its listener, butx-modelablestill queues its entangle microtask. That microtask runs aftercloneNode()has returned, when effects are real again, so the clone ends up with a live entanglement over the live component's data (the clone shares its data stack).This causes two problems:
The fix wraps the
x-modelabledirective inskipDuringClone(), the same asx-init,x-effect,x-on,x-forandx-if(as @tevinch also suggested in the issue). The clone is only used to seed the morph, so it doesn't need a binding of its own.Tests: two new Cypress tests in
morph.spec.js. One checks that a change made right after a morph is kept; the other checks that changing the value after five morphs reads the outer model the same number of times as before morphing. Both fail without the change.