fix: class:directive not working with $$restProps (#15389)

* add spread to test

* fix #15386

* do no set cssHash on non-scoped element

* changeset
pull/15394/head
adiGuba 7 months ago committed by GitHub
parent da98c894b8
commit cf56973bf0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,6 @@
---
'svelte': patch
---
fix: class:directive not working with $$restProps #15386
fix: spread add an useless cssHash on non-scoped element

@ -88,7 +88,9 @@ export function build_set_attributes(
element_id,
is_dynamic ? attributes_id : b.literal(null),
b.object(values),
context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash),
element.metadata.scoped &&
context.state.analysis.css.hash !== '' &&
b.literal(context.state.analysis.css.hash),
preserve_attribute_case,
is_custom_element,
is_ignored(element, 'hydration_attribute_changed') && b.true

@ -368,9 +368,10 @@ function build_element_spread_attributes(
})
);
const css_hash = context.state.analysis.css.hash
? b.literal(context.state.analysis.css.hash)
: b.null;
const css_hash =
element.metadata.scoped && context.state.analysis.css.hash
? b.literal(context.state.analysis.css.hash)
: b.null;
const args = [object, css_hash, classes, styles, flags ? b.literal(flags) : undefined];
context.state.template.push(b.call('$.spread_attributes', ...args));

@ -326,8 +326,16 @@ export function set_attributes(
continue;
}
if (key === 'class') {
var is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
current[key] = value;
current[CLASS] = next[CLASS];
continue;
}
var prev_value = current[key];
if (value === prev_value && key !== 'class') continue;
if (value === prev_value) continue;
current[key] = value;
@ -377,9 +385,6 @@ export function set_attributes(
// @ts-ignore
element[`__${event_name}`] = undefined;
}
} else if (key === 'class') {
var is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
} else if (key === 'style' && value != null) {
element.style.cssText = value + '';
} else if (key === 'autofocus') {

@ -6,8 +6,8 @@ import { hydrating } from '../hydration.js';
* @param {boolean | number} is_html
* @param {string | null} value
* @param {string} [hash]
* @param {Record<string, boolean>} [prev_classes]
* @param {Record<string, boolean>} [next_classes]
* @param {Record<string, any>} [prev_classes]
* @param {Record<string, any>} [next_classes]
* @returns {Record<string, boolean> | undefined}
*/
export function set_class(dom, is_html, value, hash, prev_classes, next_classes) {
@ -34,12 +34,10 @@ export function set_class(dom, is_html, value, hash, prev_classes, next_classes)
// @ts-expect-error need to add __className to patched prototype
dom.__className = value;
} else if (next_classes) {
prev_classes ??= {};
for (var key in next_classes) {
var is_present = !!next_classes[key];
if (is_present !== !!prev_classes[key]) {
if (prev_classes == null || is_present !== !!prev_classes[key]) {
dom.classList.toggle(key, is_present);
}
}

@ -1,4 +1,4 @@
import { flushSync } from 'svelte';
import { flushSync, tick } from 'svelte';
import { test } from '../../test';
// This test counts mutations on hydration
@ -16,7 +16,12 @@ export default test({
html: `
<main id="main" class="browser">
<div class="custom svelte-1cjqok6 foo bar"></div>
<div class="custom svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 foo bar"></span>
<b class="custom foo bar"></b>
<i class="foo bar"></i>
<div class="custom svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 foo bar"></span>
<b class="custom foo bar"></b>
<i class="foo bar"></i>
@ -25,19 +30,97 @@ export default test({
ssrHtml: `
<main id="main">
<div class="custom svelte-1cjqok6 foo bar"></div>
<div class="custom svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 foo bar"></span>
<b class="custom foo bar"></b>
<i class="foo bar"></i>
<div class="custom svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 foo bar"></span>
<b class="custom foo bar"></b>
<i class="foo bar"></i>
</main>
`,
async test({ assert, component, instance }) {
async test({ target, assert, component, instance }) {
flushSync();
tick();
assert.deepEqual(instance.get_and_clear_mutations(), ['MAIN']);
component.foo = false;
flushSync();
assert.deepEqual(instance.get_and_clear_mutations(), ['DIV', 'SPAN', 'B', 'I']);
tick();
assert.deepEqual(
instance.get_and_clear_mutations(),
['DIV', 'SPAN', 'B', 'I', 'DIV', 'SPAN', 'B', 'I'],
'first mutation'
);
assert.htmlEqual(
target.innerHTML,
`
<main id="main" class="browser">
<div class="custom svelte-1cjqok6 bar" title="a title"></div>
<span class="svelte-1cjqok6 bar"></span>
<b class="custom bar"></b>
<i class="bar"></i>
<div class="custom svelte-1cjqok6 bar" title="a title"></div>
<span class="svelte-1cjqok6 bar"></span>
<b class="custom bar"></b>
<i class="bar"></i>
</main>
`
);
component.foo = true;
flushSync();
assert.deepEqual(
instance.get_and_clear_mutations(),
['DIV', 'SPAN', 'B', 'I', 'DIV', 'SPAN', 'B', 'I'],
'second mutation'
);
assert.htmlEqual(
target.innerHTML,
`
<main id="main" class="browser">
<div class="custom svelte-1cjqok6 bar foo" title="a title"></div>
<span class="svelte-1cjqok6 bar foo"></span>
<b class="custom bar foo"></b>
<i class="bar foo"></i>
<div class="custom svelte-1cjqok6 bar foo" title="a title"></div>
<span class="svelte-1cjqok6 bar foo"></span>
<b class="custom bar foo"></b>
<i class="bar foo"></i>
</main>
`
);
component.classname = 'another';
flushSync();
assert.deepEqual(
instance.get_and_clear_mutations(),
['DIV', 'B', 'DIV', 'B'],
'class mutation'
);
assert.htmlEqual(
target.innerHTML,
`
<main id="main" class="browser">
<div class="another svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 bar foo"></span>
<b class="another foo bar"></b>
<i class="bar foo"></i>
<div class="another svelte-1cjqok6 foo bar" title="a title"></div>
<span class="svelte-1cjqok6 bar foo"></span>
<b class="another foo bar"></b>
<i class="bar foo"></i>
</main>
`
);
}
});

@ -33,10 +33,15 @@
</script>
<main id="main" class:browser>
<div class={classname} class:foo class:bar></div>
<div class={classname} title="a title" class:foo class:bar></div>
<span class:foo class:bar></span>
<b class={classname} class:foo class:bar></b>
<i class:foo class:bar></i>
<div {...{class:classname, title:"a title"}} class:foo class:bar></div>
<span {...{}} class:foo class:bar></span>
<b {...{class:classname}} class:foo class:bar></b>
<i {...{}} class:foo class:bar></i>
</main>
<style>

Loading…
Cancel
Save