From 25a547a359a4cdb9fde83723497b75c99c11a5cc Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 27 Aug 2020 20:36:47 -0500 Subject: [PATCH] fix(prerender): hAsync only returns promise if it has to --- src/hydrate/platform/h-async.ts | 27 +++++++++++-- src/mock-doc/window.ts | 68 +++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/hydrate/platform/h-async.ts b/src/hydrate/platform/h-async.ts index 5320023ce32..ed99749ee44 100644 --- a/src/hydrate/platform/h-async.ts +++ b/src/hydrate/platform/h-async.ts @@ -1,9 +1,28 @@ import * as d from '../../declarations'; import { h } from '@runtime'; +import { isPromise } from '@utils'; +import { consoleDevError } from '@platform'; -export const hAsync = async (nodeName: any, vnodeData: any, ...children: d.ChildType[]) => { - if (children) { - children = await Promise.all(children); +export const hAsync = (nodeName: any, vnodeData: any, ...children: d.ChildType[]) => { + if (Array.isArray(children) && children.length > 0) { + // only return a promise if we have to + if (children.some(isPromise)) { + // has children and at least one of them is async + // wait on all of them to be resolved + return Promise.all(children) + .then(resolvedChildren => { + return h(nodeName, vnodeData, ...resolvedChildren); + }) + .catch(err => { + consoleDevError(err); + return h(nodeName, vnodeData); + }); + } + + // no async children, return sync + return h(nodeName, vnodeData, ...children); } - return h(nodeName, vnodeData, ...children); + + // no children, return sync + return h(nodeName, vnodeData); }; diff --git a/src/mock-doc/window.ts b/src/mock-doc/window.ts index a6acb0f5d21..fd0952914c6 100644 --- a/src/mock-doc/window.ts +++ b/src/mock-doc/window.ts @@ -423,39 +423,47 @@ export class MockWindow { if (this.__allowInterval) { const intervalId = this.__setInterval(() => { - this.__timeouts.delete(intervalId); - - try { - callback(...args); - } catch (e) { - if (this.console) { - this.console.error(e); - } else { - console.error(e); + if (this.__timeouts) { + this.__timeouts.delete(intervalId); + + try { + callback(...args); + } catch (e) { + if (this.console) { + this.console.error(e); + } else { + console.error(e); + } } } }, ms) as any; - this.__timeouts.add(intervalId); + if (this.__timeouts) { + this.__timeouts.add(intervalId); + } return intervalId; } const timeoutId = this.__setTimeout(() => { - this.__timeouts.delete(timeoutId); + if (this.__timeouts) { + this.__timeouts.delete(timeoutId); - try { - callback(...args); - } catch (e) { - if (this.console) { - this.console.error(e); - } else { - console.error(e); + try { + callback(...args); + } catch (e) { + if (this.console) { + this.console.error(e); + } else { + console.error(e); + } } } }, ms) as any; - this.__timeouts.add(timeoutId); + if (this.__timeouts) { + this.__timeouts.add(timeoutId); + } return timeoutId; } @@ -468,20 +476,24 @@ export class MockWindow { ms = Math.min(ms, this.__maxTimeout); const timeoutId = (this.__setTimeout(() => { - this.__timeouts.delete(timeoutId); + if (this.__timeouts) { + this.__timeouts.delete(timeoutId); - try { - callback(...args); - } catch (e) { - if (this.console) { - this.console.error(e); - } else { - console.error(e); + try { + callback(...args); + } catch (e) { + if (this.console) { + this.console.error(e); + } else { + console.error(e); + } } } }, ms) as any) as number; - this.__timeouts.add(timeoutId); + if (this.__timeouts) { + this.__timeouts.add(timeoutId); + } return timeoutId; }