chore: tidy up each block compiler logic (#12513)

* small tidy-up

* each_type -> flags

* tidy up
pull/12527/head
Rich Harris 4 months ago committed by GitHub
parent ca2f02c23e
commit a01f658f01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -2362,7 +2362,6 @@ export const template_visitors = {
EachBlock(node, context) {
const each_node_meta = node.metadata;
const collection = /** @type {Expression} */ (context.visit(node.expression));
let each_item_is_reactive = true;
if (!each_node_meta.is_controlled) {
context.state.template.push('<!>');
@ -2372,36 +2371,29 @@ export const template_visitors = {
context.state.init.push(b.const(each_node_meta.array_name, b.thunk(collection)));
}
// The runtime needs to know what kind of each block this is in order to optimize for the
// key === item (we avoid extra allocations). In that case, the item doesn't need to be reactive.
// We can guarantee this by knowing that in order for the item of the each block to change, they
// would need to mutate the key/item directly in the array. Given that in runes mode we use ===
// equality, we can apply a fast-path (as long as the index isn't reactive).
let each_type = 0;
let flags = 0;
if (
node.key &&
(node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index)
) {
each_type |= EACH_KEYED;
// If there's a destructuring, then we likely need the generated $$index
if (node.index || node.context.type !== 'Identifier') {
each_type |= EACH_INDEX_REACTIVE;
flags |= EACH_KEYED;
if (node.index) {
flags |= EACH_INDEX_REACTIVE;
}
if (
context.state.analysis.runes &&
// In runes mode, if key === item, we don't need to wrap the item in a source
const key_is_item =
node.key.type === 'Identifier' &&
node.context.type === 'Identifier' &&
node.context.name === node.key.name &&
(each_type & EACH_INDEX_REACTIVE) === 0
) {
// Fast-path for when the key === item
each_item_is_reactive = false;
} else {
each_type |= EACH_ITEM_REACTIVE;
node.context.name === node.key.name;
if (!context.state.analysis.runes || !key_is_item) {
flags |= EACH_ITEM_REACTIVE;
}
} else {
each_type |= EACH_ITEM_REACTIVE;
flags |= EACH_ITEM_REACTIVE;
}
// Since `animate:` can only appear on elements that are the sole child of a keyed each block,
@ -2414,15 +2406,15 @@ export const template_visitors = {
return child.attributes.some((attr) => attr.type === 'AnimateDirective');
})
) {
each_type |= EACH_IS_ANIMATED;
flags |= EACH_IS_ANIMATED;
}
if (each_node_meta.is_controlled) {
each_type |= EACH_IS_CONTROLLED;
flags |= EACH_IS_CONTROLLED;
}
if (context.state.analysis.runes) {
each_type |= EACH_IS_STRICT_EQUALS;
flags |= EACH_IS_STRICT_EQUALS;
}
// If the array is a store expression, we need to invalidate it when the array is changed.
@ -2447,10 +2439,12 @@ export const template_visitors = {
);
return [array, ...transitive_dependencies];
});
if (each_node_meta.array_name) {
indirect_dependencies.push(b.call(each_node_meta.array_name));
} else {
indirect_dependencies.push(collection);
const transitive_dependencies = serialize_transitive_dependencies(
each_node_meta.references,
context
@ -2469,6 +2463,7 @@ export const template_visitors = {
// into separate expressions, at which point this is called again with an identifier or member expression
return serialize_set_binding(assignment, context, () => assignment);
}
const left = object(assignment.left);
const value = get_assignment_value(assignment, context);
const invalidate = b.call(
@ -2509,10 +2504,12 @@ export const template_visitors = {
const item_with_loc = with_loc(item, id);
return b.call('$.unwrap', item_with_loc);
};
if (node.index) {
const index_binding = /** @type {import('#compiler').Binding} */ (
context.state.scope.get(node.index)
);
index_binding.expression = (id) => {
const index_with_loc = with_loc(index, id);
return b.call('$.unwrap', index_with_loc);
@ -2575,7 +2572,7 @@ export const template_visitors = {
declarations.push(b.let(node.index, index));
}
if (context.state.options.dev && (each_type & EACH_KEYED) !== 0) {
if (context.state.options.dev && (flags & EACH_KEYED) !== 0) {
context.state.init.push(
b.stmt(b.call('$.validate_each_keys', b.thunk(collection), key_function))
);
@ -2584,7 +2581,7 @@ export const template_visitors = {
/** @type {Expression[]} */
const args = [
context.state.node,
b.literal(each_type),
b.literal(flags),
each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection),
key_function,
b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(block.body)))

Loading…
Cancel
Save