|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/** @import { BlockStatement, Expression, Identifier, Pattern, Statement } from 'estree' */
|
|
|
|
|
/** @import { BlockStatement, Expression, Identifier, Pattern, SequenceExpression, Statement } from 'estree' */
|
|
|
|
|
/** @import { AST, Binding } from '#compiler' */
|
|
|
|
|
/** @import { ComponentContext } from '../types' */
|
|
|
|
|
/** @import { Scope } from '../../../scope' */
|
|
|
|
@ -106,16 +106,6 @@ export function EachBlock(node, context) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Legacy mode: find the parent each blocks which contain the arrays to invalidate
|
|
|
|
|
const indirect_dependencies = collect_parent_each_blocks(context).flatMap((block) => {
|
|
|
|
|
const array = /** @type {Expression} */ (context.visit(block.expression));
|
|
|
|
|
const transitive_dependencies = build_transitive_dependencies(
|
|
|
|
|
block.metadata.expression.dependencies,
|
|
|
|
|
context
|
|
|
|
|
);
|
|
|
|
|
return [array, ...transitive_dependencies];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** @type {Identifier | null} */
|
|
|
|
|
let collection_id = null;
|
|
|
|
|
|
|
|
|
@ -129,18 +119,6 @@ export function EachBlock(node, context) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (collection_id) {
|
|
|
|
|
indirect_dependencies.push(b.call(collection_id));
|
|
|
|
|
} else {
|
|
|
|
|
indirect_dependencies.push(collection);
|
|
|
|
|
|
|
|
|
|
const transitive_dependencies = build_transitive_dependencies(
|
|
|
|
|
each_node_meta.expression.dependencies,
|
|
|
|
|
context
|
|
|
|
|
);
|
|
|
|
|
indirect_dependencies.push(...transitive_dependencies);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const child_state = {
|
|
|
|
|
...context.state,
|
|
|
|
|
transform: { ...context.state.transform },
|
|
|
|
@ -181,19 +159,51 @@ export function EachBlock(node, context) {
|
|
|
|
|
/** @type {Statement[]} */
|
|
|
|
|
const declarations = [];
|
|
|
|
|
|
|
|
|
|
const invalidate = b.call(
|
|
|
|
|
'$.invalidate_inner_signals',
|
|
|
|
|
b.thunk(b.sequence(indirect_dependencies))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const invalidate_store = store_to_invalidate
|
|
|
|
|
? b.call('$.invalidate_store', b.id('$$stores'), b.literal(store_to_invalidate))
|
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
|
|
/** @type {Expression[]} */
|
|
|
|
|
const sequence = [];
|
|
|
|
|
if (!context.state.analysis.runes) sequence.push(invalidate);
|
|
|
|
|
if (invalidate_store) sequence.push(invalidate_store);
|
|
|
|
|
|
|
|
|
|
if (!context.state.analysis.runes) {
|
|
|
|
|
/** @type {Set<Identifier>} */
|
|
|
|
|
const transitive_deps = new Set();
|
|
|
|
|
|
|
|
|
|
if (collection_id) {
|
|
|
|
|
transitive_deps.add(collection_id);
|
|
|
|
|
child_state.transform[collection_id.name] = { read: b.call };
|
|
|
|
|
} else {
|
|
|
|
|
for (const binding of each_node_meta.transitive_deps) {
|
|
|
|
|
transitive_deps.add(binding.node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const block of collect_parent_each_blocks(context)) {
|
|
|
|
|
for (const binding of block.metadata.transitive_deps) {
|
|
|
|
|
transitive_deps.add(binding.node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (transitive_deps.size > 0) {
|
|
|
|
|
const invalidate = b.call(
|
|
|
|
|
'$.invalidate_inner_signals',
|
|
|
|
|
b.thunk(
|
|
|
|
|
b.sequence(
|
|
|
|
|
[...transitive_deps].map(
|
|
|
|
|
(node) => /** @type {Expression} */ (context.visit({ ...node }, child_state))
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
sequence.push(invalidate);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (invalidate_store) {
|
|
|
|
|
sequence.push(invalidate_store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node.context?.type === 'Identifier') {
|
|
|
|
|
const binding = /** @type {Binding} */ (context.state.scope.get(node.context.name));
|
|
|
|
@ -329,41 +339,3 @@ export function EachBlock(node, context) {
|
|
|
|
|
function collect_parent_each_blocks(context) {
|
|
|
|
|
return /** @type {AST.EachBlock[]} */ (context.path.filter((node) => node.type === 'EachBlock'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Set<Binding>} references
|
|
|
|
|
* @param {ComponentContext} context
|
|
|
|
|
*/
|
|
|
|
|
function build_transitive_dependencies(references, context) {
|
|
|
|
|
/** @type {Set<Binding>} */
|
|
|
|
|
const dependencies = new Set();
|
|
|
|
|
|
|
|
|
|
for (const ref of references) {
|
|
|
|
|
const deps = collect_transitive_dependencies(ref);
|
|
|
|
|
for (const dep of deps) {
|
|
|
|
|
dependencies.add(dep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [...dependencies].map((dep) => build_getter({ ...dep.node }, context.state));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Binding} binding
|
|
|
|
|
* @param {Set<Binding>} seen
|
|
|
|
|
* @returns {Binding[]}
|
|
|
|
|
*/
|
|
|
|
|
function collect_transitive_dependencies(binding, seen = new Set()) {
|
|
|
|
|
if (binding.kind !== 'legacy_reactive') return [];
|
|
|
|
|
|
|
|
|
|
for (const dep of binding.legacy_dependencies) {
|
|
|
|
|
if (!seen.has(dep)) {
|
|
|
|
|
seen.add(dep);
|
|
|
|
|
for (const transitive_dep of collect_transitive_dependencies(dep, seen)) {
|
|
|
|
|
seen.add(transitive_dep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [...seen];
|
|
|
|
|
}
|
|
|
|
|