mirror of https://github.com/sveltejs/svelte
fix: ensure custom element attribute/prop changes are in their own context (#14016)
Fixes #13848. When we set custom element attributes/props, we should be doing so without the current effect/reaction active. Otherwise, the custom element lifecycle might attach effects/dependencies to the wrong reaction and all manner of things can incorrectly occur --------- Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>pull/14056/head
parent
4c6255f8dd
commit
cdec39afac
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: ensure custom element attribute/prop changes are in their own context
|
@ -0,0 +1,24 @@
|
||||
import { test } from '../../assert';
|
||||
const tick = () => Promise.resolve();
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
target.innerHTML = '<my-app/>';
|
||||
await tick();
|
||||
await tick();
|
||||
|
||||
/** @type {any} */
|
||||
const el = target.querySelector('my-app');
|
||||
const button = el.shadowRoot.querySelector('button');
|
||||
const p = el.shadowRoot.querySelector('my-tracking').shadowRoot.querySelector('p');
|
||||
|
||||
assert.equal(button.innerHTML, '0');
|
||||
assert.equal(p.innerHTML, 'false');
|
||||
|
||||
button.click();
|
||||
await tick();
|
||||
|
||||
assert.equal(button.innerHTML, '1');
|
||||
assert.equal(p.innerHTML, 'false');
|
||||
}
|
||||
});
|
@ -0,0 +1,31 @@
|
||||
<svelte:options customElement="my-app" />
|
||||
|
||||
<script module>
|
||||
class Tracking extends HTMLElement {
|
||||
static observedAttributes = ["count"];
|
||||
tracking = false;
|
||||
|
||||
set count(_) {
|
||||
this.tracking = $effect.tracking();
|
||||
this.render();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
render() {
|
||||
this.shadowRoot.innerHTML = `<p>${this.tracking}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("my-tracking", Tracking);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
let count = $state(0);
|
||||
</script>
|
||||
|
||||
<button onclick={() => (count += 1)}>{count}</button>
|
||||
<my-tracking {count}></my-tracking>
|
Loading…
Reference in new issue