Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always flush render hooks, even if initiator is a nested component #273

Merged
merged 1 commit into from
Jan 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>