diff --git a/src/compile/Component.ts b/src/compile/Component.ts index 065500dbe1..5b403095fd 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -360,6 +360,11 @@ export default class Component { }); } + findDependenciesForFunctionCall(name) { + // TODO + return null; + } + walkJs() { const { js } = this.ast; if (!js) return; diff --git a/src/compile/nodes/shared/Expression.ts b/src/compile/nodes/shared/Expression.ts index afbf5e0547..13623e9369 100644 --- a/src/compile/nodes/shared/Expression.ts +++ b/src/compile/nodes/shared/Expression.ts @@ -4,6 +4,7 @@ import isReference from 'is-reference'; import flattenReference from '../../../utils/flattenReference'; import { createScopes } from '../../../utils/annotateWithScopes'; import { Node } from '../../../interfaces'; +import addToSet from '../../../utils/addToSet'; const binaryOperators: Record = { '**': 15, @@ -106,6 +107,19 @@ export default class Expression { expression.thisReferences.push(node); } + if (node.type === 'CallExpression') { + if (node.callee.type === 'Identifier') { + const dependencies_for_invocation = component.findDependenciesForFunctionCall(node.callee.name); + if (dependencies_for_invocation) { + addToSet(dependencies, dependencies_for_invocation); + } else { + dependencies.add('$$BAIL$$'); + } + } else { + dependencies.add('$$BAIL$$'); + } + } + if (isReference(node, parent)) { const { name, nodes } = flattenReference(node); diff --git a/src/compile/render-dom/wrappers/EachBlock.ts b/src/compile/render-dom/wrappers/EachBlock.ts index 2857b7cb62..19a824b0ed 100644 --- a/src/compile/render-dom/wrappers/EachBlock.ts +++ b/src/compile/render-dom/wrappers/EachBlock.ts @@ -427,6 +427,8 @@ export default class EachBlockWrapper extends Wrapper { } // TODO do this for keyed blocks as well + const bail = allDependencies.has('$$BAIL$$'); + const condition = Array.from(allDependencies) .map(dependency => `changed.${dependency}`) .join(' || '); @@ -476,7 +478,7 @@ export default class EachBlockWrapper extends Wrapper { `; } - block.builders.update.addBlock(deindent` + const update = deindent` if (${condition}) { ${this.vars.each_block_value} = ${snippet}; @@ -488,7 +490,17 @@ export default class EachBlockWrapper extends Wrapper { ${destroy} } - `); + `; + + if (bail) { + block.builders.update.addBlock(update); + } else { + block.builders.update.addBlock(deindent` + if (${condition}) { + ${update} + } + `); + } } if (outroBlock && this.renderer.component.options.nestedTransitions) { diff --git a/src/compile/render-dom/wrappers/Element/Attribute.ts b/src/compile/render-dom/wrappers/Element/Attribute.ts index 2d52b6dd7d..07e3f495da 100644 --- a/src/compile/render-dom/wrappers/Element/Attribute.ts +++ b/src/compile/render-dom/wrappers/Element/Attribute.ts @@ -99,7 +99,7 @@ export default class AttributeWrapper { const isSelectValueAttribute = name === 'value' && element.node.name === 'select'; - const shouldCache = this.node.shouldCache || isSelectValueAttribute; + const shouldCache = !this.node.dependencies.has('$$BAIL$$') && (this.node.shouldCache || isSelectValueAttribute); const last = shouldCache && block.getUniqueName( `${element.var}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value` diff --git a/src/compile/render-dom/wrappers/Element/StyleAttribute.ts b/src/compile/render-dom/wrappers/Element/StyleAttribute.ts index 89bdd41c82..f6c7eae01d 100644 --- a/src/compile/render-dom/wrappers/Element/StyleAttribute.ts +++ b/src/compile/render-dom/wrappers/Element/StyleAttribute.ts @@ -44,16 +44,22 @@ export default class StyleAttributeWrapper extends AttributeWrapper { .join(' + '); if (propDependencies.size) { - const dependencies = Array.from(propDependencies); - const condition = ( - (block.hasOutros ? `!#current || ` : '') + - dependencies.map(dependency => `changed.${dependency}`).join(' || ') - ); - - block.builders.update.addConditional( - condition, - `@setStyle(${this.parent.var}, "${prop.key}", ${value});` - ); + if (propDependencies.has('$$BAIL$$')) { + block.builders.update.addLine( + `@setStyle(${this.parent.var}, "${prop.key}", ${value});` + ); + } else { + const dependencies = Array.from(propDependencies); + const condition = ( + (block.hasOutros ? `!#current || ` : '') + + dependencies.map(dependency => `changed.${dependency}`).join(' || ') + ); + + block.builders.update.addConditional( + condition, + `@setStyle(${this.parent.var}, "${prop.key}", ${value});` + ); + } } } else { value = stringify(prop.value[0].data); diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index 7baf255a53..d0de4cc9e7 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -588,7 +588,7 @@ export default class ElementWrapper extends Wrapper { this.node.attributes .filter(attr => attr.type === 'Attribute' || attr.type === 'Spread') .forEach(attr => { - const condition = attr.dependencies.size > 0 + const condition = (attr.dependencies.size > 0 && !attr.dependencies.has('$$BAIL$$')) ? `(${[...attr.dependencies].map(d => `changed.${d}`).join(' || ')})` : null; diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index 04bdb66358..57875da004 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -134,6 +134,8 @@ export default class InlineComponentWrapper extends Wrapper { this.node.attributes.forEach(attr => { const { name, dependencies } = attr; + // TODO probably need to account for $$BAIL$$ but + // not totally sure how. will come back to it const condition = dependencies.size > 0 && (dependencies.size !== allDependencies.size) ? `(${[...dependencies].map(d => `changed.${d}`).join(' || ')})` : null; diff --git a/src/compile/render-dom/wrappers/shared/Tag.ts b/src/compile/render-dom/wrappers/shared/Tag.ts index 4829867849..12cc20905b 100644 --- a/src/compile/render-dom/wrappers/shared/Tag.ts +++ b/src/compile/render-dom/wrappers/shared/Tag.ts @@ -48,9 +48,13 @@ export default class Tag extends Wrapper { const updateCachedValue = `${value} !== (${value} = ${snippet})`; - const condition = this.node.shouldCache ? - (dependencies.size ? `(${changedCheck}) && ${updateCachedValue}` : updateCachedValue) : - changedCheck; + const condition = dependencies.has('$$BAIL$$') + ? updateCachedValue + : this.node.shouldCache + ? dependencies.size > 0 + ? `(${changedCheck}) && ${updateCachedValue}` + : updateCachedValue + : changedCheck; block.builders.update.addConditional( condition, diff --git a/src/utils/CodeBuilder.ts b/src/utils/CodeBuilder.ts index 5d0477ce68..05e26b232c 100644 --- a/src/utils/CodeBuilder.ts +++ b/src/utils/CodeBuilder.ts @@ -35,7 +35,8 @@ export default class CodeBuilder { addConditional(condition: string, body: string) { this.reifyConditions(); - body = body.replace(/^/gm, `${this.indent}\t`); + const indent = this.indent + (condition ? '\t' : ''); + body = body.replace(/^/gm, indent); if (condition === this.lastCondition) { this.result += `\n${body}`; @@ -44,7 +45,11 @@ export default class CodeBuilder { this.result += `\n${this.indent}}`; } - this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}if (${condition}) {\n${body}`; + const block = condition + ? `if (${condition}) {\n${body}` + : body; + + this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}${block}`; this.lastCondition = condition; } diff --git a/test/runtime/samples/computed-values/_config.js b/test/runtime/samples/computed-values/_config.js index 55bad498ce..000ffa6b13 100644 --- a/test/runtime/samples/computed-values/_config.js +++ b/test/runtime/samples/computed-values/_config.js @@ -1,10 +1,16 @@ export default { - html: '

1 + 2 = 3

\n

3 * 3 = 9

', + html: ` +

1 + 2 = 3

+

3 * 3 = 9

+ `, test(assert, component, target) { component.a = 3; - assert.equal(component.c, 5); - assert.equal(component.cSquared, 25); - assert.equal(target.innerHTML, '

3 + 2 = 5

\n

5 * 5 = 25

'); + assert.equal(component.c(), 5); + assert.equal(component.cSquared(), 25); + assert.htmlEqual(target.innerHTML, ` +

3 + 2 = 5

+

5 * 5 = 25

+ `); } }; diff --git a/test/runtime/samples/computed-values/main.html b/test/runtime/samples/computed-values/main.html index 1af546bc06..a847e254b1 100644 --- a/test/runtime/samples/computed-values/main.html +++ b/test/runtime/samples/computed-values/main.html @@ -2,13 +2,11 @@ export let a = 1; export let b = 2; - function c() { + export function c() { return a + b; } - function cSquared() { - return c() * c(); - } + export const cSquared = () => c() * c();

{a} + {b} = {c()}