pull/3539/head
Richard Harris 6 years ago
parent 1091d23ed1
commit fe7d0d371b

@ -838,7 +838,7 @@ export default class Component {
}
if (value) {
return `$$invalidate('${name}', ${value})`;
return x`$$invalidate('${name}', ${value})`;
}
// if this is a reactive declaration, invalidate dependencies recursively

@ -1,4 +1,4 @@
import { b, x } from 'code-red';
import { b, x, p } from 'code-red';
import { stringify, escape } from '../utils/stringify';
import Component from '../Component';
import Renderer from './Renderer';
@ -8,7 +8,7 @@ import add_to_set from '../utils/add_to_set';
import { extract_names } from '../utils/scope';
import { invalidate } from '../utils/invalidate';
import Block from './Block';
import { ClassDeclaration, FunctionExpression } from 'estree';
import { ClassDeclaration, FunctionExpression, Node } from 'estree';
export default function dom(
component: Component,
@ -82,12 +82,12 @@ export default function dom(
const set = (uses_props || writable_props.length > 0 || component.slots.size > 0)
? x`
${$$props} => {
${uses_props && component.invalidate('$$props', b`$$props = @assign(@assign({}, $$props), $$new_props)`)}
${uses_props && component.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), $$new_props)`)}
${writable_props.map(prop =>
b`if ('${prop.export_name}' in ${$$props}) ${component.invalidate(prop.name, `${prop.name} = ${$$props}.${prop.export_name}`)};`
)}
${component.slots.size > 0 &&
b`if ('$$scope' in ${$$props}) ${component.invalidate('$$scope', `$$scope = ${$$props}.$$scope`)};`}
b`if ('$$scope' in ${$$props}) ${component.invalidate('$$scope', x`$$scope = ${$$props}.$$scope`)};`}
}
`
: null;
@ -261,9 +261,9 @@ export default function dom(
const filtered_declarations = component.vars
.filter(v => ((v.referenced || v.export_name) && !v.hoistable))
.map(v => v.name);
.map(v => p`${v.name}`);
if (uses_props) filtered_declarations.push(`$$props: $$props = ${component.helper('exclude_internal_props')}($$props)`);
if (uses_props) filtered_declarations.push(p`$$props: $$props = ${component.helper('exclude_internal_props')}($$props)`);
const filtered_props = props.filter(prop => {
const variable = component.var_lookup.get(prop.name);
@ -276,11 +276,11 @@ export default function dom(
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
if (component.slots.size > 0) {
filtered_declarations.push('$$slots', '$$scope');
filtered_declarations.push(p`$$slots`, p`$$scope`);
}
if (renderer.binding_groups.length > 0) {
filtered_declarations.push(`$$binding_groups`);
filtered_declarations.push(p`$$binding_groups`);
}
const has_definition = (
@ -319,31 +319,30 @@ export default function dom(
.map(({ name }) => `$$self.$$.on_destroy.push(() => $$unsubscribe_${name.slice(1)}());`);
if (has_definition) {
const reactive_declarations = [];
const reactive_declarations: (Node | Node[]) = [];
const fixed_reactive_declarations = []; // not really 'reactive' but whatever
component.reactive_declarations
.forEach(_d => {
// const dependencies = Array.from(d.dependencies);
// const uses_props = !!dependencies.find(n => n === '$$props');
// const condition = !uses_props && dependencies
// .filter(n => {
// const variable = component.var_lookup.get(n);
// return variable && (variable.writable || variable.mutated);
// })
// .map(n => `$$dirty.${n}`).join(' || ');
throw new Error(`bad`);
// let snippet = `[✂${d.node.body.start}-${d.node.end}✂]`;
// if (condition) snippet = `if (${condition}) { ${snippet} }`;
// if (condition || uses_props) {
// reactive_declarations.push(snippet);
// } else {
// fixed_reactive_declarations.push(snippet);
// }
});
component.reactive_declarations.forEach(d => {
const dependencies = Array.from(d.dependencies);
const uses_props = !!dependencies.find(n => n === '$$props');
const condition = !uses_props && dependencies
.filter(n => {
const variable = component.var_lookup.get(n);
return variable && (variable.writable || variable.mutated);
})
.map(n => x`$$dirty.${n}`)
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
let statement = d.node;
if (condition) statement = b`if (${condition}) { ${statement} }`[0];
if (condition || uses_props) {
reactive_declarations.push(statement);
} else {
fixed_reactive_declarations.push(statement);
}
});
const injected = Array.from(component.injected_reactive_declaration_vars).filter(name => {
const variable = component.var_lookup.get(name);
@ -365,7 +364,7 @@ export default function dom(
let unknown_props_check;
if (component.compile_options.dev && !component.var_lookup.has('$$props') && writable_props.length) {
unknown_props_check = b`
const writable_props = [${writable_props.map(prop => `'${prop.export_name}'`).join(', ')}];
const writable_props = [${writable_props.map(prop => `'${prop.export_name}'`)}];
@_Object.keys($$props).forEach(key => {
if (!writable_props.includes(key) && !key.startsWith('$$')) @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
});
@ -374,13 +373,17 @@ export default function dom(
const return_value = {
type: 'ObjectExpression',
properties: filtered_declarations.map(name => {
const id = { type: 'Identifier', name };
properties: filtered_declarations
};
const reactive_dependencies = {
type: 'ObjectPattern',
properties: Array.from(all_reactive_dependencies).map(name => {
return {
type: 'Property',
key: id,
value: id,
kind: 'init'
kind: 'init',
key: { type: 'Identifier', name },
value: { type: 'Literal', value: 1 }
};
})
};
@ -412,7 +415,7 @@ export default function dom(
${injected.length && `let ${injected.join(', ')};`}
${reactive_declarations.length > 0 && b`
$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
$$self.$$.update = ($$dirty = ${reactive_dependencies}) => {
${reactive_declarations}
};
`}

@ -7,6 +7,7 @@ import { b, x } from 'code-red';
import Expression from '../../../nodes/shared/Expression';
import Text from '../../../nodes/Text';
import { changed } from '../shared/changed';
import { Literal } from 'estree';
export default class AttributeWrapper {
node: Attribute;
@ -173,7 +174,7 @@ export default class AttributeWrapper {
? b`@set_input_type(${element.var}, ${value});`
: property_name
? b`${element.var}.${property_name} = ${value};`
: b`${method}(${element.var}, "${name}", ${value});`
: b`${method}(${element.var}, "${name}", ${value.type === 'Literal' && (value as Literal).value === true ? x`""` : value});`
);
block.chunks.hydrate.push(statement);

@ -341,8 +341,8 @@ export default class IfBlockWrapper extends Wrapper {
const if_blocks = block.get_unique_name(`if_blocks`);
const if_current_block_type_index = has_else
? ''
: `if (~${current_block_type_index}) `;
? nodes => nodes
: nodes => b`if (~${current_block_type_index}) { ${nodes} }`;
block.add_variable(current_block_type_index);
block.add_variable(name);
@ -350,7 +350,7 @@ export default class IfBlockWrapper extends Wrapper {
/* eslint-disable @typescript-eslint/indent,indent */
block.chunks.init.push(b`
const ${if_block_creators} = [
${this.branches.map(branch => branch.block.name).join(',\n')}
${this.branches.map(branch => branch.block.name)}
];
const ${if_blocks} = [];
@ -393,9 +393,10 @@ export default class IfBlockWrapper extends Wrapper {
const initial_mount_node = parent_node || '#target';
const anchor_node = parent_node ? 'null' : 'anchor';
throw new Error(`womp womp`);
block.chunks.mount.push(
b`${if_current_block_type_index}${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`
if_current_block_type_index(
b`${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`
)
);
if (this.needs_update) {
@ -442,7 +443,7 @@ export default class IfBlockWrapper extends Wrapper {
let ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(#changed, #ctx);
if (${current_block_type_index} === ${previous_block_index}) {
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(#changed, #ctx);
${if_current_block_type_index(b`${if_blocks}[${current_block_type_index}].p(#changed, #ctx);`)}
} else {
${change_block}
}
@ -460,9 +461,9 @@ export default class IfBlockWrapper extends Wrapper {
block.chunks.update.push(b`${name}.p(#changed, #ctx);`);
}
block.chunks.destroy.push(b`
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].d(${detaching});
`);
block.chunks.destroy.push(
if_current_block_type_index(b`${if_blocks}[${current_block_type_index}].d(${detaching});`)
);
}
render_simple(

@ -3,7 +3,7 @@ import Renderer from '../../Renderer';
import Block from '../../Block';
import InlineComponent from '../../../nodes/InlineComponent';
import FragmentWrapper from '../Fragment';
import { quote_name_if_necessary, quote_prop_if_necessary, sanitize } from '../../../../utils/names';
import { quote_name_if_necessary, sanitize } from '../../../../utils/names';
import add_to_set from '../../../utils/add_to_set';
import { b, x } from 'code-red';
import Attribute from '../../../nodes/Attribute';
@ -15,7 +15,7 @@ import TemplateScope from '../../../nodes/shared/TemplateScope';
import is_dynamic from '../shared/is_dynamic';
import bind_this from '../shared/bind_this';
import { changed } from '../shared/changed';
import { Node, Identifier } from 'estree';
import { Node, Identifier, Expression } from 'estree';
export default class InlineComponentWrapper extends Wrapper {
var: Identifier;
@ -124,7 +124,7 @@ export default class InlineComponentWrapper extends Wrapper {
const uses_spread = !!this.node.attributes.find(a => a.is_spread);
let attribute_object;
let attribute_object = x`{}`;
if (this.node.attributes.length > 0 || this.node.bindings.length > 0 || this.slots.size > 0) {
if (!uses_spread && this.node.bindings.length === 0) {
@ -165,7 +165,7 @@ export default class InlineComponentWrapper extends Wrapper {
value: attr.get_value(block)
}
}).concat(initial_props.properties)
};
} as Expression;
}
component_opts.properties.push({
@ -175,13 +175,13 @@ export default class InlineComponentWrapper extends Wrapper {
value: attribute_object
});
} else {
props = block.get_unique_name(`${name.name}_props`);
component_opts.properties.push({
type: 'Property',
kind: 'init',
key: { type: 'Identifier', name: 'props' },
value: props
});
props = block.get_unique_name(`${name}_props`);
}
}
@ -241,7 +241,7 @@ export default class InlineComponentWrapper extends Wrapper {
const { name, dependencies } = attr;
const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
? `(${Array.from(dependencies).map(d => `changed.${d}`).join(' || ')})`
? changed(Array.from(dependencies))
: null;
if (attr.is_spread) {
@ -254,16 +254,16 @@ export default class InlineComponentWrapper extends Wrapper {
}
changes.push(condition ? `${condition} && ${value_object}` : value_object);
} else {
const obj = `{ ${quote_name_if_necessary(name)}: ${attr.get_value(block)} }`;
const obj = x`{ ${quote_name_if_necessary(name)}: ${attr.get_value(block)} }`;
initial_props.push(obj);
changes.push(condition ? `${condition} && ${obj}` : `${levels}[${i}]`);
changes.push(condition ? x`${condition} && ${obj}` : x`${levels}[${i}]`);
}
});
block.chunks.init.push(b`
const ${levels} = [
${initial_props.join(',\n')}
${initial_props}
];
`);
@ -278,7 +278,7 @@ export default class InlineComponentWrapper extends Wrapper {
updates.push(b`
const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
${changes.join(',\n')}
${changes}
]) : {}
`);
} else {
@ -293,7 +293,7 @@ export default class InlineComponentWrapper extends Wrapper {
const condition = changed(dependencies);
updates.push(b`
if (${condition}) ${name_changes}${quote_prop_if_necessary(attribute.name)} = ${attribute.get_value(block)};
if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
`);
}
});
@ -301,7 +301,10 @@ export default class InlineComponentWrapper extends Wrapper {
}
if (non_let_dependencies.length > 0) {
updates.push(b`if (${changed(non_let_dependencies)} ${name_changes}.$$scope = { changed: #changed, ctx: #ctx };`);
updates.push(b`
if (${changed(non_let_dependencies)}) {
${name_changes}.$$scope = { changed: #changed, ctx: #ctx };
}`);
}
const munged_bindings = this.node.bindings.map(binding => {
@ -311,7 +314,7 @@ export default class InlineComponentWrapper extends Wrapper {
return bind_this(component, block, binding, this.var);
}
const id = component.get_unique_name(`${this.var}_${binding.name}_binding`);
const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
component.add_var({
name: id.name,
@ -326,13 +329,13 @@ export default class InlineComponentWrapper extends Wrapper {
statements.push(b`
if (${snippet} !== void 0) {
${props}${quote_prop_if_necessary(binding.name)} = ${snippet};
${props}.${binding.name} = ${snippet};
}`
);
updates.push(b`
if (!${updating} && ${[...binding.expression.dependencies].map((dependency: string) => `changed.${dependency}`).join(' || ')}) {
${name_changes}${quote_prop_if_necessary(binding.name)} = ${snippet};
if (!${updating} && ${changed(Array.from(binding.expression.dependencies))}) {
${name_changes}.${binding.name} = ${snippet};
}
`);
@ -353,11 +356,22 @@ export default class InlineComponentWrapper extends Wrapper {
const value = block.get_unique_name('value');
const args: any[] = [value];
if (contextual_dependencies.length > 0) {
args.push(x`{ ${contextual_dependencies.join(', ')} }`);
args.push({
type: 'ObjectPattern',
properties: contextual_dependencies.map(name => {
const id = { type: 'Identifier', name };
return {
type: 'Property',
kind: 'init',
key: id,
value: id
};
})
});
block.chunks.init.push(b`
function ${name}(${value}) {
#ctx.${name}.call(null, ${value}, #ctx);
function ${id}(${value}) {
#ctx.${id}.call(null, ${value}, #ctx);
${updating} = true;
@add_flush_callback(() => ${updating} = false);
}
@ -367,7 +381,7 @@ export default class InlineComponentWrapper extends Wrapper {
} else {
block.chunks.init.push(b`
function ${id}(${value}) {
#ctx.${name}.call(null, ${value});
#ctx.${id}.call(null, ${value});
${updating} = true;
@add_flush_callback(() => ${updating} = false);
}
@ -375,7 +389,7 @@ export default class InlineComponentWrapper extends Wrapper {
}
const body = b`
function ${id}(${args.join(', ')}) {
function ${id}(${args}) {
${lhs} = ${value};
${component.invalidate(dependencies[0])};
}
@ -383,7 +397,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.partly_hoisted.push(body);
return `@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
});
const munged_handlers = this.node.handlers.map(handler => {

@ -44,7 +44,7 @@ export default function bind_this(component: Component, block: Block, binding: B
if (contextual_dependencies.length) {
component.partly_hoisted.push(b`
function ${fn}(${['$$value', ...contextual_dependencies].join(', ')}) {
function ${fn}(${['$$value', ...contextual_dependencies]}) {
if (${lhs} === $$value) return;
@binding_callbacks[$$value ? 'unshift' : 'push'](() => {
${body}
@ -59,12 +59,12 @@ export default function bind_this(component: Component, block: Block, binding: B
block.add_variable(id, x`#ctx.${id}`);
}
const assign = block.get_unique_name(`assign_${variable}`);
const unassign = block.get_unique_name(`unassign_${variable}`);
const assign = block.get_unique_name(`assign_${variable.name}`);
const unassign = block.get_unique_name(`unassign_${variable.name}`);
block.chunks.init.push(b`
const ${assign} = () => #ctx.${fn}(${[variable].concat(args).join(', ')});
const ${unassign} = () => #ctx.${fn}(${['null'].concat(args).join(', ')});
const ${assign} = () => #ctx.${fn}(${[variable].concat(args)});
const ${unassign} = () => #ctx.${fn}(${['null'].concat(args)});
`);
const condition = Array.from(contextual_dependencies).map(name => `${name} !== #ctx.${name}`).join(' || ');
@ -75,7 +75,7 @@ export default function bind_this(component: Component, block: Block, binding: B
block.chunks.update.push(b`
if (${condition}) {
${unassign}();
${args.map(a => `${a} = #ctx.${a}`).join(', ')};
${args.map(a => b`${a} = #ctx.${a}`)};
${assign}();
}`
);

@ -3,7 +3,7 @@ import { Node, Identifier } from 'estree';
export default function flatten_reference(node: Node) {
// TODO temporary (#3539)
if ((node as any).type === 'Expression') {
throw new Error('bad');
throw new Error('flatten_reference bad');
}
const nodes = [];

@ -1,4 +1,4 @@
export function snip(expression) {
throw new Error(`bad`);
throw new Error(`snip bad`);
return `[✂${expression.node.start}-${expression.node.end}✂]`;
}
Loading…
Cancel
Save