From 11e4ba017e15a83eb07e611e522a03fa07498e09 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 14 Nov 2024 17:10:09 +0000 Subject: [PATCH 01/23] feat: add support for bind getters/setters --- .../2-analyze/visitors/BindDirective.js | 8 ++ .../client/visitors/BindDirective.js | 32 ++++--- .../client/visitors/RegularElement.js | 5 ++ .../client/visitors/shared/component.js | 88 +++++++++++-------- .../client/visitors/shared/utils.js | 15 +++- .../server/visitors/shared/component.js | 46 ++++++---- .../server/visitors/shared/element.js | 25 ++++-- .../src/compiler/types/legacy-nodes.d.ts | 5 +- .../svelte/src/compiler/types/template.d.ts | 5 +- packages/svelte/types/index.d.ts | 4 +- 10 files changed, 155 insertions(+), 78 deletions(-) diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js index 5b56d9ddac38..e9796737f029 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js @@ -20,6 +20,14 @@ export function BindDirective(node, context) { validate_no_const_assignment(node, node.expression, context.state.scope, true); const assignee = node.expression; + + if (assignee.type === 'SequenceExpression') { + if (assignee.expressions.length !== 2) { + e.bind_invalid_expression(node); + } + return; + } + const left = object(assignee); if (left === null) { diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js index 79969240c771..43e0c0029a84 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js @@ -36,18 +36,26 @@ export function BindDirective(node, context) { ); } - const get = b.thunk(/** @type {Expression} */ (context.visit(expression))); - - /** @type {Expression | undefined} */ - let set = b.unthunk( - b.arrow( - [b.id('$$value')], - /** @type {Expression} */ (context.visit(b.assignment('=', expression, b.id('$$value')))) - ) - ); - - if (get === set) { - set = undefined; + let get, set; + + if (expression.type === 'SequenceExpression') { + const [get_expression, set_expression] = expression.expressions; + get = /** @type {Expression} */ (context.visit(get_expression)); + set = /** @type {Expression} */ (context.visit(set_expression)); + } else { + get = b.thunk(/** @type {Expression} */ (context.visit(expression))); + + /** @type {Expression | undefined} */ + set = b.unthunk( + b.arrow( + [b.id('$$value')], + /** @type {Expression} */ (context.visit(b.assignment('=', expression, b.id('$$value')))) + ) + ); + + if (get === set) { + set = undefined; + } } /** @type {CallExpression} */ 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 4d3cebcee6fe..5e88ca1b98b6 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 @@ -450,6 +450,11 @@ function setup_select_synchronization(value_binding, context) { if (context.state.analysis.runes) return; let bound = value_binding.expression; + + if (bound.type === 'SequenceExpression') { + return; + } + while (bound.type === 'MemberExpression') { bound = /** @type {Identifier | MemberExpression} */ (bound.object); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index 8e1a53670708..34875a6ba435 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -161,49 +161,63 @@ export function build_component(node, component_name, context, anchor = context. push_prop(b.init(attribute.name, value)); } } else if (attribute.type === 'BindDirective') { - const expression = /** @type {Expression} */ (context.visit(attribute.expression)); - - if ( - dev && - expression.type === 'MemberExpression' && - context.state.analysis.runes && - !is_ignored(node, 'binding_property_non_reactive') - ) { - validate_binding(context.state, attribute, expression); - } - - if (attribute.name === 'this') { - bind_this = attribute.expression; + if (attribute.expression.type === 'SequenceExpression') { + const [get_expression, set_expression] = attribute.expression.expressions; + const get = /** @type {Expression} */ (context.visit(get_expression)); + const set = /** @type {Expression} */ (context.visit(set_expression)); + const get_id = b.id(context.state.scope.generate('bind_get')); + const set_id = b.id(context.state.scope.generate('bind_set')); + + context.state.init.push(b.var(get_id, get)); + context.state.init.push(b.var(set_id, set)); + + push_prop(b.get(attribute.name, [b.return(b.call(get_id))])); + push_prop(b.set(attribute.name, [b.stmt(b.call(set_id, b.id('$$value')))])); } else { - if (dev) { - binding_initializers.push( - b.stmt( - b.call( - b.id('$.add_owner_effect'), - b.thunk(expression), - b.id(component_name), - is_ignored(node, 'ownership_invalid_binding') && b.true - ) - ) - ); + const expression = /** @type {Expression} */ (context.visit(attribute.expression)); + + if ( + dev && + expression.type === 'MemberExpression' && + context.state.analysis.runes && + !is_ignored(node, 'binding_property_non_reactive') + ) { + validate_binding(context.state, attribute, expression); } - const is_store_sub = - attribute.expression.type === 'Identifier' && - context.state.scope.get(attribute.expression.name)?.kind === 'store_sub'; - - if (is_store_sub) { + if (attribute.name === 'this') { + bind_this = attribute.expression; + } else { + if (dev) { + binding_initializers.push( + b.stmt( + b.call( + b.id('$.add_owner_effect'), + b.thunk(expression), + b.id(component_name), + is_ignored(node, 'ownership_invalid_binding') && b.true + ) + ) + ); + } + + const is_store_sub = + attribute.expression.type === 'Identifier' && + context.state.scope.get(attribute.expression.name)?.kind === 'store_sub'; + + if (is_store_sub) { + push_prop( + b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)]) + ); + } else { + push_prop(b.get(attribute.name, [b.return(expression)])); + } + + const assignment = b.assignment('=', attribute.expression, b.id('$$value')); push_prop( - b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)]) + b.set(attribute.name, [b.stmt(/** @type {Expression} */ (context.visit(assignment)))]) ); - } else { - push_prop(b.get(attribute.name, [b.return(expression)])); } - - const assignment = b.assignment('=', attribute.expression, b.id('$$value')); - push_prop( - b.set(attribute.name, [b.stmt(/** @type {Expression} */ (context.visit(assignment)))]) - ); } } } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js index 21b902d5c281..d66475e9aab7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js @@ -1,4 +1,4 @@ -/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement, Super } from 'estree' */ +/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Statement, Super } from 'estree' */ /** @import { AST, SvelteNode } from '#compiler' */ /** @import { ComponentClientTransformState } from '../../types' */ import { walk } from 'zimmerframe'; @@ -157,11 +157,19 @@ export function build_update_assignment(state, id, init, value, update) { /** * Serializes `bind:this` for components and elements. - * @param {Identifier | MemberExpression} expression + * @param {Identifier | MemberExpression | SequenceExpression} expression * @param {Expression} value * @param {import('zimmerframe').Context} context */ export function build_bind_this(expression, value, { state, visit }) { + if (expression.type === 'SequenceExpression') { + const [get_expression, set_expression] = expression.expressions; + const get = /** @type {Expression} */ (visit(get_expression)); + const set = /** @type {Expression} */ (visit(set_expression)); + + return b.call('$.bind_this', value, get, set); + } + /** @type {Identifier[]} */ const ids = []; @@ -238,6 +246,9 @@ export function build_bind_this(expression, value, { state, visit }) { * @param {MemberExpression} expression */ export function validate_binding(state, binding, expression) { + if (binding.expression.type === 'SequenceExpression') { + return; + } // If we are referencing a $store.foo then we don't need to add validation const left = object(binding.expression); const left_binding = left && state.scope.get(left.name); diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js index 79df3cdd04c6..6f73c532848d 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js @@ -81,22 +81,36 @@ export function build_inline_component(node, expression, context) { const value = build_attribute_value(attribute.value, context, false, true); push_prop(b.prop('init', b.key(attribute.name), value)); } else if (attribute.type === 'BindDirective' && attribute.name !== 'this') { - // TODO this needs to turn the whole thing into a while loop because the binding could be mutated eagerly in the child - push_prop( - b.get(attribute.name, [ - b.return(/** @type {Expression} */ (context.visit(attribute.expression))) - ]) - ); - push_prop( - b.set(attribute.name, [ - b.stmt( - /** @type {Expression} */ ( - context.visit(b.assignment('=', attribute.expression, b.id('$$value'))) - ) - ), - b.stmt(b.assignment('=', b.id('$$settled'), b.false)) - ]) - ); + if (attribute.expression.type === 'SequenceExpression') { + const [get_expression, set_expression] = attribute.expression.expressions; + const get = /** @type {Expression} */ (context.visit(get_expression)); + const set = /** @type {Expression} */ (context.visit(set_expression)); + const get_id = b.id(context.state.scope.generate('bind_get')); + const set_id = b.id(context.state.scope.generate('bind_set')); + + context.state.init.push(b.var(get_id, get)); + context.state.init.push(b.var(set_id, set)); + + push_prop(b.get(attribute.name, [b.return(b.call(get_id))])); + push_prop(b.set(attribute.name, [b.stmt(b.call(set_id, b.id('$$value')))])); + } else { + // TODO this needs to turn the whole thing into a while loop because the binding could be mutated eagerly in the child + push_prop( + b.get(attribute.name, [ + b.return(/** @type {Expression} */ (context.visit(attribute.expression))) + ]) + ); + push_prop( + b.set(attribute.name, [ + b.stmt( + /** @type {Expression} */ ( + context.visit(b.assignment('=', attribute.expression, b.id('$$value'))) + ) + ), + b.stmt(b.assignment('=', b.id('$$settled'), b.false)) + ]) + ); + } } } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js index c386c4f7c05e..5999f0b0b666 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js @@ -110,11 +110,16 @@ export function build_element_attributes(node, context) { if (binding?.omit_in_ssr) continue; if (is_content_editable_binding(attribute.name)) { - content = /** @type {Expression} */ (context.visit(attribute.expression)); + content = + attribute.expression.type === 'SequenceExpression' + ? b.call(/** @type {Expression} */ (context.visit(attribute.expression.expressions[0]))) + : /** @type {Expression} */ (context.visit(attribute.expression)); } else if (attribute.name === 'value' && node.name === 'textarea') { content = b.call( '$.escape', - /** @type {Expression} */ (context.visit(attribute.expression)) + attribute.expression.type === 'SequenceExpression' + ? b.call(/** @type {Expression} */ (context.visit(attribute.expression.expressions[0]))) + : /** @type {Expression} */ (context.visit(attribute.expression)) ); } else if (attribute.name === 'group') { const value_attribute = /** @type {AST.Attribute | undefined} */ ( @@ -129,6 +134,11 @@ export function build_element_attributes(node, context) { is_text_attribute(attr) && attr.value[0].data === 'checkbox' ); + const attribute_expression = + attribute.expression.type === 'SequenceExpression' + ? b.call(attribute.expression.expressions[0]) + : attribute.expression; + attributes.push( create_attribute('checked', -1, -1, [ { @@ -138,12 +148,12 @@ export function build_element_attributes(node, context) { parent: attribute, expression: is_checkbox ? b.call( - b.member(attribute.expression, 'includes'), + b.member(attribute_expression, 'includes'), build_attribute_value(value_attribute.value, context) ) : b.binary( '===', - attribute.expression, + attribute_expression, build_attribute_value(value_attribute.value, context) ), metadata: { @@ -153,6 +163,11 @@ export function build_element_attributes(node, context) { ]) ); } else { + const attribute_expression = + attribute.expression.type === 'SequenceExpression' + ? b.call(attribute.expression.expressions[0]) + : attribute.expression; + attributes.push( create_attribute(attribute.name, -1, -1, [ { @@ -160,7 +175,7 @@ export function build_element_attributes(node, context) { start: -1, end: -1, parent: attribute, - expression: attribute.expression, + expression: attribute_expression, metadata: { expression: create_expression_metadata() } diff --git a/packages/svelte/src/compiler/types/legacy-nodes.d.ts b/packages/svelte/src/compiler/types/legacy-nodes.d.ts index 2bd5fbbfa6d2..0013f5c17a60 100644 --- a/packages/svelte/src/compiler/types/legacy-nodes.d.ts +++ b/packages/svelte/src/compiler/types/legacy-nodes.d.ts @@ -6,7 +6,8 @@ import type { Identifier, MemberExpression, ObjectExpression, - Pattern + Pattern, + SequenceExpression } from 'estree'; interface BaseNode { @@ -49,7 +50,7 @@ export interface LegacyBinding extends BaseNode { /** The 'x' in `bind:x` */ name: string; /** The y in `bind:x={y}` */ - expression: Identifier | MemberExpression; + expression: Identifier | MemberExpression | SequenceExpression; } export interface LegacyBody extends BaseElement { diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index fd1824d3b3db..cc153b263a28 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -14,7 +14,8 @@ import type { Pattern, Program, ChainExpression, - SimpleCallExpression + SimpleCallExpression, + SequenceExpression } from 'estree'; import type { Scope } from '../phases/scope'; @@ -185,7 +186,7 @@ export namespace AST { /** The 'x' in `bind:x` */ name: string; /** The y in `bind:x={y}` */ - expression: Identifier | MemberExpression; + expression: Identifier | MemberExpression | SequenceExpression; /** @internal */ metadata: { binding_group_name: Identifier; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 00ba2556d9a1..3079071fef40 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -606,7 +606,7 @@ declare module 'svelte/animate' { } declare module 'svelte/compiler' { - import type { Expression, Identifier, ArrayExpression, ArrowFunctionExpression, VariableDeclaration, VariableDeclarator, MemberExpression, ObjectExpression, Pattern, Program, ChainExpression, SimpleCallExpression } from 'estree'; + import type { Expression, Identifier, ArrayExpression, ArrowFunctionExpression, VariableDeclaration, VariableDeclarator, MemberExpression, ObjectExpression, Pattern, Program, ChainExpression, SimpleCallExpression, SequenceExpression } from 'estree'; import type { SourceMap } from 'magic-string'; import type { Location } from 'locate-character'; /** @@ -1047,7 +1047,7 @@ declare module 'svelte/compiler' { /** The 'x' in `bind:x` */ name: string; /** The y in `bind:x={y}` */ - expression: Identifier | MemberExpression; + expression: Identifier | MemberExpression | SequenceExpression; } /** A `class:` directive */ From fa99fa0985ff7d8c315b5c3b9bb2323c6d31d363 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 14 Nov 2024 18:54:05 +0000 Subject: [PATCH 02/23] different direction --- ...023-02-21-streaming-snapshots-sveltekit.md | 2 +- .../98-reference/.generated/compile-errors.md | 6 ++ .../05-bindings/00-text-inputs/App.svelte | 2 +- .../05-bindings/01-numeric-inputs/App.svelte | 8 +-- .../05-bindings/02-checkbox-inputs/App.svelte | 2 +- .../05-bindings/03-group-inputs/App.svelte | 8 +-- .../05-bindings/04-textarea-inputs/App.svelte | 2 +- .../05-bindings/06-select-bindings/App.svelte | 4 +- .../07-multiple-select-bindings/App.svelte | 8 +-- .../08-each-block-bindings/App.svelte | 4 +- .../05-bindings/09-media-elements/App.svelte | 3 +- .../05-bindings/10-dimensions/App.svelte | 6 +- .../05-bindings/11-bind-this/App.svelte | 2 +- .../12-component-bindings/App.svelte | 2 +- .../06-lifecycle/02-update/App.svelte | 2 +- .../examples/08-motion/01-spring/App.svelte | 4 +- .../09-transitions/00-transition/App.svelte | 2 +- .../App.svelte | 2 +- .../09-transitions/02-in-and-out/App.svelte | 2 +- .../03-custom-css-transitions/App.svelte | 2 +- .../04-custom-js-transitions/App.svelte | 2 +- .../05-transition-events/App.svelte | 2 +- .../10-animations/00-animate/App.svelte | 4 +- .../examples/11-easing/00-easing/App.svelte | 2 +- .../11-easing/00-easing/Controls.svelte | 6 +- .../examples/12-svg/02-bar-chart/App.svelte | 2 +- .../examples/12-svg/03-area-chart/App.svelte | 2 +- .../12-svg/04-scatterplot/Scatterplot.svelte | 2 +- .../12-svg/05-svg-transitions/App.svelte | 2 +- .../App.svelte | 2 +- .../14-classes/01-class-shorthand/App.svelte | 2 +- .../15-composition/05-modal/Modal.svelte | 6 +- .../16-context/00-context-api/Map.svelte | 2 +- .../01-svelte-component/App.svelte | 2 +- .../02-svelte-element/App.svelte | 2 +- .../04-svelte-window-bindings/App.svelte | 2 +- .../01-module-exports/AudioPlayer.svelte | 2 +- .../examples/19-debugging/00-debug/App.svelte | 4 +- .../20-7guis/01-7guis-counter/App.svelte | 2 +- .../03-7guis-flight-booker/App.svelte | 6 +- .../20-7guis/04-7guis-timer/App.svelte | 2 +- .../20-7guis/05-7guis-crud/App.svelte | 8 +-- .../02-immutable-data/ImmutableTodo.svelte | 2 +- .../02-immutable-data/MutableTodo.svelte | 2 +- .../20190420-blog-write-less-code/App.svelte | 4 +- .../01-text-inputs/app-b/App.svelte | 2 +- .../06-bindings/01-text-inputs/text.md | 2 +- .../02-numeric-inputs/app-b/App.svelte | 8 +-- .../06-bindings/02-numeric-inputs/text.md | 4 +- .../03-checkbox-inputs/app-b/App.svelte | 2 +- .../06-bindings/03-checkbox-inputs/text.md | 2 +- .../04-group-inputs/app-b/App.svelte | 8 +-- .../06-bindings/04-group-inputs/text.md | 4 +- .../06-select-bindings/app-a/App.svelte | 2 +- .../06-select-bindings/app-b/App.svelte | 4 +- .../app-a/App.svelte | 8 +-- .../app-b/App.svelte | 8 +-- .../07-multiple-select-bindings/text.md | 2 +- .../app-b/App.svelte | 2 +- .../08-contenteditable-bindings/text.md | 2 +- .../09-each-block-bindings/app-b/App.svelte | 4 +- .../09-each-block-bindings/text.md | 4 +- .../10-media-elements/app-b/App.svelte | 3 +- .../06-bindings/10-media-elements/text.md | 3 +- .../11-dimensions/app-a/App.svelte | 4 +- .../11-dimensions/app-b/App.svelte | 6 +- .../06-bindings/11-dimensions/text.md | 2 +- .../06-bindings/12-bind-this/app-b/App.svelte | 2 +- .../tutorial/06-bindings/12-bind-this/text.md | 2 +- .../13-component-bindings/app-b/App.svelte | 2 +- .../06-bindings/13-component-bindings/text.md | 2 +- .../14-component-this/app-a/InputField.svelte | 2 +- .../14-component-this/app-b/App.svelte | 2 +- .../14-component-this/app-b/InputField.svelte | 2 +- .../06-bindings/14-component-this/text.md | 2 +- .../07-lifecycle/03-update/app-a/App.svelte | 2 +- .../07-lifecycle/03-update/app-b/App.svelte | 2 +- .../06-store-bindings/app-b/App.svelte | 2 +- .../08-stores/06-store-bindings/text.md | 2 +- .../09-motion/02-spring/app-a/App.svelte | 4 +- .../09-motion/02-spring/app-b/App.svelte | 4 +- .../01-transition/app-a/App.svelte | 2 +- .../01-transition/app-b/App.svelte | 2 +- .../app-a/App.svelte | 2 +- .../app-b/App.svelte | 2 +- .../03-in-and-out/app-a/App.svelte | 2 +- .../03-in-and-out/app-b/App.svelte | 2 +- .../app-a/App.svelte | 2 +- .../app-b/App.svelte | 2 +- .../05-custom-js-transitions/app-a/App.svelte | 2 +- .../05-custom-js-transitions/app-b/App.svelte | 2 +- .../06-transition-events/app-a/App.svelte | 2 +- .../06-transition-events/app-b/App.svelte | 2 +- .../07-global-transitions/app-a/App.svelte | 4 +- .../07-global-transitions/app-b/App.svelte | 4 +- .../app-a/App.svelte | 2 +- .../app-b/App.svelte | 2 +- .../02-class-shorthand/app-a/App.svelte | 2 +- .../02-class-shorthand/app-b/App.svelte | 2 +- .../03-inline-styles/app-a/App.svelte | 2 +- .../03-inline-styles/app-b/App.svelte | 2 +- .../04-style-directive/app-a/App.svelte | 2 +- .../04-style-directive/app-b/App.svelte | 2 +- .../01-context-api/app-a/Map.svelte | 2 +- .../01-context-api/app-b/Map.svelte | 2 +- .../02-svelte-component/app-a/App.svelte | 2 +- .../02-svelte-component/app-b/App.svelte | 2 +- .../03-svelte-element/app-a/App.svelte | 2 +- .../03-svelte-element/app-b/App.svelte | 2 +- .../app-b/App.svelte | 2 +- .../05-svelte-window-bindings/text.md | 2 +- .../09-svelte-options/app-a/Todo.svelte | 2 +- .../09-svelte-options/app-b/Todo.svelte | 2 +- .../01-sharing-code/app-a/AudioPlayer.svelte | 2 +- .../01-sharing-code/app-b/AudioPlayer.svelte | 2 +- .../app-a/AudioPlayer.svelte | 2 +- .../app-b/AudioPlayer.svelte | 2 +- .../18-special-tags/01-debug/app-a/App.svelte | 4 +- .../18-special-tags/01-debug/app-b/App.svelte | 4 +- .../messages/compile-errors/template.md | 4 ++ packages/svelte/src/compiler/errors.js | 9 +++ .../compiler/phases/1-parse/state/element.js | 48 ++++++++++++++-- .../2-analyze/visitors/BindDirective.js | 11 ++-- .../client/visitors/BindDirective.js | 55 ++++++++++++------- .../client/visitors/RegularElement.js | 7 +-- .../client/visitors/shared/component.js | 4 +- .../client/visitors/shared/utils.js | 8 +-- .../server/visitors/shared/component.js | 4 +- .../server/visitors/shared/element.js | 25 ++++----- .../src/compiler/types/legacy-nodes.d.ts | 2 +- .../svelte/src/compiler/types/template.d.ts | 2 +- packages/svelte/types/index.d.ts | 4 +- .../src/lib/Input/ComponentSelector.svelte | 3 +- .../src/lib/Input/ModuleEditor.svelte | 3 +- .../src/lib/Output/AstNode.svelte | 3 +- .../src/lib/Output/CompilerOptions.svelte | 12 ++-- .../src/lib/Output/Output.svelte | 9 +-- .../src/lib/Output/Viewer.svelte | 3 +- sites/svelte-5-preview/src/lib/Repl.svelte | 4 +- .../svelte-5-preview/src/routes/+page.svelte | 3 +- .../routes/docs/content/01-api/02-runes.md | 14 ++--- .../routes/docs/content/01-api/05-imports.md | 10 ++-- .../02-examples/02-fine-grained-reactivity.md | 4 +- .../03-appendix/02-breaking-changes.md | 2 +- 144 files changed, 335 insertions(+), 267 deletions(-) diff --git a/documentation/blog/2023-02-21-streaming-snapshots-sveltekit.md b/documentation/blog/2023-02-21-streaming-snapshots-sveltekit.md index a030e8fc410d..c70f946e48f7 100644 --- a/documentation/blog/2023-02-21-streaming-snapshots-sveltekit.md +++ b/documentation/blog/2023-02-21-streaming-snapshots-sveltekit.md @@ -147,7 +147,7 @@ For example, here is how you would capture and restore the value of a textarea:
-