diff --git a/.changeset/pre.json b/.changeset/pre.json index 0b38a0a5f..b063d166f 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -163,6 +163,7 @@ "loud-cheetahs-flow", "loud-ravens-drop", "lovely-carpets-lick", + "lovely-houses-own", "lovely-items-turn", "lovely-rules-eat", "lucky-schools-hang", @@ -225,6 +226,7 @@ "real-guests-do", "real-items-suffer", "real-pandas-brush", + "red-cycles-pretend", "red-doors-own", "red-feet-worry", "red-poets-study", @@ -297,6 +299,7 @@ "spotty-turkeys-sparkle", "stale-books-perform", "stale-comics-look", + "stale-fans-rest", "stale-jeans-refuse", "strange-apricots-happen", "strong-gifts-smoke", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index b4c264810..820ffb687 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,15 @@ # svelte +## 5.0.0-next.84 + +### Patch Changes + +- fix: reliably remove undefined attributes during hydration ([#10917](https://github.com/sveltejs/svelte/pull/10917)) + +- fix: Add `elementtiming` HTMLAttribute, remove `crossorigin` from HTMLInputAttributes ([#10921](https://github.com/sveltejs/svelte/pull/10921)) + +- feat: shorter compiler output for attribute updates ([#10917](https://github.com/sveltejs/svelte/pull/10917)) + ## 5.0.0-next.83 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 30037ceba..0af78004b 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.0.0-next.83", + "version": "5.0.0-next.84", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts index 01ad67d04..8b4a00c4c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts @@ -32,12 +32,7 @@ export interface ComponentClientTransformState extends ClientTransformState { /** Stuff that happens before the render effect(s) */ readonly init: Statement[]; /** Stuff that happens inside the render effect */ - readonly update: { - /** If the update array only contains a single entry, this singular entry will be used, if present */ - singular?: Statement; - /** Used if condition for singular prop is false (see comment above) */ - grouped: Statement; - }[]; + readonly update: Statement[]; /** Stuff that happens after the render effect (control blocks, dynamic elements, bindings, actions, etc) */ readonly after_update: Statement[]; /** The HTML template string */ diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index 423a13f53..dfca2bcae 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -59,7 +59,7 @@ function get_attribute_name(element, attribute, context) { } /** - * Serializes each style directive into something like `$.style(element, style_property, value)` + * Serializes each style directive into something like `$.set_style(element, style_property, value)` * and adds it either to init or update, depending on whether or not the value or the attributes are dynamic. * @param {import('#compiler').StyleDirective[]} style_directives * @param {import('estree').Identifier} element_id @@ -74,9 +74,10 @@ function serialize_style_directives(style_directives, element_id, context, is_at directive.value === true ? serialize_get_binding({ name: directive.name, type: 'Identifier' }, context.state) : serialize_attribute_value(directive.value, context)[1]; - const grouped = b.stmt( + + const update = b.stmt( b.call( - '$.style', + '$.set_style', element_id, b.literal(directive.name), value, @@ -85,17 +86,6 @@ function serialize_style_directives(style_directives, element_id, context, is_at ) ) ); - const singular = b.stmt( - b.call( - '$.style_effect', - element_id, - b.literal(directive.name), - b.arrow([], value), - /** @type {import('estree').Expression} */ ( - directive.modifiers.includes('important') ? b.true : undefined - ) - ) - ); const contains_call_expression = Array.isArray(directive.value) && @@ -104,11 +94,11 @@ function serialize_style_directives(style_directives, element_id, context, is_at ); if (!is_attributes_reactive && contains_call_expression) { - state.init.push(singular); + state.init.push(serialize_update(update)); } else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) { - state.update.push({ grouped, singular }); + state.update.push(update); } else { - state.init.push(grouped); + state.init.push(update); } } } @@ -146,18 +136,15 @@ function serialize_class_directives(class_directives, element_id, context, is_at const state = context.state; for (const directive of class_directives) { const value = /** @type {import('estree').Expression} */ (context.visit(directive.expression)); - const grouped = b.stmt(b.call('$.class_toggle', element_id, b.literal(directive.name), value)); - const singular = b.stmt( - b.call('$.class_toggle_effect', element_id, b.literal(directive.name), b.arrow([], value)) - ); + const update = b.stmt(b.call('$.toggle_class', element_id, b.literal(directive.name), value)); const contains_call_expression = directive.expression.type === 'CallExpression'; if (!is_attributes_reactive && contains_call_expression) { - state.init.push(singular); + state.init.push(serialize_update(update)); } else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) { - state.update.push({ grouped, singular }); + state.update.push(update); } else { - state.init.push(grouped); + state.init.push(update); } } } @@ -293,23 +280,14 @@ function serialize_element_spread_attributes( const lowercase_attributes = element.metadata.svg || is_custom_element_node(element) ? b.false : b.true; - const id = context.state.scope.generate('spread_attributes'); + const id = context.state.scope.generate('attributes'); - const standalone = b.stmt( - b.call( - '$.spread_attributes_effect', - element_id, - b.thunk(b.array(values)), - lowercase_attributes, - b.literal(context.state.analysis.css.hash) - ) - ); - const inside_effect = b.stmt( + const update = b.stmt( b.assignment( '=', b.id(id), b.call( - '$.spread_attributes', + '$.set_attributes', element_id, b.id(id), b.array(values), @@ -319,32 +297,21 @@ function serialize_element_spread_attributes( ) ); - if (!needs_isolation || needs_select_handling) { - context.state.init.push(b.let(id)); - } + context.state.init.push(b.let(id)); // objects could contain reactive getters -> play it safe and always assume spread attributes are reactive if (needs_isolation) { - if (needs_select_handling) { - context.state.init.push( - b.stmt(b.call('$.render_effect', b.arrow([], b.block([inside_effect])))) - ); - } else { - context.state.init.push(standalone); - } + context.state.init.push(serialize_update(update)); } else { - context.state.update.push({ - singular: needs_select_handling ? undefined : standalone, - grouped: inside_effect - }); + context.state.update.push(update); } if (needs_select_handling) { context.state.init.push( b.stmt(b.call('$.init_select', element_id, b.thunk(b.member(b.id(id), b.id('value'))))) ); - context.state.update.push({ - grouped: b.if( + context.state.update.push( + b.if( b.binary('in', b.literal('value'), b.id(id)), b.block([ // This ensures a one-way street to the DOM in case it's