From 3e222fca39f4c0ba84dfe3130176dc38149a2bf1 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 9 Dec 2024 22:46:05 +0000 Subject: [PATCH 01/12] feat: add state.opqaue rune --- .changeset/large-papayas-serve.md | 5 +++ .../98-reference/.generated/compile-errors.md | 6 +++ .../svelte/messages/compile-errors/script.md | 4 ++ packages/svelte/src/ambient.d.ts | 29 ++++++++++++++ packages/svelte/src/compiler/errors.js | 9 +++++ .../2-analyze/visitors/CallExpression.js | 15 +++++++- .../2-analyze/visitors/VariableDeclarator.js | 18 ++++++--- .../client/visitors/VariableDeclaration.js | 16 +++++++- .../client/visitors/shared/declarations.js | 12 +++++- .../server/visitors/VariableDeclaration.js | 13 ++++++- packages/svelte/src/compiler/types/index.d.ts | 1 + packages/svelte/src/internal/client/index.js | 2 +- .../internal/client/reactivity/equality.js | 4 ++ .../src/internal/client/reactivity/sources.js | 13 ++++++- packages/svelte/src/utils.js | 1 + .../samples/opaque-state/_config.js | 38 +++++++++++++++++++ .../samples/opaque-state/main.svelte | 19 ++++++++++ packages/svelte/types/index.d.ts | 29 ++++++++++++++ 18 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 .changeset/large-papayas-serve.md create mode 100644 packages/svelte/tests/runtime-runes/samples/opaque-state/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/opaque-state/main.svelte diff --git a/.changeset/large-papayas-serve.md b/.changeset/large-papayas-serve.md new file mode 100644 index 000000000000..383c649c6238 --- /dev/null +++ b/.changeset/large-papayas-serve.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: add $state.opqaue rune diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 3bd162d8d74d..180579db450e 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -748,6 +748,12 @@ This snippet is shadowing the prop `%prop%` with the same name Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties ``` +### state_invalid_opaque_declaration + +``` +`$state.opaque` must be declared with an array destructuring pattern (e.g. `let [state, invalidate] = $state.opaque(data);`) +``` + ### state_invalid_placement ``` diff --git a/packages/svelte/messages/compile-errors/script.md b/packages/svelte/messages/compile-errors/script.md index 69007bfb5919..f616918c9f7a 100644 --- a/packages/svelte/messages/compile-errors/script.md +++ b/packages/svelte/messages/compile-errors/script.md @@ -168,6 +168,10 @@ It's possible to export a snippet from a ` + * + * + * ``` + * + * https://svelte.dev/docs/svelte/$state#$state.opaque + * + * @param initial The initial value + */ + export function opaque(initial: T): [T, () => void]; + export function opaque(): [T | undefined, () => void]; + /** * To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: * diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 901ea1983ea7..5f2a77a40eac 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -432,6 +432,15 @@ export function state_invalid_export(node) { e(node, "state_invalid_export", "Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties"); } +/** + * `$state.opaque` must be declared with an array destructuring pattern (e.g. `let [state, invalidate] = $state.opaque(data);`) + * @param {null | number | NodeLike} node + * @returns {never} + */ +export function state_invalid_opaque_declaration(node) { + e(node, "state_invalid_opaque_declaration", "`$state.opaque` must be declared with an array destructuring pattern (e.g. `let [state, invalidate] = $state.opaque(data);`)"); +} + /** * `%rune%(...)` can only be used as a variable declaration initializer or a class field * @param {null | number | NodeLike} node diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js index c7ade4856bcb..b669441cb587 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js @@ -75,6 +75,7 @@ export function CallExpression(node, context) { case '$state': case '$state.raw': + case '$state.opaque': case '$derived': case '$derived.by': if ( @@ -86,9 +87,21 @@ export function CallExpression(node, context) { if ((rune === '$derived' || rune === '$derived.by') && node.arguments.length !== 1) { e.rune_invalid_arguments_length(node, rune, 'exactly one argument'); - } else if (rune === '$state' && node.arguments.length > 1) { + } else if ( + (rune === '$state' || rune === '$state.raw' || rune === '$state.opaque') && + node.arguments.length > 1 + ) { e.rune_invalid_arguments_length(node, rune, 'zero or one arguments'); } + if ( + rune === '$state.opaque' && + (parent.type !== 'VariableDeclarator' || + parent.id.type !== 'ArrayPattern' || + parent.id.elements.length !== 2 || + parent.id.elements[0]?.type !== 'Identifier') + ) { + e.state_invalid_opaque_declaration(node); + } break; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js index a7d08d315d8f..e2d8bd8986fa 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js @@ -27,11 +27,15 @@ export function VariableDeclarator(node, context) { if ( rune === '$state' || rune === '$state.raw' || + rune === '$state.opaque' || rune === '$derived' || rune === '$derived.by' || rune === '$props' ) { - for (const path of paths) { + for (let i = 0; i < paths.length; i++) { + if (rune === '$state.opaque' && i === 1) continue; + + const path = paths[i]; // @ts-ignore this fails in CI for some insane reason const binding = /** @type {Binding} */ (context.state.scope.get(path.node.name)); binding.kind = @@ -39,11 +43,13 @@ export function VariableDeclarator(node, context) { ? 'state' : rune === '$state.raw' ? 'raw_state' - : rune === '$derived' || rune === '$derived.by' - ? 'derived' - : path.is_rest - ? 'rest_prop' - : 'prop'; + : rune === '$state.opaque' + ? 'opaque_state' + : rune === '$derived' || rune === '$derived.by' + ? 'derived' + : path.is_rest + ? 'rest_prop' + : 'prop'; } } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index 04685b66bd0c..331dff952e6e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -1,4 +1,4 @@ -/** @import { CallExpression, Expression, Identifier, Literal, VariableDeclaration, VariableDeclarator } from 'estree' */ +/** @import { ArrayPattern, CallExpression, Expression, Identifier, Literal, VariableDeclaration, VariableDeclarator } from 'estree' */ /** @import { Binding } from '#compiler' */ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; @@ -156,6 +156,20 @@ export function VariableDeclaration(node, context) { continue; } + if (rune === '$state.opaque') { + const pattern = /** @type {ArrayPattern} */ (declarator.id); + const state_id = /** @type {Identifier} */ (pattern.elements[0]); + const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]); + declarations.push( + b.declarator(state_id, b.call('$.opaque_state', value)), + b.declarator( + invalidation_id, + b.thunk(b.call('$.set', state_id, b.member(state_id, b.id('v')))) + ) + ); + continue; + } + if (rune === '$derived' || rune === '$derived.by') { if (declarator.id.type === 'Identifier') { declarations.push( diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js index 0bd8c352f6a9..759c2fa91c5e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js @@ -1,4 +1,4 @@ -/** @import { Identifier } from 'estree' */ +/** @import { Expression, Identifier } from 'estree' */ /** @import { ComponentContext, Context } from '../../types' */ import { is_state_source } from '../../utils.js'; import * as b from '../../../../../utils/builders.js'; @@ -48,6 +48,16 @@ export function add_state_transformers(context) { ); } }; + } else if (binding.kind === 'opaque_state') { + context.state.transform[name] = { + read: binding.declaration_kind === 'var' ? (node) => b.call('$.safe_get', node) : get_value, + assign: (node, value) => { + return b.assignment('=', b.member(node, b.id('v')), /** @type {Expression} */ (value)); + }, + update: (node) => { + return b.update(node.operator, b.member(node.argument, b.id('v')), node.prefix); + } + }; } } } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js index 31de811ac76f..889fffd31a97 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js @@ -1,4 +1,4 @@ -/** @import { VariableDeclaration, VariableDeclarator, Expression, CallExpression, Pattern, Identifier } from 'estree' */ +/** @import { ArrayPattern, VariableDeclaration, VariableDeclarator, Expression, CallExpression, Pattern, Identifier } from 'estree' */ /** @import { Binding } from '#compiler' */ /** @import { Context } from '../types.js' */ /** @import { Scope } from '../../../scope.js' */ @@ -92,6 +92,17 @@ export function VariableDeclaration(node, context) { continue; } + if (rune === '$state.opaque') { + const pattern = /** @type {ArrayPattern} */ (declarator.id); + const state_id = /** @type {Identifier} */ (pattern.elements[0]); + const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]); + declarations.push( + b.declarator(state_id, value), + b.declarator(invalidation_id, b.thunk(b.block([]))) + ); + continue; + } + declarations.push(...create_state_declarators(declarator, context.state.scope, value)); } } else { diff --git a/packages/svelte/src/compiler/types/index.d.ts b/packages/svelte/src/compiler/types/index.d.ts index fe306bd020e1..89359eb3414d 100644 --- a/packages/svelte/src/compiler/types/index.d.ts +++ b/packages/svelte/src/compiler/types/index.d.ts @@ -274,6 +274,7 @@ export interface Binding { | 'rest_prop' | 'state' | 'raw_state' + | 'opaque_state' | 'derived' | 'each' | 'snippet' diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index b706e52a5378..e5be80d50801 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -108,7 +108,7 @@ export { user_effect, user_pre_effect } from './reactivity/effects.js'; -export { mutable_state, mutate, set, state } from './reactivity/sources.js'; +export { mutable_state, mutate, set, state, opaque_state } from './reactivity/sources.js'; export { prop, rest_props, diff --git a/packages/svelte/src/internal/client/reactivity/equality.js b/packages/svelte/src/internal/client/reactivity/equality.js index 37a9994ab8cc..929d4cbc54b7 100644 --- a/packages/svelte/src/internal/client/reactivity/equality.js +++ b/packages/svelte/src/internal/client/reactivity/equality.js @@ -28,3 +28,7 @@ export function not_equal(a, b) { export function safe_equals(value) { return !safe_not_equal(value, this.v); } + +export function opaque_equals() { + return false; +} diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 4bbd470d08c8..f9b54853ec04 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -20,7 +20,7 @@ import { set_is_flushing_effect, is_flushing_effect } from '../runtime.js'; -import { equals, safe_equals } from './equality.js'; +import { equals, opaque_equals, safe_equals } from './equality.js'; import { CLEAN, DERIVED, @@ -88,6 +88,17 @@ export function mutable_source(initial_value, immutable = false) { return s; } +/** + * @template V + * @param {V} v + * @returns {Source} + */ +export function opaque_state(v) { + var s = source(v); + s.equals = opaque_equals; + return push_derived_source(s); +} + /** * @template V * @param {V} v diff --git a/packages/svelte/src/utils.js b/packages/svelte/src/utils.js index 75171c17865a..1144717b3dee 100644 --- a/packages/svelte/src/utils.js +++ b/packages/svelte/src/utils.js @@ -420,6 +420,7 @@ export function is_mathml(name) { const RUNES = /** @type {const} */ ([ '$state', '$state.raw', + '$state.opaque', '$state.snapshot', '$props', '$bindable', diff --git a/packages/svelte/tests/runtime-runes/samples/opaque-state/_config.js b/packages/svelte/tests/runtime-runes/samples/opaque-state/_config.js new file mode 100644 index 000000000000..77c0fd0aa8ec --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/opaque-state/_config.js @@ -0,0 +1,38 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { assert_ok } from '../../../suite'; + +export default test({ + html: `
0
0
`, + ssrHtml: `
0
0
`, + + test({ assert, target }) { + const [b1, b2] = target.querySelectorAll('button'); + const input = target.querySelector('input'); + assert_ok(input); + + b1?.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `
0
0
` + ); + assert.equal(input.value, '0'); + + b2?.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `
1
1
` + ); + assert.equal(input.value, '1'); + + input.value = '2'; + input.dispatchEvent(new window.Event('input')); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `
1
1
` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/opaque-state/main.svelte b/packages/svelte/tests/runtime-runes/samples/opaque-state/main.svelte new file mode 100644 index 000000000000..54016cefce3b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/opaque-state/main.svelte @@ -0,0 +1,19 @@ + + + + + + +
{count}
+
{value.count}
+ + diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 0d761919a8e0..c1c8f5654ddf 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -2665,6 +2665,35 @@ declare namespace $state { */ export function raw(initial: T): T; export function raw(): T | undefined; + + /** + * Declares state that is _not_ known to Svelte and thus is completely opaque to + * reassignments and mutations. To let Svelte know that the value has changed, + * you must invoke its invalidate function manually. + * + * Example: + * ```ts + * + * + * + * ``` + * + * https://svelte.dev/docs/svelte/$state#$state.opaque + * + * @param initial The initial value + */ + export function opaque(initial: T): [T, () => void]; + export function opaque(): [T | undefined, () => void]; + /** * To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: * From 9a8b448899c2e9f0c4b2b5af1c0ad6528a37ce53 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 9 Dec 2024 22:53:31 +0000 Subject: [PATCH 02/12] typo --- .changeset/large-papayas-serve.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/large-papayas-serve.md b/.changeset/large-papayas-serve.md index 383c649c6238..f4885eda88d9 100644 --- a/.changeset/large-papayas-serve.md +++ b/.changeset/large-papayas-serve.md @@ -2,4 +2,4 @@ 'svelte': minor --- -feat: add $state.opqaue rune +feat: adds $state.opaque rune From 409bebc1b5dc4a5864bb48c2bbc89a31409d33b1 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 9 Dec 2024 23:01:16 +0000 Subject: [PATCH 03/12] lint --- .../docs/98-reference/.generated/compile-errors.md | 2 +- packages/svelte/messages/compile-errors/script.md | 2 +- packages/svelte/src/compiler/errors.js | 7 ++++--- .../compiler/phases/2-analyze/visitors/CallExpression.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 180579db450e..7509f0db632a 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -751,7 +751,7 @@ Cannot export state from a module if it is reassigned. Either export a function ### state_invalid_opaque_declaration ``` -`$state.opaque` must be declared with an array destructuring pattern (e.g. `let [state, invalidate] = $state.opaque(data);`) +`%rune%(...)` must be declared with an array destructuring pattern (e.g. `let [state, invalidate] = $state.opaque(data);`) ``` ### state_invalid_placement diff --git a/packages/svelte/messages/compile-errors/script.md b/packages/svelte/messages/compile-errors/script.md index f616918c9f7a..e5f59612acff 100644 --- a/packages/svelte/messages/compile-errors/script.md +++ b/packages/svelte/messages/compile-errors/script.md @@ -170,7 +170,7 @@ It's possible to export a snippet from a ` + +

{obj.count}

diff --git a/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/_config.js b/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/_config.js new file mode 100644 index 000000000000..b5f7e8815459 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/_config.js @@ -0,0 +1,18 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `

0

`, + + test({ assert, target }) { + const button = target.querySelector('button'); + + button?.click(); + flushSync(); + assert.htmlEqual(target.innerHTML, `

1

`); + + button?.click(); + flushSync(); + assert.htmlEqual(target.innerHTML, `

2

`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/main.svelte b/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/main.svelte new file mode 100644 index 000000000000..8efd150aece4 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/opaque-state-fn/main.svelte @@ -0,0 +1,8 @@ + + + + diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 82a20ff9c524..f39299a08af3 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -2691,8 +2691,8 @@ declare namespace $state { * * @param initial The initial value */ - export function opaque(initial: T): [T, () => void]; - export function opaque(): [T | undefined, () => void]; + export function opaque(initial: T): [T, (mutate?: (value: T) => void) => void]; + export function opaque(): [T | undefined, (mutate?: (value: T) => void) => void]; /** * To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: From 13ca61e33ed2ac04500bd63572ab33c85a881be3 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 13 Dec 2024 16:14:54 +0000 Subject: [PATCH 11/12] fix --- .../client/visitors/VariableDeclaration.js | 2 +- .../server/visitors/VariableDeclaration.js | 2 +- packages/svelte/src/compiler/utils/builders.js | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index c88db8b6d997..6e9bcb00094c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -167,7 +167,7 @@ export function VariableDeclaration(node, context) { b.arrow( [b.id('$$fn')], b.sequence([ - b.call(b.id('$$fn'), b.member(state_id, b.id('v'))), + b.chain_call(b.id('$$fn'), b.member(state_id, b.id('v'))), b.call('$.set', state_id, b.member(state_id, b.id('v'))) ]) ) diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js index a70f2852b855..122e664f4bb2 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js @@ -98,7 +98,7 @@ export function VariableDeclaration(node, context) { const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]); declarations.push( b.declarator(state_id, value), - b.declarator(invalidation_id, b.arrow([b.id('$$fn')], b.call(b.id('$$fn'), state_id))) + b.declarator(invalidation_id, b.arrow([b.id('$$fn')], b.chain_call(b.id('$$fn'), state_id))) ); continue; } diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index ecb595d74dbd..c1e68363a050 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -130,6 +130,17 @@ export function call(callee, ...args) { }; } +/** + * @param {string | ESTree.Expression} callee + * @param {...(ESTree.Expression | ESTree.SpreadElement | false | undefined)} args + * @returns {ESTree.ChainExpression} + */ +export function chain_call(callee, ...args) { + const expression = /** @type {ESTree.SimpleCallExpression} */ (call(callee, ...args)); + expression.optional = true; + return { type: 'ChainExpression', expression }; +} + /** * @param {string | ESTree.Expression} callee * @param {...ESTree.Expression} args From 21b08650a6775b45e6186d9014b58abb2a282ebf Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 13 Dec 2024 16:18:31 +0000 Subject: [PATCH 12/12] fix --- .../3-transform/server/visitors/VariableDeclaration.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js index 122e664f4bb2..a522310203c9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js @@ -98,7 +98,10 @@ export function VariableDeclaration(node, context) { const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]); declarations.push( b.declarator(state_id, value), - b.declarator(invalidation_id, b.arrow([b.id('$$fn')], b.chain_call(b.id('$$fn'), state_id))) + b.declarator( + invalidation_id, + b.arrow([b.id('$$fn')], b.chain_call(b.id('$$fn'), state_id)) + ) ); continue; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy