Skip to content

Commit 50cc07e

Browse files
committed
Fix bind:this not working in onMount
If a component was instantiated with new Component(), its onMount callback was being called before the bind:this bindings were set up, so that the binding variable was undefined. Now the bind:this bindings are properly bound before the onMount callbacks are called.
1 parent 78e0256 commit 50cc07e

File tree

5 files changed

+77
-8
lines changed

5 files changed

+77
-8
lines changed

src/runtime/internal/scheduler.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { run_all } from './utils';
1+
import { run_all, Queue } from './utils';
22
import { set_current_component } from './lifecycle';
33

4-
export const dirty_components = [];
4+
export const dirty_components = new Queue<any>();
55
export const intros = { enabled: false };
66

77
export const binding_callbacks = [];
@@ -31,17 +31,14 @@ export function add_flush_callback(fn) {
3131
flush_callbacks.push(fn);
3232
}
3333

34-
let flushing = false;
3534
const seen_callbacks = new Set();
3635
export function flush() {
37-
if (flushing) return;
38-
flushing = true;
3936

4037
do {
4138
// first, call beforeUpdate functions
4239
// and update components
43-
for (let i = 0; i < dirty_components.length; i += 1) {
44-
const component = dirty_components[i];
40+
while (dirty_components.length) {
41+
const component = dirty_components.shift();
4542
set_current_component(component);
4643
update(component.$$);
4744
}
@@ -73,7 +70,6 @@ export function flush() {
7370
}
7471

7572
update_scheduled = false;
76-
flushing = false;
7773
seen_callbacks.clear();
7874
}
7975

src/runtime/internal/utils.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,40 @@ export function is_empty(obj) {
5858
return Object.keys(obj).length === 0;
5959
}
6060

61+
export class Queue<T> {
62+
forward: T[];
63+
reverse: T[];
64+
65+
constructor() {
66+
this.forward = [];
67+
this.reverse = [];
68+
}
69+
push(value: T) {
70+
return this.forward.push(value);
71+
}
72+
shift() {
73+
if (this.reverse.length === 0) {
74+
while (this.forward.length) {
75+
this.reverse.push(this.forward.pop());
76+
}
77+
}
78+
return this.reverse.pop();
79+
}
80+
get length() {
81+
return this.forward.length + this.reverse.length;
82+
}
83+
set length(len: number) {
84+
if (len === 0) {
85+
this.forward.length = 0;
86+
this.reverse.length = 0;
87+
} else {
88+
while (this.length > len) {
89+
this.shift();
90+
}
91+
}
92+
}
93+
}
94+
6195
export function validate_store(store, name) {
6296
if (store != null && typeof store.subscribe !== 'function') {
6397
throw new Error(`'${name}' is not a store with a 'subscribe' method`);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
import { onMount } from 'svelte';
3+
4+
let element;
5+
let bound = false;
6+
onMount(() => {
7+
if (element) bound = true;
8+
});
9+
10+
</script>
11+
12+
<div bind:this={element}></div>
13+
<p>
14+
Bound? {bound}
15+
</p>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default {
2+
async test({ assert, target }) {
3+
assert.htmlEqual(target.innerHTML, `
4+
<div id="target"><div></div>
5+
<p>
6+
Bound? true
7+
</p>
8+
</div>
9+
`);
10+
}
11+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import Mount from './Mount.svelte';
3+
import { onMount } from 'svelte';
4+
5+
onMount(() => {
6+
const component = new Mount({
7+
target: document.querySelector('#target'),
8+
props: {},
9+
});
10+
});
11+
</script>
12+
13+
<div id="target" />

0 commit comments

Comments
 (0)