start making slots lazy

pull/1998/head
Richard Harris 7 years ago
parent ff6e378fcb
commit c3e3a8c8f2

@ -637,16 +637,6 @@ export default class Element extends Node {
return this.name === 'audio' || this.name === 'video';
}
remount(name: string) {
const slot = this.attributes.find(attribute => attribute.name === 'slot');
if (slot) {
const prop = quotePropIfNecessary(slot.chunks[0].data);
return `@append(${name}.$$.slotted${prop}, ${this.var});`;
}
return `@append(${name}.$$.slotted.default, ${this.var});`;
}
addCssClass(className = this.component.stylesheet.id) {
const classAttribute = this.attributes.find(a => a.name === 'class');
if (classAttribute && !classAttribute.isTrue) {

@ -48,10 +48,6 @@ export default class Node {
if (this.parent) return this.parent.findNearest(selector);
}
remount(name: string) {
return `${this.var}.m(${name}.$$.slotted.default, null);`;
}
warnIfEmptyBlock() {
if (!this.component.options.dev) return;
if (!/Block$/.test(this.type) || !this.children) return;

@ -61,7 +61,7 @@ export default class Block {
variables: Map<string, string>;
getUniqueName: (name: string) => string;
hasUpdateMethod: boolean;
hasUpdateMethod = false;
autofocus: string;
constructor(options: BlockOptions) {
@ -106,8 +106,6 @@ export default class Block {
this.aliases = new Map().set('ctx', this.getUniqueName('ctx'));
if (this.key) this.aliases.set('key', this.getUniqueName('key'));
this.hasUpdateMethod = false; // determined later
}
assignVariableNames() {
@ -151,6 +149,8 @@ export default class Block {
dependencies.forEach(dependency => {
this.dependencies.add(dependency);
});
this.hasUpdateMethod = true;
}
addElement(
@ -407,7 +407,7 @@ export default class Block {
return deindent`
${this.comment && `// ${this.comment}`}
function ${this.name}($$, ${this.key ? `${localKey}, ` : ''}ctx) {
function ${this.name}(${this.key ? `${localKey}, ` : ''}ctx) {
${this.getContents(localKey)}
}
`;

@ -10,6 +10,7 @@ import addToSet from '../../utils/addToSet';
import getObject from '../../utils/getObject';
import { extractNames } from '../../utils/annotateWithScopes';
import { nodes_match } from '../../utils/nodes_match';
import sanitize from '../../utils/sanitize';
export default function dom(
component: Component,
@ -71,7 +72,7 @@ export default function dom(
const props = component.props.filter(x => component.writable_declarations.has(x.name));
const set = component.meta.props || props.length > 0
const set = (component.meta.props || props.length > 0 || renderer.slots.size > 0)
? deindent`
$$props => {
${component.meta.props && deindent`
@ -81,6 +82,8 @@ export default function dom(
`}
${props.map(prop =>
`if ('${prop.as}' in $$props) $$invalidate('${prop.name}', ${prop.name} = $$props.${prop.as});`)}
${renderer.slots.size > 0 &&
`if ('$$scope' in $$props) $$invalidate('$$scope', $$scope = $$props.$$scope);`}
}
`
: null;
@ -235,10 +238,12 @@ export default function dom(
}
const args = ['$$self'];
if (component.props.length > 0 || component.has_reactive_assignments) args.push('$$props', '$$invalidate');
if (component.props.length > 0 || component.has_reactive_assignments || renderer.slots.size > 0) {
args.push('$$props', '$$invalidate');
}
builder.addBlock(deindent`
function create_fragment($$, ctx) {
function create_fragment(ctx) {
${block.getContents()}
}
@ -264,6 +269,11 @@ export default function dom(
const reactive_stores = Array.from(component.template_references).filter(n => n[0] === '$');
filtered_declarations.push(...reactive_stores);
if (renderer.slots.size > 0) {
const arr = Array.from(renderer.slots);
filtered_declarations.push(...arr.map(name => `$$slot_${sanitize(name)}`), '$$scope');
}
const has_definition = (
component.javascript ||
filtered_props.length > 0 ||
@ -301,6 +311,8 @@ export default function dom(
function ${definition}(${args.join(', ')}) {
${user_code}
${renderer.slots.size && `let { ${[...renderer.slots].map(name => `$$slot_${sanitize(name)}`).join(', ')}, $$scope } = $$props;`}
${component.partly_hoisted.length > 0 && component.partly_hoisted.join('\n\n')}
${reactive_store_subscriptions}

@ -135,7 +135,6 @@ export default class AwaitBlockWrapper extends Wrapper {
block.maintainContext = true;
const infoProps = [
'$$',
'ctx',
'current: null',
this.pending.block.name && `pending: ${this.pending.block.name}`,

@ -41,10 +41,6 @@ class ElseBlockWrapper extends Wrapper {
);
this.isDynamic = this.block.dependencies.size > 0;
if (this.isDynamic) {
// TODO this can't be right
this.block.hasUpdateMethod = true;
}
}
}
@ -149,7 +145,6 @@ export default class EachBlockWrapper extends Wrapper {
}
block.addDependencies(this.block.dependencies);
this.block.hasUpdateMethod = this.block.dependencies.size > 0; // TODO should this logic be in Block?
if (this.block.hasOutros || (this.else && this.else.block.hasOutros)) {
block.addOutro();
@ -216,7 +211,7 @@ export default class EachBlockWrapper extends Wrapper {
// TODO neaten this up... will end up with an empty line in the block
block.builders.init.addBlock(deindent`
if (!${this.vars.each_block_value}.${this.vars.length}) {
${each_block_else} = ${this.else.block.name}($$, ctx);
${each_block_else} = ${this.else.block.name}(ctx);
${each_block_else}.c();
}
`);
@ -234,7 +229,7 @@ export default class EachBlockWrapper extends Wrapper {
if (!${this.vars.each_block_value}.${this.vars.length} && ${each_block_else}) {
${each_block_else}.p(changed, ctx);
} else if (!${this.vars.each_block_value}.${this.vars.length}) {
${each_block_else} = ${this.else.block.name}($$, ctx);
${each_block_else} = ${this.else.block.name}(ctx);
${each_block_else}.c();
${each_block_else}.m(${initialMountNode}, ${this.vars.anchor});
} else if (${each_block_else}) {
@ -250,7 +245,7 @@ export default class EachBlockWrapper extends Wrapper {
${each_block_else} = null;
}
} 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}.m(${initialMountNode}, ${this.vars.anchor});
}
@ -306,7 +301,7 @@ export default class EachBlockWrapper extends Wrapper {
for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) {
let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i);
let key = ${get_key}(child_ctx);
${iterations}[#i] = ${lookup}[key] = ${create_each_block}($$, key, child_ctx);
${iterations}[#i] = ${lookup}[key] = ${create_each_block}(key, child_ctx);
}
`);
@ -342,7 +337,7 @@ export default class EachBlockWrapper extends Wrapper {
${this.block.hasOutros && `@group_outros();`}
${this.node.hasAnimation && `for (let #i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].r();`}
${iterations} = @updateKeyedEach(${iterations}, $$, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${updateMountNode}, ${destroy}, ${create_each_block}, ${anchor}, ${this.vars.get_each_context});
${iterations} = @updateKeyedEach(${iterations}, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.vars.each_block_value}, ${lookup}, ${updateMountNode}, ${destroy}, ${create_each_block}, ${anchor}, ${this.vars.get_each_context});
${this.node.hasAnimation && `for (let #i = 0; #i < ${iterations}.length; #i += 1) ${iterations}[#i].a();`}
${this.block.hasOutros && `@check_outros();`}
`);
@ -375,7 +370,7 @@ export default class EachBlockWrapper extends Wrapper {
var ${iterations} = [];
for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) {
${iterations}[#i] = ${create_each_block}($$, ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i));
${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i));
}
`);
@ -439,14 +434,14 @@ export default class EachBlockWrapper extends Wrapper {
if (${iterations}[#i]) {
${iterations}[#i].p(changed, child_ctx);
} else {
${iterations}[#i] = ${create_each_block}($$, child_ctx);
${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c();
${iterations}[#i].m(${updateMountNode}, ${anchor});
}
${has_transitions && `${iterations}[#i].i();`}
`
: deindent`
${iterations}[#i] = ${create_each_block}($$, child_ctx);
${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c();
${iterations}[#i].m(${updateMountNode}, ${anchor});
${has_transitions && `${iterations}[#i].i();`}
@ -499,9 +494,4 @@ export default class EachBlockWrapper extends Wrapper {
block.builders.destroy.addBlock(`@destroyEach(${iterations}, detach);`);
}
remount(name: string) {
// TODO consider keyed blocks
return `for (var #i = 0; #i < ${this.vars.iterations}.length; #i += 1) ${this.vars.iterations}[#i].m(${name}.$$.slotted.default, null);`;
}
}

@ -124,11 +124,11 @@ export default class BindingWrapper {
const bindingGroup = getBindingGroup(parent.renderer, this.node.expression.node);
block.builders.hydrate.addLine(
`($$.binding_groups[${bindingGroup}] || ($$.binding_groups[${bindingGroup}] = [])).push(${parent.var});`
`(ctx.$$binding_groups[${bindingGroup}] || (ctx.$$binding_groups[${bindingGroup}] = [])).push(${parent.var});`
);
block.builders.destroy.addLine(
`$$.binding_groups[${bindingGroup}].splice($$.binding_groups[${bindingGroup}].indexOf(${parent.var}), 1);`
`ctx.$$binding_groups[${bindingGroup}].splice(ctx.$$binding_groups[${bindingGroup}].indexOf(${parent.var}), 1);`
);
break;
@ -278,7 +278,7 @@ function getValueFromDom(
if (name === 'group') {
const bindingGroup = getBindingGroup(renderer, binding.node.expression.node);
if (type === 'checkbox') {
return `@getBindingGroupValue($$self.$$.binding_groups[${bindingGroup}])`;
return `@getBindingGroupValue($$self.ctx.$$binding_groups[${bindingGroup}])`;
}
return `this.__value`;

@ -19,6 +19,8 @@ import InlineComponentWrapper from '../InlineComponent';
import addToSet from '../../../../utils/addToSet';
import addEventHandlers from '../shared/addEventHandlers';
import addActions from '../shared/addActions';
import createDebuggingComment from '../../../../utils/createDebuggingComment';
import sanitize from '../../../../utils/sanitize';
const events = [
{
@ -91,7 +93,7 @@ export default class ElementWrapper extends Wrapper {
bindings: Binding[];
classDependencies: string[];
slotOwner?: InlineComponentWrapper;
slot_block: Block;
selectBindingDependencies?: Set<string>;
var: string;
@ -126,8 +128,17 @@ export default class ElementWrapper extends Wrapper {
}
if (owner && owner.node.type === 'InlineComponent') {
this.slotOwner = <InlineComponentWrapper>owner;
owner._slots.add(attribute.getStaticValue());
const name = attribute.getStaticValue();
this.slot_block = block.child({
comment: createDebuggingComment(node, this.renderer.component),
name: this.renderer.component.getUniqueName(`create_${sanitize(name)}_slot`)
});
(<InlineComponentWrapper>owner).slots.set(name, this.slot_block);
this.renderer.blocks.push(this.slot_block);
block = this.slot_block;
}
}
if (attribute.name === 'style') {
@ -179,6 +190,10 @@ export default class ElementWrapper extends Wrapper {
}
this.fragment = new FragmentWrapper(renderer, block, node.children, this, stripWhitespace, nextSibling);
if (this.slot_block) {
block.parent.addDependencies(block.dependencies);
}
}
render(block: Block, parentNode: string, parentNodes: string) {
@ -194,15 +209,8 @@ export default class ElementWrapper extends Wrapper {
const node = this.var;
const nodes = parentNodes && block.getUniqueName(`${this.var}_nodes`) // if we're in unclaimable territory, i.e. <head>, parentNodes is null
const slot = this.node.attributes.find((attribute: Node) => attribute.name === 'slot');
const prop = slot && quotePropIfNecessary(slot.chunks[0].data);
let initialMountNode;
if (this.slotOwner) {
initialMountNode = `${this.slotOwner.var}.$$.slotted${prop}`;
} else {
initialMountNode = parentNode;
if (this.slot_block) {
block = this.slot_block;
}
block.addVariable(node);
@ -224,12 +232,12 @@ export default class ElementWrapper extends Wrapper {
}
}
if (initialMountNode) {
if (parentNode) {
block.builders.mount.addLine(
`@append(${initialMountNode}, ${node});`
`@append(${parentNode}, ${node});`
);
if (initialMountNode === 'document.head') {
if (parentNode === 'document.head') {
block.builders.destroy.addLine(`@detachNode(${node});`);
}
} else {
@ -755,16 +763,6 @@ export default class ElementWrapper extends Wrapper {
return null;
}
remount(name: string) {
const slot = this.attributes.find(attribute => attribute.node.name === 'slot');
if (slot) {
const prop = quotePropIfNecessary(slot.node.chunks[0].data);
return `@append(${name}.$$.slotted${prop}, ${this.var});`;
}
return `@append(${name}.$$.slotted.default, ${this.var});`;
}
addCssClass(className = this.component.stylesheet.id) {
const classAttribute = this.attributes.find(a => a.name === 'class');
if (classAttribute && !classAttribute.isTrue) {

@ -222,7 +222,7 @@ export default class IfBlockWrapper extends Wrapper {
block.builders.init.addBlock(deindent`
var ${current_block_type} = ${select_block_type}(ctx);
var ${name} = ${current_block_type_and}${current_block_type}($$, ctx);
var ${name} = ${current_block_type_and}${current_block_type}(ctx);
`);
const initialMountNode = parentNode || '#target';
@ -235,7 +235,7 @@ export default class IfBlockWrapper extends Wrapper {
const changeBlock = deindent`
${if_name}${name}.d(1);
${name} = ${current_block_type_and}${current_block_type}($$, ctx);
${name} = ${current_block_type_and}${current_block_type}(ctx);
if (${name}) {
${name}.c();
${name}.m(${updateMountNode}, ${anchor});
@ -302,12 +302,12 @@ export default class IfBlockWrapper extends Wrapper {
if (hasElse) {
block.builders.init.addBlock(deindent`
${current_block_type_index} = ${select_block_type}(ctx);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}]($$, ctx);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
`);
} else {
block.builders.init.addBlock(deindent`
if (~(${current_block_type_index} = ${select_block_type}(ctx))) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}]($$, ctx);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
}
`);
}
@ -334,7 +334,7 @@ export default class IfBlockWrapper extends Wrapper {
const createNewBlock = deindent`
${name} = ${if_blocks}[${current_block_type_index}];
if (!${name}) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}]($$, ctx);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](ctx);
${name}.c();
}
${name}.m(${updateMountNode}, ${anchor});
@ -394,7 +394,7 @@ export default class IfBlockWrapper extends Wrapper {
const branch = this.branches[0];
block.builders.init.addBlock(deindent`
var ${name} = (${branch.condition}) && ${branch.block.name}($$, ctx);
var ${name} = (${branch.condition}) && ${branch.block.name}(ctx);
`);
const initialMountNode = parentNode || '#target';
@ -411,7 +411,7 @@ export default class IfBlockWrapper extends Wrapper {
if (${name}) {
${name}.p(changed, ctx);
} else {
${name} = ${branch.block.name}($$, ctx);
${name} = ${branch.block.name}(ctx);
${name}.c();
${name}.m(${updateMountNode}, ${anchor});
}
@ -419,7 +419,7 @@ export default class IfBlockWrapper extends Wrapper {
`
: deindent`
if (!${name}) {
${name} = ${branch.block.name}($$, ctx);
${name} = ${branch.block.name}(ctx);
${name}.c();
${name}.m(${updateMountNode}, ${anchor});
}

@ -10,12 +10,13 @@ import addToSet from '../../../../utils/addToSet';
import deindent from '../../../../utils/deindent';
import Attribute from '../../../nodes/Attribute';
import getObject from '../../../../utils/getObject';
import Binding from '../../../nodes/Binding';
import flattenReference from '../../../../utils/flattenReference';
import createDebuggingComment from '../../../../utils/createDebuggingComment';
import sanitize from '../../../../utils/sanitize';
export default class InlineComponentWrapper extends Wrapper {
var: string;
_slots: Set<string>; // TODO lose the underscore
slots: Map<string, Block> = new Map();
node: InlineComponent;
fragment: FragmentWrapper;
@ -65,8 +66,15 @@ export default class InlineComponentWrapper extends Wrapper {
).toLowerCase();
if (this.node.children.length) {
this._slots = new Set(['default']);
this.fragment = new FragmentWrapper(renderer, block, node.children, this, stripWhitespace, nextSibling);
const default_slot = block.child({
comment: createDebuggingComment(node, renderer.component),
name: renderer.component.getUniqueName(`create_default_slot`)
});
this.renderer.blocks.push(default_slot);
this.slots.set('default', default_slot);
this.fragment = new FragmentWrapper(renderer, default_slot, node.children, this, stripWhitespace, nextSibling);
block.addDependencies(default_slot.dependencies);
}
block.addOutro();
@ -84,15 +92,6 @@ export default class InlineComponentWrapper extends Wrapper {
const component_opts = [];
if (this.fragment) {
const slots = Array.from(this._slots).map(name => `${quoteNameIfNecessary(name)}: @createFragment()`);
component_opts.push(`slots: { ${slots.join(', ')} }`);
this.fragment.nodes.forEach((child: Wrapper) => {
child.render(block, `${this.var}.$$.slotted.default`, 'nodes');
});
}
const statements: string[] = [];
const updates: string[] = [];
const postupdates: string[] = [];
@ -102,13 +101,16 @@ export default class InlineComponentWrapper extends Wrapper {
const usesSpread = !!this.node.attributes.find(a => a.isSpread);
const slot_props = Array.from(this.slots).map(([name, block]) => `$$slot_${sanitize(name)}: ${block.name}`);
if (slot_props.length > 0) slot_props.push(`$$scope: { ctx }`);
const attributeObject = usesSpread
? '{}'
? stringifyProps(slot_props)
: stringifyProps(
this.node.attributes.map(attr => `${quoteNameIfNecessary(attr.name)}: ${attr.getValue()}`)
this.node.attributes.map(attr => `${quoteNameIfNecessary(attr.name)}: ${attr.getValue()}`).concat(slot_props)
);
if (this.node.attributes.length || this.node.bindings.length) {
if (this.node.attributes.length || this.node.bindings.length || slot_props.length) {
if (!usesSpread && this.node.bindings.length === 0) {
component_opts.push(`props: ${attributeObject}`);
} else {
@ -117,6 +119,14 @@ export default class InlineComponentWrapper extends Wrapper {
}
}
if (this.fragment) {
const default_slot = this.slots.get('default');
this.fragment.nodes.forEach((child: Wrapper) => {
child.render(default_slot, null, 'nodes');
});
}
if (component.options.dev) {
// TODO this is a terrible hack, but without it the component
// will complain that options.target is missing. This would
@ -125,7 +135,16 @@ export default class InlineComponentWrapper extends Wrapper {
component_opts.push(`$$inline: true`);
}
if (!usesSpread && (this.node.attributes.filter(a => a.isDynamic).length || this.node.bindings.length)) {
const fragment_dependencies = new Set();
this.slots.forEach(block => {
block.dependencies.forEach(name => {
if (renderer.component.mutable_props.has(name)) {
fragment_dependencies.add(name);
}
});
});
if (!usesSpread && (this.node.attributes.filter(a => a.isDynamic).length || this.node.bindings.length || fragment_dependencies.size > 0)) {
updates.push(`var ${name_changes} = {};`);
}
@ -196,6 +215,10 @@ export default class InlineComponentWrapper extends Wrapper {
}
}
if (fragment_dependencies.size > 0) {
updates.push(`if (${[...fragment_dependencies].map(n => `changed.${n}`).join(' || ')}) ${name_changes}.$$scope = { changed, ctx };`);
}
const munged_bindings = this.node.bindings.map(binding => {
component.has_reactive_assignments = true;
@ -375,7 +398,6 @@ export default class InlineComponentWrapper extends Wrapper {
${munged_bindings}
${munged_handlers}
${this.fragment && this.fragment.nodes.map(child => child.remount(name))}
${name}.$$.fragment.c();
@mount_component(${name}, ${updateMountNode}, ${anchor});
${name}.$$.fragment.i();
@ -448,10 +470,6 @@ export default class InlineComponentWrapper extends Wrapper {
`if (${name}) ${name}.$$.fragment.o();`
);
}
remount(name: string) {
return `${this.var}.$$.fragment.m(${name}.$$.slotted.default, null);`;
}
}
function isComputed(node: Node) {

@ -41,42 +41,24 @@ export default class SlotWrapper extends Wrapper {
) {
const { renderer } = this;
const slotName = this.node.getStaticAttributeValue('name') || 'default';
renderer.slots.add(slotName);
const slot_name = this.node.getStaticAttributeValue('name') || 'default';
renderer.slots.add(slot_name);
const content_name = block.getUniqueName(`slot_content_${sanitize(slotName)}`);
const prop = quotePropIfNecessary(slotName);
block.addVariable(content_name, `$$.slotted${prop}`);
const slot = block.getUniqueName(`${sanitize(slot_name)}_slot`);
// TODO can we use isDomNode instead of type === 'Element'?
const needsAnchorBefore = this.prev ? this.prev.node.type !== 'Element' : !parentNode;
const needsAnchorAfter = this.next ? this.next.node.type !== 'Element' : !parentNode;
const anchorBefore = needsAnchorBefore
? block.getUniqueName(`${content_name}_before`)
: (this.prev && this.prev.var) || 'null';
const anchorAfter = needsAnchorAfter
? block.getUniqueName(`${content_name}_after`)
: (this.next && this.next.var) || 'null';
if (needsAnchorBefore) block.addVariable(anchorBefore);
if (needsAnchorAfter) block.addVariable(anchorAfter);
block.builders.init.addLine(
`const ${slot} = ctx.$$slot_${sanitize(slot_name)} && ctx.$$slot_${sanitize(slot_name)}(ctx.$$scope.ctx);`
);
let mountBefore = block.builders.mount.toString();
let destroyBefore = block.builders.destroy.toString();
block.builders.create.pushCondition(`!${content_name}`);
block.builders.hydrate.pushCondition(`!${content_name}`);
block.builders.mount.pushCondition(`!${content_name}`);
block.builders.update.pushCondition(`!${content_name}`);
block.builders.destroy.pushCondition(`!${content_name}`);
block.builders.create.pushCondition(`!${slot}`);
block.builders.hydrate.pushCondition(`!${slot}`);
block.builders.mount.pushCondition(`!${slot}`);
block.builders.update.pushCondition(`!${slot}`);
block.builders.destroy.pushCondition(`!${slot}`);
const listeners = block.event_listeners;
block.event_listeners = [];
this.fragment.render(block, parentNode, parentNodes);
block.renderListeners(`_${content_name}`);
block.event_listeners = listeners;
block.builders.create.popCondition();
block.builders.hydrate.popCondition();
@ -84,62 +66,26 @@ export default class SlotWrapper extends Wrapper {
block.builders.update.popCondition();
block.builders.destroy.popCondition();
block.builders.create.addLine(
`if (${slot}) ${slot}.c();`
);
block.builders.claim.addLine(
`if (${slot}) ${slot}.l(${parentNodes});`
);
const mountLeadin = block.builders.mount.toString() !== mountBefore
? `else`
: `if (${content_name})`;
if (parentNode) {
block.builders.mount.addBlock(deindent`
${mountLeadin} {
${needsAnchorBefore && `@append(${parentNode}, ${anchorBefore} || (${anchorBefore} = @createComment()));`}
@append(${parentNode}, ${content_name});
${needsAnchorAfter && `@append(${parentNode}, ${anchorAfter} || (${anchorAfter} = @createComment()));`}
}
`);
} else {
block.builders.mount.addBlock(deindent`
${mountLeadin} {
${needsAnchorBefore && `@insert(#target, ${anchorBefore} || (${anchorBefore} = @createComment()), anchor);`}
@insert(#target, ${content_name}, anchor);
${needsAnchorAfter && `@insert(#target, ${anchorAfter} || (${anchorAfter} = @createComment()), anchor);`}
}
`);
}
// if the slot is unmounted, move nodes back into the document fragment,
// so that it can be reinserted later
// TODO so that this can work with public API, component.$$.slotted should
// be all fragments, derived from options.slots. Not === options.slots
const unmountLeadin = block.builders.destroy.toString() !== destroyBefore
? `else`
: `if (${content_name})`;
if (anchorBefore === 'null' && anchorAfter === 'null') {
block.builders.destroy.addBlock(deindent`
${unmountLeadin} {
@reinsertChildren(${parentNode}, ${content_name});
}
`);
} else if (anchorBefore === 'null') {
block.builders.destroy.addBlock(deindent`
${unmountLeadin} {
@reinsertBefore(${anchorAfter}, ${content_name});
}
`);
} else if (anchorAfter === 'null') {
block.builders.destroy.addBlock(deindent`
${unmountLeadin} {
@reinsertAfter(${anchorBefore}, ${content_name});
}
`);
} else {
block.builders.destroy.addBlock(deindent`
${unmountLeadin} {
@reinsertBetween(${anchorBefore}, ${anchorAfter}, ${content_name});
@detachNode(${anchorBefore});
@detachNode(${anchorAfter});
}
`);
}
: `if (${slot})`;
block.builders.mount.addBlock(deindent`
${mountLeadin} {
${slot}.m(${parentNode || '#target'}, anchor);
}
`);
block.builders.update.addLine(
`if (${slot} && changed.$$scope) ${slot}.p(ctx.$$scope.changed, ctx.$$scope.ctx);`
);
}
}

@ -60,8 +60,4 @@ export default class TextWrapper extends Wrapper {
parentNode
);
}
remount(name: string) {
return `@append(${name}.$$.slotted.default, ${this.var});`;
}
}

@ -51,8 +51,4 @@ export default class Tag extends Wrapper {
return { init: content };
}
remount(name: string) {
return `@append(${name}.$$.slotted.default, ${this.var});`;
}
}

@ -85,8 +85,4 @@ export default class Wrapper {
render(block: Block, parentNode: string, parentNodes: string) {
throw new Error(`render method not implemented by subclass ${this.node.type}`);
}
remount(name: string) {
return `${this.var}.m(${name}.$$.slotted.default, null);`;
}
}

@ -57,9 +57,11 @@ export function init(component, options, instance, create_fragment, not_equal) {
const previous_component = current_component;
set_current_component(component);
const props = options.props || {};
const $$ = component.$$ = {
fragment: null,
ctx: options.props || {},
ctx: null,
// state
set: noop,
@ -75,15 +77,13 @@ export function init(component, options, instance, create_fragment, not_equal) {
// everything else
callbacks: blankObject(),
slotted: options.slots || {},
dirty: null,
binding_groups: []
dirty: null
};
let ready = false;
if (instance) {
$$.ctx = instance(component, $$.ctx, (key, value) => {
$$.ctx = instance
? instance(component, props, (key, value) => {
if ($$.bound[key]) $$.bound[key](value);
if ($$.ctx) {
@ -95,13 +95,15 @@ export function init(component, options, instance, create_fragment, not_equal) {
$$.ctx[key] = value;
return changed;
}
});
}
})
: props;
$$.ctx.$$binding_groups = []; // TODO this is awkward and usually unncessary
$$.update();
ready = true;
run_all($$.before_render);
$$.fragment = create_fragment($$, $$.ctx);
$$.fragment = create_fragment($$.ctx);
if (options.target) {
if (options.hydrate) {

@ -11,7 +11,7 @@ export function handlePromise(promise, info) {
info.resolved = key && { [key]: value };
const child_ctx = assign(assign({}, info.ctx), info.resolved);
const block = type && (info.current = type)(info.$$, child_ctx);
const block = type && (info.current = type)(child_ctx);
if (info.block) {
if (info.blocks) {

@ -18,7 +18,7 @@ export function fixAndOutroAndDestroyBlock(block, lookup) {
outroAndDestroyBlock(block, lookup);
}
export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {
export function updateKeyedEach(old_blocks, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {
var o = old_blocks.length;
var n = list.length;
@ -37,7 +37,7 @@ export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic
var block = lookup[key];
if (!block) {
block = create_each_block(component, key, child_ctx);
block = create_each_block(key, child_ctx);
block.c();
} else if (dynamic) {
block.p(changed, child_ctx);

@ -10,12 +10,19 @@ export default function createDebuggingComment(
let c = node.start;
if (node.type === 'ElseBlock') {
while (source[c - 1] !== '{') c -= 1;
while (source[c - 1] === '{') c -= 1;
// while (source[c - 1] === '{') c -= 1;
}
let d = node.expression ? node.expression.node.end : c;
while (source[d] !== '}') d += 1;
while (source[d] === '}') d += 1;
let d;
if (node.type === 'InlineComponent' || node.type === 'Element') {
d = node.children[0].start;
while (source[d - 1] !== '>') d -= 1;
} else {
d = node.expression ? node.expression.node.end : c;
while (source[d] !== '}') d += 1;
// while (source[d] === '}') d += 1;
}
const start = locate(c);
const loc = `(${start.line + 1}:${start.column})`;

Loading…
Cancel
Save