Skip to content

Commit b498829

Browse files
authored
Merge pull request #3150 from sveltejs/gh-2281
Change onMount/afterUpdate order
2 parents 05bc930 + 8d805a0 commit b498829

File tree

9 files changed

+113
-21
lines changed

9 files changed

+113
-21
lines changed

src/runtime/internal/Component.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ interface T$$ {
1111
bound: any;
1212
update: () => void;
1313
callbacks: any;
14-
after_render: any[];
14+
after_update: any[];
1515
props: any;
1616
fragment: null|any;
1717
not_equal: any;
18-
before_render: any[];
18+
before_update: any[];
1919
context: Map<any, any>;
2020
on_mount: any[];
2121
on_destroy: any[];
@@ -28,13 +28,11 @@ export function bind(component, name, callback) {
2828
}
2929

3030
export function mount_component(component, target, anchor) {
31-
const { fragment, on_mount, on_destroy, after_render } = component.$$;
31+
const { fragment, on_mount, on_destroy, after_update } = component.$$;
3232

3333
fragment.m(target, anchor);
3434

35-
// onMount happens after the initial afterUpdate. Because
36-
// afterUpdate callbacks happen in reverse order (inner first)
37-
// we schedule onMount callbacks before afterUpdate callbacks
35+
// onMount happens before the initial afterUpdate
3836
add_render_callback(() => {
3937
const new_on_destroy = on_mount.map(run).filter(is_function);
4038
if (on_destroy) {
@@ -47,7 +45,7 @@ export function mount_component(component, target, anchor) {
4745
component.$$.on_mount = [];
4846
});
4947

50-
after_render.forEach(add_render_callback);
48+
after_update.forEach(add_render_callback);
5149
}
5250

5351
export function destroy_component(component, detaching) {
@@ -91,8 +89,8 @@ export function init(component, options, instance, create_fragment, not_equal, p
9189
// lifecycle
9290
on_mount: [],
9391
on_destroy: [],
94-
before_render: [],
95-
after_render: [],
92+
before_update: [],
93+
after_update: [],
9694
context: new Map(parent_component ? parent_component.$$.context : []),
9795

9896
// everything else
@@ -113,7 +111,7 @@ export function init(component, options, instance, create_fragment, not_equal, p
113111

114112
$$.update();
115113
ready = true;
116-
run_all($$.before_render);
114+
run_all($$.before_update);
117115
$$.fragment = create_fragment($$.ctx);
118116

119117
if (options.target) {

src/runtime/internal/lifecycle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ function get_current_component() {
1212
}
1313

1414
export function beforeUpdate(fn) {
15-
get_current_component().$$.before_render.push(fn);
15+
get_current_component().$$.before_update.push(fn);
1616
}
1717

1818
export function onMount(fn) {
1919
get_current_component().$$.on_mount.push(fn);
2020
}
2121

2222
export function afterUpdate(fn) {
23-
get_current_component().$$.after_render.push(fn);
23+
get_current_component().$$.after_update.push(fn);
2424
}
2525

2626
export function onDestroy(fn) {

src/runtime/internal/scheduler.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,18 @@ export function flush() {
4848
// then, once components are updated, call
4949
// afterUpdate functions. This may cause
5050
// subsequent updates...
51-
while (render_callbacks.length) {
52-
const callback = render_callbacks.pop();
51+
for (let i = 0; i < render_callbacks.length; i += 1) {
52+
const callback = render_callbacks[i];
53+
5354
if (!seen_callbacks.has(callback)) {
5455
callback();
5556

5657
// ...so guard against infinite loops
5758
seen_callbacks.add(callback);
5859
}
5960
}
61+
62+
render_callbacks.length = 0;
6063
} while (dirty_components.length);
6164

6265
while (flush_callbacks.length) {
@@ -69,10 +72,10 @@ export function flush() {
6972
function update($$) {
7073
if ($$.fragment) {
7174
$$.update($$.dirty);
72-
run_all($$.before_render);
75+
run_all($$.before_update);
7376
$$.fragment.p($$.dirty, $$.ctx);
7477
$$.dirty = null;
7578

76-
$$.after_render.forEach(add_render_callback);
79+
$$.after_update.forEach(add_render_callback);
7780
}
7881
}

src/runtime/internal/ssr.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export function create_ssr_component(fn) {
7878

7979
// these will be immediately discarded
8080
on_mount: [],
81-
before_render: [],
82-
after_render: [],
81+
before_update: [],
82+
after_update: [],
8383
callbacks: blank_object()
8484
};
8585

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script>
2+
import { onMount, beforeUpdate, afterUpdate } from 'svelte';
3+
import order from './order.js';
4+
5+
export let index;
6+
export let id;
7+
export let name;
8+
9+
function logRender () {
10+
order.push(`${index}: render`);
11+
return index;
12+
}
13+
14+
beforeUpdate(() => {
15+
order.push(`${index}: beforeUpdate`);
16+
});
17+
18+
afterUpdate(() => {
19+
order.push(`${index}: afterUpdate`);
20+
});
21+
22+
onMount(() => {
23+
order.push(`${index}: onMount`);
24+
});
25+
</script>
26+
27+
<li>
28+
{logRender()}
29+
</li>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import order from './order.js';
2+
3+
export default {
4+
skip_if_ssr: true,
5+
6+
test({ assert, component, target }) {
7+
assert.deepEqual(order, [
8+
'0: beforeUpdate',
9+
'0: render',
10+
'1: beforeUpdate',
11+
'1: render',
12+
'2: beforeUpdate',
13+
'2: render',
14+
'3: beforeUpdate',
15+
'3: render',
16+
'1: onMount',
17+
'1: afterUpdate',
18+
'2: onMount',
19+
'2: afterUpdate',
20+
'3: onMount',
21+
'3: afterUpdate',
22+
'0: onMount',
23+
'0: afterUpdate'
24+
]);
25+
26+
order.length = 0;
27+
}
28+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<script>
2+
import { onMount, beforeUpdate, afterUpdate } from 'svelte';
3+
import order from './order.js';
4+
import Item from './Item.svelte';
5+
6+
const parentIndex = 0;
7+
8+
function logRender () {
9+
order.push(`${parentIndex}: render`);
10+
return parentIndex;
11+
}
12+
13+
beforeUpdate(() => {
14+
order.push(`${parentIndex}: beforeUpdate`);
15+
});
16+
17+
afterUpdate(() => {
18+
order.push(`${parentIndex}: afterUpdate`);
19+
});
20+
21+
onMount(() => {
22+
order.push(`${parentIndex}: onMount`);
23+
})
24+
</script>
25+
26+
{logRender()}
27+
<ul>
28+
{#each [1,2,3] as index}
29+
<Item {index} />
30+
{/each}
31+
</ul>
32+
33+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default [];

test/runtime/samples/lifecycle-render-order/_config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import order from './order.js';
33
export default {
44
skip_if_ssr: true,
55

6-
test({ assert, component, target }) {
6+
test({ assert }) {
77
assert.deepEqual(order, [
88
'beforeUpdate',
99
'render',
10-
'afterUpdate',
11-
'onMount'
10+
'onMount',
11+
'afterUpdate'
1212
]);
1313

1414
order.length = 0;

0 commit comments

Comments
 (0)