From 3eee9d5f9d19d30b2580d258e44dcf110f2dd872 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 26 Jun 2025 21:59:38 -0400 Subject: [PATCH] Revert "dry out" This reverts commit 25855163bf7d915492f62d3d0e5370ed74e65132. --- .../3-transform/client/visitors/RenderTag.js | 16 ++++--- .../client/visitors/SlotElement.js | 16 ++++--- .../client/visitors/shared/component.js | 16 ++++--- .../client/visitors/shared/element.js | 13 ++++-- .../client/visitors/shared/utils.js | 43 ++++++------------- 5 files changed, 51 insertions(+), 53 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js index 528f867e01..5255693fe3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js @@ -3,6 +3,7 @@ /** @import { ComponentContext } from '../types' */ import { unwrap_optional } from '../../../../utils/ast.js'; import * as b from '#compiler/builders'; +import { create_derived } from '../utils.js'; import { build_expression, Memoizer } from './shared/utils.js'; /** @@ -35,7 +36,9 @@ export function RenderTag(node, context) { memoizer.apply(); /** @type {Statement[]} */ - const statements = memoizer.deriveds(); + const statements = memoizer.sync.map((memo) => + b.var(memo.id, create_derived(context.state, b.thunk(memo.expression))) + ); let snippet_function = build_expression( context, @@ -64,16 +67,17 @@ export function RenderTag(node, context) { ); } - const async_values = memoizer.async_values(); - - if (async_values) { + if (memoizer.async.length > 0) { context.state.init.push( b.stmt( b.call( '$.async', context.state.node, - async_values, - b.arrow([context.state.node, ...memoizer.async_ids()], b.block(statements)) + b.array(memoizer.async.map((memo) => b.thunk(memo.expression, true))), + b.arrow( + [context.state.node, ...memoizer.async.map((memo) => memo.id)], + b.block(statements) + ) ) ) ); diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js index fce445c626..70de454c0e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js @@ -2,6 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import * as b from '#compiler/builders'; +import { create_derived } from '../utils.js'; import { build_attribute_value } from './shared/element.js'; import { Memoizer } from './shared/utils.js'; @@ -59,7 +60,9 @@ export function SlotElement(node, context) { context.state.init.push(...lets); /** @type {Statement[]} */ - const statements = memoizer.deriveds(); + const statements = memoizer.sync.map((memo) => + b.var(memo.id, create_derived(context.state, b.thunk(memo.expression))) + ); const props_expression = spreads.length === 0 ? b.object(props) : b.call('$.spread_props', b.object(props), ...spreads); @@ -73,16 +76,17 @@ export function SlotElement(node, context) { b.stmt(b.call('$.slot', context.state.node, b.id('$$props'), name, props_expression, fallback)) ); - const async_values = memoizer.async_values(); - - if (async_values) { + if (memoizer.async.length > 0) { context.state.init.push( b.stmt( b.call( '$.async', context.state.node, - async_values, - b.arrow([context.state.node, ...memoizer.async_ids()], b.block(statements)) + b.array(memoizer.async.map((memo) => b.thunk(memo.expression, true))), + b.arrow( + [context.state.node, ...memoizer.async.map((memo) => memo.id)], + b.block(statements) + ) ) ) ); 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 582b57a7ad..77535cf16e 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 @@ -8,6 +8,7 @@ import { build_bind_this, Memoizer, validate_binding } from '../shared/utils.js' import { build_attribute_value } from '../shared/element.js'; import { build_event_handler } from './events.js'; import { determine_slot } from '../../../../../utils/slot.js'; +import { create_derived } from '../../utils.js'; /** * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node @@ -446,7 +447,12 @@ export function build_component(node, component_name, context) { }; } - const statements = [...snippet_declarations, ...memoizer.deriveds()]; + const statements = [ + ...snippet_declarations, + ...memoizer.sync.map((memo) => + b.let(memo.id, create_derived(context.state, b.thunk(memo.expression))) + ) + ]; if (is_component_dynamic) { const prev = fn; @@ -495,15 +501,13 @@ export function build_component(node, component_name, context) { memoizer.apply(); - const async_values = memoizer.async_values(); - - if (async_values) { + if (memoizer.async.length > 0) { return b.stmt( b.call( '$.async', anchor, - async_values, - b.arrow([b.id('$$anchor'), ...memoizer.async_ids()], b.block(statements)) + b.array(memoizer.async.map(({ expression }) => b.thunk(expression, true))), + b.arrow([b.id('$$anchor'), ...memoizer.async.map(({ id }) => id)], b.block(statements)) ) ); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js index d63658b481..8da489409b 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js @@ -78,16 +78,21 @@ export function build_attribute_effect( ); } - memoizer.apply(); + const all = memoizer.apply(); context.state.init.push( b.stmt( b.call( '$.attribute_effect', element_id, - b.arrow(memoizer.all_ids(), b.object(values)), - memoizer.sync_values(), - memoizer.async_values(), + b.arrow( + all.map(({ id }) => id), + b.object(values) + ), + memoizer.sync.length > 0 && + b.array(memoizer.sync.map(({ expression }) => b.thunk(expression))), + memoizer.async.length > 0 && + b.array(memoizer.async.map(({ expression }) => b.thunk(expression, true))), element.metadata.scoped && context.state.analysis.css.hash !== '' && b.literal(context.state.analysis.css.hash), 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 f032f49a48..ed9b8ad8a4 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 @@ -12,10 +12,10 @@ import { build_getter } from '../../utils.js'; export class Memoizer { /** @type {Array<{ id: Identifier, expression: Expression }>} */ - #sync = []; + sync = []; /** @type {Array<{ id: Identifier, expression: Expression }>} */ - #async = []; + async = []; /** * @param {Expression} expression @@ -24,39 +24,19 @@ export class Memoizer { add(expression, has_await) { const id = b.id(`#`); // filled in later - (has_await ? this.#async : this.#sync).push({ id, expression }); + (has_await ? this.async : this.sync).push({ id, expression }); return id; } apply() { - [...this.#async, ...this.#sync].forEach((memo, i) => { + const all = [...this.async, ...this.sync]; + + all.forEach((memo, i) => { memo.id.name = `$${i}`; }); - } - - all_ids() { - return [...this.#async, ...this.#sync].map((memo) => memo.id); - } - - async_ids() { - return this.#async.map((memo) => memo.id); - } - - async_values() { - if (this.#async.length === 0) return; - return b.array(this.#async.map((memo) => b.thunk(memo.expression, true))); - } - - deriveds(runes = true) { - return this.#sync.map((memo) => - b.let(memo.id, b.call(runes ? '$.derived' : '$.derived_safe_equal', b.thunk(memo.expression))) - ); - } - sync_values() { - if (this.#sync.length === 0) return; - return b.array(this.#sync.map((memo) => b.thunk(memo.expression))); + return all; } } @@ -163,19 +143,20 @@ export function build_template_chunk( export function build_render_statement(state) { const { memoizer } = state; - state.memoizer.apply(); + const all = state.memoizer.apply(); return b.stmt( b.call( '$.template_effect', b.arrow( - memoizer.all_ids(), + all.map(({ id }) => id), state.update.length === 1 && state.update[0].type === 'ExpressionStatement' ? state.update[0].expression : b.block(state.update) ), - memoizer.sync_values(), - memoizer.async_values() + all.length > 0 && b.array(memoizer.sync.map(({ expression }) => b.thunk(expression))), + memoizer.async.length > 0 && + b.array(memoizer.async.map(({ expression }) => b.thunk(expression, true))) ) ); }