Lint and format src/compiler/compile/render_dom/wrappers/AwaitBlock.js

pull/8569/head
Simon Holthausen 3 years ago
parent cb0d76e264
commit 788902480c

@ -9,213 +9,226 @@ import Expression from '../../nodes/shared/Expression.js';
/** @extends Wrapper */ /** @extends Wrapper */
class AwaitBlockBranch extends Wrapper { class AwaitBlockBranch extends Wrapper {
/** @type {AwaitBlockWrapper} */
parent;
/** @type {AwaitBlockWrapper} */ /** @type {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} */
parent; node;
/** @type {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} */ /** @type {import('../Block.js').default} */
node; block;
/** @type {import('../Block.js').default} */ /** @type {import('./Fragment.js').default} */
block; fragment;
/** @type {import('./Fragment.js').default} */ /** @type {boolean} */
fragment; is_dynamic;
/** */
var = null;
/** @type {boolean} */ /** @type {Status} */
is_dynamic; status;
/** */
var = null;
/** @type {Status} */ /** @type {string} */
status; value;
/** @type {string} */ /** @type {import('estree').Literal} */
value; value_index;
/** @type {import('estree').Literal} */ /** @type {import('../../nodes/shared/Context.js').Context[]} */
value_index; value_contexts;
/** @type {import('../../nodes/shared/Context.js').Context[]} */ /** @type {boolean} */
value_contexts; is_destructured;
/** @type {boolean} */ /**
is_destructured; * @param {Status} status
* @param {import('../Renderer.js').default} renderer
* @param {import('../Block.js').default} block
* @param {AwaitBlockWrapper} parent
* @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node
* @param {boolean} strip_whitespace
* @param {import('./shared/Wrapper.js').default} next_sibling
*/
constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
super(renderer, block, parent, node);
this.status = status;
this.block = block.child({
comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_${status}_block`),
type: status
});
this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
this.fragment = new FragmentWrapper(
renderer,
this.block,
this.node.children,
parent,
strip_whitespace,
next_sibling
);
this.is_dynamic = this.block.dependencies.size > 0;
}
/** /**
* @param {Status} status * @param {import('estree').Node | null} node
* @param {import('../Renderer.js').default} renderer * @param {import('../../nodes/shared/Context.js').Context[]} contexts
* @param {import('../Block.js').default} block */
* @param {AwaitBlockWrapper} parent add_context(node, contexts) {
* @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node if (!node) return;
* @param {boolean} strip_whitespace if (node.type === 'Identifier') {
* @param {import('./shared/Wrapper.js').default} next_sibling this.value = node.name;
*/ this.renderer.add_to_context(this.value, true);
constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) { } else {
super(renderer, block, parent, node); contexts.forEach((context) => {
this.status = status; if (context.type !== 'DestructuredVariable') return;
this.block = block.child({ this.renderer.add_to_context(context.key.name, true);
comment: create_debugging_comment(node, this.renderer.component), });
name: this.renderer.component.get_unique_name(`create_${status}_block`), this.value = this.block.parent.get_unique_name('value').name;
type: status this.value_contexts = contexts;
}); this.renderer.add_to_context(this.value, true);
this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']); this.is_destructured = true;
this.fragment = new FragmentWrapper(renderer, this.block, this.node.children, parent, strip_whitespace, next_sibling); }
this.is_dynamic = this.block.dependencies.size > 0; this.value_index = this.renderer.context_lookup.get(this.value).index;
} if (this.has_consts(this.node)) {
add_const_tags_context(this.renderer, this.node.const_tags);
}
}
/** /**
* @param {import('estree').Node | null} node * @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node
* @param {import('../../nodes/shared/Context.js').Context[]} contexts * @returns {boolean}
*/ */
add_context(node, contexts) { has_consts(node) {
if (!node) return node instanceof ThenBlock || node instanceof CatchBlock;
return; }
if (node.type === 'Identifier') {
this.value = node.name;
this.renderer.add_to_context(this.value, true);
}
else {
contexts.forEach((context) => {
if (context.type !== 'DestructuredVariable')
return;
this.renderer.add_to_context(context.key.name, true);
});
this.value = this.block.parent.get_unique_name('value').name;
this.value_contexts = contexts;
this.renderer.add_to_context(this.value, true);
this.is_destructured = true;
}
this.value_index = this.renderer.context_lookup.get(this.value).index;
if (this.has_consts(this.node)) {
add_const_tags_context(this.renderer, this.node.const_tags);
}
}
/** /**
* @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node * @param {import('../Block.js').default} block
* @returns {boolean} * @param {import('estree').Identifier} parent_node
*/ * @param {import('estree').Identifier} parent_nodes
has_consts(node) { */
return node instanceof ThenBlock || node instanceof CatchBlock; render(block, parent_node, parent_nodes) {
} this.fragment.render(block, parent_node, parent_nodes);
if (this.is_destructured || (this.has_consts(this.node) && this.node.const_tags.length > 0)) {
/** this.render_get_context();
* @param {import('../Block.js').default} block }
* @param {import('estree').Identifier} parent_node }
* @param {import('estree').Identifier} parent_nodes render_get_context() {
*/ const props = this.is_destructured
render(block, parent_node, parent_nodes) { ? this.value_contexts.map((prop) => {
this.fragment.render(block, parent_node, parent_nodes); if (prop.type === 'ComputedProperty') {
if (this.is_destructured || (this.has_consts(this.node) && this.node.const_tags.length > 0)) { const expression = new Expression(
this.render_get_context(); this.renderer.component,
} this.node,
} this.has_consts(this.node) ? this.node.scope : null,
render_get_context() { prop.key
const props = this.is_destructured );
? this.value_contexts.map((prop) => { return b`const ${prop.property_name} = ${expression.manipulate(this.block, '#ctx')};`;
if (prop.type === 'ComputedProperty') { } else {
const expression = new Expression(this.renderer.component, this.node, this.has_consts(this.node) ? this.node.scope : null, prop.key); /** @param {any} name */
return b `const ${prop.property_name} = ${expression.manipulate(this.block, '#ctx')};`; const to_ctx = (name) => this.renderer.reference(name);
} return b`#ctx[${
else { this.block.renderer.context_lookup.get(prop.key.name).index
}] = ${prop.default_modifier(prop.modifier(x`#ctx[${this.value_index}]`), to_ctx)};`;
/** @param {any} name */ }
const to_ctx = (name) => this.renderer.reference(name); })
return b `#ctx[${this.block.renderer.context_lookup.get(prop.key.name).index}] = ${prop.default_modifier(prop.modifier(x `#ctx[${this.value_index}]`), to_ctx)};`; : null;
} const const_tags_props = this.has_consts(this.node)
}) ? add_const_tags(this.block, this.node.const_tags, '#ctx')
: null; : null;
const const_tags_props = this.has_consts(this.node) const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
? add_const_tags(this.block, this.node.const_tags, '#ctx') this.block.renderer.blocks.push(b`
: null;
const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
this.block.renderer.blocks.push(b `
function ${get_context}(#ctx) { function ${get_context}(#ctx) {
${props} ${props}
${const_tags_props} ${const_tags_props}
} }
`); `);
this.block.chunks.declarations.push(b `${get_context}(#ctx)`); this.block.chunks.declarations.push(b`${get_context}(#ctx)`);
if (this.block.has_update_method) { if (this.block.has_update_method) {
this.block.chunks.update.unshift(b `${get_context}(#ctx)`); this.block.chunks.update.unshift(b`${get_context}(#ctx)`);
} }
} }
} }
/** @extends Wrapper */ /** @extends Wrapper */
export default class AwaitBlockWrapper extends Wrapper { export default class AwaitBlockWrapper extends Wrapper {
/** @type {import('../../nodes/AwaitBlock.js').default} */
node;
/** @type {import('../../nodes/AwaitBlock.js').default} */ /** @type {AwaitBlockBranch} */
node; pending;
/** @type {AwaitBlockBranch} */
pending;
/** @type {AwaitBlockBranch} */ /** @type {AwaitBlockBranch} */
then; then;
/** @type {AwaitBlockBranch} */ /** @type {AwaitBlockBranch} */
catch; catch;
/** @type {import('estree').Identifier} */ /** @type {import('estree').Identifier} */
var = { type: 'Identifier', name: 'await_block' }; var = { type: 'Identifier', name: 'await_block' };
/** /**
* @param {import('../Renderer.js').default} renderer * @param {import('../Renderer.js').default} renderer
* @param {import('../Block.js').default} block * @param {import('../Block.js').default} block
* @param {import('./shared/Wrapper.js').default} parent * @param {import('./shared/Wrapper.js').default} parent
* @param {import('../../nodes/AwaitBlock.js').default} node * @param {import('../../nodes/AwaitBlock.js').default} node
* @param {boolean} strip_whitespace * @param {boolean} strip_whitespace
* @param {import('./shared/Wrapper.js').default} next_sibling * @param {import('./shared/Wrapper.js').default} next_sibling
*/ */
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) { constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
block.add_dependencies(this.node.expression.dependencies); block.add_dependencies(this.node.expression.dependencies);
let is_dynamic = false; let is_dynamic = false;
let has_intros = false; let has_intros = false;
let has_outros = false; let has_outros = false;
['pending', 'then', 'catch'].forEach((status) => { ['pending', 'then', 'catch'].forEach((status) => {
const child = this.node[status]; const child = this.node[status];
const branch = new AwaitBlockBranch(status, renderer, block, this, child, strip_whitespace, next_sibling); const branch = new AwaitBlockBranch(
renderer.blocks.push(branch.block); status,
if (branch.is_dynamic) { renderer,
is_dynamic = true; block,
// TODO should blocks update their own parents? this,
block.add_dependencies(branch.block.dependencies); child,
} strip_whitespace,
if (branch.block.has_intros) next_sibling
has_intros = true; );
if (branch.block.has_outros) renderer.blocks.push(branch.block);
has_outros = true; if (branch.is_dynamic) {
this[status] = branch; is_dynamic = true;
}); // TODO should blocks update their own parents?
['pending', 'then', 'catch'].forEach((status) => { block.add_dependencies(branch.block.dependencies);
this[status].block.has_update_method = is_dynamic; }
this[status].block.has_intro_method = has_intros; if (branch.block.has_intros) has_intros = true;
this[status].block.has_outro_method = has_outros; if (branch.block.has_outros) has_outros = true;
}); this[status] = branch;
if (has_outros) { });
block.add_outro(); ['pending', 'then', 'catch'].forEach((status) => {
} this[status].block.has_update_method = is_dynamic;
} this[status].block.has_intro_method = has_intros;
this[status].block.has_outro_method = has_outros;
});
if (has_outros) {
block.add_outro();
}
}
/** /**
* @param {import('../Block.js').default} block * @param {import('../Block.js').default} block
* @param {import('estree').Identifier} parent_node * @param {import('estree').Identifier} parent_node
* @param {import('estree').Identifier} parent_nodes * @param {import('estree').Identifier} parent_nodes
*/ */
render(block, parent_node, parent_nodes) { render(block, parent_node, parent_nodes) {
const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes); const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
const update_mount_node = this.get_update_mount_node(anchor); const update_mount_node = this.get_update_mount_node(anchor);
const snippet = this.node.expression.manipulate(block); const snippet = this.node.expression.manipulate(block);
const info = block.get_unique_name('info'); const info = block.get_unique_name('info');
const promise = block.get_unique_name('promise'); const promise = block.get_unique_name('promise');
block.add_variable(promise); block.add_variable(promise);
block.maintain_context = true; block.maintain_context = true;
/** @type {any} */ /** @type {any} */
const info_props = x `{ const info_props = x`{
ctx: #ctx, ctx: #ctx,
current: null, current: null,
token: null, token: null,
@ -225,82 +238,79 @@ export default class AwaitBlockWrapper extends Wrapper {
catch: ${this.catch.block.name}, catch: ${this.catch.block.name},
value: ${this.then.value_index}, value: ${this.then.value_index},
error: ${this.catch.value_index}, error: ${this.catch.value_index},
blocks: ${this.pending.block.has_outro_method && x `[,,,]`} blocks: ${this.pending.block.has_outro_method && x`[,,,]`}
}`; }`;
block.chunks.init.push(b ` block.chunks.init.push(b`
let ${info} = ${info_props}; let ${info} = ${info_props};
`); `);
block.chunks.init.push(b ` block.chunks.init.push(b`
@handle_promise(${promise} = ${snippet}, ${info}); @handle_promise(${promise} = ${snippet}, ${info});
`); `);
block.chunks.create.push(b ` block.chunks.create.push(b`
${info}.block.c(); ${info}.block.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`
${info}.block.l(${parent_nodes}); ${info}.block.l(${parent_nodes});
`); `);
} }
const initial_mount_node = parent_node || '#target'; const initial_mount_node = parent_node || '#target';
const anchor_node = parent_node ? 'null' : '#anchor'; const anchor_node = parent_node ? 'null' : '#anchor';
const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method; const has_transitions =
block.chunks.mount.push(b ` this.pending.block.has_intro_method || this.pending.block.has_outro_method;
block.chunks.mount.push(b`
${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node}); ${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
${info}.mount = () => ${update_mount_node}; ${info}.mount = () => ${update_mount_node};
${info}.anchor = ${anchor}; ${info}.anchor = ${anchor};
`); `);
if (has_transitions) { if (has_transitions) {
block.chunks.intro.push(b `@transition_in(${info}.block);`); block.chunks.intro.push(b`@transition_in(${info}.block);`);
} }
const dependencies = this.node.expression.dynamic_dependencies(); const dependencies = this.node.expression.dynamic_dependencies();
const update_await_block_branch = b `@update_await_block_branch(${info}, #ctx, #dirty)`; const update_await_block_branch = b`@update_await_block_branch(${info}, #ctx, #dirty)`;
if (dependencies.length > 0) { if (dependencies.length > 0) {
const condition = x ` const condition = x`
${block.renderer.dirty(dependencies)} && ${block.renderer.dirty(dependencies)} &&
${promise} !== (${promise} = ${snippet}) && ${promise} !== (${promise} = ${snippet}) &&
@handle_promise(${promise}, ${info})`; @handle_promise(${promise}, ${info})`;
block.chunks.update.push(b `${info}.ctx = #ctx;`); block.chunks.update.push(b`${info}.ctx = #ctx;`);
if (this.pending.block.has_update_method) { if (this.pending.block.has_update_method) {
block.chunks.update.push(b ` block.chunks.update.push(b`
if (${condition}) { if (${condition}) {
} else { } else {
${update_await_block_branch} ${update_await_block_branch}
} }
`); `);
} } else {
else { block.chunks.update.push(b`
block.chunks.update.push(b `
${condition} ${condition}
`); `);
} }
} } else {
else { if (this.pending.block.has_update_method) {
if (this.pending.block.has_update_method) { block.chunks.update.push(b`
block.chunks.update.push(b `
${update_await_block_branch} ${update_await_block_branch}
`); `);
} }
} }
if (this.pending.block.has_outro_method) { if (this.pending.block.has_outro_method) {
block.chunks.outro.push(b ` block.chunks.outro.push(b`
for (let #i = 0; #i < 3; #i += 1) { for (let #i = 0; #i < 3; #i += 1) {
const block = ${info}.blocks[#i]; const block = ${info}.blocks[#i];
@transition_out(block); @transition_out(block);
} }
`); `);
} }
block.chunks.destroy.push(b ` block.chunks.destroy.push(b`
${info}.block.d(${parent_node ? null : 'detaching'}); ${info}.block.d(${parent_node ? null : 'detaching'});
${info}.token = null; ${info}.token = null;
${info} = null; ${info} = null;
`); `);
[this.pending, this.then, this.catch].forEach((branch) => { [this.pending, this.then, this.catch].forEach((branch) => {
branch.render(branch.block, null, /** @type {import('estree').Identifier} */ (x `#nodes`)); branch.render(branch.block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
}); });
} }
} }
/** @typedef {'pending' | 'then' | 'catch'} Status */ /** @typedef {'pending' | 'then' | 'catch'} Status */

Loading…
Cancel
Save