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

pull/8569/head
Simon Holthausen 3 years ago
parent 6bdbfbb735
commit fb06ba3bae

@ -10,212 +10,237 @@ import create_debugging_comment from './shared/create_debugging_comment.js';
/** @extends Wrapper */ /** @extends Wrapper */
export default class SlotWrapper extends Wrapper { export default class SlotWrapper extends Wrapper {
/** @type {import('../../nodes/Slot.js').default} */
/** @type {import('../../nodes/Slot.js').default} */ node;
node;
/** @type {import('./Fragment.js').default} */
/** @type {import('./Fragment.js').default} */ fragment;
fragment;
/** @type {import('../Block.js').default | null} */
/** @type {import('../Block.js').default | null} */ fallback = null;
fallback = null;
/** @type {import('../Block.js').default} */
/** @type {import('../Block.js').default} */ slot_block;
slot_block;
/** @type {import('estree').Identifier} */
/** @type {import('estree').Identifier} */ var = { type: 'Identifier', name: 'slot' };
var = { type: 'Identifier', name: 'slot' };
/** @type {Set<string>} */
/** @type {Set<string>} */ dependencies = new Set(['$$scope']);
dependencies = new Set(['$$scope']);
/**
/** * @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/Slot.js').default} node
* @param {import('../../nodes/Slot.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); if (this.node.children.length) {
if (this.node.children.length) { this.fallback = block.child({
this.fallback = block.child({ comment: create_debugging_comment(this.node.children[0], this.renderer.component),
comment: create_debugging_comment(this.node.children[0], this.renderer.component), name: this.renderer.component.get_unique_name('fallback_block'),
name: this.renderer.component.get_unique_name('fallback_block'), type: 'fallback'
type: 'fallback' });
}); renderer.blocks.push(this.fallback);
renderer.blocks.push(this.fallback); }
} this.fragment = new FragmentWrapper(
this.fragment = new FragmentWrapper(renderer, this.fallback, node.children, this, strip_whitespace, next_sibling); renderer,
this.node.values.forEach((attribute) => { this.fallback,
add_to_set(this.dependencies, attribute.dependencies); node.children,
}); this,
block.add_dependencies(this.dependencies); strip_whitespace,
// we have to do this, just in case next_sibling
block.add_intro(); );
block.add_outro(); this.node.values.forEach((attribute) => {
} add_to_set(this.dependencies, attribute.dependencies);
});
/** block.add_dependencies(this.dependencies);
* @param {import('../Block.js').default} block // we have to do this, just in case
* @param {import('estree').Identifier} parent_node block.add_intro();
* @param {import('estree').Identifier} parent_nodes block.add_outro();
*/ }
render(block, parent_node, parent_nodes) {
const { renderer } = this; /**
const { slot_name } = this.node; * @param {import('../Block.js').default} block
if (this.slot_block) { * @param {import('estree').Identifier} parent_node
block = this.slot_block; * @param {import('estree').Identifier} parent_nodes
} */
render(block, parent_node, parent_nodes) {
/** @type {import('estree').Identifier | 'null'} */ const { renderer } = this;
let get_slot_changes_fn; const { slot_name } = this.node;
if (this.slot_block) {
/** @type {import('estree').Identifier | undefined} */ block = this.slot_block;
let get_slot_spread_changes_fn; }
/** @type {import('estree').Identifier | 'null'} */ /** @type {import('estree').Identifier | 'null'} */
let get_slot_context_fn; let get_slot_changes_fn;
if (this.node.values.size > 0) {
get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`); /** @type {import('estree').Identifier | undefined} */
get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`); let get_slot_spread_changes_fn;
const changes = /** @type {import('estree').ObjectExpression} */ (x `{}`);
const spread_dynamic_dependencies = new Set(); /** @type {import('estree').Identifier | 'null'} */
this.node.values.forEach((attribute) => { let get_slot_context_fn;
if (attribute.type === 'Spread') { if (this.node.values.size > 0) {
add_to_set(spread_dynamic_dependencies, Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name))); get_slot_changes_fn = renderer.component.get_unique_name(
} `get_${sanitize(slot_name)}_slot_changes`
else { );
const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name)); get_slot_context_fn = renderer.component.get_unique_name(
if (dynamic_dependencies.length > 0) { `get_${sanitize(slot_name)}_slot_context`
changes.properties.push(p `${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`); );
} const changes = /** @type {import('estree').ObjectExpression} */ (x`{}`);
} const spread_dynamic_dependencies = new Set();
}); this.node.values.forEach((attribute) => {
renderer.blocks.push(b ` if (attribute.type === 'Spread') {
add_to_set(
spread_dynamic_dependencies,
Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name))
);
} else {
const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) =>
this.is_dependency_dynamic(name)
);
if (dynamic_dependencies.length > 0) {
changes.properties.push(p`${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`);
}
}
});
renderer.blocks.push(b`
const ${get_slot_changes_fn} = #dirty => ${changes}; const ${get_slot_changes_fn} = #dirty => ${changes};
const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)}; const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
`); `);
if (spread_dynamic_dependencies.size) { if (spread_dynamic_dependencies.size) {
get_slot_spread_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_spread_changes`); get_slot_spread_changes_fn = renderer.component.get_unique_name(
renderer.blocks.push(b ` `get_${sanitize(slot_name)}_slot_spread_changes`
const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))}; );
renderer.blocks.push(b`
const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(
Array.from(spread_dynamic_dependencies)
)};
`); `);
} }
} } else {
else { get_slot_changes_fn = 'null';
get_slot_changes_fn = 'null'; get_slot_context_fn = 'null';
get_slot_context_fn = 'null'; }
} let has_fallback = !!this.fallback;
let has_fallback = !!this.fallback; if (this.fallback) {
if (this.fallback) { this.fragment.render(
this.fragment.render(this.fallback, null, /** @type {import('estree').Identifier} */ (x `#nodes`)); this.fallback,
has_fallback = this.fallback.has_content(); null,
if (!has_fallback) { /** @type {import('estree').Identifier} */ (x`#nodes`)
renderer.remove_block(this.fallback); );
} has_fallback = this.fallback.has_content();
} if (!has_fallback) {
const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`); renderer.remove_block(this.fallback);
const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`); }
const slot_or_fallback = has_fallback }
? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
: slot; const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
block.chunks.init.push(b ` const slot_or_fallback = has_fallback
? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`)
: slot;
block.chunks.init.push(b`
const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name}; const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}); const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference(
${has_fallback ? b `const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null} '$$scope'
)}, ${get_slot_context_fn});
${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
`); `);
block.chunks.create.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.c();`); block.chunks.create.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
if (renderer.options.hydratable) { if (renderer.options.hydratable) {
block.chunks.claim.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`); block.chunks.claim.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
} }
block.chunks.mount.push(b ` block.chunks.mount.push(b`
if (${slot_or_fallback}) { if (${slot_or_fallback}) {
${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'}); ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
} }
`); `);
block.chunks.intro.push(b `@transition_in(${slot_or_fallback}, #local);`); block.chunks.intro.push(b`@transition_in(${slot_or_fallback}, #local);`);
block.chunks.outro.push(b `@transition_out(${slot_or_fallback}, #local);`); block.chunks.outro.push(b`@transition_out(${slot_or_fallback}, #local);`);
const dynamic_dependencies = Array.from(this.dependencies).filter((name) => this.is_dependency_dynamic(name)); const dynamic_dependencies = Array.from(this.dependencies).filter((name) =>
const fallback_dynamic_dependencies = has_fallback this.is_dependency_dynamic(name)
? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name)) );
: []; const fallback_dynamic_dependencies = has_fallback
let condition = renderer.dirty(dynamic_dependencies); ? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
if (block.has_outros) { : [];
condition = x `!#current || ${condition}`; let condition = renderer.dirty(dynamic_dependencies);
} if (block.has_outros) {
// conditions to treat everything as dirty condition = x`!#current || ${condition}`;
const all_dirty_conditions = [ }
get_slot_spread_changes_fn ? x `${get_slot_spread_changes_fn}(#dirty)` : null, // conditions to treat everything as dirty
block.has_outros ? x `!#current` : null const all_dirty_conditions = [
].filter(Boolean); get_slot_spread_changes_fn ? x`${get_slot_spread_changes_fn}(#dirty)` : null,
const all_dirty_condition = all_dirty_conditions.length block.has_outros ? x`!#current` : null
? all_dirty_conditions.reduce((condition1, condition2) => x `${condition1} || ${condition2}`) ].filter(Boolean);
: null; const all_dirty_condition = all_dirty_conditions.length
? all_dirty_conditions.reduce((condition1, condition2) => x`${condition1} || ${condition2}`)
/** @type {import('estree').Node[]} */ : null;
let slot_update;
if (all_dirty_condition) { /** @type {import('estree').Node[]} */
const dirty = x `${all_dirty_condition} ? @get_all_dirty_from_scope(${renderer.reference('$$scope')}) : @get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn})`; let slot_update;
slot_update = b ` if (all_dirty_condition) {
const dirty = x`${all_dirty_condition} ? @get_all_dirty_from_scope(${renderer.reference(
'$$scope'
)}) : @get_slot_changes(${slot_definition}, ${renderer.reference(
'$$scope'
)}, #dirty, ${get_slot_changes_fn})`;
slot_update = b`
if (${slot}.p && ${condition}) { if (${slot}.p && ${condition}) {
@update_slot_base(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_context_fn}); @update_slot_base(${slot}, ${slot_definition}, #ctx, ${renderer.reference(
'$$scope'
)}, ${dirty}, ${get_slot_context_fn});
} }
`; `;
} } else {
else { slot_update = b`
slot_update = b `
if (${slot}.p && ${condition}) { if (${slot}.p && ${condition}) {
@update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn}); @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference(
'$$scope'
)}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn});
} }
`; `;
} }
let fallback_condition = renderer.dirty(fallback_dynamic_dependencies); let fallback_condition = renderer.dirty(fallback_dynamic_dependencies);
let fallback_dirty = x `#dirty`; let fallback_dirty = x`#dirty`;
if (block.has_outros) { if (block.has_outros) {
fallback_condition = x `!#current || ${fallback_condition}`; fallback_condition = x`!#current || ${fallback_condition}`;
fallback_dirty = x `!#current ? ${renderer.get_initial_dirty()} : ${fallback_dirty}`; fallback_dirty = x`!#current ? ${renderer.get_initial_dirty()} : ${fallback_dirty}`;
} }
const fallback_update = has_fallback && const fallback_update =
fallback_dynamic_dependencies.length > 0 && has_fallback &&
b ` fallback_dynamic_dependencies.length > 0 &&
b`
if (${slot_or_fallback} && ${slot_or_fallback}.p && ${fallback_condition}) { if (${slot_or_fallback} && ${slot_or_fallback}.p && ${fallback_condition}) {
${slot_or_fallback}.p(#ctx, ${fallback_dirty}); ${slot_or_fallback}.p(#ctx, ${fallback_dirty});
} }
`; `;
if (fallback_update) { if (fallback_update) {
block.chunks.update.push(b ` block.chunks.update.push(b`
if (${slot}) { if (${slot}) {
${slot_update} ${slot_update}
} else { } else {
${fallback_update} ${fallback_update}
} }
`); `);
} } else {
else { block.chunks.update.push(b`
block.chunks.update.push(b `
if (${slot}) { if (${slot}) {
${slot_update} ${slot_update}
} }
`); `);
} }
block.chunks.destroy.push(b `if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`); block.chunks.destroy.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
} }
/** @param {string} name */ /** @param {string} name */
is_dependency_dynamic(name) { is_dependency_dynamic(name) {
if (name === '$$scope') if (name === '$$scope') return true;
return true; if (this.node.scope.is_let(name)) return true;
if (this.node.scope.is_let(name)) if (is_reserved_keyword(name)) return true;
return true; const variable = this.renderer.component.var_lookup.get(name);
if (is_reserved_keyword(name)) return is_dynamic(variable);
return true; }
const variable = this.renderer.component.var_lookup.get(name);
return is_dynamic(variable);
}
} }

Loading…
Cancel
Save