fix: add already connected validation

svelte-element-element
paoloricciuti 6 months ago
parent 91be79d58a
commit 7903a35519

@ -133,3 +133,9 @@ Reading state that was created inside the same derived is forbidden. Consider us
``` ```
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state` Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
``` ```
### svelte_element_already_connected
```
You can't use an HTML element as the `this` attribute of `svelte:element` if it's already connected to a document
```

@ -87,3 +87,7 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long
## state_unsafe_mutation ## state_unsafe_mutation
> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state` > Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
## svelte_element_already_connected
> You can't use an HTML element as the `this` attribute of `svelte:element` if it's already connected to a document

@ -23,6 +23,7 @@ import { DEV } from 'esm-env';
import { EFFECT_TRANSPARENT } from '../../constants.js'; import { EFFECT_TRANSPARENT } from '../../constants.js';
import { assign_nodes } from '../template.js'; import { assign_nodes } from '../template.js';
import { is_raw_text_element } from '../../../../utils.js'; import { is_raw_text_element } from '../../../../utils.js';
import * as e from '../../errors.js';
/** /**
* @param {Comment | Element} node * @param {Comment | Element} node
@ -70,11 +71,19 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
block(() => { block(() => {
const next_tag = get_tag() || null; const next_tag = get_tag() || null;
var ns = get_namespace ? get_namespace() : is_svg || next_tag === 'svg' ? NAMESPACE_SVG : null; var ns = get_namespace
? get_namespace()
: is_svg || (typeof next_tag === 'string' ? next_tag === 'svg' : next_tag?.tagName === 'svg')
? NAMESPACE_SVG
: null;
// Assumption: Noone changes the namespace but not the tag (what would that even mean?) // Assumption: Noone changes the namespace but not the tag (what would that even mean?)
if (next_tag === tag) return; if (next_tag === tag) return;
if (typeof next_tag !== 'string' && next_tag?.isConnected) {
e.svelte_element_already_connected();
}
// See explanation of `each_item_block` above // See explanation of `each_item_block` above
var previous_each_item = current_each_item; var previous_each_item = current_each_item;
set_current_each_item(each_item_block); set_current_each_item(each_item_block);

@ -335,4 +335,19 @@ export function state_unsafe_mutation() {
} else { } else {
throw new Error(`https://svelte.dev/e/state_unsafe_mutation`); throw new Error(`https://svelte.dev/e/state_unsafe_mutation`);
} }
}
/**
* You can't use an HTML element as the `this` attribute of `svelte:element` if it's already connected to a document
* @returns {never}
*/
export function svelte_element_already_connected() {
if (DEV) {
const error = new Error(`svelte_element_already_connected\nYou can't use an HTML element as the \`this\` attribute of \`svelte:element\` if it's already connected to a document\nhttps://svelte.dev/e/svelte_element_already_connected`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/svelte_element_already_connected`);
}
} }

@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
test({ assert, target }) {
const btn = target.querySelector('button');
assert.throws(() => {
flushSync(() => {
btn?.click();
});
}, 'svelte_element_already_connected');
}
});

@ -0,0 +1,9 @@
<script>
let div = $state(null);
let show = $state(false);
</script>
<div bind:this={div}></div>
<button onclick={() => show = !show}></button>
<svelte:element this={show && div}>
</svelte:element>
Loading…
Cancel
Save