|
|
|
@ -55,9 +55,6 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
each_block_value: Identifier;
|
|
|
|
|
get_each_context: Identifier;
|
|
|
|
|
iterations: Identifier;
|
|
|
|
|
fixed_length: number;
|
|
|
|
|
data_length: string;
|
|
|
|
|
view_length: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
context_props: Array<Node | Node[]>;
|
|
|
|
@ -92,7 +89,6 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
type: 'each',
|
|
|
|
|
// @ts-ignore todo: probably error
|
|
|
|
|
key: node.key as string,
|
|
|
|
|
|
|
|
|
|
bindings: new Map(block.bindings),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -103,42 +99,16 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
? { type: 'Identifier', name: this.node.index }
|
|
|
|
|
: renderer.component.get_unique_name(`${this.node.context}_index`);
|
|
|
|
|
|
|
|
|
|
const fixed_length =
|
|
|
|
|
node.expression.node.type === 'ArrayExpression' &&
|
|
|
|
|
node.expression.node.elements.every((element) => element.type !== 'SpreadElement')
|
|
|
|
|
? node.expression.node.elements.length
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
// hack the sourcemap, so that if data is missing the bug
|
|
|
|
|
// is easy to find
|
|
|
|
|
let c = this.node.start + 2;
|
|
|
|
|
while (renderer.component.source[c] !== 'e') c += 1;
|
|
|
|
|
const start = renderer.component.locate(c);
|
|
|
|
|
const end = { line: start.line, column: start.column + 4 };
|
|
|
|
|
const length = {
|
|
|
|
|
type: 'Identifier',
|
|
|
|
|
name: 'length',
|
|
|
|
|
loc: { start, end },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
|
|
|
|
|
const iterations = block.get_unique_name(`${this.var.name}_blocks`);
|
|
|
|
|
|
|
|
|
|
renderer.add_to_context(each_block_value.name, true);
|
|
|
|
|
renderer.add_to_context(this.index_name.name, true);
|
|
|
|
|
|
|
|
|
|
this.vars = {
|
|
|
|
|
create_each_block: this.block.name,
|
|
|
|
|
each_block_value,
|
|
|
|
|
each_block_value: renderer.component.get_unique_name(`${this.var.name}_value`),
|
|
|
|
|
get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
|
|
|
|
|
iterations,
|
|
|
|
|
|
|
|
|
|
// optimisation for array literal
|
|
|
|
|
fixed_length,
|
|
|
|
|
data_length: fixed_length === null ? x`${each_block_value}.${length}` : fixed_length,
|
|
|
|
|
view_length: fixed_length === null ? x`${iterations}.length` : fixed_length,
|
|
|
|
|
iterations: block.get_unique_name(`${this.var.name}_blocks`),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
renderer.add_to_context(this.vars.each_block_value.name, true);
|
|
|
|
|
renderer.add_to_context(this.index_name.name, true);
|
|
|
|
|
|
|
|
|
|
const store =
|
|
|
|
|
node.expression.node.type === 'Identifier' && node.expression.node.name[0] === '$'
|
|
|
|
|
? node.expression.node.name.slice(1)
|
|
|
|
@ -182,7 +152,8 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
|
|
|
|
|
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
|
|
|
|
|
if (this.fragment.nodes.length === 0) return;
|
|
|
|
|
|
|
|
|
|
const __DEV__ = this.renderer.options.dev;
|
|
|
|
|
const { each_block_value, iterations: each_block } = this.vars;
|
|
|
|
|
const { renderer } = this;
|
|
|
|
|
const { component } = renderer;
|
|
|
|
|
|
|
|
|
@ -193,20 +164,17 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (this.node.has_binding)
|
|
|
|
|
this.context_props.push(
|
|
|
|
|
b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`
|
|
|
|
|
);
|
|
|
|
|
this.context_props.push(b`child_ctx[${renderer.context_lookup.get(each_block_value.name).index}] = list;`);
|
|
|
|
|
if (this.node.has_binding || this.node.index)
|
|
|
|
|
this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
|
|
|
|
|
|
|
|
|
|
const snippet = this.node.expression.manipulate(block);
|
|
|
|
|
|
|
|
|
|
block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`);
|
|
|
|
|
if (this.renderer.options.dev) {
|
|
|
|
|
block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`);
|
|
|
|
|
block.chunks.init.push(b`let ${each_block_value} = ${snippet};`);
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
block.chunks.init.push(b`@validate_each_argument(${each_block_value});`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO which is better — Object.create(array) or array.slice()?
|
|
|
|
|
renderer.blocks.push(b`
|
|
|
|
|
function ${this.vars.get_each_context}(#ctx, list, i) {
|
|
|
|
|
const child_ctx = #ctx.slice();
|
|
|
|
@ -246,11 +214,7 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.block.has_intro_method || this.block.has_outro_method) {
|
|
|
|
|
block.chunks.intro.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
|
|
|
|
|
@transition_in(${this.vars.iterations}[#i]);
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
block.chunks.intro.push(for_loop(each_block, (item) => b`@transition_in(${item});`));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needs_anchor) {
|
|
|
|
@ -260,20 +224,18 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
if (this.else) {
|
|
|
|
|
const each_block_else = component.get_unique_name(`${this.var.name}_else`);
|
|
|
|
|
|
|
|
|
|
block.chunks.init.push(b`let ${each_block_else} = null;`);
|
|
|
|
|
|
|
|
|
|
// TODO neaten this up... will end up with an empty line in the block
|
|
|
|
|
block.chunks.init.push(b`
|
|
|
|
|
if (!${this.vars.data_length}) {
|
|
|
|
|
block.chunks.init.push(
|
|
|
|
|
b`let ${each_block_else} = null;`,
|
|
|
|
|
b`if (!${each_block_value}.length) {
|
|
|
|
|
${each_block_else} = ${this.else.block.name}(#ctx);
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
block.chunks.create.push(b`
|
|
|
|
|
if (${each_block_else}) {
|
|
|
|
|
${each_block_else}.c();
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}`);
|
|
|
|
|
|
|
|
|
|
if (this.renderer.options.hydratable) {
|
|
|
|
|
block.chunks.claim.push(b`
|
|
|
|
@ -288,40 +250,37 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
if (this.else.block.has_update_method) {
|
|
|
|
|
this.updates.push(b`
|
|
|
|
|
if (!${this.vars.data_length} && ${each_block_else}) {
|
|
|
|
|
${each_block_else}.p(#ctx, #dirty);
|
|
|
|
|
} else if (!${this.vars.data_length}) {
|
|
|
|
|
const no_each_else = x`!${each_block_value}.length`;
|
|
|
|
|
const update_else = b`${each_block_else}.p(#ctx, #dirty);`;
|
|
|
|
|
const destroy_else = b`${each_block_else}.d(1);${each_block_else} = null;`;
|
|
|
|
|
const create_else = b`
|
|
|
|
|
${each_block_else} = ${this.else.block.name}(#ctx);
|
|
|
|
|
${each_block_else}.c();
|
|
|
|
|
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
} else if (${each_block_else}) {
|
|
|
|
|
${each_block_else}.d(1);
|
|
|
|
|
${each_block_else} = null;
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
} else {
|
|
|
|
|
this.updates.push(b`
|
|
|
|
|
if (${this.vars.data_length}) {
|
|
|
|
|
if (${each_block_else}) {
|
|
|
|
|
${each_block_else}.d(1);
|
|
|
|
|
${each_block_else} = null;
|
|
|
|
|
}
|
|
|
|
|
} else if (!${each_block_else}) {
|
|
|
|
|
${each_block_else} = ${this.else.block.name}(#ctx);
|
|
|
|
|
${each_block_else}.c();
|
|
|
|
|
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});`;
|
|
|
|
|
|
|
|
|
|
this.updates.push(
|
|
|
|
|
$if({
|
|
|
|
|
if: each_block_else,
|
|
|
|
|
true: $if({
|
|
|
|
|
if: no_each_else,
|
|
|
|
|
true: update_else,
|
|
|
|
|
false: destroy_else,
|
|
|
|
|
}),
|
|
|
|
|
false: $if({
|
|
|
|
|
if: no_each_else,
|
|
|
|
|
true: create_else,
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
block.chunks.destroy.push(b`
|
|
|
|
|
if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
|
|
|
|
|
if (${each_block_else}){
|
|
|
|
|
${each_block_else}.d(${parent_node ? '' : 'detaching'});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.updates = this.updates.filter(Boolean);
|
|
|
|
|
if (this.updates.length) {
|
|
|
|
|
block.chunks.update.push(b`
|
|
|
|
|
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
|
|
|
|
@ -356,104 +315,76 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
update_anchor_node: Identifier;
|
|
|
|
|
update_mount_node: Identifier;
|
|
|
|
|
}) {
|
|
|
|
|
const { create_each_block, iterations, data_length, view_length } = this.vars;
|
|
|
|
|
const __DEV__ = this.renderer.options.dev;
|
|
|
|
|
const {
|
|
|
|
|
create_each_block,
|
|
|
|
|
iterations: each_block,
|
|
|
|
|
each_block_value,
|
|
|
|
|
get_each_context: each_context_getter,
|
|
|
|
|
} = this.vars;
|
|
|
|
|
|
|
|
|
|
const for_each_block = (fn) => for_loop(each_block, fn);
|
|
|
|
|
|
|
|
|
|
const get_key = block.get_unique_name('get_key');
|
|
|
|
|
const key_getter = block.get_unique_name('get_key');
|
|
|
|
|
const lookup = block.get_unique_name(`${this.var.name}_lookup`);
|
|
|
|
|
|
|
|
|
|
block.add_variable(iterations, x`[]`);
|
|
|
|
|
block.add_variable(each_block, x`[]`);
|
|
|
|
|
block.add_variable(lookup, x`new @_Map()`);
|
|
|
|
|
|
|
|
|
|
if (this.fragment.nodes[0].is_dom_node()) {
|
|
|
|
|
this.block.first = this.fragment.nodes[0].var;
|
|
|
|
|
} else {
|
|
|
|
|
this.block.first = this.block.get_unique_name('first');
|
|
|
|
|
this.block.add_element(this.block.first, x`@empty()`, parent_nodes && x`@empty()`, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.chunks.init.push(b`
|
|
|
|
|
const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
|
|
|
|
|
if (this.fragment.nodes[0].is_dom_node()) this.block.first = this.fragment.nodes[0].var;
|
|
|
|
|
else
|
|
|
|
|
this.block.add_element(
|
|
|
|
|
(this.block.first = this.block.get_unique_name('first')),
|
|
|
|
|
x`@empty()`,
|
|
|
|
|
parent_nodes && x`@empty()`,
|
|
|
|
|
null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
${
|
|
|
|
|
this.renderer.options.dev &&
|
|
|
|
|
b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`
|
|
|
|
|
}
|
|
|
|
|
for (let #i = 0; #i < ${data_length}; #i += 1) {
|
|
|
|
|
let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
|
|
|
|
|
let key = ${get_key}(child_ctx);
|
|
|
|
|
${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
const validate_each_keys =
|
|
|
|
|
__DEV__ && b`@validate_each_keys(#ctx, ${each_block_value}, ${each_context_getter}, ${key_getter});`;
|
|
|
|
|
|
|
|
|
|
block.chunks.create.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].c();
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
const validate_each_argument = __DEV__ && b`@validate_each_argument(${each_block_value});`;
|
|
|
|
|
|
|
|
|
|
if (parent_nodes && this.renderer.options.hydratable) {
|
|
|
|
|
block.chunks.claim.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].l(${parent_nodes});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
block.chunks.init.push(
|
|
|
|
|
b`const ${key_getter} = (#ctx) => ${this.node.key.manipulate(block)};`,
|
|
|
|
|
validate_each_keys,
|
|
|
|
|
for_loop(
|
|
|
|
|
each_block_value,
|
|
|
|
|
(_, index) => b`
|
|
|
|
|
const #child_ctx = ${each_context_getter}(#ctx, ${each_block_value}, ${index});
|
|
|
|
|
const #key = ${key_getter}(#child_ctx);
|
|
|
|
|
${lookup}.set(#key, (${each_block}[${index}] = ${create_each_block}(#key, #child_ctx)));`
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
block.chunks.mount.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
|
|
|
|
|
if (parent_nodes && this.renderer.options.hydratable)
|
|
|
|
|
block.chunks.claim.push(for_each_block((block) => b`${block}.l(${parent_nodes});`));
|
|
|
|
|
block.chunks.mount.push(for_each_block((block) => b`${block}.m(${initial_mount_node}, ${initial_anchor_node});`));
|
|
|
|
|
|
|
|
|
|
const dynamic = this.block.has_update_method;
|
|
|
|
|
|
|
|
|
|
// const destroy = this.node.has_animation
|
|
|
|
|
// ? this.block.has_outros
|
|
|
|
|
// ? `@fix_and_outro_and_destroy_block`
|
|
|
|
|
// : `@fix_and_destroy_block`
|
|
|
|
|
// : this.block.has_outros
|
|
|
|
|
// ? `@outro_and_destroy_block`
|
|
|
|
|
// : `@destroy_block`;
|
|
|
|
|
const has_animation = this.node.has_animation || null;
|
|
|
|
|
const { has_outros } = this.block;
|
|
|
|
|
|
|
|
|
|
if (this.dependencies.size) {
|
|
|
|
|
const transition_state = bit_state([dynamic, has_animation, has_outros]);
|
|
|
|
|
const update_keyed_each = (transition_out) =>
|
|
|
|
|
b`${each_block} = @update_keyed_each(${each_block}, #dirty, #ctx, ${transition_state}, ${key_getter}, ${each_block_value}, ${lookup}, ${update_mount_node}, ${create_each_block}, ${update_anchor_node}, ${each_context_getter}, ${transition_out});`;
|
|
|
|
|
const measure_animations = has_animation && b`${for_each_block((block) => b`${block}.r();`)}`;
|
|
|
|
|
|
|
|
|
|
this.updates.push(
|
|
|
|
|
b`
|
|
|
|
|
const ${this.vars.each_block_value} = ${snippet};
|
|
|
|
|
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}`,
|
|
|
|
|
this.block.group_transition_out(
|
|
|
|
|
(transition_out) => b`
|
|
|
|
|
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1){ ${iterations}[#i].r();}`}
|
|
|
|
|
${
|
|
|
|
|
this.renderer.options.dev &&
|
|
|
|
|
b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`
|
|
|
|
|
}
|
|
|
|
|
${iterations} = @update_keyed_each(${iterations}, #dirty, #ctx, ${bit_state([
|
|
|
|
|
dynamic,
|
|
|
|
|
this.node.has_animation,
|
|
|
|
|
this.block.has_outros,
|
|
|
|
|
])}, ${get_key}, ${
|
|
|
|
|
this.vars.each_block_value
|
|
|
|
|
}, ${lookup}, ${update_mount_node}, ${create_each_block}, ${update_anchor_node}, ${
|
|
|
|
|
this.vars.get_each_context
|
|
|
|
|
}, ${transition_out});
|
|
|
|
|
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1){ ${iterations}[#i].a();}`}`
|
|
|
|
|
)
|
|
|
|
|
b`const ${each_block_value} = ${snippet};`,
|
|
|
|
|
validate_each_keys,
|
|
|
|
|
validate_each_argument,
|
|
|
|
|
measure_animations,
|
|
|
|
|
this.block.group_transition_out((transition_out) => update_keyed_each(transition_out)),
|
|
|
|
|
has_animation && for_each_block((block) => b`${block}.a();`)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.block.has_outros) {
|
|
|
|
|
block.chunks.outro.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
@transition_out(${iterations}[#i]);
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
if (has_outros) block.chunks.outro.push(for_each_block((block) => b`@transition_out(${block});`));
|
|
|
|
|
|
|
|
|
|
block.chunks.destroy.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].d(${parent_node ? null : 'detaching'});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
block.chunks.destroy.push(for_each_block((block) => b`${block}.d(${parent_node ? null : 'detaching'});`));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render_unkeyed({
|
|
|
|
@ -473,117 +404,109 @@ export default class EachBlockWrapper extends Wrapper {
|
|
|
|
|
update_anchor_node: Identifier;
|
|
|
|
|
update_mount_node: Identifier;
|
|
|
|
|
}) {
|
|
|
|
|
const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
|
|
|
|
|
|
|
|
|
|
block.chunks.init.push(b`
|
|
|
|
|
let ${iterations} = [];
|
|
|
|
|
for (let #i = 0; #i < ${data_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
block.chunks.create.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].c();
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
const __DEV__ = this.renderer.options.dev;
|
|
|
|
|
const {
|
|
|
|
|
create_each_block,
|
|
|
|
|
iterations: each_block,
|
|
|
|
|
each_block_value,
|
|
|
|
|
get_each_context: each_context_getter,
|
|
|
|
|
} = this.vars;
|
|
|
|
|
const for_each_block = (fn, opts?) => for_loop(each_block, fn, opts);
|
|
|
|
|
|
|
|
|
|
if (parent_nodes && this.renderer.options.hydratable) {
|
|
|
|
|
block.chunks.claim.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].l(${parent_nodes});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
block.chunks.init.push(
|
|
|
|
|
b`let ${each_block} = [];`,
|
|
|
|
|
for_loop(
|
|
|
|
|
each_block_value,
|
|
|
|
|
(_, index) =>
|
|
|
|
|
b`${each_block}[${index}] = ${create_each_block}(${each_context_getter}(#ctx, ${each_block_value}, ${index}));`
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
block.chunks.mount.push(b`
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
|
|
|
|
|
if (parent_nodes && this.renderer.options.hydratable)
|
|
|
|
|
block.chunks.claim.push(for_each_block((block) => b`${block}.l(${parent_nodes});`));
|
|
|
|
|
block.chunks.mount.push(for_each_block((block) => b`${block}.m(${initial_mount_node}, ${initial_anchor_node});`));
|
|
|
|
|
|
|
|
|
|
if (this.dependencies.size) {
|
|
|
|
|
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
|
|
|
|
|
const { has_update_method } = this.block;
|
|
|
|
|
|
|
|
|
|
const for_loop_body = this.block.has_update_method
|
|
|
|
|
? b`
|
|
|
|
|
if (${iterations}[#i]) {
|
|
|
|
|
${iterations}[#i].p(child_ctx, #dirty);
|
|
|
|
|
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
|
|
|
|
|
} else {
|
|
|
|
|
${iterations}[#i] = ${create_each_block}(child_ctx);
|
|
|
|
|
${iterations}[#i].c();
|
|
|
|
|
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
|
|
|
|
|
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
: has_transitions
|
|
|
|
|
? b`
|
|
|
|
|
if (${iterations}[#i]) {
|
|
|
|
|
@transition_in(${this.vars.iterations}[#i], 1);
|
|
|
|
|
} else {
|
|
|
|
|
${iterations}[#i] = ${create_each_block}(child_ctx);
|
|
|
|
|
${iterations}[#i].c();
|
|
|
|
|
@transition_in(${this.vars.iterations}[#i], 1);
|
|
|
|
|
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
: b`
|
|
|
|
|
if (!${iterations}[#i]) {
|
|
|
|
|
${iterations}[#i] = ${create_each_block}(child_ctx);
|
|
|
|
|
${iterations}[#i].c();
|
|
|
|
|
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const start = this.block.has_update_method ? 0 : `#old_length`;
|
|
|
|
|
|
|
|
|
|
const remove_old_blocks = this.block.group_transition_out((transition_out) =>
|
|
|
|
|
transition_out
|
|
|
|
|
? b`
|
|
|
|
|
for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
|
|
|
|
|
${transition_out}(${iterations}[#i], () => { ${iterations}[#i] = null; });
|
|
|
|
|
}`
|
|
|
|
|
: b`
|
|
|
|
|
for (${this.block.has_update_method ? null : x`#i = ${data_length}`};
|
|
|
|
|
#i < ${this.block.has_update_method ? view_length : '#old_length'};
|
|
|
|
|
#i += 1 ) {
|
|
|
|
|
${iterations}[#i].d(1);
|
|
|
|
|
}
|
|
|
|
|
${!fixed_length && b`${view_length} = ${data_length};`}
|
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
const start = has_update_method ? 0 : `#old_length`;
|
|
|
|
|
|
|
|
|
|
// We declare `i` as block scoped here, as the `remove_old_blocks` code
|
|
|
|
|
// may rely on continuing where this iteration stopped.
|
|
|
|
|
const update = b`
|
|
|
|
|
${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`}
|
|
|
|
|
${this.vars.each_block_value} = ${snippet};
|
|
|
|
|
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
|
|
|
|
|
|
|
|
|
|
this.updates.push(b`
|
|
|
|
|
${!has_update_method && b`const #old_length = ${each_block_value}.length;`}
|
|
|
|
|
${each_block_value} = ${snippet};
|
|
|
|
|
${__DEV__ && b`@validate_each_argument(${each_block_value});`}
|
|
|
|
|
let #i;
|
|
|
|
|
for (#i = ${start}; #i < ${data_length}; #i += 1) {
|
|
|
|
|
const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
|
|
|
|
|
|
|
|
|
|
${for_loop_body}
|
|
|
|
|
${for_each_block(
|
|
|
|
|
(block, index) => b`
|
|
|
|
|
const #child_ctx = ${each_context_getter}(#ctx, ${each_block_value}, ${index});
|
|
|
|
|
${$if({
|
|
|
|
|
if: (has_update_method || has_transitions) && block,
|
|
|
|
|
true: b`
|
|
|
|
|
${has_update_method && b`${block}.p(#child_ctx, #dirty);`}
|
|
|
|
|
${has_transitions && b`@transition_in(${block}, 1);`}
|
|
|
|
|
`,
|
|
|
|
|
false: b`
|
|
|
|
|
${block} = ${create_each_block}(#child_ctx);
|
|
|
|
|
${block}.c();
|
|
|
|
|
${has_transitions && b`@transition_in(${block}, 1);`}
|
|
|
|
|
${block}.m(${update_mount_node}, ${update_anchor_node});
|
|
|
|
|
`,
|
|
|
|
|
})}`,
|
|
|
|
|
{ i: start }
|
|
|
|
|
)}
|
|
|
|
|
${this.block.group_transition_out((transition_out) =>
|
|
|
|
|
for_each_block(
|
|
|
|
|
(block) =>
|
|
|
|
|
transition_out ? b`${transition_out}(${block}, () => { ${block} = null; });` : b`${block}.d(1);`,
|
|
|
|
|
{
|
|
|
|
|
i: has_update_method && !transition_out ? null : x`#i = ${each_block_value}.length`,
|
|
|
|
|
length: has_update_method || transition_out ? x`${each_block}.length` : x`#old_length`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
${remove_old_blocks}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
this.updates.push(update);
|
|
|
|
|
)
|
|
|
|
|
)}
|
|
|
|
|
${each_block}.length = ${each_block_value}.length;
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.block.has_outros) {
|
|
|
|
|
block.chunks.outro.push(b`
|
|
|
|
|
${iterations} = ${iterations}.filter(@_Boolean);
|
|
|
|
|
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
|
|
|
|
@transition_out(${iterations}[#i]);
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
${each_block} = ${each_block}.filter(@_Boolean);
|
|
|
|
|
${for_each_block((block) => b`@transition_out(${block})`)}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block.chunks.destroy.push(b`@destroy_each(${iterations}, detaching);`);
|
|
|
|
|
block.chunks.destroy.push(b`@destroy_each(${each_block}, detaching);`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const bit_state = (arr) => arr.reduce((state, bool, index) => (bool ? (state |= 1 << index) : state), 0);
|
|
|
|
|
|
|
|
|
|
const for_loop = <T>(
|
|
|
|
|
arr: T,
|
|
|
|
|
callback: (item: Node, index: Node, array: T) => Node[],
|
|
|
|
|
{ length = x`${arr}.length`, i = undefined } = {}
|
|
|
|
|
) =>
|
|
|
|
|
i || i === null
|
|
|
|
|
? b`for (${i}; #i < ${length}; #i++) { ${callback(x`${arr}[#i]`, x`#i`, arr)} }`
|
|
|
|
|
: b`for (let #i = 0; #i < ${length}; #i++) { ${callback(x`${arr}[#i]`, x`#i`, arr)} }`;
|
|
|
|
|
|
|
|
|
|
const $if = ({ if: condition, true: success, false: failure = null }) => {
|
|
|
|
|
if (condition) {
|
|
|
|
|
if (success) {
|
|
|
|
|
if (failure) {
|
|
|
|
|
return b`if(${condition}){ ${success} } else { ${failure} }`;
|
|
|
|
|
} else {
|
|
|
|
|
return b`if(${condition}){ ${success} }`;
|
|
|
|
|
}
|
|
|
|
|
} else if (failure) {
|
|
|
|
|
return b`if(!${condition}){ ${success} }`;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!failure) {
|
|
|
|
|
return failure;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
throw new Error('Error in if_else');
|
|
|
|
|
};
|
|
|
|
|