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

@ -238,9 +238,11 @@ export default class Expression {
let contextual_dependencies: Set<string>; let contextual_dependencies: Set<string>;
const node = walk(this.node, { const node = walk(this.node, {
enter(node: any, parent: any, key: string) { enter(node: any, parent: any) {
// don't manipulate shorthand props twice if (node.type === 'Property' && node.shorthand) {
if (key === 'value' && parent.shorthand) return; node.value = JSON.parse(JSON.stringify(node.value));
node.shorthand = false;
}
if (map.has(node)) { if (map.has(node)) {
scope = map.get(node); scope = map.get(node);
@ -283,7 +285,7 @@ export default class Expression {
} }
}, },
leave(node: Node) { leave(node: Node, parent: Node) {
if (map.has(node)) scope = scope.parent; if (map.has(node)) scope = scope.parent;
if (node === function_expression) { if (node === function_expression) {
@ -366,6 +368,10 @@ export default class Expression {
function_expression = null; function_expression = null;
dependencies = null; dependencies = null;
contextual_dependencies = null; contextual_dependencies = null;
if (parent && parent.type === 'Property') {
parent.method = false;
}
} }
if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') { if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {

@ -7,6 +7,7 @@ import FragmentWrapper from './Fragment';
import { b, x } from 'code-red'; import { b, x } from 'code-red';
import ElseBlock from '../../nodes/ElseBlock'; import ElseBlock from '../../nodes/ElseBlock';
import { Identifier, Node } from 'estree'; import { Identifier, Node } from 'estree';
import { changed } from './shared/changed';
export class ElseBlockWrapper extends Wrapper { export class ElseBlockWrapper extends Wrapper {
node: ElseBlock; node: ElseBlock;
@ -268,7 +269,7 @@ export default class EachBlockWrapper extends Wrapper {
if (this.else.block.has_update_method) { if (this.else.block.has_update_method) {
block.chunks.update.push(b` block.chunks.update.push(b`
if (!${this.vars.data_length} && ${each_block_else}) { if (!${this.vars.data_length} && ${each_block_else}) {
${each_block_else}.p(changed, #ctx); ${each_block_else}.p(#changed, #ctx);
} else if (!${this.vars.data_length}) { } else if (!${this.vars.data_length}) {
${each_block_else} = ${this.else.block.name}(#ctx); ${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c(); ${each_block_else}.c();
@ -473,23 +474,13 @@ export default class EachBlockWrapper extends Wrapper {
all_dependencies.add(dependency); all_dependencies.add(dependency);
}); });
let condition; if (all_dependencies.size) {
if (all_dependencies.size > 0) {
// TODO make this more elegant somehow?
const array = Array.from(all_dependencies);
let condition = x`#changed.${array[0]}`;
for (let i = 1; i < array.length; i += 1) {
condition = x`${condition} || #changed.${array[i]}`;
}
}
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method); const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
if (condition) {
const for_loop_body = this.block.has_update_method const for_loop_body = this.block.has_update_method
? b` ? b`
if (${iterations}[#i]) { if (${iterations}[#i]) {
${iterations}[#i].p(changed, child_ctx); ${iterations}[#i].p(#changed, child_ctx);
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`} ${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
} else { } else {
${iterations}[#i] = ${create_each_block}(child_ctx); ${iterations}[#i] = ${create_each_block}(child_ctx);
@ -541,7 +532,7 @@ export default class EachBlockWrapper extends Wrapper {
for (${this.block.has_update_method ? `` : `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) { for (${this.block.has_update_method ? `` : `#i = ${data_length}`}; #i < ${this.block.has_update_method ? view_length : '#old_length'}; #i += 1) {
${iterations}[#i].d(1); ${iterations}[#i].d(1);
} }
${!fixed_length && `${view_length} = ${data_length};`} ${!fixed_length && b`${view_length} = ${data_length};`}
`; `;
} }
@ -562,7 +553,7 @@ export default class EachBlockWrapper extends Wrapper {
`; `;
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition}) { if (${changed(Array.from(all_dependencies))}) {
${update} ${update}
} }
`); `);

@ -809,8 +809,7 @@ export default class ElementWrapper extends Wrapper {
if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) { if ((dependencies && dependencies.size > 0) || this.class_dependencies.length) {
const all_dependencies = this.class_dependencies.concat(...dependencies); const all_dependencies = this.class_dependencies.concat(...dependencies);
const deps = all_dependencies.map(dependency => `changed${quote_prop_if_necessary(dependency)}`).join(' || '); const condition = changed(all_dependencies);
const condition = all_dependencies.length > 1 ? `(${deps})` : deps;
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition}) { if (${condition}) {

@ -10,6 +10,7 @@ import { b, x } from 'code-red';
import { walk } from 'estree-walker'; import { walk } from 'estree-walker';
import { is_head } from './shared/is_head'; import { is_head } from './shared/is_head';
import { Identifier, Node } from 'estree'; import { Identifier, Node } from 'estree';
import { changed } from './shared/changed';
function is_else_if(node: ElseBlock) { function is_else_if(node: ElseBlock) {
return ( return (
@ -260,7 +261,7 @@ export default class IfBlockWrapper extends Wrapper {
? b` ? b`
${snippet && ( ${snippet && (
dependencies.length > 0 dependencies.length > 0
? b`if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})` ? b`if ((${condition} == null) || ${changed(dependencies)}) ${condition} = !!(${snippet})`
: b`if (${condition} == null) ${condition} = !!(${snippet})` : b`if (${condition} == null) ${condition} = !!(${snippet})`
)} )}
if (${condition}) return ${block.name};` if (${condition}) return ${block.name};`
@ -360,7 +361,7 @@ export default class IfBlockWrapper extends Wrapper {
function ${select_block_type}(#changed, #ctx) { function ${select_block_type}(#changed, #ctx) {
${this.branches.map(({ dependencies, condition, snippet }, i) => condition ${this.branches.map(({ dependencies, condition, snippet }, i) => condition
? b` ? b`
${snippet && b`if ((${condition} == null) || ${dependencies.map(n => `changed.${n}`).join(' || ')}) ${condition} = !!(${snippet})`} ${snippet && b`if ((${condition} == null) || ${changed(dependencies)}) ${condition} = !!(${snippet})`}
if (${condition}) return ${String(i)};` if (${condition}) return ${String(i)};`
: b`return ${i};`)} : b`return ${i};`)}
${!has_else && b`return -1;`} ${!has_else && b`return -1;`}
@ -516,7 +517,7 @@ export default class IfBlockWrapper extends Wrapper {
`; `;
if (branch.snippet) { if (branch.snippet) {
block.chunks.update.push(b`if (${branch.dependencies.map(n => `changed.${n}`).join(' || ')}) ${branch.condition} = ${branch.snippet}`); block.chunks.update.push(b`if (${changed(branch.dependencies)}) ${branch.condition} = ${branch.snippet}`);
} }
// no `p()` here — we don't want to update outroing nodes, // no `p()` here — we don't want to update outroing nodes,

@ -252,7 +252,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (attr.expression.node.type !== 'ObjectExpression') { if (attr.expression.node.type !== 'ObjectExpression') {
value_object = x`@get_spread_object(${value})`; value_object = x`@get_spread_object(${value})`;
} }
changes.push(condition ? `${condition} && ${value_object}` : value_object); changes.push(condition ? x`${condition} && ${value_object}` : value_object);
} else { } else {
const obj = x`{ ${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); initial_props.push(obj);
@ -404,7 +404,7 @@ export default class InlineComponentWrapper extends Wrapper {
let snippet = handler.render(block); let snippet = handler.render(block);
if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`; if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`;
return `${name}.$on("${handler.name}", ${snippet});`; return b`${name}.$on("${handler.name}", ${snippet});`;
}); });
if (this.node.name === 'svelte:component') { if (this.node.name === 'svelte:component') {
@ -418,7 +418,7 @@ export default class InlineComponentWrapper extends Wrapper {
function ${switch_props}(#ctx) { function ${switch_props}(#ctx) {
${(this.node.attributes.length || this.node.bindings.length) && b` ${(this.node.attributes.length || this.node.bindings.length) && b`
${props && `let ${props} = ${attribute_object};`}`} ${props && b`let ${props} = ${attribute_object};`}`}
${statements} ${statements}
return ${component_opts}; return ${component_opts};
} }
@ -479,6 +479,8 @@ export default class InlineComponentWrapper extends Wrapper {
} else { } else {
${name} = null; ${name} = null;
} }
} else if (${switch_value}) {
${updates.length && b`${name}.$set(${name_changes});`}
} }
`); `);
@ -486,14 +488,6 @@ export default class InlineComponentWrapper extends Wrapper {
if (${name}) @transition_in(${name}.$$.fragment, #local); if (${name}) @transition_in(${name}.$$.fragment, #local);
`); `);
if (updates.length) {
block.chunks.update.push(b`
else if (${switch_value}) {
${name}.$set(${name_changes});
}
`);
}
block.chunks.outro.push( block.chunks.outro.push(
b`if (${name}) @transition_out(${name}.$$.fragment, #local);` b`if (${name}) @transition_out(${name}.$$.fragment, #local);`
); );
@ -501,7 +495,7 @@ export default class InlineComponentWrapper extends Wrapper {
block.chunks.destroy.push(b`if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`); block.chunks.destroy.push(b`if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`);
} else { } else {
const expression = this.node.name === 'svelte:self' const expression = this.node.name === 'svelte:self'
? '__svelte:self__' // TODO conflict-proof this ? component.name
: component.qualify(this.node.name); : component.qualify(this.node.name);
block.chunks.init.push(b` block.chunks.init.push(b`

@ -11,6 +11,7 @@ import { stringify_props } from '../../utils/stringify_props';
import Expression from '../../nodes/shared/Expression'; import Expression from '../../nodes/shared/Expression';
import is_dynamic from './shared/is_dynamic'; import is_dynamic from './shared/is_dynamic';
import { Identifier } from 'estree'; import { Identifier } from 'estree';
import { changed } from './shared/changed';
export default class SlotWrapper extends Wrapper { export default class SlotWrapper extends Wrapper {
node: Slot; node: Slot;
@ -163,11 +164,8 @@ export default class SlotWrapper extends Wrapper {
return is_dynamic(variable); return is_dynamic(variable);
}); });
let update_conditions = dynamic_dependencies.map(name => `changed.${name}`).join(' || ');
if (dynamic_dependencies.length > 1) update_conditions = `(${update_conditions})`;
block.chunks.update.push(b` block.chunks.update.push(b`
if (${slot} && ${slot}.p && ${update_conditions}) { if (${slot} && ${slot}.p && ${changed(dynamic_dependencies)}) {
${slot}.p( ${slot}.p(
@get_slot_changes(${slot_definition}, #ctx, changed, ${get_slot_changes}), @get_slot_changes(${slot_definition}, #ctx, changed, ${get_slot_changes}),
@get_slot_context(${slot_definition}, #ctx, ${get_slot_context}) @get_slot_context(${slot_definition}, #ctx, ${get_slot_context})

@ -1,4 +1,4 @@
import { b } from 'code-red'; import { b, x } from 'code-red';
import Wrapper from './shared/Wrapper'; import Wrapper from './shared/Wrapper';
import Renderer from '../Renderer'; import Renderer from '../Renderer';
import Block from '../Block'; import Block from '../Block';
@ -7,6 +7,7 @@ import { stringify } from '../../utils/stringify';
import add_to_set from '../../utils/add_to_set'; import add_to_set from '../../utils/add_to_set';
import Text from '../../nodes/Text'; import Text from '../../nodes/Text';
import { Identifier } from 'estree'; import { Identifier } from 'estree';
import { changed } from './shared/changed';
export default class TitleWrapper extends Wrapper { export default class TitleWrapper extends Wrapper {
node: Title; node: Title;
@ -28,7 +29,7 @@ export default class TitleWrapper extends Wrapper {
if (is_dynamic) { if (is_dynamic) {
let value; let value;
const all_dependencies = new Set(); const all_dependencies: Set<string> = new Set();
// TODO some of this code is repeated in Tag.ts — would be good to // TODO some of this code is repeated in Tag.ts — would be good to
// DRY it out if that's possible without introducing crazy indirection // DRY it out if that's possible without introducing crazy indirection
@ -72,22 +73,26 @@ export default class TitleWrapper extends Wrapper {
block.chunks.init.push( block.chunks.init.push(
b`@_document.title = ${init};` b`@_document.title = ${init};`
); );
const updater = b`@_document.title = ${this.node.should_cache ? last : value};`; const updater = b`@_document.title = ${this.node.should_cache ? last : value};`;
if (all_dependencies.size) { if (all_dependencies.size) {
const dependencies = Array.from(all_dependencies); const dependencies = Array.from(all_dependencies);
const changed_check = (
(block.has_outros ? `!#current || ` : '') +
dependencies.map(dependency => `changed.${dependency}`).join(' || ')
);
const update_cached_value = `${last} !== (${last} = ${value})`; let condition = changed(dependencies);
const condition = this.node.should_cache ? if (block.has_outros) {
(dependencies.length ? `(${changed_check}) && ${update_cached_value}` : update_cached_value) : condition = x`!#current || ${condition}`;
changed_check; }
if (this.node.should_cache) {
condition = x`${condition} && (${last} !== (${last} = ${value}))`;
}
block.chunks.update.push(b`if (${condition}) ${updater}`); block.chunks.update.push(b`
if (${condition}) {
${updater}
}`);
} }
} else { } else {
const value = this.node.children.length > 0 const value = this.node.children.length > 0

@ -6,6 +6,8 @@ require('./setup');
require('./helpers'); require('./helpers');
require('../internal'); require('../internal');
console.clear();
glob('*/index.js', { cwd: 'test' }).forEach((file) => { glob('*/index.js', { cwd: 'test' }).forEach((file) => {
require('./' + file); require('./' + file);
}); });

Loading…
Cancel
Save