diff --git a/src/interfaces.d.ts b/src/interfaces.d.ts index dd53d412..155ae159 100644 --- a/src/interfaces.d.ts +++ b/src/interfaces.d.ts @@ -72,6 +72,7 @@ export interface ProjectionOptions extends ProjectorOptions { deferredRenderCallbacks: Function []; afterRenderCallbacks: Function[]; merge: boolean; + sync: boolean; mergeElement?: Element; rootNode: Element; } diff --git a/src/mixins/Projector.ts b/src/mixins/Projector.ts index b0015b39..d3aac403 100644 --- a/src/mixins/Projector.ts +++ b/src/mixins/Projector.ts @@ -349,6 +349,8 @@ export function ProjectorMixin
>>(Base: T) } }); + this._projectionOptions = { ...this._projectionOptions, ...{ sync: !this._async } }; + switch (type) { case AttachType.Append: this._projection = dom.append(this.root, this._boundRender(), this, this._projectionOptions); diff --git a/src/vdom.ts b/src/vdom.ts index 4f388fc8..7ceba31e 100644 --- a/src/vdom.ts +++ b/src/vdom.ts @@ -790,31 +790,47 @@ function addDeferredProperties(hnode: InternalHNode, projectionOptions: Projecti function runDeferredRenderCallbacks(projectionOptions: ProjectionOptions) { if (projectionOptions.deferredRenderCallbacks.length) { - global.requestAnimationFrame(() => { + if (projectionOptions.sync) { while (projectionOptions.deferredRenderCallbacks.length) { const callback = projectionOptions.deferredRenderCallbacks.shift(); callback && callback(); } - }); + } + else { + global.requestAnimationFrame(() => { + while (projectionOptions.deferredRenderCallbacks.length) { + const callback = projectionOptions.deferredRenderCallbacks.shift(); + callback && callback(); + } + }); + } } } function runAfterRenderCallbacks(projectionOptions: ProjectionOptions) { - if (global.requestIdleCallback) { - global.requestIdleCallback(() => { - while (projectionOptions.afterRenderCallbacks.length) { - const callback = projectionOptions.afterRenderCallbacks.shift(); - callback && callback(); - } - }); + if (projectionOptions.sync) { + while (projectionOptions.afterRenderCallbacks.length) { + const callback = projectionOptions.afterRenderCallbacks.shift(); + callback && callback(); + } } else { - setTimeout(() => { - while (projectionOptions.afterRenderCallbacks.length) { - const callback = projectionOptions.afterRenderCallbacks.shift(); - callback && callback(); - } - }); + if (global.requestIdleCallback) { + global.requestIdleCallback(() => { + while (projectionOptions.afterRenderCallbacks.length) { + const callback = projectionOptions.afterRenderCallbacks.shift(); + callback && callback(); + } + }); + } + else { + setTimeout(() => { + while (projectionOptions.afterRenderCallbacks.length) { + const callback = projectionOptions.afterRenderCallbacks.shift(); + callback && callback(); + } + }); + } } } diff --git a/tests/unit/vdom.ts b/tests/unit/vdom.ts index b6a45ae2..c3562594 100644 --- a/tests/unit/vdom.ts +++ b/tests/unit/vdom.ts @@ -2278,6 +2278,23 @@ describe('vdom', () => { }); + describe('sync mode', () => { + + it('should run afterRenderCallbacks sync', () => { + const projection = dom.create(v('div', { key: '1' }), projectorStub, { sync: true }); + assert.isTrue(projectorStub.emit.calledWith({ type: 'element-created', element: (projection.domNode.childNodes[0] as Element), key: '1' })); + }); + + it('should run defferedRenderCallbacks sync', () => { + let callCount = 0; + dom.create(v('div', () => { + callCount++; + return {}; + }), projectorStub, { sync: true }); + assert.strictEqual(callCount, 2); + }); + }); + describe('node callbacks', () => { it('element-created not emitted for new nodes without a key', () => {