handle nightmarish infinite loop situation

pull/1864/head
Rich Harris 7 years ago
parent 72f3fde2b8
commit e03f8d6590

@ -757,7 +757,7 @@ export default class ElementWrapper extends Wrapper {
block.builders.intro.addConditional(`@intro.enabled`, deindent`
if (${name}) ${name}.invalidate();
@after_update(() => {
@after_render(() => {
if (!${name}) ${name} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
${name}.run(1);
});
@ -792,7 +792,7 @@ export default class ElementWrapper extends Wrapper {
}
block.builders.intro.addConditional(`@intro.enabled`, deindent`
@after_update(() => {
@after_render(() => {
${introName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
${introName}.run(1);
});

@ -1,4 +1,4 @@
import { schedule_update, flush, intro } from './scheduler.js';
import { after_render, flush, intro, schedule_update } from './scheduler.js';
import { set_current_component } from './lifecycle.js'
import { is_function, run, run_all, noop } from './utils.js';
import { blankObject } from './utils.js';
@ -33,11 +33,13 @@ export class $$Component {
this.$$.inject_props(options.props);
}
run_all(this.$$beforeRender);
this.$$fragment = this.$$create_fragment(this, this.$$.get_state());
if (options.target) {
intro.enabled = !!options.intro;
this.$$mount(options.target);
flush();
intro.enabled = true;
}
@ -90,7 +92,6 @@ export class $$Component {
}
$$mount(target, anchor) {
run_all(this.$$beforeRender);
this.$$fragment.c();
this.$$fragment[this.$$fragment.i ? 'i' : 'm'](target, anchor);
this.$$.inject_refs(this.$$refs);
@ -99,15 +100,16 @@ export class $$Component {
this.$$onDestroy.push(...onDestroy);
this.$$onMount = [];
run_all(this.$$afterRender);
this.$$afterRender.forEach(after_render);
}
$$update() {
run_all(this.$$beforeRender);
this.$$fragment.p(this.$$dirty, this.$$.get_state());
this.$$.inject_refs(this.$$refs);
run_all(this.$$afterRender);
this.$$dirty = null;
this.$$afterRender.forEach(after_render);
}
}

@ -1,7 +1,7 @@
let update_scheduled = false;
const dirty_components = [];
const after_update_callbacks = [];
let dirty_components = [];
const after_render_callbacks = [];
export const intro = { enabled: false };
@ -13,18 +13,33 @@ export function schedule_update(component) {
}
}
export function after_update(fn) {
after_update_callbacks.push(fn);
export function after_render(fn) {
after_render_callbacks.push(fn);
}
export function flush() {
while (dirty_components.length) {
dirty_components.pop().$$update();
}
while (after_update_callbacks.length) {
after_update_callbacks.shift()();
}
const seen_callbacks = new Set();
do {
// first, call beforeRender functions
// and update components
while (dirty_components.length) {
dirty_components.shift().$$update();
}
// then, once components are updated, call
// afterRender functions. This may cause
// subsequent updates...
while (after_render_callbacks.length) {
const callback = after_render_callbacks.pop();
if (!seen_callbacks.has(callback)) {
callback();
// ...so guard against infinite loops
seen_callbacks.add(callback);
}
}
} while (dirty_components.length);
update_scheduled = false;
}

Loading…
Cancel
Save