Skip to content

Commit 6a66c28

Browse files
committed
merge main
2 parents ae8975b + 2f685c1 commit 6a66c28

File tree

4 files changed

+87
-2
lines changed

4 files changed

+87
-2
lines changed

.changeset/real-cameras-attack.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: always use `setAttribute` when setting `style`

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ export function set_custom_element_data(node, prop, value) {
214214
// or effect
215215
var previous_reaction = active_reaction;
216216
var previous_effect = active_effect;
217+
217218
// If we're hydrating but the custom element is from Svelte, and it already scaffolded,
218219
// then it might run block logic in hydration mode, which we have to prevent.
219220
let was_hydrating = hydrating;
@@ -223,17 +224,20 @@ export function set_custom_element_data(node, prop, value) {
223224

224225
set_active_reaction(null);
225226
set_active_effect(null);
227+
226228
try {
227229
if (
230+
// `style` should use `set_attribute` rather than the setter
231+
prop !== 'style' &&
228232
// Don't compute setters for custom elements while they aren't registered yet,
229233
// because during their upgrade/instantiation they might add more setters.
230234
// Instead, fall back to a simple "an object, then set as property" heuristic.
231-
setters_cache.has(node.nodeName) ||
235+
(setters_cache.has(node.nodeName) ||
232236
// customElements may not be available in browser extension contexts
233237
!customElements ||
234238
customElements.get(node.tagName.toLowerCase())
235239
? get_setters(node).includes(prop)
236-
: value && typeof value === 'object'
240+
: value && typeof value === 'object')
237241
) {
238242
// @ts-expect-error
239243
node[prop] = value;
@@ -385,6 +389,9 @@ export function set_attributes(element, prev, next, css_hash, skip_warning = fal
385389
// @ts-ignore
386390
element[`__${event_name}`] = undefined;
387391
}
392+
} else if (key === 'style') {
393+
// avoid using the setter
394+
set_attribute(element, key, value);
388395
} else if (key === 'autofocus') {
389396
autofocus(/** @type {HTMLElement} */ (element), Boolean(value));
390397
} else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
const style_1 = 'invalid-key:0; margin:4px;;color: green ;color:blue ';
5+
const style_2 = ' other-key : 0 ; padding:2px; COLOR:green; color: blue';
6+
7+
// https://github.com/sveltejs/svelte/issues/15309
8+
export default test({
9+
props: {
10+
style: style_1
11+
},
12+
13+
html: `
14+
<div style="${style_1}"></div>
15+
<div style="${style_1}"></div>
16+
17+
<custom-element style="${style_1}"></custom-element>
18+
<custom-element style="${style_1}"></custom-element>
19+
`,
20+
21+
async test({ assert, target, component }) {
22+
component.style = style_2;
23+
flushSync();
24+
25+
assert.htmlEqual(
26+
target.innerHTML,
27+
`
28+
<div style="${style_2}"></div>
29+
<div style="${style_2}"></div>
30+
31+
<custom-element style="${style_2}"></custom-element>
32+
<custom-element style="${style_2}"></custom-element>
33+
`
34+
);
35+
36+
component.style = '';
37+
flushSync();
38+
39+
assert.htmlEqual(
40+
target.innerHTML,
41+
`
42+
<div style=""></div>
43+
<div style=""></div>
44+
45+
<custom-element style=""></custom-element>
46+
<custom-element style=""></custom-element>
47+
`
48+
);
49+
50+
component.style = null;
51+
flushSync();
52+
53+
assert.htmlEqual(
54+
target.innerHTML,
55+
`
56+
<div></div>
57+
<div></div>
58+
59+
<custom-element></custom-element>
60+
<custom-element></custom-element>
61+
`
62+
);
63+
}
64+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
let { style } = $props();
3+
</script>
4+
5+
<div {style}></div>
6+
<div {...{style}}></div>
7+
8+
<custom-element {style}></custom-element>
9+
<custom-element {...{style}}></custom-element>

0 commit comments

Comments
 (0)