Skip to content

chore: remove memoize_expression #16358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/** @import { BlockStatement, Expression, ExpressionStatement, Literal, Property } from 'estree' */
/** @import { BlockStatement, Expression, ExpressionStatement, Literal, Property, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders';
import { build_attribute_value } from './shared/element.js';
import { memoize_expression } from './shared/utils.js';
import { Memoizer } from './shared/utils.js';

/**
* @param {AST.SlotElement} node
Expand All @@ -22,7 +22,7 @@ export function SlotElement(node, context) {
/** @type {ExpressionStatement[]} */
const lets = [];

let is_default = true;
const memoizer = new Memoizer();

let name = b.literal('default');

Expand All @@ -33,12 +33,11 @@ export function SlotElement(node, context) {
const { value, has_state } = build_attribute_value(
attribute.value,
context,
(value, metadata) => (metadata.has_call ? memoize_expression(context.state, value) : value)
(value, metadata) => (metadata.has_call ? b.call('$.get', memoizer.add(value)) : value)
);

if (attribute.name === 'name') {
name = /** @type {Literal} */ (value);
is_default = false;
} else if (attribute.name !== 'slot') {
if (has_state) {
props.push(b.get(attribute.name, [b.return(value)]));
Expand All @@ -51,9 +50,14 @@ export function SlotElement(node, context) {
}
}

memoizer.apply();

// Let bindings first, they can be used on attributes
context.state.init.push(...lets);

/** @type {Statement[]} */
const statements = memoizer.deriveds(context.state.analysis.runes);

const props_expression =
spreads.length === 0 ? b.object(props) : b.call('$.spread_props', b.object(props), ...spreads);

Expand All @@ -62,14 +66,9 @@ export function SlotElement(node, context) {
? b.null
: b.arrow([b.id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment)));

const slot = b.call(
'$.slot',
context.state.node,
b.id('$$props'),
name,
props_expression,
fallback
statements.push(
b.stmt(b.call('$.slot', context.state.node, b.id('$$props'), name, props_expression, fallback))
);

context.state.init.push(b.stmt(slot));
context.state.init.push(statements.length === 1 ? statements[0] : b.block(statements));
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
import {
build_bind_this,
memoize_expression,
validate_binding,
add_svelte_meta
} from '../shared/utils.js';
import { add_svelte_meta, 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';
Expand Down Expand Up @@ -48,6 +43,8 @@ export function build_component(node, component_name, context) {
/** @type {Record<string, Expression[]>} */
const events = {};

const memoizer = new Memoizer();

/** @type {Property[]} */
const custom_css_props = [];

Expand Down Expand Up @@ -133,15 +130,13 @@ export function build_component(node, component_name, context) {
} else if (attribute.type === 'SpreadAttribute') {
const expression = /** @type {Expression} */ (context.visit(attribute));
if (attribute.metadata.expression.has_state) {
let value = expression;

if (attribute.metadata.expression.has_call) {
const id = b.id(context.state.scope.generate('spread_element'));
context.state.init.push(b.var(id, b.call('$.derived', b.thunk(value))));
value = b.call('$.get', id);
}

props_and_spreads.push(b.thunk(value));
props_and_spreads.push(
b.thunk(
attribute.metadata.expression.has_call
? b.call('$.get', memoizer.add(expression))
: expression
)
);
} else {
props_and_spreads.push(expression);
}
Expand All @@ -150,10 +145,10 @@ export function build_component(node, component_name, context) {
custom_css_props.push(
b.init(
attribute.name,
build_attribute_value(attribute.value, context, (value, metadata) =>
build_attribute_value(attribute.value, context, (value, metadata) => {
// TODO put the derived in the local block
metadata.has_call ? memoize_expression(context.state, value) : value
).value
return metadata.has_call ? b.call('$.get', memoizer.add(value)) : value;
}).value
)
);
continue;
Expand Down Expand Up @@ -184,7 +179,7 @@ export function build_component(node, component_name, context) {
);
});

return should_wrap_in_derived ? memoize_expression(context.state, value) : value;
return should_wrap_in_derived ? b.call('$.get', memoizer.add(value)) : value;
}
);

Expand Down Expand Up @@ -444,7 +439,7 @@ export function build_component(node, component_name, context) {
};
}

const statements = [...snippet_declarations];
const statements = [...snippet_declarations, ...memoizer.deriveds(context.state.analysis.runes)];

if (is_component_dynamic) {
const prev = fn;
Expand Down Expand Up @@ -492,5 +487,7 @@ export function build_component(node, component_name, context) {
statements.push(add_svelte_meta(fn(anchor), node, 'component', { componentTag: node.name }));
}

memoizer.apply();

return statements.length > 1 ? b.block(statements) : statements[0];
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,7 @@ import { sanitize_template_string } from '../../../../../utils/sanitize_template
import { regex_is_valid_identifier } from '../../../../patterns.js';
import is_reference from 'is-reference';
import { dev, is_ignored, locator, component_name } from '../../../../../state.js';
import { build_getter, create_derived } from '../../utils.js';

/**
* @param {ComponentClientTransformState} state
* @param {Expression} value
*/
export function memoize_expression(state, value) {
const id = b.id(state.scope.generate('expression'));
state.init.push(b.const(id, create_derived(state, b.thunk(value))));
return b.call('$.get', id);
}
import { build_getter } from '../../utils.js';

/**
* A utility for extracting complex expressions (such as call expressions)
Expand Down
Loading