Skip to content

Commit

Permalink
always flush render hooks, even if initiator is a nested component (#263
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Rich-Harris committed Jan 31, 2017
1 parent 62ad181 commit 3235b2c
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 18 deletions.
33 changes: 17 additions & 16 deletions src/generators/dom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ export default function dom ( parsed, source, options, names ) {
const builders = {
main: new CodeBuilder(),
init: new CodeBuilder(),
set: new CodeBuilder()
_set: new CodeBuilder()
};

builders.set.addLine( 'var oldState = this._state;' );
builders.set.addLine( 'this._state = Object.assign( {}, oldState, newState );' );
builders._set.addLine( 'var oldState = this._state;' );
builders._set.addLine( 'this._state = Object.assign( {}, oldState, newState );' );

if ( computations.length ) {
const builder = new CodeBuilder();
Expand All @@ -197,11 +197,11 @@ export default function dom ( parsed, source, options, names ) {
}
` );

builders.set.addLine( `applyComputations( this._state, newState, oldState )` );
builders._set.addLine( `applyComputations( this._state, newState, oldState )` );
}

// TODO is the `if` necessary?
builders.set.addBlock( deindent`
builders._set.addBlock( deindent`
dispatchObservers( this, this._observers.pre, newState, oldState );
if ( this._fragment ) this._fragment.update( newState, this._state );
dispatchObservers( this, this._observers.post, newState, oldState );
Expand Down Expand Up @@ -246,7 +246,7 @@ export default function dom ( parsed, source, options, names ) {
while ( this._bindings.length ) this._bindings.pop()();
` );

builders.set.addLine( `while ( this._bindings.length ) this._bindings.pop()();` );
builders._set.addLine( `while ( this._bindings.length ) this._bindings.pop()();` );
} else {
builders.init.addBlock( deindent`
this._fragment = renderMainFragment( this._state, this );
Expand All @@ -255,15 +255,10 @@ export default function dom ( parsed, source, options, names ) {
}

if ( generator.hasComponents ) {
const statement = deindent`
while ( this._renderHooks.length ) {
var hook = this._renderHooks.pop();
hook.fn.call( hook.context );
}
`;
const statement = `this._flush();`;

builders.init.addBlock( statement );
builders.set.addBlock( statement );
builders._set.addBlock( statement );
}

if ( templateProperties.onrender ) {
Expand Down Expand Up @@ -310,6 +305,8 @@ export default function dom ( parsed, source, options, names ) {
${name}.prototype.fire = fire;
${name}.prototype.observe = observe;
${name}.prototype.on = on;
${name}.prototype.set = set;
${name}.prototype._flush = _flush;
` :
deindent`
${name}.prototype.get = ${shared.get};
Expand All @@ -319,11 +316,15 @@ export default function dom ( parsed, source, options, names ) {
${name}.prototype.observe = ${shared.observe};
${name}.prototype.on = ${shared.on};
${name}.prototype.set = ${shared.set};
${name}.prototype._flush = ${shared._flush};
` );

builders.main.addBlock( deindent`
${name}.prototype.set = function set ( newState ) {
${builders.set}
${name}.prototype._set = function _set ( newState ) {
${builders._set}
};
${name}.prototype.teardown = function teardown ( detach ) {
Expand All @@ -341,7 +342,7 @@ export default function dom ( parsed, source, options, names ) {
throw new Error( `Components with shared helpers must be compiled to ES2015 modules (format: 'es')` );
}

const names = [ 'get', 'fire', 'observe', 'on', 'dispatchObservers' ].concat( Object.keys( generator.uses ) );
const names = [ 'get', 'fire', 'observe', 'on', 'set', '_flush', 'dispatchObservers' ].concat( Object.keys( generator.uses ) );
builders.main.addLineAtStart(
`import { ${names.join( ', ' )} } from ${JSON.stringify( sharedPath )}`
);
Expand Down
4 changes: 2 additions & 2 deletions src/generators/dom/visitors/attributes/binding/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default function createBinding ( generator, node, attribute, current, loc
var index = this.__svelte.${indexName};
list[index]${parts.slice( 1 ).map( part => `.${part}` ).join( '' )} = ${value};
component.set({ ${prop}: component.get( '${prop}' ) });
component._set({ ${prop}: component.get( '${prop}' ) });
`;
} else if ( deep ) {
setter = deindent`
Expand Down Expand Up @@ -98,7 +98,7 @@ export default function createBinding ( generator, node, attribute, current, loc

local.update.addBlock( deindent`
if ( !${local.name}_updating && '${parts[0]}' in changed ) {
${local.name}.set({ ${attribute.name}: ${contextual ? attribute.value : `root.${attribute.value}`} });
${local.name}._set({ ${attribute.name}: ${contextual ? attribute.value : `root.${attribute.value}`} });
}
` );
} else {
Expand Down
14 changes: 14 additions & 0 deletions src/shared/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,17 @@ export function on ( eventName, handler ) {
}
};
}

export function set ( newState ) {
this._set( newState );
( this._root || this )._flush();
}

export function _flush () {
if ( !this._renderHooks ) return;

while ( this._renderHooks.length ) {
var hook = this._renderHooks.pop();
hook.fn.call( hook.context );
}
}
16 changes: 16 additions & 0 deletions test/generator/onrender-chain/Item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<span>{{foo}}</span>

<script>
export default {
data () {
return {
foo: 'XX'
};
},
onrender () {
this.observe( 'item', item => {
this.set({ foo: item });
});
}
};
</script>
25 changes: 25 additions & 0 deletions test/generator/onrender-chain/List.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{{#each items as item}}
<Item item={{item}} />
{{/each}}

<script>
import Item from './Item.html';

export default {
data () {
return {
items: [ 3, 2, 1 ]
};
},
methods: {
update () {
this.set({
items: [ 1, 2, 3, 4, 5 ]
});
}
},
components: {
Item
}
};
</script>
15 changes: 15 additions & 0 deletions test/generator/onrender-chain/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default {
html: `
<span>3</span><span>2</span><span>1</span>
`,

test ( assert, component, target ) {
component.refs.list.update();

assert.htmlEqual( target.innerHTML, `
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
` );

component.teardown();
}
};
11 changes: 11 additions & 0 deletions test/generator/onrender-chain/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<List ref:list/>

<script>
import List from './List.html';

export default {
components: {
List
}
};
</script>

0 comments on commit 3235b2c

Please sign in to comment.