diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index dbb054e7c650..ddf3f39cabe2 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -94,11 +94,10 @@ export default function dom ( parsed, source, options ) { const differs = generator.helper( 'differs' ); computations.forEach( ({ key, deps }) => { - builder.addBlock( deindent` - if ( isInitial || ${deps.map( dep => `( '${dep}' in newState && ${differs}( state.${dep}, oldState.${dep} ) )` ).join( ' || ' )} ) { - state.${key} = newState.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} ); - } - ` ); + const condition = `isInitial || ${deps.map( dep => `( '${dep}' in newState && ${differs}( state.${dep}, oldState.${dep} ) )` ).join( ' || ' )}`; + const statement = `state.${key} = newState.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} );`; + + builder.addConditionalLine( condition, statement ); }); builders.main.addBlock( deindent` diff --git a/src/utils/CodeBuilder.js b/src/utils/CodeBuilder.js index 1caaf9ff84b9..357bf85af861 100644 --- a/src/utils/CodeBuilder.js +++ b/src/utils/CodeBuilder.js @@ -7,9 +7,31 @@ export default class CodeBuilder { this.first = null; this.last = null; + + this.lastCondition = null; + } + + addConditionalLine ( condition, line ) { + if ( condition === this.lastCondition ) { + this.result += `\n\t${line}`; + } else { + if ( this.lastCondition ) { + this.result += `\n}`; + } + + this.result += `if ( ${condition} ) {\n\t${line}`; + this.lastCondition = condition; + } + + this.last = BLOCK; } addLine ( line ) { + if ( this.lastCondition ) { + this.result += `\n}`; + this.lastCondition = null; + } + if ( this.last === BLOCK ) { this.result += `\n\n${line}`; } else if ( this.last === LINE ) { @@ -36,6 +58,11 @@ export default class CodeBuilder { } addBlock ( block ) { + if ( this.lastCondition ) { + this.result += `\n}`; + this.lastCondition = null; + } + if ( this.result ) { this.result += `\n\n${block}`; } else { @@ -62,6 +89,6 @@ export default class CodeBuilder { } toString () { - return this.result.trim(); + return this.result.trim() + ( this.lastCondition ? `\n}` : `` ); } } diff --git a/test/js/samples/computed-collapsed-if/expected.js b/test/js/samples/computed-collapsed-if/expected.js new file mode 100644 index 000000000000..d8792a974f1b --- /dev/null +++ b/test/js/samples/computed-collapsed-if/expected.js @@ -0,0 +1,74 @@ +import { assign, differs, dispatchObservers, noop, proto } from "svelte/shared.js"; + +function recompute ( state, newState, oldState, isInitial ) { + if ( isInitial || ( 'x' in newState && differs( state.x, oldState.x ) ) ) { + state.a = newState.a = template.computed.a( state.x ); + state.b = newState.b = template.computed.b( state.x ); + } +} + +var template = (function () { + return { + computed: { + a: x => x * 2, + b: x => x * 3 + } + }; +}()); + +function create_main_fragment ( root, component ) { + + + return { + mount: noop, + + update: noop, + + destroy: noop + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + recompute( this._state, this._state, {}, true ); + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + recompute( this._state, newState, oldState, false ) + + dispatchObservers( this, this._observers.pre, newState, oldState ); + if ( this._fragment ) this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; \ No newline at end of file diff --git a/test/js/samples/computed-collapsed-if/input.html b/test/js/samples/computed-collapsed-if/input.html new file mode 100644 index 000000000000..a68513b860fe --- /dev/null +++ b/test/js/samples/computed-collapsed-if/input.html @@ -0,0 +1,8 @@ + \ No newline at end of file