chore: remove memoize_expression (#16358)

pull/16347/head
Rich Harris 2 months ago committed by GitHub
parent df5801c5fe
commit f6a2599ee1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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
@ -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');
@ -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)]));
@ -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);
@ -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));
}

@ -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';
@ -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 = [];
@ -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);
}
@ -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;
@ -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;
}
);
@ -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;
@ -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];
}

@ -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)

Loading…
Cancel
Save