Skip to content
This repository has been archived by the owner on May 5, 2021. It is now read-only.

Commit

Permalink
[FIX] Renderer: fix rendering promises
Browse files Browse the repository at this point in the history
The render function (of the renderer) can be called many times
synchronously, the render functions are called for all nodes even if they
are rendered together. Example, in a for loop, we call render (of the
renderer) for a text, so the render function is called for each
character. It is necessary to check in the promise (including in the
following microtask) if the rendering has not already been done.
  • Loading branch information
Gorash authored and dmo-odoo committed Jun 5, 2020
1 parent dba411a commit 281e77e
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions packages/plugin-renderer/src/RenderingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,20 @@ export class RenderingEngine<T = {}> {
* @param nodes
* @param rendering
*/
async rendered(nodes: VNode[], rendering: [Renderer<T>, Promise<T>]): Promise<T> {
async rendered(nodes: VNode[], renderer: Renderer<T>, rendered: Promise<T>): Promise<T> {
for (const node of nodes) {
const renderings = this.renderings.get(node) || [];
renderings.push(rendering);
let renderings = this.renderings.get(node);
if (!renderings) {
renderings = [];
this.renderings.set(node, renderings);
}
const index = renderings.findIndex(rendering => rendering[0] === renderer);
if (index === -1) {
renderings.push([renderer, rendered, true]);
} else {
renderings[index][1] = rendered;
renderings[index][2] = true;
}
}
return rendered;
}
Expand Down Expand Up @@ -137,10 +147,15 @@ export class RenderingEngine<T = {}> {
// later with the same return value as the asynchronous render call.
const rendererProm = new Promise<T>((resolve): void => {
Promise.resolve().then(() => {
nextRenderer.render(node).then(resolve);
const rendering = renderings.find(rendering => rendering[0] === nextRenderer);
const promise = rendering[2] ? rendering[1] : nextRenderer.render(node);
promise.then((n: T) => {
rendering[2] = true;
resolve(n);
});
});
});
renderings.push([nextRenderer, rendererProm]);
renderings.push([nextRenderer, rendererProm, false]);
this.renderings.set(node, renderings);
return rendererProm;
}
Expand Down

0 comments on commit 281e77e

Please sign in to comment.