Skip to content

Commit b6a5065

Browse files
committed
memoize clsx
1 parent cd56c1d commit b6a5065

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -573,14 +573,17 @@ function build_element_attribute_update_assignment(
573573

574574
const is_autofocus = name === 'autofocus';
575575

576-
let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
577-
metadata.has_call
578-
? // if it's autofocus we will not add this to a template effect so we don't want to get the expression id
579-
// but separately memoize the expression
580-
is_autofocus
581-
? memoize_expression(state, value)
582-
: get_expression_id(state, value)
583-
: value
576+
let { value, has_state, has_call } = build_attribute_value(
577+
attribute.value,
578+
context,
579+
(value, metadata) =>
580+
metadata.has_call
581+
? // if it's autofocus we will not add this to a template effect so we don't want to get the expression id
582+
// but separately memoize the expression
583+
is_autofocus
584+
? memoize_expression(state, value)
585+
: get_expression_id(state, value)
586+
: value
584587
);
585588

586589
if (is_autofocus) {
@@ -608,6 +611,7 @@ function build_element_attribute_update_assignment(
608611
attribute,
609612
value,
610613
has_state,
614+
has_call,
611615
class_directives,
612616
context,
613617
!is_svg && !is_mathml

packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function SvelteElement(node, context) {
8787
is_text_attribute(attributes[0])
8888
) {
8989
// special case when there only a class attribute, without call expression
90-
let { value, has_state } = build_attribute_value(
90+
let { value, has_state, has_call } = build_attribute_value(
9191
attributes[0].value,
9292
context,
9393
(value, metadata) => (metadata.has_call ? get_expression_id(context.state, value) : value)
@@ -99,6 +99,7 @@ export function SvelteElement(node, context) {
9999
attributes[0],
100100
value,
101101
has_state,
102+
has_call,
102103
class_directives,
103104
inner_context,
104105
false

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,25 +155,26 @@ export function build_style_directives(
155155
* @param {AST.Attribute['value']} value
156156
* @param {ComponentContext} context
157157
* @param {(value: Expression, metadata: ExpressionMetadata) => Expression} memoize
158-
* @returns {{ value: Expression, has_state: boolean }}
158+
* @returns {{ value: Expression, has_state: boolean, has_call: boolean }}
159159
*/
160160
export function build_attribute_value(value, context, memoize = (value) => value) {
161161
if (value === true) {
162-
return { value: b.literal(true), has_state: false };
162+
return { value: b.literal(true), has_state: false, has_call: false };
163163
}
164164

165165
if (!Array.isArray(value) || value.length === 1) {
166166
const chunk = Array.isArray(value) ? value[0] : value;
167167

168168
if (chunk.type === 'Text') {
169-
return { value: b.literal(chunk.data), has_state: false };
169+
return { value: b.literal(chunk.data), has_state: false, has_call: false };
170170
}
171171

172172
let expression = /** @type {Expression} */ (context.visit(chunk.expression));
173173

174174
return {
175175
value: memoize(expression, chunk.metadata.expression),
176-
has_state: chunk.metadata.expression.has_state
176+
has_state: chunk.metadata.expression.has_state,
177+
has_call: chunk.metadata.expression.has_call
177178
};
178179
}
179180

@@ -198,6 +199,7 @@ export function get_attribute_name(element, attribute) {
198199
* @param {AST.Attribute | null} attribute
199200
* @param {Expression} value
200201
* @param {boolean} has_state
202+
* @param {boolean} has_call
201203
* @param {AST.ClassDirective[]} class_directives
202204
* @param {ComponentContext} context
203205
* @param {boolean} is_html
@@ -209,12 +211,16 @@ export function build_set_class(
209211
attribute,
210212
value,
211213
has_state,
214+
has_call,
212215
class_directives,
213216
context,
214217
is_html
215218
) {
216219
if (attribute && attribute.metadata.needs_clsx) {
217220
value = b.call('$.clsx', value);
221+
if (has_state && !has_call) {
222+
value = get_expression_id(context.state, value);
223+
}
218224
}
219225

220226
/** @type {Identifier | undefined} */

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function compare_expressions(a, b) {
8080
* @param {(node: AST.SvelteNode, state: any) => any} visit
8181
* @param {ComponentClientTransformState} state
8282
* @param {(value: Expression, metadata: ExpressionMetadata) => Expression} memoize
83-
* @returns {{ value: Expression, has_state: boolean }}
83+
* @returns {{ value: Expression, has_state: boolean, has_call: boolean }}
8484
*/
8585
export function build_template_chunk(
8686
values,
@@ -95,6 +95,7 @@ export function build_template_chunk(
9595
const quasis = [quasi];
9696

9797
let has_state = false;
98+
let has_call = false;
9899

99100
for (let i = 0; i < values.length; i++) {
100101
const node = values[i];
@@ -116,11 +117,12 @@ export function build_template_chunk(
116117
);
117118

118119
has_state ||= node.metadata.expression.has_state;
120+
has_call ||= node.metadata.expression.has_call;
119121

120122
if (values.length === 1) {
121123
// If we have a single expression, then pass that in directly to possibly avoid doing
122124
// extra work in the template_effect (instead we do the work in set_text).
123-
return { value, has_state };
125+
return { value, has_state, has_call };
124126
}
125127

126128
if (
@@ -162,7 +164,7 @@ export function build_template_chunk(
162164
? b.template(quasis, expressions)
163165
: b.literal(/** @type {string} */ (quasi.value.cooked));
164166

165-
return { value, has_state };
167+
return { value, has_state, has_call };
166168
}
167169

168170
/**

0 commit comments

Comments
 (0)