fix transitions on each else block

pull/5179/head
Carlos Edinson Roso Espinosa 5 years ago
parent fb8bab8164
commit 3580665195

@ -9,209 +9,209 @@ import ElseBlock from '../../nodes/ElseBlock';
import { Identifier, Node } from 'estree'; import { Identifier, Node } from 'estree';
export class ElseBlockWrapper extends Wrapper { export class ElseBlockWrapper extends Wrapper {
node: ElseBlock; node: ElseBlock;
block: Block; block: Block;
fragment: FragmentWrapper; fragment: FragmentWrapper;
is_dynamic: boolean; is_dynamic: boolean;
var = null; var = null;
constructor( constructor(
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
parent: Wrapper, parent: Wrapper,
node: ElseBlock, node: ElseBlock,
strip_whitespace: boolean, strip_whitespace: boolean,
next_sibling: Wrapper next_sibling: Wrapper
) { ) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.block = block.child({ this.block = block.child({
comment: create_debugging_comment(node, this.renderer.component), comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_else_block`), name: this.renderer.component.get_unique_name(`create_else_block`),
type: 'else' type: 'else'
}); });
this.fragment = new FragmentWrapper( this.fragment = new FragmentWrapper(
renderer, renderer,
this.block, this.block,
this.node.children, this.node.children,
parent, parent,
strip_whitespace, strip_whitespace,
next_sibling next_sibling
); );
this.is_dynamic = this.block.dependencies.size > 0; this.is_dynamic = this.block.dependencies.size > 0;
} }
} }
export default class EachBlockWrapper extends Wrapper { export default class EachBlockWrapper extends Wrapper {
block: Block; block: Block;
node: EachBlock; node: EachBlock;
fragment: FragmentWrapper; fragment: FragmentWrapper;
else?: ElseBlockWrapper; else?: ElseBlockWrapper;
vars: { vars: {
create_each_block: Identifier; create_each_block: Identifier;
each_block_value: Identifier; each_block_value: Identifier;
get_each_context: Identifier; get_each_context: Identifier;
iterations: Identifier; iterations: Identifier;
fixed_length: number; fixed_length: number;
data_length: string; data_length: string;
view_length: string; view_length: string;
} }
context_props: Array<Node | Node[]>; context_props: Array<Node | Node[]>;
index_name: Identifier; index_name: Identifier;
updates: Array<Node | Node[]> = []; updates: Array<Node | Node[]> = [];
dependencies: Set<string>; dependencies: Set<string>;
var: Identifier = { type: 'Identifier', name: 'each' }; var: Identifier = { type: 'Identifier', name: 'each' };
constructor( constructor(
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
parent: Wrapper, parent: Wrapper,
node: EachBlock, node: EachBlock,
strip_whitespace: boolean, strip_whitespace: boolean,
next_sibling: Wrapper next_sibling: Wrapper
) { ) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.cannot_use_innerhtml(); this.cannot_use_innerhtml();
this.not_static_content(); this.not_static_content();
const { dependencies } = node.expression; const { dependencies } = node.expression;
block.add_dependencies(dependencies); block.add_dependencies(dependencies);
this.node.contexts.forEach(context => { this.node.contexts.forEach(context => {
renderer.add_to_context(context.key.name, true); renderer.add_to_context(context.key.name, true);
}); });
this.block = block.child({ this.block = block.child({
comment: create_debugging_comment(this.node, this.renderer.component), comment: create_debugging_comment(this.node, this.renderer.component),
name: renderer.component.get_unique_name('create_each_block'), name: renderer.component.get_unique_name('create_each_block'),
type: 'each', type: 'each',
// @ts-ignore todo: probably error // @ts-ignore todo: probably error
key: node.key as string, key: node.key as string,
bindings: new Map(block.bindings) bindings: new Map(block.bindings)
}); });
// TODO this seems messy // TODO this seems messy
this.block.has_animation = this.node.has_animation; this.block.has_animation = this.node.has_animation;
this.index_name = this.node.index this.index_name = this.node.index
? { type: 'Identifier', name: this.node.index } ? { type: 'Identifier', name: this.node.index }
: renderer.component.get_unique_name(`${this.node.context}_index`); : renderer.component.get_unique_name(`${this.node.context}_index`);
const fixed_length = const fixed_length =
node.expression.node.type === 'ArrayExpression' && node.expression.node.type === 'ArrayExpression' &&
node.expression.node.elements.every(element => element.type !== 'SpreadElement') node.expression.node.elements.every(element => element.type !== 'SpreadElement')
? node.expression.node.elements.length ? node.expression.node.elements.length
: null; : null;
// hack the sourcemap, so that if data is missing the bug // hack the sourcemap, so that if data is missing the bug
// is easy to find // is easy to find
let c = this.node.start + 2; let c = this.node.start + 2;
while (renderer.component.source[c] !== 'e') c += 1; while (renderer.component.source[c] !== 'e') c += 1;
const start = renderer.component.locate(c); const start = renderer.component.locate(c);
const end = { line: start.line, column: start.column + 4 }; const end = { line: start.line, column: start.column + 4 };
const length = { const length = {
type: 'Identifier', type: 'Identifier',
name: 'length', name: 'length',
loc: { start, end } loc: { start, end }
}; };
const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`); const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
const iterations = block.get_unique_name(`${this.var.name}_blocks`); const iterations = block.get_unique_name(`${this.var.name}_blocks`);
renderer.add_to_context(each_block_value.name, true); renderer.add_to_context(each_block_value.name, true);
renderer.add_to_context(this.index_name.name, true); renderer.add_to_context(this.index_name.name, true);
this.vars = { this.vars = {
create_each_block: this.block.name, create_each_block: this.block.name,
each_block_value, each_block_value,
get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`), get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
iterations, iterations,
// optimisation for array literal // optimisation for array literal
fixed_length, fixed_length,
data_length: fixed_length === null ? x`${each_block_value}.${length}` : fixed_length, data_length: fixed_length === null ? x`${each_block_value}.${length}` : fixed_length,
view_length: fixed_length === null ? x`${iterations}.length` : fixed_length view_length: fixed_length === null ? x`${iterations}.length` : fixed_length
}; };
const store = const store =
node.expression.node.type === 'Identifier' && node.expression.node.type === 'Identifier' &&
node.expression.node.name[0] === '$' node.expression.node.name[0] === '$'
? node.expression.node.name.slice(1) ? node.expression.node.name.slice(1)
: null; : null;
node.contexts.forEach(prop => { node.contexts.forEach(prop => {
this.block.bindings.set(prop.key.name, { this.block.bindings.set(prop.key.name, {
object: this.vars.each_block_value, object: this.vars.each_block_value,
property: this.index_name, property: this.index_name,
modifier: prop.modifier, modifier: prop.modifier,
snippet: prop.modifier(x`${this.vars.each_block_value}[${this.index_name}]` as Node), snippet: prop.modifier(x`${this.vars.each_block_value}[${this.index_name}]` as Node),
store, store,
tail: prop.modifier(x`[${this.index_name}]` as Node) tail: prop.modifier(x`[${this.index_name}]` as Node)
}); });
}); });
if (this.node.index) { if (this.node.index) {
this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254) this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
} }
renderer.blocks.push(this.block); renderer.blocks.push(this.block);
this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling); this.fragment = new FragmentWrapper(renderer, this.block, node.children, this, strip_whitespace, next_sibling);
if (this.node.else) { if (this.node.else) {
this.else = new ElseBlockWrapper( this.else = new ElseBlockWrapper(
renderer, renderer,
block, block,
this, this,
this.node.else, this.node.else,
strip_whitespace, strip_whitespace,
next_sibling next_sibling
); );
renderer.blocks.push(this.else.block); renderer.blocks.push(this.else.block);
if (this.else.is_dynamic) { if (this.else.is_dynamic) {
this.block.add_dependencies(this.else.block.dependencies); this.block.add_dependencies(this.else.block.dependencies);
} }
} }
block.add_dependencies(this.block.dependencies); block.add_dependencies(this.block.dependencies);
if (this.block.has_outros || (this.else && this.else.block.has_outros)) { if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
block.add_outro(); block.add_outro();
} }
} }
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
if (this.fragment.nodes.length === 0) return; if (this.fragment.nodes.length === 0) return;
const { renderer } = this; const { renderer } = this;
const { component } = renderer; const { component } = renderer;
const needs_anchor = this.next const needs_anchor = this.next
? !this.next.is_dom_node() : ? !this.next.is_dom_node() :
!parent_node || !this.parent.is_dom_node(); !parent_node || !this.parent.is_dom_node();
this.context_props = this.node.contexts.map(prop => b`child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x`list[i]`)};`); this.context_props = this.node.contexts.map(prop => b`child_ctx[${renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x`list[i]`)};`);
if (this.node.has_binding) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`); if (this.node.has_binding) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`);
if (this.node.has_binding || this.node.has_index_binding || this.node.index) this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`); if (this.node.has_binding || this.node.has_index_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); const snippet = this.node.expression.manipulate(block);
block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`); block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`);
if (this.renderer.options.dev) { if (this.renderer.options.dev) {
block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`); block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`);
} }
// TODO which is better — Object.create(array) or array.slice()? // TODO which is better — Object.create(array) or array.slice()?
renderer.blocks.push(b` renderer.blocks.push(b`
function ${this.vars.get_each_context}(#ctx, list, i) { function ${this.vars.get_each_context}(#ctx, list, i) {
const child_ctx = #ctx.slice(); const child_ctx = #ctx.slice();
${this.context_props} ${this.context_props}
@ -219,178 +219,195 @@ export default class EachBlockWrapper extends Wrapper {
} }
`); `);
const initial_anchor_node: Identifier = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' }; const initial_anchor_node: Identifier = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' };
const initial_mount_node: Identifier = parent_node || { type: 'Identifier', name: '#target' }; const initial_mount_node: Identifier = parent_node || { type: 'Identifier', name: '#target' };
const update_anchor_node = needs_anchor const update_anchor_node = needs_anchor
? block.get_unique_name(`${this.var.name}_anchor`) ? block.get_unique_name(`${this.var.name}_anchor`)
: (this.next && this.next.var) || { type: 'Identifier', name: 'null' }; : (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
const update_mount_node: Identifier = this.get_update_mount_node((update_anchor_node as Identifier)); const update_mount_node: Identifier = this.get_update_mount_node((update_anchor_node as Identifier));
const args = { const args = {
block, block,
parent_node, parent_node,
parent_nodes, parent_nodes,
snippet, snippet,
initial_anchor_node, initial_anchor_node,
initial_mount_node, initial_mount_node,
update_anchor_node, update_anchor_node,
update_mount_node update_mount_node
}; };
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
this.node.expression.dynamic_dependencies().forEach((dependency: string) => { this.node.expression.dynamic_dependencies().forEach((dependency: string) => {
all_dependencies.add(dependency); all_dependencies.add(dependency);
}); });
this.dependencies = all_dependencies; this.dependencies = all_dependencies;
if (this.node.key) { if (this.node.key) {
this.render_keyed(args); this.render_keyed(args);
} else { } else {
this.render_unkeyed(args); this.render_unkeyed(args);
} }
if (this.block.has_intro_method || this.block.has_outro_method) { if (this.block.has_intro_method || this.block.has_outro_method) {
block.chunks.intro.push(b` block.chunks.intro.push(b`
for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) { for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
@transition_in(${this.vars.iterations}[#i]); @transition_in(${this.vars.iterations}[#i]);
} }
`); `);
} }
if (needs_anchor) { if (needs_anchor) {
block.add_element( block.add_element(
update_anchor_node as Identifier, update_anchor_node as Identifier,
x`@empty()`, x`@empty()`,
parent_nodes && x`@empty()`, parent_nodes && x`@empty()`,
parent_node parent_node
); );
} }
if (this.else) { if (this.else) {
const each_block_else = component.get_unique_name(`${this.var.name}_else`); const each_block_else = component.get_unique_name(`${this.var.name}_else`);
block.chunks.init.push(b`let ${each_block_else} = null;`); block.chunks.init.push(b`let ${each_block_else} = null;`);
// TODO neaten this up... will end up with an empty line in the block // TODO neaten this up... will end up with an empty line in the block
block.chunks.init.push(b` block.chunks.init.push(b`
if (!${this.vars.data_length}) { if (!${this.vars.data_length}) {
${each_block_else} = ${this.else.block.name}(#ctx); ${each_block_else} = ${this.else.block.name}(#ctx);
} }
`); `);
block.chunks.create.push(b` block.chunks.create.push(b`
if (${each_block_else}) { if (${each_block_else}) {
${each_block_else}.c(); ${each_block_else}.c();
} }
`); `);
if (this.renderer.options.hydratable) { if (this.renderer.options.hydratable) {
block.chunks.claim.push(b` block.chunks.claim.push(b`
if (${each_block_else}) { if (${each_block_else}) {
${each_block_else}.l(${parent_nodes}); ${each_block_else}.l(${parent_nodes});
} }
`); `);
} }
block.chunks.mount.push(b` block.chunks.mount.push(b`
if (${each_block_else}) { if (${each_block_else}) {
${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node}); ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
} }
`); `);
if (this.else.block.has_update_method) { const has_transitions = !!(this.else.block.has_intro_method || this.else.block.has_outro_method);
this.updates.push(b`
const destroy_block_else = this.else.block.has_outro_method
?
b`
@group_outros();
@transition_out(${each_block_else}, 1, 1, () => {
${each_block_else} = null;
});
@check_outros();
`
: b`
${each_block_else}.d(1);
${each_block_else} = null;
`;
if (this.else.block.has_update_method) {
this.updates.push(b`
if (!${this.vars.data_length} && ${each_block_else}) { if (!${this.vars.data_length} && ${each_block_else}) {
${each_block_else}.p(#ctx, #dirty); ${each_block_else}.p(#ctx, #dirty);
} else if (!${this.vars.data_length}) { } else if (!${this.vars.data_length}) {
${each_block_else} = ${this.else.block.name}(#ctx); ${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c(); ${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node}); ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
} else if (${each_block_else}) { } else if (${each_block_else}) {
${each_block_else}.d(1); ${destroy_block_else};
${each_block_else} = null;
} }
`); `);
} else { } else {
this.updates.push(b`
this.updates.push(b`
if (${this.vars.data_length}) { if (${this.vars.data_length}) {
if (${each_block_else}) { if (${each_block_else}) {
${each_block_else}.d(1); ${destroy_block_else};
${each_block_else} = null;
} }
} else if (!${each_block_else}) { } else if (!${each_block_else}) {
${each_block_else} = ${this.else.block.name}(#ctx); ${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c(); ${each_block_else}.c();
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node}); ${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
} }
`); `);
} }
block.chunks.destroy.push(b` 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'});
`); `);
} }
if (this.updates.length) { if (this.updates.length) {
block.chunks.update.push(b` block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) { if (${block.renderer.dirty(Array.from(all_dependencies))}) {
${this.updates} ${this.updates}
} }
`); `);
} }
this.fragment.render(this.block, null, x`#nodes` as Identifier); this.fragment.render(this.block, null, x`#nodes` as Identifier);
if (this.else) { if (this.else) {
this.else.fragment.render(this.else.block, null, x`#nodes` as Identifier); this.else.fragment.render(this.else.block, null, x`#nodes` as Identifier);
} }
} }
render_keyed({ render_keyed({
block, block,
parent_node, parent_node,
parent_nodes, parent_nodes,
snippet, snippet,
initial_anchor_node, initial_anchor_node,
initial_mount_node, initial_mount_node,
update_anchor_node, update_anchor_node,
update_mount_node update_mount_node
}: { }: {
block: Block; block: Block;
parent_node: Identifier; parent_node: Identifier;
parent_nodes: Identifier; parent_nodes: Identifier;
snippet: Node; snippet: Node;
initial_anchor_node: Identifier; initial_anchor_node: Identifier;
initial_mount_node: Identifier; initial_mount_node: Identifier;
update_anchor_node: Identifier; update_anchor_node: Identifier;
update_mount_node: Identifier; update_mount_node: Identifier;
}) { }) {
const { const {
create_each_block, create_each_block,
iterations, iterations,
data_length, data_length,
view_length view_length
} = this.vars; } = this.vars;
const get_key = block.get_unique_name('get_key'); const get_key = block.get_unique_name('get_key');
const lookup = block.get_unique_name(`${this.var.name}_lookup`); const lookup = block.get_unique_name(`${this.var.name}_lookup`);
block.add_variable(iterations, x`[]`); block.add_variable(iterations, x`[]`);
block.add_variable(lookup, x`new @_Map()`); block.add_variable(lookup, x`new @_Map()`);
if (this.fragment.nodes[0].is_dom_node()) { if (this.fragment.nodes[0].is_dom_node()) {
this.block.first = this.fragment.nodes[0].var; this.block.first = this.fragment.nodes[0].var;
} else { } else {
this.block.first = this.block.get_unique_name('first'); this.block.first = this.block.get_unique_name('first');
this.block.add_element( this.block.add_element(
this.block.first, this.block.first,
x`@empty()`, x`@empty()`,
parent_nodes && x`@empty()`, parent_nodes && x`@empty()`,
null null
); );
} }
block.chunks.init.push(b` block.chunks.init.push(b`
const ${get_key} = #ctx => ${this.node.key.manipulate(block)}; const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`} ${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`}
@ -401,38 +418,38 @@ export default class EachBlockWrapper extends Wrapper {
} }
`); `);
block.chunks.create.push(b` block.chunks.create.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].c(); ${iterations}[#i].c();
} }
`); `);
if (parent_nodes && this.renderer.options.hydratable) { if (parent_nodes && this.renderer.options.hydratable) {
block.chunks.claim.push(b` block.chunks.claim.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].l(${parent_nodes}); ${iterations}[#i].l(${parent_nodes});
} }
`); `);
} }
block.chunks.mount.push(b` block.chunks.mount.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
} }
`); `);
const dynamic = this.block.has_update_method; const dynamic = this.block.has_update_method;
const destroy = this.node.has_animation const destroy = this.node.has_animation
? (this.block.has_outros ? (this.block.has_outros
? `@fix_and_outro_and_destroy_block` ? `@fix_and_outro_and_destroy_block`
: `@fix_and_destroy_block`) : `@fix_and_destroy_block`)
: this.block.has_outros : this.block.has_outros
? `@outro_and_destroy_block` ? `@outro_and_destroy_block`
: `@destroy_block`; : `@destroy_block`;
if (this.dependencies.size) { if (this.dependencies.size) {
this.updates.push(b` this.updates.push(b`
const ${this.vars.each_block_value} = ${snippet}; const ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
@ -443,49 +460,49 @@ export default class EachBlockWrapper extends Wrapper {
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`} ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`}
${this.block.has_outros && b`@check_outros();`} ${this.block.has_outros && b`@check_outros();`}
`); `);
} }
if (this.block.has_outros) { if (this.block.has_outros) {
block.chunks.outro.push(b` block.chunks.outro.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
@transition_out(${iterations}[#i]); @transition_out(${iterations}[#i]);
} }
`); `);
} }
block.chunks.destroy.push(b` block.chunks.destroy.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].d(${parent_node ? null : 'detaching'}); ${iterations}[#i].d(${parent_node ? null : 'detaching'});
} }
`); `);
} }
render_unkeyed({ render_unkeyed({
block, block,
parent_nodes, parent_nodes,
snippet, snippet,
initial_anchor_node, initial_anchor_node,
initial_mount_node, initial_mount_node,
update_anchor_node, update_anchor_node,
update_mount_node update_mount_node
}: { }: {
block: Block; block: Block;
parent_nodes: Identifier; parent_nodes: Identifier;
snippet: Node; snippet: Node;
initial_anchor_node: Identifier; initial_anchor_node: Identifier;
initial_mount_node: Identifier; initial_mount_node: Identifier;
update_anchor_node: Identifier; update_anchor_node: Identifier;
update_mount_node: Identifier; update_mount_node: Identifier;
}) { }) {
const { const {
create_each_block, create_each_block,
iterations, iterations,
fixed_length, fixed_length,
data_length, data_length,
view_length view_length
} = this.vars; } = this.vars;
block.chunks.init.push(b` block.chunks.init.push(b`
let ${iterations} = []; let ${iterations} = [];
for (let #i = 0; #i < ${data_length}; #i += 1) { for (let #i = 0; #i < ${data_length}; #i += 1) {
@ -493,31 +510,31 @@ export default class EachBlockWrapper extends Wrapper {
} }
`); `);
block.chunks.create.push(b` block.chunks.create.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].c(); ${iterations}[#i].c();
} }
`); `);
if (parent_nodes && this.renderer.options.hydratable) { if (parent_nodes && this.renderer.options.hydratable) {
block.chunks.claim.push(b` block.chunks.claim.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].l(${parent_nodes}); ${iterations}[#i].l(${parent_nodes});
} }
`); `);
} }
block.chunks.mount.push(b` block.chunks.mount.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); ${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
} }
`); `);
if (this.dependencies.size) { if (this.dependencies.size) {
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method); const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
const for_loop_body = this.block.has_update_method const for_loop_body = this.block.has_update_method
? b` ? b`
if (${iterations}[#i]) { if (${iterations}[#i]) {
${iterations}[#i].p(child_ctx, #dirty); ${iterations}[#i].p(child_ctx, #dirty);
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`} ${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
@ -528,8 +545,8 @@ export default class EachBlockWrapper extends Wrapper {
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node}); ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
} }
` `
: has_transitions : has_transitions
? b` ? b`
if (${iterations}[#i]) { if (${iterations}[#i]) {
@transition_in(${this.vars.iterations}[#i], 1); @transition_in(${this.vars.iterations}[#i], 1);
} else { } else {
@ -539,7 +556,7 @@ export default class EachBlockWrapper extends Wrapper {
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node}); ${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
} }
` `
: b` : b`
if (!${iterations}[#i]) { if (!${iterations}[#i]) {
${iterations}[#i] = ${create_each_block}(child_ctx); ${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c(); ${iterations}[#i].c();
@ -547,37 +564,37 @@ export default class EachBlockWrapper extends Wrapper {
} }
`; `;
const start = this.block.has_update_method ? 0 : `#old_length`; const start = this.block.has_update_method ? 0 : `#old_length`;
let remove_old_blocks; let remove_old_blocks;
if (this.block.has_outros) { if (this.block.has_outros) {
const out = block.get_unique_name('out'); const out = block.get_unique_name('out');
block.chunks.init.push(b` block.chunks.init.push(b`
const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => { const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
${iterations}[i] = null; ${iterations}[i] = null;
}); });
`); `);
remove_old_blocks = b` remove_old_blocks = b`
@group_outros(); @group_outros();
for (#i = ${data_length}; #i < ${view_length}; #i += 1) { for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
${out}(#i); ${out}(#i);
} }
@check_outros(); @check_outros();
`; `;
} else { } else {
remove_old_blocks = b` remove_old_blocks = b`
for (${this.block.has_update_method ? null : x`#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) { 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); ${iterations}[#i].d(1);
} }
${!fixed_length && b`${view_length} = ${data_length};`} ${!fixed_length && b`${view_length} = ${data_length};`}
`; `;
} }
// We declare `i` as block scoped here, as the `remove_old_blocks` code // We declare `i` as block scoped here, as the `remove_old_blocks` code
// may rely on continuing where this iteration stopped. // may rely on continuing where this iteration stopped.
const update = b` const update = b`
${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`} ${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`}
${this.vars.each_block_value} = ${snippet}; ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
@ -592,18 +609,18 @@ export default class EachBlockWrapper extends Wrapper {
${remove_old_blocks} ${remove_old_blocks}
`; `;
this.updates.push(update); this.updates.push(update);
} }
if (this.block.has_outros) { if (this.block.has_outros) {
block.chunks.outro.push(b` block.chunks.outro.push(b`
${iterations} = ${iterations}.filter(@_Boolean); ${iterations} = ${iterations}.filter(@_Boolean);
for (let #i = 0; #i < ${view_length}; #i += 1) { for (let #i = 0; #i < ${view_length}; #i += 1) {
@transition_out(${iterations}[#i]); @transition_out(${iterations}[#i]);
} }
`); `);
} }
block.chunks.destroy.push(b`@destroy_each(${iterations}, detaching);`); block.chunks.destroy.push(b`@destroy_each(${iterations}, detaching);`);
} }
} }

Loading…
Cancel
Save