Skip to content

Skip x-modelable when cloning during a morph - #4939

Open
HawkForge wants to merge 1 commit into
alpinejs:mainfrom
HawkForge:fix/modelable-morph
Open

HawkForge wants to merge 1 commit into
alpinejs:mainfrom
HawkForge:fix/modelable-morph

Conversation

@HawkForge

Copy link
Copy Markdown

Fixes #4928.

Alpine.morph() clones every element it patches with Alpine.cloneNode(). On the clone, x-model already skips its listener, but x-modelable still queues its entangle microtask. That microtask runs after cloneNode() 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:

  1. The entanglement's first run copies the outer value onto the inner one, so a change made to the inner value right after a morph is overwritten.
  2. The clone is thrown away without cleanup, so the entanglement is never released. Each morph adds one more, which adds up in Livewire, where components are morphed on every request.

The fix wraps the x-modelable directive in skipDuringClone(), the same as x-init, x-effect, x-on, x-for and x-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.


Replaces #4929, which got closed when my fork was accidentally detached.

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

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant