pull/15844/head
Rich Harris 2 months ago
parent 2b4410007d
commit 25855163bf

@ -3,7 +3,6 @@
/** @import { ComponentContext } from '../types' */ /** @import { ComponentContext } from '../types' */
import { unwrap_optional } from '../../../../utils/ast.js'; import { unwrap_optional } from '../../../../utils/ast.js';
import * as b from '#compiler/builders'; import * as b from '#compiler/builders';
import { create_derived } from '../utils.js';
import { build_expression, Memoizer } from './shared/utils.js'; import { build_expression, Memoizer } from './shared/utils.js';
/** /**
@ -36,9 +35,7 @@ export function RenderTag(node, context) {
memoizer.apply(); memoizer.apply();
/** @type {Statement[]} */ /** @type {Statement[]} */
const statements = memoizer.sync.map((memo) => const statements = memoizer.deriveds();
b.var(memo.id, create_derived(context.state, b.thunk(memo.expression)))
);
let snippet_function = build_expression( let snippet_function = build_expression(
context, context,
@ -67,17 +64,16 @@ export function RenderTag(node, context) {
); );
} }
if (memoizer.async.length > 0) { const async_values = memoizer.async_values();
if (async_values) {
context.state.init.push( context.state.init.push(
b.stmt( b.stmt(
b.call( b.call(
'$.async', '$.async',
context.state.node, context.state.node,
b.array(memoizer.async.map((memo) => b.thunk(memo.expression, true))), async_values,
b.arrow( b.arrow([context.state.node, ...memoizer.async_ids()], b.block(statements))
[context.state.node, ...memoizer.async.map((memo) => memo.id)],
b.block(statements)
)
) )
) )
); );

@ -2,7 +2,6 @@
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */ /** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders'; import * as b from '#compiler/builders';
import { create_derived } from '../utils.js';
import { build_attribute_value } from './shared/element.js'; import { build_attribute_value } from './shared/element.js';
import { Memoizer } from './shared/utils.js'; import { Memoizer } from './shared/utils.js';
@ -60,9 +59,7 @@ export function SlotElement(node, context) {
context.state.init.push(...lets); context.state.init.push(...lets);
/** @type {Statement[]} */ /** @type {Statement[]} */
const statements = memoizer.sync.map((memo) => const statements = memoizer.deriveds();
b.var(memo.id, create_derived(context.state, b.thunk(memo.expression)))
);
const props_expression = const props_expression =
spreads.length === 0 ? b.object(props) : b.call('$.spread_props', b.object(props), ...spreads); spreads.length === 0 ? b.object(props) : b.call('$.spread_props', b.object(props), ...spreads);
@ -76,17 +73,16 @@ export function SlotElement(node, context) {
b.stmt(b.call('$.slot', context.state.node, b.id('$$props'), name, props_expression, fallback)) b.stmt(b.call('$.slot', context.state.node, b.id('$$props'), name, props_expression, fallback))
); );
if (memoizer.async.length > 0) { const async_values = memoizer.async_values();
if (async_values) {
context.state.init.push( context.state.init.push(
b.stmt( b.stmt(
b.call( b.call(
'$.async', '$.async',
context.state.node, context.state.node,
b.array(memoizer.async.map((memo) => b.thunk(memo.expression, true))), async_values,
b.arrow( b.arrow([context.state.node, ...memoizer.async_ids()], b.block(statements))
[context.state.node, ...memoizer.async.map((memo) => memo.id)],
b.block(statements)
)
) )
) )
); );

@ -8,7 +8,6 @@ import { build_bind_this, Memoizer, validate_binding } from '../shared/utils.js'
import { build_attribute_value } from '../shared/element.js'; import { build_attribute_value } from '../shared/element.js';
import { build_event_handler } from './events.js'; import { build_event_handler } from './events.js';
import { determine_slot } from '../../../../../utils/slot.js'; import { determine_slot } from '../../../../../utils/slot.js';
import { create_derived } from '../../utils.js';
/** /**
* @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
@ -447,12 +446,7 @@ export function build_component(node, component_name, context) {
}; };
} }
const statements = [ const statements = [...snippet_declarations, ...memoizer.deriveds()];
...snippet_declarations,
...memoizer.sync.map((memo) =>
b.let(memo.id, create_derived(context.state, b.thunk(memo.expression)))
)
];
if (is_component_dynamic) { if (is_component_dynamic) {
const prev = fn; const prev = fn;
@ -501,13 +495,15 @@ export function build_component(node, component_name, context) {
memoizer.apply(); memoizer.apply();
if (memoizer.async.length > 0) { const async_values = memoizer.async_values();
if (async_values) {
return b.stmt( return b.stmt(
b.call( b.call(
'$.async', '$.async',
anchor, anchor,
b.array(memoizer.async.map(({ expression }) => b.thunk(expression, true))), async_values,
b.arrow([b.id('$$anchor'), ...memoizer.async.map(({ id }) => id)], b.block(statements)) b.arrow([b.id('$$anchor'), ...memoizer.async_ids()], b.block(statements))
) )
); );
} }

@ -78,21 +78,16 @@ export function build_attribute_effect(
); );
} }
const all = memoizer.apply(); memoizer.apply();
context.state.init.push( context.state.init.push(
b.stmt( b.stmt(
b.call( b.call(
'$.attribute_effect', '$.attribute_effect',
element_id, element_id,
b.arrow( b.arrow(memoizer.all_ids(), b.object(values)),
all.map(({ id }) => id), memoizer.sync_values(),
b.object(values) memoizer.async_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 && element.metadata.scoped &&
context.state.analysis.css.hash !== '' && context.state.analysis.css.hash !== '' &&
b.literal(context.state.analysis.css.hash), b.literal(context.state.analysis.css.hash),

@ -12,10 +12,10 @@ import { build_getter } from '../../utils.js';
export class Memoizer { export class Memoizer {
/** @type {Array<{ id: Identifier, expression: Expression }>} */ /** @type {Array<{ id: Identifier, expression: Expression }>} */
sync = []; #sync = [];
/** @type {Array<{ id: Identifier, expression: Expression }>} */ /** @type {Array<{ id: Identifier, expression: Expression }>} */
async = []; #async = [];
/** /**
* @param {Expression} expression * @param {Expression} expression
@ -24,19 +24,39 @@ export class Memoizer {
add(expression, has_await) { add(expression, has_await) {
const id = b.id(`#`); // filled in later 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; return id;
} }
apply() { apply() {
const all = [...this.async, ...this.sync]; [...this.#async, ...this.#sync].forEach((memo, i) => {
all.forEach((memo, i) => {
memo.id.name = `$${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)))
);
}
return all; sync_values() {
if (this.#sync.length === 0) return;
return b.array(this.#sync.map((memo) => b.thunk(memo.expression)));
} }
} }
@ -143,20 +163,19 @@ export function build_template_chunk(
export function build_render_statement(state) { export function build_render_statement(state) {
const { memoizer } = state; const { memoizer } = state;
const all = state.memoizer.apply(); state.memoizer.apply();
return b.stmt( return b.stmt(
b.call( b.call(
'$.template_effect', '$.template_effect',
b.arrow( b.arrow(
all.map(({ id }) => id), memoizer.all_ids(),
state.update.length === 1 && state.update[0].type === 'ExpressionStatement' state.update.length === 1 && state.update[0].type === 'ExpressionStatement'
? state.update[0].expression ? state.update[0].expression
: b.block(state.update) : b.block(state.update)
), ),
all.length > 0 && b.array(memoizer.sync.map(({ expression }) => b.thunk(expression))), memoizer.sync_values(),
memoizer.async.length > 0 && memoizer.async_values()
b.array(memoizer.async.map(({ expression }) => b.thunk(expression, true)))
) )
); );
} }

Loading…
Cancel
Save