fix: add css hash to custom element rendered with `svelte:element` (#12715)

* fix: add css hash to custom element rendered with `svelte:element`

* simplify

* skip arg where possible

* drive-by improvements — remove some unnecessary arguments where possible

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/12735/head
Paolo Ricciuti 3 months ago committed by GitHub
parent 8e04a91c67
commit 93cfa6cd69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: add css hash to custom element rendered with `svelte:element`

@ -470,10 +470,8 @@ function build_element_spread_attributes(
attribute.type === 'SpreadAttribute' && attribute.metadata.expression.has_call; attribute.type === 'SpreadAttribute' && attribute.metadata.expression.has_call;
} }
const lowercase_attributes = const preserve_attribute_case =
element.metadata.svg || element.metadata.mathml || is_custom_element_node(element) element.metadata.svg || element.metadata.mathml || is_custom_element_node(element);
? b.false
: b.true;
const id = context.state.scope.generate('attributes'); const id = context.state.scope.generate('attributes');
const update = b.stmt( const update = b.stmt(
@ -485,8 +483,8 @@ function build_element_spread_attributes(
element_id, element_id,
b.id(id), b.id(id),
b.object(values), b.object(values),
lowercase_attributes, context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash),
b.literal(context.state.analysis.css.hash), preserve_attribute_case && b.true,
is_ignored(element, 'hydration_attribute_changed') && b.true is_ignored(element, 'hydration_attribute_changed') && b.true
) )
) )

@ -200,7 +200,7 @@ function build_dynamic_element_attributes(attributes, context, element_id) {
element_id, element_id,
b.id(id), b.id(id),
b.object(values), b.object(values),
b.literal(context.state.analysis.css.hash) context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash)
) )
) )
); );
@ -221,7 +221,7 @@ function build_dynamic_element_attributes(attributes, context, element_id) {
element_id, element_id,
b.literal(null), b.literal(null),
b.object(values), b.object(values),
b.literal(context.state.analysis.css.hash) context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash)
) )
) )
); );

@ -147,13 +147,19 @@ export function set_custom_element_data(node, prop, value) {
* @param {Element & ElementCSSInlineStyle} element * @param {Element & ElementCSSInlineStyle} element
* @param {Record<string, any> | undefined} prev * @param {Record<string, any> | undefined} prev
* @param {Record<string, any>} next New attributes - this function mutates this object * @param {Record<string, any>} next New attributes - this function mutates this object
* @param {boolean} lowercase_attributes * @param {string} [css_hash]
* @param {string} css_hash * @param {boolean} preserve_attribute_case
* @param {boolean} [skip_warning] * @param {boolean} [skip_warning]
* @returns {Record<string, any>} * @returns {Record<string, any>}
*/ */
export function set_attributes(element, prev, next, lowercase_attributes, css_hash, skip_warning) { export function set_attributes(
var has_hash = css_hash.length !== 0; element,
prev,
next,
css_hash,
preserve_attribute_case = false,
skip_warning
) {
var current = prev || {}; var current = prev || {};
var is_option_element = element.tagName === 'OPTION'; var is_option_element = element.tagName === 'OPTION';
@ -163,8 +169,8 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
} }
} }
if (has_hash && !next.class) { if (css_hash !== undefined) {
next.class = ''; next.class = next.class ? next.class + ' ' + css_hash : css_hash;
} }
var setters = setters_cache.get(element.nodeName); var setters = setters_cache.get(element.nodeName);
@ -267,7 +273,7 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
element.value = element[key] = element.__value = value; element.value = element[key] = element.__value = value;
} else { } else {
var name = key; var name = key;
if (lowercase_attributes) { if (!preserve_attribute_case) {
name = normalize_attribute(name); name = normalize_attribute(name);
} }
@ -279,11 +285,6 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
element[name] = value; element[name] = value;
} }
} else if (typeof value !== 'function') { } else if (typeof value !== 'function') {
if (has_hash && name === 'class') {
if (value) value += ' ';
value += css_hash;
}
set_attribute(element, name, value); set_attribute(element, name, value);
} }
} }
@ -309,7 +310,7 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
* @param {Element} node * @param {Element} node
* @param {Record<string, any> | undefined} prev * @param {Record<string, any> | undefined} prev
* @param {Record<string, any>} next The new attributes - this function mutates this object * @param {Record<string, any>} next The new attributes - this function mutates this object
* @param {string} css_hash * @param {string} [css_hash]
*/ */
export function set_dynamic_element_attributes(node, prev, next, css_hash) { export function set_dynamic_element_attributes(node, prev, next, css_hash) {
if (node.tagName.includes('-')) { if (node.tagName.includes('-')) {
@ -319,6 +320,10 @@ export function set_dynamic_element_attributes(node, prev, next, css_hash) {
} }
} }
if (css_hash !== undefined) {
next.class = next.class ? next.class + ' ' + css_hash : css_hash;
}
for (key in next) { for (key in next) {
set_custom_element_data(node, key, next[key]); set_custom_element_data(node, key, next[key]);
} }
@ -330,8 +335,8 @@ export function set_dynamic_element_attributes(node, prev, next, css_hash) {
/** @type {Element & ElementCSSInlineStyle} */ (node), /** @type {Element & ElementCSSInlineStyle} */ (node),
prev, prev,
next, next,
node.namespaceURI !== NAMESPACE_SVG, css_hash,
css_hash node.namespaceURI !== NAMESPACE_SVG
); );
} }

@ -0,0 +1,14 @@
import { ok, test } from '../../test';
export default test({
html: `<custom-element class="red svelte-p153w3"></custom-element><custom-element class="red svelte-p153w3"></custom-element>`,
async test({ assert, target }) {
const [el, el2] = target.querySelectorAll('custom-element');
ok(el);
ok(el2);
assert.deepEqual(el.className, 'red svelte-p153w3');
assert.deepEqual(el2.className, 'red svelte-p153w3');
}
});

@ -0,0 +1,8 @@
<svelte:element this={'custom-element'} class="red"></svelte:element>
<custom-element class="red"></custom-element>
<style>
.red {
color: red;
}
</style>
Loading…
Cancel
Save