From a1400eba074c215c9fa776b2b122f0b5db516874 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 25 Nov 2018 10:02:50 -0500 Subject: [PATCH] flush bindings in separate phase before render callbacks --- .../render-dom/wrappers/Element/index.ts | 8 ++++---- .../wrappers/InlineComponent/index.ts | 2 +- src/compile/render-dom/wrappers/Window.ts | 2 +- src/internal/Component.js | 8 ++++---- src/internal/scheduler.js | 17 ++++++++++++----- test/server-side-rendering/index.js | 4 ++-- 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index 9a129e9ece..85cc3b19b7 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -550,7 +550,7 @@ export default class ElementWrapper extends Wrapper { renderer.hasComplexBindings = true; block.builders.hydrate.addLine( - `if (${someInitialStateIsUndefined}) @after_render(() => ${callee}.call(${this.var}));` + `if (${someInitialStateIsUndefined}) @add_render_callback(() => ${callee}.call(${this.var}));` ); } @@ -558,7 +558,7 @@ export default class ElementWrapper extends Wrapper { renderer.hasComplexBindings = true; block.builders.hydrate.addLine( - `@after_render(() => ${callee}.call(${this.var}));` + `@add_render_callback(() => ${callee}.call(${this.var}));` ); } }); @@ -669,7 +669,7 @@ export default class ElementWrapper extends Wrapper { block.builders.intro.addConditional(`@intro.enabled`, deindent` if (${name}) ${name}.invalidate(); - @after_render(() => { + @add_render_callback(() => { if (!${name}) ${name} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true); ${name}.run(1); }); @@ -704,7 +704,7 @@ export default class ElementWrapper extends Wrapper { } block.builders.intro.addConditional(`@intro.enabled`, deindent` - @after_render(() => { + @add_render_callback(() => { ${introName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true); ${introName}.run(1); }); diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index 9a65b25325..81ff8b1d2b 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -257,7 +257,7 @@ export default class InlineComponentWrapper extends Wrapper { component.partly_hoisted.push(body); - return `${this.var}.$$bind('${binding.name}', ${name});`; + return `@add_binding_callback(() => ${this.var}.$$bind('${binding.name}', ${name}));`; }); const munged_handlers = this.node.handlers.map(handler => { diff --git a/src/compile/render-dom/wrappers/Window.ts b/src/compile/render-dom/wrappers/Window.ts index ffa8e87b53..154697b6d1 100644 --- a/src/compile/render-dom/wrappers/Window.ts +++ b/src/compile/render-dom/wrappers/Window.ts @@ -119,7 +119,7 @@ export default class WindowWrapper extends Wrapper { block.builders.init.addBlock(deindent` window.addEventListener("${event}", ctx.${handler_name}); - @after_render(ctx.${handler_name}); + @add_render_callback(ctx.${handler_name}); `); block.builders.destroy.addBlock(deindent` diff --git a/src/internal/Component.js b/src/internal/Component.js index cd7c8517ec..965bcb19b3 100644 --- a/src/internal/Component.js +++ b/src/internal/Component.js @@ -1,4 +1,4 @@ -import { after_render, flush, intro, schedule_update } from './scheduler.js'; +import { add_render_callback, 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'; @@ -111,7 +111,7 @@ export class $$Component { // onMount happens after the initial afterRender. Because // afterRender callbacks happen in reverse order (inner first) // we schedule onMount callbacks before afterRender callbacks - after_render(() => { + add_render_callback(() => { const onDestroy = this.$$onMount.map(run).filter(is_function); if (this.$$onDestroy) { this.$$onDestroy.push(...onDestroy); @@ -123,7 +123,7 @@ export class $$Component { this.$$onMount = []; }); - this.$$afterRender.forEach(after_render); + this.$$afterRender.forEach(add_render_callback); } $$update() { @@ -132,7 +132,7 @@ export class $$Component { this.$$.inject_refs(this.$$refs); this.$$dirty = null; - this.$$afterRender.forEach(after_render); + this.$$afterRender.forEach(add_render_callback); } } diff --git a/src/internal/scheduler.js b/src/internal/scheduler.js index dc03e40751..e02fa35edb 100644 --- a/src/internal/scheduler.js +++ b/src/internal/scheduler.js @@ -1,7 +1,8 @@ let update_scheduled = false; let dirty_components = []; -const after_render_callbacks = []; +const binding_callbacks = []; +const render_callbacks = []; export const intro = { enabled: false }; @@ -13,8 +14,12 @@ export function schedule_update(component) { } } -export function after_render(fn) { - after_render_callbacks.push(fn); +export function add_render_callback(fn) { + render_callbacks.push(fn); +} + +export function add_binding_callback(fn) { + binding_callbacks.push(fn); } export function flush() { @@ -27,11 +32,13 @@ export function flush() { dirty_components.shift().$$update(); } + while (binding_callbacks.length) binding_callbacks.pop()(); + // then, once components are updated, call // afterRender functions. This may cause // subsequent updates... - while (after_render_callbacks.length) { - const callback = after_render_callbacks.pop(); + while (render_callbacks.length) { + const callback = render_callbacks.pop(); if (!seen_callbacks.has(callback)) { callback(); diff --git a/test/server-side-rendering/index.js b/test/server-side-rendering/index.js index b0dfc119a0..8c1e67ff5b 100644 --- a/test/server-side-rendering/index.js +++ b/test/server-side-rendering/index.js @@ -21,7 +21,7 @@ function tryToReadFile(file) { describe("ssr", () => { before(() => { - require("../../ssr/register")({ + require("../../register")({ extensions: ['.svelte', '.html'], store: true }); @@ -112,7 +112,7 @@ describe("ssr", () => { const compileOptions = config.compileOptions || {}; - require("../../ssr/register")(compileOptions); + require("../../register")(compileOptions); try { const component = require(`../runtime/samples/${dir}/main.html`);