Skip to content

Commit c1187d2

Browse files
authored
Merge pull request #273 from sveltejs/gh-263
always flush render hooks, even if initiator is a nested component
2 parents 62ad181 + 3235b2c commit c1187d2

File tree

7 files changed

+100
-18
lines changed

7 files changed

+100
-18
lines changed

src/generators/dom/index.js

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,11 @@ export default function dom ( parsed, source, options, names ) {
174174
const builders = {
175175
main: new CodeBuilder(),
176176
init: new CodeBuilder(),
177-
set: new CodeBuilder()
177+
_set: new CodeBuilder()
178178
};
179179

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

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

200-
builders.set.addLine( `applyComputations( this._state, newState, oldState )` );
200+
builders._set.addLine( `applyComputations( this._state, newState, oldState )` );
201201
}
202202

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

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

257257
if ( generator.hasComponents ) {
258-
const statement = deindent`
259-
while ( this._renderHooks.length ) {
260-
var hook = this._renderHooks.pop();
261-
hook.fn.call( hook.context );
262-
}
263-
`;
258+
const statement = `this._flush();`;
264259

265260
builders.init.addBlock( statement );
266-
builders.set.addBlock( statement );
261+
builders._set.addBlock( statement );
267262
}
268263

269264
if ( templateProperties.onrender ) {
@@ -310,6 +305,8 @@ export default function dom ( parsed, source, options, names ) {
310305
${name}.prototype.fire = fire;
311306
${name}.prototype.observe = observe;
312307
${name}.prototype.on = on;
308+
${name}.prototype.set = set;
309+
${name}.prototype._flush = _flush;
313310
` :
314311
deindent`
315312
${name}.prototype.get = ${shared.get};
@@ -319,11 +316,15 @@ export default function dom ( parsed, source, options, names ) {
319316
${name}.prototype.observe = ${shared.observe};
320317
321318
${name}.prototype.on = ${shared.on};
319+
320+
${name}.prototype.set = ${shared.set};
321+
322+
${name}.prototype._flush = ${shared._flush};
322323
` );
323324

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

344-
const names = [ 'get', 'fire', 'observe', 'on', 'dispatchObservers' ].concat( Object.keys( generator.uses ) );
345+
const names = [ 'get', 'fire', 'observe', 'on', 'set', '_flush', 'dispatchObservers' ].concat( Object.keys( generator.uses ) );
345346
builders.main.addLineAtStart(
346347
`import { ${names.join( ', ' )} } from ${JSON.stringify( sharedPath )}`
347348
);

src/generators/dom/visitors/attributes/binding/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export default function createBinding ( generator, node, attribute, current, loc
6464
var index = this.__svelte.${indexName};
6565
list[index]${parts.slice( 1 ).map( part => `.${part}` ).join( '' )} = ${value};
6666
67-
component.set({ ${prop}: component.get( '${prop}' ) });
67+
component._set({ ${prop}: component.get( '${prop}' ) });
6868
`;
6969
} else if ( deep ) {
7070
setter = deindent`
@@ -98,7 +98,7 @@ export default function createBinding ( generator, node, attribute, current, loc
9898

9999
local.update.addBlock( deindent`
100100
if ( !${local.name}_updating && '${parts[0]}' in changed ) {
101-
${local.name}.set({ ${attribute.name}: ${contextual ? attribute.value : `root.${attribute.value}`} });
101+
${local.name}._set({ ${attribute.name}: ${contextual ? attribute.value : `root.${attribute.value}`} });
102102
}
103103
` );
104104
} else {

src/shared/methods.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,17 @@ export function on ( eventName, handler ) {
4141
}
4242
};
4343
}
44+
45+
export function set ( newState ) {
46+
this._set( newState );
47+
( this._root || this )._flush();
48+
}
49+
50+
export function _flush () {
51+
if ( !this._renderHooks ) return;
52+
53+
while ( this._renderHooks.length ) {
54+
var hook = this._renderHooks.pop();
55+
hook.fn.call( hook.context );
56+
}
57+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<span>{{foo}}</span>
2+
3+
<script>
4+
export default {
5+
data () {
6+
return {
7+
foo: 'XX'
8+
};
9+
},
10+
onrender () {
11+
this.observe( 'item', item => {
12+
this.set({ foo: item });
13+
});
14+
}
15+
};
16+
</script>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{#each items as item}}
2+
<Item item={{item}} />
3+
{{/each}}
4+
5+
<script>
6+
import Item from './Item.html';
7+
8+
export default {
9+
data () {
10+
return {
11+
items: [ 3, 2, 1 ]
12+
};
13+
},
14+
methods: {
15+
update () {
16+
this.set({
17+
items: [ 1, 2, 3, 4, 5 ]
18+
});
19+
}
20+
},
21+
components: {
22+
Item
23+
}
24+
};
25+
</script>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default {
2+
html: `
3+
<span>3</span><span>2</span><span>1</span>
4+
`,
5+
6+
test ( assert, component, target ) {
7+
component.refs.list.update();
8+
9+
assert.htmlEqual( target.innerHTML, `
10+
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
11+
` );
12+
13+
component.teardown();
14+
}
15+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<List ref:list/>
2+
3+
<script>
4+
import List from './List.html';
5+
6+
export default {
7+
components: {
8+
List
9+
}
10+
};
11+
</script>

0 commit comments

Comments
 (0)