perf: reuse the cached value in the `<option>`/`<select>` value guard (#18713)

One fewer evaluation of the value expression per update.

---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
pull/18717/head
Mathias Picker 4 weeks ago committed by GitHub
parent 8299cbf11b
commit 6b99f9fb52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
perf: reuse the cached value in the `<option>`/`<select>` value guard

@ -701,28 +701,32 @@ function build_element_special_value_attribute(
);
const evaluated = context.state.scope.evaluate(value);
const assignment = b.assignment('=', b.member(node_id, '__value'), value);
const set_value_assignment = b.assignment(
'=',
b.member(node_id, 'value'),
evaluated.is_defined ? assignment : b.logical('??', assignment, b.literal(''))
);
/** @param {Expression} value */
const build_update = (value) => {
const assignment = b.assignment('=', b.member(node_id, '__value'), value);
const update = b.stmt(
is_select_with_value
? b.sequence([
set_value_assignment,
// This ensures a one-way street to the DOM in case it's <select {value}>
// and not <select bind:value>. We need it in addition to $.init_select
// because the select value is not reflected as an attribute, so the
// mutation observer wouldn't notice.
b.call('$.select_option', node_id, value)
])
: synthetic
? assignment
: set_value_assignment
);
const set_value_assignment = b.assignment(
'=',
b.member(node_id, 'value'),
evaluated.is_defined ? assignment : b.logical('??', assignment, b.literal(''))
);
return b.stmt(
is_select_with_value
? b.sequence([
set_value_assignment,
// This ensures a one-way street to the DOM in case it's <select {value}>
// and not <select bind:value>. We need it in addition to $.init_select
// because the select value is not reflected as an attribute, so the
// mutation observer wouldn't notice.
b.call('$.select_option', node_id, value)
])
: synthetic
? assignment
: set_value_assignment
);
};
if (has_state) {
const id = b.id(state.scope.generate(`${node_id.name}_value`));
@ -733,9 +737,14 @@ function build_element_special_value_attribute(
const init = element === 'option' ? b.object([]) : undefined;
state.init.push(b.var(id, init));
state.update.push(b.if(b.binary('!==', id, b.assignment('=', id, value)), b.block([update])));
// the guard already evaluated `value` into `id`, so read that back rather than
// evaluating the same expression (and its signal reads) a second time
state.update.push(
b.if(b.binary('!==', id, b.assignment('=', id, value)), b.block([build_update(id)]))
);
} else {
state.init.push(update);
state.init.push(build_update(value));
}
if (is_select_with_value) {

@ -74,7 +74,7 @@ export default function Select_with_rich_content($$anchor) {
$.set_text(text, $.get(item));
if (option_5_value !== (option_5_value = $.get(item))) {
option_5.__value = $.get(item);
option_5.__value = option_5_value;
}
});
@ -137,7 +137,7 @@ export default function Select_with_rich_content($$anchor) {
$.set_text(text_1, $.get(x));
if (option_8_value !== (option_8_value = $.get(x))) {
option_8.__value = $.get(x);
option_8.__value = option_8_value;
}
});
@ -175,7 +175,7 @@ export default function Select_with_rich_content($$anchor) {
$.set_text(text_2, $.get(item));
if (option_10_value !== (option_10_value = $.get(item))) {
option_10.__value = $.get(item);
option_10.__value = option_10_value;
}
});
@ -240,7 +240,7 @@ export default function Select_with_rich_content($$anchor) {
$.set_text(text_4, $.get(item));
if (option_13_value !== (option_13_value = $.get(item))) {
option_13.__value = $.get(item);
option_13.__value = option_13_value;
}
});

Loading…
Cancel
Save