mirror of https://github.com/sveltejs/svelte
parent
8e9e323b13
commit
c6d49b7295
@ -1,159 +0,0 @@
|
|||||||
import deindent from '../../../utils/deindent';
|
|
||||||
import visit from '../visit';
|
|
||||||
import { DomGenerator } from '../index';
|
|
||||||
import Block from '../Block';
|
|
||||||
import isDomNode from './shared/isDomNode';
|
|
||||||
import { Node } from '../../../interfaces';
|
|
||||||
import { State } from '../interfaces';
|
|
||||||
|
|
||||||
export default function visitAwaitBlock(
|
|
||||||
generator: DomGenerator,
|
|
||||||
block: Block,
|
|
||||||
state: State,
|
|
||||||
node: Node,
|
|
||||||
elementStack: Node[],
|
|
||||||
componentStack: Node[]
|
|
||||||
) {
|
|
||||||
const name = node.var;
|
|
||||||
|
|
||||||
const needsAnchor = node.next ? !isDomNode(node.next, generator) : !state.parentNode || !isDomNode(node.parent, generator);
|
|
||||||
const anchor = needsAnchor
|
|
||||||
? block.getUniqueName(`${name}_anchor`)
|
|
||||||
: (node.next && node.next.var) || 'null';
|
|
||||||
|
|
||||||
const params = block.params.join(', ');
|
|
||||||
|
|
||||||
block.contextualise(node.expression);
|
|
||||||
const { snippet } = node.metadata;
|
|
||||||
|
|
||||||
if (needsAnchor) {
|
|
||||||
block.addElement(
|
|
||||||
anchor,
|
|
||||||
`@createComment()`,
|
|
||||||
`@createComment()`,
|
|
||||||
state.parentNode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const promise = block.getUniqueName(`promise`);
|
|
||||||
const resolved = block.getUniqueName(`resolved`);
|
|
||||||
const await_block = block.getUniqueName(`await_block`);
|
|
||||||
const await_block_type = block.getUniqueName(`await_block_type`);
|
|
||||||
const token = block.getUniqueName(`token`);
|
|
||||||
const await_token = block.getUniqueName(`await_token`);
|
|
||||||
const handle_promise = block.getUniqueName(`handle_promise`);
|
|
||||||
const replace_await_block = block.getUniqueName(`replace_await_block`);
|
|
||||||
const old_block = block.getUniqueName(`old_block`);
|
|
||||||
const value = block.getUniqueName(`value`);
|
|
||||||
const error = block.getUniqueName(`error`);
|
|
||||||
const create_pending_block = node.pending._block.name;
|
|
||||||
const create_then_block = node.then._block.name;
|
|
||||||
const create_catch_block = node.catch._block.name;
|
|
||||||
|
|
||||||
block.addVariable(await_block);
|
|
||||||
block.addVariable(await_block_type);
|
|
||||||
block.addVariable(await_token);
|
|
||||||
block.addVariable(promise);
|
|
||||||
block.addVariable(resolved);
|
|
||||||
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
function ${replace_await_block}(${token}, type, ${value}, ${params}) {
|
|
||||||
if (${token} !== ${await_token}) return;
|
|
||||||
|
|
||||||
var ${old_block} = ${await_block};
|
|
||||||
${await_block} = (${await_block_type} = type)(${params}, ${resolved} = ${value}, #component);
|
|
||||||
|
|
||||||
if (${old_block}) {
|
|
||||||
${old_block}.u();
|
|
||||||
${old_block}.d();
|
|
||||||
${await_block}.c();
|
|
||||||
${await_block}.m(${state.parentNode || `${anchor}.parentNode`}, ${anchor});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ${handle_promise}(${promise}, ${params}) {
|
|
||||||
var ${token} = ${await_token} = {};
|
|
||||||
|
|
||||||
if (@isPromise(${promise})) {
|
|
||||||
${promise}.then(function(${value}) {
|
|
||||||
${replace_await_block}(${token}, ${create_then_block}, ${value}, ${params});
|
|
||||||
}, function (${error}) {
|
|
||||||
${replace_await_block}(${token}, ${create_catch_block}, ${error}, ${params});
|
|
||||||
});
|
|
||||||
|
|
||||||
// if we previously had a then/catch block, destroy it
|
|
||||||
if (${await_block_type} !== ${create_pending_block}) {
|
|
||||||
${replace_await_block}(${token}, ${create_pending_block}, null, ${params});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
${resolved} = ${promise};
|
|
||||||
if (${await_block_type} !== ${create_then_block}) {
|
|
||||||
${replace_await_block}(${token}, ${create_then_block}, ${resolved}, ${params});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
${handle_promise}(${promise} = ${snippet}, ${params});
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.create.addBlock(deindent`
|
|
||||||
${await_block}.c();
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.claim.addBlock(deindent`
|
|
||||||
${await_block}.l(${state.parentNodes});
|
|
||||||
`);
|
|
||||||
|
|
||||||
const targetNode = state.parentNode || '#target';
|
|
||||||
const anchorNode = state.parentNode ? 'null' : 'anchor';
|
|
||||||
|
|
||||||
block.builders.mount.addBlock(deindent`
|
|
||||||
${await_block}.m(${targetNode}, ${anchorNode});
|
|
||||||
`);
|
|
||||||
|
|
||||||
const conditions = [];
|
|
||||||
if (node.metadata.dependencies) {
|
|
||||||
conditions.push(
|
|
||||||
`(${node.metadata.dependencies.map(dep => `'${dep}' in changed`).join(' || ')})`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
conditions.push(
|
|
||||||
`${promise} !== (${promise} = ${snippet})`,
|
|
||||||
`${handle_promise}(${promise}, ${params})`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (node.pending._block.hasUpdateMethod) {
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
if (${conditions.join(' && ')}) {
|
|
||||||
// nothing
|
|
||||||
} else {
|
|
||||||
${await_block}.p(changed, ${params}, ${resolved});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
} else {
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
if (${conditions.join(' && ')}) {
|
|
||||||
${await_block}.c();
|
|
||||||
${await_block}.m(${anchor}.parentNode, ${anchor});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.unmount.addBlock(deindent`
|
|
||||||
${await_block}.u();
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.destroy.addBlock(deindent`
|
|
||||||
${await_token} = null;
|
|
||||||
${await_block}.d();
|
|
||||||
`);
|
|
||||||
|
|
||||||
[node.pending, node.then, node.catch].forEach(status => {
|
|
||||||
status.children.forEach(child => {
|
|
||||||
visit(generator, status._block, status._state, child, elementStack, componentStack);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,491 +0,0 @@
|
|||||||
import deindent from '../../../utils/deindent';
|
|
||||||
import visit from '../visit';
|
|
||||||
import { DomGenerator } from '../index';
|
|
||||||
import Block from '../Block';
|
|
||||||
import isDomNode from './shared/isDomNode';
|
|
||||||
import { Node } from '../../../interfaces';
|
|
||||||
import { State } from '../interfaces';
|
|
||||||
|
|
||||||
export default function visitEachBlock(
|
|
||||||
generator: DomGenerator,
|
|
||||||
block: Block,
|
|
||||||
state: State,
|
|
||||||
node: Node,
|
|
||||||
elementStack: Node[],
|
|
||||||
componentStack: Node[]
|
|
||||||
) {
|
|
||||||
const each = node.var;
|
|
||||||
|
|
||||||
const create_each_block = node._block.name;
|
|
||||||
const each_block_value = node._block.listName;
|
|
||||||
const iterations = node.iterations;
|
|
||||||
const params = block.params.join(', ');
|
|
||||||
|
|
||||||
const needsAnchor = node.next ? !isDomNode(node.next, generator) : !state.parentNode || !isDomNode(node.parent, generator);
|
|
||||||
const anchor = needsAnchor
|
|
||||||
? block.getUniqueName(`${each}_anchor`)
|
|
||||||
: (node.next && node.next.var) || 'null';
|
|
||||||
|
|
||||||
// hack the sourcemap, so that if data is missing the bug
|
|
||||||
// is easy to find
|
|
||||||
let c = node.start + 3;
|
|
||||||
while (generator.source[c] !== 'e') c += 1;
|
|
||||||
generator.code.overwrite(c, c + 4, 'length');
|
|
||||||
const length = `[✂${c}-${c+4}✂]`;
|
|
||||||
|
|
||||||
const mountOrIntro = node._block.hasIntroMethod ? 'i' : 'm';
|
|
||||||
const vars = {
|
|
||||||
each,
|
|
||||||
create_each_block,
|
|
||||||
each_block_value,
|
|
||||||
length,
|
|
||||||
iterations,
|
|
||||||
params,
|
|
||||||
anchor,
|
|
||||||
mountOrIntro,
|
|
||||||
};
|
|
||||||
|
|
||||||
block.contextualise(node.expression);
|
|
||||||
const { snippet } = node.metadata;
|
|
||||||
|
|
||||||
block.builders.init.addLine(`var ${each_block_value} = ${snippet};`);
|
|
||||||
|
|
||||||
if (node.key) {
|
|
||||||
keyed(generator, block, state, node, snippet, vars);
|
|
||||||
} else {
|
|
||||||
unkeyed(generator, block, state, node, snippet, vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isToplevel = !state.parentNode;
|
|
||||||
|
|
||||||
if (needsAnchor) {
|
|
||||||
block.addElement(
|
|
||||||
anchor,
|
|
||||||
`@createComment()`,
|
|
||||||
`@createComment()`,
|
|
||||||
state.parentNode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.else) {
|
|
||||||
const each_block_else = generator.getUniqueName(`${each}_else`);
|
|
||||||
|
|
||||||
block.builders.init.addLine(`var ${each_block_else} = null;`);
|
|
||||||
|
|
||||||
// TODO neaten this up... will end up with an empty line in the block
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
if (!${each_block_value}.${length}) {
|
|
||||||
${each_block_else} = ${node.else._block.name}(${params}, #component);
|
|
||||||
${each_block_else}.c();
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.mount.addBlock(deindent`
|
|
||||||
if (${each_block_else}) {
|
|
||||||
${each_block_else}.${mountOrIntro}(${state.parentNode || '#target'}, null);
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const parentNode = state.parentNode || `${anchor}.parentNode`;
|
|
||||||
|
|
||||||
if (node.else._block.hasUpdateMethod) {
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
if (!${each_block_value}.${length} && ${each_block_else}) {
|
|
||||||
${each_block_else}.p( changed, ${params} );
|
|
||||||
} else if (!${each_block_value}.${length}) {
|
|
||||||
${each_block_else} = ${node.else._block.name}(${params}, #component);
|
|
||||||
${each_block_else}.c();
|
|
||||||
${each_block_else}.${mountOrIntro}(${parentNode}, ${anchor});
|
|
||||||
} else if (${each_block_else}) {
|
|
||||||
${each_block_else}.u();
|
|
||||||
${each_block_else}.d();
|
|
||||||
${each_block_else} = null;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
} else {
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
if (${each_block_value}.${length}) {
|
|
||||||
if (${each_block_else}) {
|
|
||||||
${each_block_else}.u();
|
|
||||||
${each_block_else}.d();
|
|
||||||
${each_block_else} = null;
|
|
||||||
}
|
|
||||||
} else if (!${each_block_else}) {
|
|
||||||
${each_block_else} = ${node.else._block.name}(${params}, #component);
|
|
||||||
${each_block_else}.c();
|
|
||||||
${each_block_else}.${mountOrIntro}(${parentNode}, ${anchor});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.unmount.addLine(
|
|
||||||
`if (${each_block_else}) ${each_block_else}.u()`
|
|
||||||
);
|
|
||||||
|
|
||||||
block.builders.destroy.addBlock(deindent`
|
|
||||||
if (${each_block_else}) ${each_block_else}.d();
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
node.children.forEach((child: Node) => {
|
|
||||||
visit(generator, node._block, node._state, child, elementStack, componentStack);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (node.else) {
|
|
||||||
node.else.children.forEach((child: Node) => {
|
|
||||||
visit(generator, node.else._block, node.else._state, child, elementStack, componentStack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyed(
|
|
||||||
generator: DomGenerator,
|
|
||||||
block: Block,
|
|
||||||
state: State,
|
|
||||||
node: Node,
|
|
||||||
snippet: string,
|
|
||||||
{
|
|
||||||
each,
|
|
||||||
create_each_block,
|
|
||||||
each_block_value,
|
|
||||||
length,
|
|
||||||
params,
|
|
||||||
anchor,
|
|
||||||
mountOrIntro,
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const key = block.getUniqueName('key');
|
|
||||||
const lookup = block.getUniqueName(`${each}_lookup`);
|
|
||||||
const iteration = block.getUniqueName(`${each}_iteration`);
|
|
||||||
const head = block.getUniqueName(`${each}_head`);
|
|
||||||
const last = block.getUniqueName(`${each}_last`);
|
|
||||||
const expected = block.getUniqueName(`${each}_expected`);
|
|
||||||
|
|
||||||
block.addVariable(lookup, `@blankObject()`);
|
|
||||||
block.addVariable(head);
|
|
||||||
block.addVariable(last);
|
|
||||||
|
|
||||||
if (node.children[0] && node.children[0].type === 'Element' && !generator.components.has(node.children[0].name)) {
|
|
||||||
// TODO or text/tag/raw
|
|
||||||
node._block.first = node.children[0]._state.parentNode; // TODO this is highly confusing
|
|
||||||
} else {
|
|
||||||
node._block.first = node._block.getUniqueName('first');
|
|
||||||
node._block.addElement(
|
|
||||||
node._block.first,
|
|
||||||
`@createComment()`,
|
|
||||||
`@createComment()`,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
|
|
||||||
var ${key} = ${each_block_value}[#i].${node.key};
|
|
||||||
var ${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
|
|
||||||
|
|
||||||
if (${last}) ${last}.next = ${iteration};
|
|
||||||
${iteration}.last = ${last};
|
|
||||||
${last} = ${iteration};
|
|
||||||
|
|
||||||
if (#i === 0) ${head} = ${iteration};
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const targetNode = state.parentNode || '#target';
|
|
||||||
const anchorNode = state.parentNode ? 'null' : 'anchor';
|
|
||||||
|
|
||||||
block.builders.create.addBlock(deindent`
|
|
||||||
var ${iteration} = ${head};
|
|
||||||
while (${iteration}) {
|
|
||||||
${iteration}.c();
|
|
||||||
${iteration} = ${iteration}.next;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.claim.addBlock(deindent`
|
|
||||||
var ${iteration} = ${head};
|
|
||||||
while (${iteration}) {
|
|
||||||
${iteration}.l(${state.parentNodes});
|
|
||||||
${iteration} = ${iteration}.next;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.mount.addBlock(deindent`
|
|
||||||
var ${iteration} = ${head};
|
|
||||||
while (${iteration}) {
|
|
||||||
${iteration}.${mountOrIntro}(${targetNode}, ${anchorNode});
|
|
||||||
${iteration} = ${iteration}.next;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const dynamic = node._block.hasUpdateMethod;
|
|
||||||
const parentNode = isDomNode(node.parent, generator) ? node.parent.var : `${anchor}.parentNode`;
|
|
||||||
|
|
||||||
let destroy;
|
|
||||||
if (node._block.hasOutroMethod) {
|
|
||||||
const fn = block.getUniqueName(`${each}_outro`);
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
function ${fn}(iteration) {
|
|
||||||
iteration.o(function() {
|
|
||||||
iteration.u();
|
|
||||||
iteration.d();
|
|
||||||
${lookup}[iteration.key] = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
destroy = deindent`
|
|
||||||
while (${expected}) {
|
|
||||||
${fn}(${expected});
|
|
||||||
${expected} = ${expected}.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (#i = 0; #i < discard_pile.length; #i += 1) {
|
|
||||||
if (discard_pile[#i].discard) {
|
|
||||||
${fn}(discard_pile[#i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
} else {
|
|
||||||
const fn = block.getUniqueName(`${each}_destroy`);
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
function ${fn}(iteration) {
|
|
||||||
iteration.u();
|
|
||||||
iteration.d();
|
|
||||||
${lookup}[iteration.key] = null;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
destroy = deindent`
|
|
||||||
while (${expected}) {
|
|
||||||
${fn}(${expected});
|
|
||||||
${expected} = ${expected}.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (#i = 0; #i < discard_pile.length; #i += 1) {
|
|
||||||
var ${iteration} = discard_pile[#i];
|
|
||||||
if (${iteration}.discard) {
|
|
||||||
${fn}(${iteration});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
var ${each_block_value} = ${snippet};
|
|
||||||
|
|
||||||
var ${expected} = ${head};
|
|
||||||
var ${last} = null;
|
|
||||||
|
|
||||||
var discard_pile = [];
|
|
||||||
|
|
||||||
for (#i = 0; #i < ${each_block_value}.${length}; #i += 1) {
|
|
||||||
var ${key} = ${each_block_value}[#i].${node.key};
|
|
||||||
var ${iteration} = ${lookup}[${key}];
|
|
||||||
|
|
||||||
${dynamic &&
|
|
||||||
`if (${iteration}) ${iteration}.p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);`}
|
|
||||||
|
|
||||||
if (${expected}) {
|
|
||||||
if (${key} === ${expected}.key) {
|
|
||||||
${expected} = ${expected}.next;
|
|
||||||
} else {
|
|
||||||
if (${iteration}) {
|
|
||||||
// probably a deletion
|
|
||||||
while (${expected} && ${expected}.key !== ${key}) {
|
|
||||||
${expected}.discard = true;
|
|
||||||
discard_pile.push(${expected});
|
|
||||||
${expected} = ${expected}.next;
|
|
||||||
};
|
|
||||||
|
|
||||||
${expected} = ${expected} && ${expected}.next;
|
|
||||||
${iteration}.discard = false;
|
|
||||||
${iteration}.last = ${last};
|
|
||||||
|
|
||||||
if (!${expected}) ${iteration}.m(${parentNode}, ${anchor});
|
|
||||||
} else {
|
|
||||||
// key is being inserted
|
|
||||||
${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
|
|
||||||
${iteration}.c();
|
|
||||||
${iteration}.${mountOrIntro}(${parentNode}, ${expected}.first);
|
|
||||||
|
|
||||||
${expected}.last = ${iteration};
|
|
||||||
${iteration}.next = ${expected};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we're appending from this point forward
|
|
||||||
if (${iteration}) {
|
|
||||||
${iteration}.discard = false;
|
|
||||||
${iteration}.next = null;
|
|
||||||
${iteration}.m(${parentNode}, ${anchor});
|
|
||||||
} else {
|
|
||||||
${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
|
|
||||||
${iteration}.c();
|
|
||||||
${iteration}.${mountOrIntro}(${parentNode}, ${anchor});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (${last}) ${last}.next = ${iteration};
|
|
||||||
${iteration}.last = ${last};
|
|
||||||
${node._block.hasIntroMethod && `${iteration}.i(${parentNode}, ${anchor});`}
|
|
||||||
${last} = ${iteration};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (${last}) ${last}.next = null;
|
|
||||||
|
|
||||||
${destroy}
|
|
||||||
|
|
||||||
${head} = ${lookup}[${each_block_value}[0] && ${each_block_value}[0].${node.key}];
|
|
||||||
`);
|
|
||||||
|
|
||||||
if (!state.parentNode) {
|
|
||||||
block.builders.unmount.addBlock(deindent`
|
|
||||||
var ${iteration} = ${head};
|
|
||||||
while (${iteration}) {
|
|
||||||
${iteration}.u();
|
|
||||||
${iteration} = ${iteration}.next;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.destroy.addBlock(deindent`
|
|
||||||
var ${iteration} = ${head};
|
|
||||||
while (${iteration}) {
|
|
||||||
${iteration}.d();
|
|
||||||
${iteration} = ${iteration}.next;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unkeyed(
|
|
||||||
generator: DomGenerator,
|
|
||||||
block: Block,
|
|
||||||
state: State,
|
|
||||||
node: Node,
|
|
||||||
snippet: string,
|
|
||||||
{
|
|
||||||
create_each_block,
|
|
||||||
each_block_value,
|
|
||||||
length,
|
|
||||||
iterations,
|
|
||||||
params,
|
|
||||||
anchor,
|
|
||||||
mountOrIntro,
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
block.builders.init.addBlock(deindent`
|
|
||||||
var ${iterations} = [];
|
|
||||||
|
|
||||||
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
|
|
||||||
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const targetNode = state.parentNode || '#target';
|
|
||||||
const anchorNode = state.parentNode ? 'null' : 'anchor';
|
|
||||||
|
|
||||||
block.builders.create.addBlock(deindent`
|
|
||||||
for (var #i = 0; #i < ${iterations}.length; #i += 1) {
|
|
||||||
${iterations}[#i].c();
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.claim.addBlock(deindent`
|
|
||||||
for (var #i = 0; #i < ${iterations}.length; #i += 1) {
|
|
||||||
${iterations}[#i].l(${state.parentNodes});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.mount.addBlock(deindent`
|
|
||||||
for (var #i = 0; #i < ${iterations}.length; #i += 1) {
|
|
||||||
${iterations}[#i].${mountOrIntro}(${targetNode}, ${anchorNode});
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const allDependencies = new Set(node._block.dependencies);
|
|
||||||
const { dependencies } = node.metadata;
|
|
||||||
dependencies.forEach((dependency: string) => {
|
|
||||||
allDependencies.add(dependency);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO do this for keyed blocks as well
|
|
||||||
const condition = Array.from(allDependencies)
|
|
||||||
.map(dependency => `changed.${dependency}`)
|
|
||||||
.join(' || ');
|
|
||||||
|
|
||||||
const parentNode = isDomNode(node.parent, generator) ? node.parent.var : `${anchor}.parentNode`;
|
|
||||||
|
|
||||||
if (condition !== '') {
|
|
||||||
const forLoopBody = node._block.hasUpdateMethod
|
|
||||||
? node._block.hasIntroMethod
|
|
||||||
? deindent`
|
|
||||||
if (${iterations}[#i]) {
|
|
||||||
${iterations}[#i].p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);
|
|
||||||
} else {
|
|
||||||
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
|
|
||||||
${iterations}[#i].c();
|
|
||||||
}
|
|
||||||
${iterations}[#i].i(${parentNode}, ${anchor});
|
|
||||||
`
|
|
||||||
: deindent`
|
|
||||||
if (${iterations}[#i]) {
|
|
||||||
${iterations}[#i].p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);
|
|
||||||
} else {
|
|
||||||
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
|
|
||||||
${iterations}[#i].c();
|
|
||||||
${iterations}[#i].m(${parentNode}, ${anchor});
|
|
||||||
}
|
|
||||||
`
|
|
||||||
: deindent`
|
|
||||||
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
|
|
||||||
${iterations}[#i].c();
|
|
||||||
${iterations}[#i].${mountOrIntro}(${parentNode}, ${anchor});
|
|
||||||
`;
|
|
||||||
|
|
||||||
const start = node._block.hasUpdateMethod ? '0' : `${iterations}.length`;
|
|
||||||
|
|
||||||
const outro = block.getUniqueName('outro');
|
|
||||||
const destroy = node._block.hasOutroMethod
|
|
||||||
? deindent`
|
|
||||||
function ${outro}(i) {
|
|
||||||
if (${iterations}[i]) {
|
|
||||||
${iterations}[i].o(function() {
|
|
||||||
${iterations}[i].u();
|
|
||||||
${iterations}[i].d();
|
|
||||||
${iterations}[i] = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; #i < ${iterations}.length; #i += 1) ${outro}(#i);
|
|
||||||
`
|
|
||||||
: deindent`
|
|
||||||
for (; #i < ${iterations}.length; #i += 1) {
|
|
||||||
${iterations}[#i].u();
|
|
||||||
${iterations}[#i].d();
|
|
||||||
}
|
|
||||||
${iterations}.length = ${each_block_value}.${length};
|
|
||||||
`;
|
|
||||||
|
|
||||||
block.builders.update.addBlock(deindent`
|
|
||||||
var ${each_block_value} = ${snippet};
|
|
||||||
|
|
||||||
if (${condition}) {
|
|
||||||
for (var #i = ${start}; #i < ${each_block_value}.${length}; #i += 1) {
|
|
||||||
${forLoopBody}
|
|
||||||
}
|
|
||||||
|
|
||||||
${destroy}
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.builders.unmount.addBlock(deindent`
|
|
||||||
for (var #i = 0; #i < ${iterations}.length; #i += 1) {
|
|
||||||
${iterations}[#i].u();
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
block.builders.destroy.addBlock(`@destroyEach(${iterations});`);
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { DomGenerator } from '../index';
|
|
||||||
import Block from '../Block';
|
|
||||||
import { Node } from '../../../interfaces';
|
|
||||||
import { State } from '../interfaces';
|
|
||||||
import { stringify } from '../../../utils/stringify';
|
|
||||||
|
|
||||||
export default function visitText(
|
|
||||||
generator: DomGenerator,
|
|
||||||
block: Block,
|
|
||||||
state: State,
|
|
||||||
node: Node
|
|
||||||
) {
|
|
||||||
if (node.shouldSkip) return;
|
|
||||||
|
|
||||||
block.addElement(
|
|
||||||
node.var,
|
|
||||||
`@createText(${stringify(node.data)})`,
|
|
||||||
`@claimText(${state.parentNodes}, ${stringify(node.data)})`,
|
|
||||||
state.parentNode
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,22 +1,14 @@
|
|||||||
import AwaitBlock from './AwaitBlock';
|
|
||||||
import Component from './Component';
|
|
||||||
import EachBlock from './EachBlock';
|
|
||||||
import Element from './Element/Element';
|
import Element from './Element/Element';
|
||||||
import IfBlock from './IfBlock';
|
import IfBlock from './IfBlock';
|
||||||
import MustacheTag from './MustacheTag';
|
import MustacheTag from './MustacheTag';
|
||||||
import RawMustacheTag from './RawMustacheTag';
|
import RawMustacheTag from './RawMustacheTag';
|
||||||
import Text from './Text';
|
|
||||||
import { Visitor } from '../interfaces';
|
import { Visitor } from '../interfaces';
|
||||||
|
|
||||||
const visitors: Record<string, Visitor> = {
|
const visitors: Record<string, Visitor> = {
|
||||||
AwaitBlock,
|
|
||||||
Component,
|
|
||||||
EachBlock,
|
|
||||||
Element,
|
Element,
|
||||||
IfBlock,
|
IfBlock,
|
||||||
MustacheTag,
|
MustacheTag,
|
||||||
RawMustacheTag,
|
RawMustacheTag
|
||||||
Text
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default visitors;
|
export default visitors;
|
@ -1,6 +1,8 @@
|
|||||||
import Node from './shared/Node';
|
import Node from './shared/Node';
|
||||||
import Block from '../dom/Block';
|
import Block from '../dom/Block';
|
||||||
|
import State from '../dom/State';
|
||||||
|
|
||||||
export default class CatchBlock extends Node {
|
export default class CatchBlock extends Node {
|
||||||
_block: Block;
|
_block: Block;
|
||||||
|
_state: State;
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import Node from './shared/Node';
|
import Node from './shared/Node';
|
||||||
import Block from '../dom/Block';
|
import Block from '../dom/Block';
|
||||||
|
import State from '../dom/State';
|
||||||
|
|
||||||
export default class PendingBlock extends Node {
|
export default class PendingBlock extends Node {
|
||||||
_block: Block;
|
_block: Block;
|
||||||
|
_state: State;
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import Node from './shared/Node';
|
import Node from './shared/Node';
|
||||||
import Block from '../dom/Block';
|
import Block from '../dom/Block';
|
||||||
|
import State from '../dom/State';
|
||||||
|
|
||||||
export default class ThenBlock extends Node {
|
export default class ThenBlock extends Node {
|
||||||
_block: Block;
|
_block: Block;
|
||||||
|
_state: State;
|
||||||
}
|
}
|
Loading…
Reference in new issue