aaa
Rich Harris 8 months ago
commit b78fed8eb7

@ -35,10 +35,6 @@ export function EachBlock(node, context) {
context.state.template.push('<!>');
}
if (each_node_meta.array_name !== null) {
context.state.init.push(b.const(each_node_meta.array_name, b.thunk(collection)));
}
let flags = 0;
if (node.metadata.keyed && node.index) {
@ -120,8 +116,21 @@ export function EachBlock(node, context) {
return [array, ...transitive_dependencies];
});
if (each_node_meta.array_name) {
indirect_dependencies.push(b.call(each_node_meta.array_name));
/** @type {Identifier | null} */
let collection_id = null;
// Check if inner scope shadows something from outer scope.
// This is necessary because we need access to the array expression of the each block
// in the inner scope if bindings are used, in order to invalidate the array.
for (const [name] of context.state.scope.declarations) {
if (context.state.scope.parent?.get(name) != null) {
collection_id = context.state.scope.root.unique('$$array');
break;
}
}
if (collection_id) {
indirect_dependencies.push(b.call(collection_id));
} else {
indirect_dependencies.push(collection);
@ -195,7 +204,7 @@ export function EachBlock(node, context) {
// TODO 6.0 this only applies in legacy mode, reassignments are
// forbidden in runes mode
return b.member(
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
collection_id ? b.call(collection_id) : collection,
(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
true
);
@ -207,7 +216,7 @@ export function EachBlock(node, context) {
uses_index = true;
const left = b.member(
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
collection_id ? b.call(collection_id) : collection,
(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
true
);
@ -285,7 +294,11 @@ export function EachBlock(node, context) {
const { is_async } = node.metadata.expression;
const thunk = each_node_meta.array_name ?? b.thunk(collection, is_async);
const thunk = b.thunk(collection, is_async);
const render_args = [b.id('$$anchor'), item];
if (uses_index || collection_id) render_args.push(index);
if (collection_id) render_args.push(collection_id);
/** @type {Expression[]} */
const args = [
@ -293,10 +306,7 @@ export function EachBlock(node, context) {
b.literal(flags),
is_async ? b.thunk(b.call('$.get', b.id('$$collection'))) : thunk,
key_function,
b.arrow(
uses_index ? [b.id('$$anchor'), item, index] : [b.id('$$anchor'), item],
b.block(declarations.concat(block.body))
)
b.arrow(render_args, b.block(declarations.concat(block.body)))
];
if (node.fallback) {

@ -592,21 +592,10 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
}
if (node.fallback) visit(node.fallback, { scope });
// Check if inner scope shadows something from outer scope.
// This is necessary because we need access to the array expression of the each block
// in the inner scope if bindings are used, in order to invalidate the array.
let needs_array_deduplication = false;
for (const [name] of scope.declarations) {
if (state.scope.get(name) !== null) {
needs_array_deduplication = true;
}
}
node.metadata = {
expression: create_expression_metadata(),
keyed: false,
contains_group_binding: false,
array_name: needs_array_deduplication ? state.scope.root.unique('$$array') : null,
index: scope.root.unique('$$index'),
declarations: scope.declarations,
is_controlled: false

@ -419,8 +419,6 @@ export namespace AST {
expression: ExpressionMetadata;
keyed: boolean;
contains_group_binding: boolean;
/** Set if something in the array expression is shadowed within the each block */
array_name: Identifier | null;
index: Identifier;
declarations: Map<string, Binding>;
/**

@ -271,7 +271,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
* @param {Array<V>} array
* @param {EachState} state
* @param {Element | Comment | Text} anchor
* @param {(anchor: Node, item: MaybeSource<V>, index: number | Source<number>) => void} render_fn
* @param {(anchor: Node, item: MaybeSource<V>, index: number | Source<number>, collection: () => V[]) => void} render_fn
* @param {number} flags
* @param {boolean} is_inert
* @param {(value: V, index: number) => any} get_key
@ -510,7 +510,7 @@ function update_item(item, value, index, type) {
* @param {V} value
* @param {unknown} key
* @param {number} index
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>) => void} render_fn
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>, collection: () => V[]) => void} render_fn
* @param {number} flags
* @param {() => V[]} get_collection
* @returns {EachItem}
@ -559,7 +559,7 @@ function create_item(
current_each_item = item;
try {
item.e = branch(() => render_fn(anchor, v, i), hydrating);
item.e = branch(() => render_fn(anchor, v, i, get_collection), hydrating);
item.e.prev = prev && prev.e;
item.e.next = next && next.e;

Loading…
Cancel
Save