From adc1c9d2b580b92446f54f3b78c1212c6831bed5 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 19 Sep 2024 17:06:28 -0400 Subject: [PATCH] fix/optimise --- .../client/visitors/RegularElement.js | 3 ++- .../client/visitors/SvelteElement.js | 15 +++++++---- .../client/dom/elements/attributes.js | 26 ++++++++++--------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js index d004da04110b..3b3888cf5b7e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js @@ -511,7 +511,8 @@ function build_element_spread_attributes( b.object(values), 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, + element.name.includes('-') && b.true ) ) ); diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js index 235d3a3ade29..01bd97003519 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js @@ -1,7 +1,7 @@ /** @import { BlockStatement, Expression, ExpressionStatement, Identifier, ObjectExpression, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import { dev, locator } from '../../../../state.js'; +import { dev, is_ignored, locator } from '../../../../state.js'; import { get_attribute_expression, is_event_attribute, @@ -84,7 +84,7 @@ export function SvelteElement(node, context) { // Always use spread because we don't know whether the element is a custom element or not, // therefore we need to do the "how to set an attribute" logic at runtime. const is_attributes_reactive = - build_dynamic_element_attributes(attributes, inner_context, element_id) !== null; + build_dynamic_element_attributes(node, attributes, inner_context, element_id) !== null; // class/style directives must be applied last since they could override class/style attributes build_class_directives(class_directives, element_id, inner_context, is_attributes_reactive); @@ -137,12 +137,13 @@ export function SvelteElement(node, context) { /** * Serializes dynamic element attribute assignments. * Returns the `true` if spread is deemed reactive. + * @param {AST.SvelteElement} element * @param {Array} attributes * @param {ComponentContext} context * @param {Identifier} element_id * @returns {boolean} */ -function build_dynamic_element_attributes(attributes, context, element_id) { +function build_dynamic_element_attributes(element, attributes, context, element_id) { if (attributes.length === 0) { if (context.state.analysis.css.hash) { context.state.init.push( @@ -202,7 +203,9 @@ function build_dynamic_element_attributes(attributes, context, element_id) { b.id(id), b.object(values), context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash), - b.binary('!==', b.member(element_id, 'namespaceURI'), b.id('$.NAMESPACE_SVG')) + b.binary('!==', b.member(element_id, 'namespaceURI'), b.id('$.NAMESPACE_SVG')), + is_ignored(element, 'hydration_attribute_changed') && b.true, + b.call(b.member(b.member(element_id, 'nodeName'), 'includes'), b.literal('-')) ) ) ); @@ -224,7 +227,9 @@ function build_dynamic_element_attributes(attributes, context, element_id) { b.literal(null), b.object(values), context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash), - b.binary('!==', b.member(element_id, 'namespaceURI'), b.id('$.NAMESPACE_SVG')) + b.binary('!==', b.member(element_id, 'namespaceURI'), b.id('$.NAMESPACE_SVG')), + is_ignored(element, 'hydration_attribute_changed') && b.true, + b.call(b.member(b.member(element_id, 'nodeName'), 'includes'), b.literal('-')) ) ) ); diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 4fe94a50b438..47b73a4a4ee0 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -150,6 +150,7 @@ export function set_custom_element_data(node, prop, value) { * @param {string} [css_hash] * @param {boolean} preserve_attribute_case * @param {boolean} [skip_warning] + * @param {boolean} [is_custom_element] * @returns {Record} */ export function set_attributes( @@ -158,7 +159,8 @@ export function set_attributes( next, css_hash, preserve_attribute_case = false, - skip_warning + skip_warning = false, + is_custom_element = false ) { var current = prev || {}; var is_option_element = element.tagName === 'OPTION'; @@ -261,14 +263,11 @@ export function set_attributes( delegate([event_name]); } } - } else if (value == null) { - attributes[key] = null; - element.removeAttribute(key); - } else if (key === 'style') { + } else if (key === 'style' && value != null) { element.style.cssText = value + ''; } else if (key === 'autofocus') { autofocus(/** @type {HTMLElement} */ (element), Boolean(value)); - } else if (key === '__value' || key === 'value') { + } else if (key === '__value' || (key === 'value' && value != null)) { // @ts-ignore element.value = element[key] = element.__value = value; } else { @@ -277,15 +276,18 @@ export function set_attributes( name = normalize_attribute(name); } - if (setters.includes(name)) { + if (value == null && !is_custom_element) { + attributes[key] = null; + element.removeAttribute(key); + } else if (setters.includes(name) && (is_custom_element || typeof value !== 'string')) { + // @ts-ignore + element[name] = value; + } else if (typeof value !== 'function') { if (hydrating && (name === 'src' || name === 'href' || name === 'srcset')) { - if (!skip_warning) check_src_in_dev_hydration(element, name, value); + if (!skip_warning) check_src_in_dev_hydration(element, name, value ?? ''); } else { - // @ts-ignore - element[name] = value; + set_attribute(element, name, value); } - } else if (typeof value !== 'function') { - set_attribute(element, name, value); } } }