From b95453e8154528350004d5b2641e4281d037d683 Mon Sep 17 00:00:00 2001 From: Vladislav Tasev Date: Tue, 26 Jan 2021 09:55:48 +0200 Subject: [PATCH 1/7] refactor(framework): Deprecate RenderScheduler in favor of Render.js --- packages/base/bundle.esm.js | 4 +- packages/base/src/Render.js | 181 ++++++++++++++++++ packages/base/src/RenderScheduler.js | 165 ++-------------- packages/base/src/StaticAreaItem.js | 4 +- packages/base/src/UI5Element.js | 20 +- packages/base/src/config/Language.js | 6 +- packages/base/src/delegate/ItemNavigation.js | 4 +- packages/base/src/locale/applyDirection.js | 6 +- packages/base/src/theming/CustomStyle.js | 4 +- .../base/test/specs/UI5ElementInvalidation.js | 31 +-- .../base/test/specs/UI5ElementLifecycle.js | 11 +- ...I5ElementListenForChildPropChanges.spec.js | 7 +- packages/fiori/src/UploadCollectionItem.js | 4 +- packages/ie11/src/integrate.js | 4 +- packages/main/bundle.esm.js | 4 +- packages/main/src/Calendar.js | 4 +- packages/main/src/DateRangePicker.js | 6 +- packages/main/src/Input.js | 4 +- packages/main/src/SegmentedButton.js | 4 +- .../test/pageobjects/DayPickerTestPage.js | 2 +- packages/main/test/pages/Input_quickview.html | 25 +-- packages/main/test/pages/MemoryLeak.html | 4 +- packages/tools/components-package/wdio.js | 4 +- .../lib/init-package/resources/bundle.esm.js | 4 +- 24 files changed, 282 insertions(+), 230 deletions(-) create mode 100644 packages/base/src/Render.js diff --git a/packages/base/bundle.esm.js b/packages/base/bundle.esm.js index 9ca625ded77f..0f35c808e156 100644 --- a/packages/base/bundle.esm.js +++ b/packages/base/bundle.esm.js @@ -15,8 +15,7 @@ import "./dist/test-resources/elements/GenericExt.js"; import "./dist/test-resources/assets/Themes.js"; // used in test pages -import RenderScheduler from "./dist/RenderScheduler.js"; -window.RenderScheduler = RenderScheduler; +import { whenFinished } from "./dist/Render.js"; import { isIE } from "./dist/Device.js"; window.isIE = isIE; // attached to the window object for testing purposes @@ -52,4 +51,5 @@ window["sap-ui-webcomponents-bundle"] = { registerI18nBundle, fetchI18nBundle, getI18nBundle, + whenFinished, }; diff --git a/packages/base/src/Render.js b/packages/base/src/Render.js new file mode 100644 index 000000000000..5e1e8cd30cd9 --- /dev/null +++ b/packages/base/src/Render.js @@ -0,0 +1,181 @@ +import EventProvider from "./EventProvider.js"; +import RenderQueue from "./RenderQueue.js"; +import { getAllRegisteredTags } from "./CustomElementsRegistry.js"; +import { isRtlAware } from "./locale/RTLAwareRegistry.js"; + +const registeredElements = new Set(); +const eventProvider = new EventProvider(); + +// Queue for invalidated web components +const invalidatedWebComponents = new RenderQueue(); + +let renderTaskPromise, + renderTaskPromiseResolve; + +let mutationObserverTimer; + +let queuePromise; + + +/** + * Schedules a render task (if not already scheduled) to render the component + * + * @param webComponent + * @returns {Promise} + */ +const renderDeferred = async webComponent => { + // Enqueue the web component + invalidatedWebComponents.add(webComponent); + + // Schedule a rendering task + await scheduleRenderTask(); +}; + +/** + * Renders a component synchronously + * + * @param webComponent + */ +const renderImmediately = webComponent => { + eventProvider.fireEvent("beforeComponentRender", webComponent); + webComponent._render(); +}; + +/** + * Cancels the rendering of a component, added to the queue with renderDeferred + * + * @param webComponent + */ +const cancelRender = webComponent => { + invalidatedWebComponents.remove(webComponent); +}; + +/** + * Schedules a rendering task, if not scheduled already + */ +const scheduleRenderTask = async () => { + if (!queuePromise) { + queuePromise = new Promise(resolve => { + window.requestAnimationFrame(() => { + // Render all components in the queue + + // console.log(`--------------------RENDER TASK START------------------------------`); // eslint-disable-line + invalidatedWebComponents.process(renderImmediately); + // console.log(`--------------------RENDER TASK END------------------------------`); // eslint-disable-line + + // Resolve the promise so that callers of renderDeferred can continue + queuePromise = null; + resolve(); + + // Wait for Mutation observer before the render task is considered finished + if (!mutationObserverTimer) { + mutationObserverTimer = setTimeout(() => { + mutationObserverTimer = undefined; + if (invalidatedWebComponents.isEmpty()) { + _resolveTaskPromise(); + } + }, 200); + } + }); + }); + } + + await queuePromise; +}; + +/** + * return a promise that will be resolved once all invalidated web components are rendered + */ +const whenDOMUpdated = () => { + if (renderTaskPromise) { + return renderTaskPromise; + } + + renderTaskPromise = new Promise(resolve => { + renderTaskPromiseResolve = resolve; + window.requestAnimationFrame(() => { + if (invalidatedWebComponents.isEmpty()) { + renderTaskPromise = undefined; + resolve(); + } + }); + }); + + return renderTaskPromise; +}; + +const whenAllCustomElementsAreDefined = () => { + const definedPromises = getAllRegisteredTags().map(tag => customElements.whenDefined(tag)); + return Promise.all(definedPromises); +}; + +const whenFinished = async () => { + await whenAllCustomElementsAreDefined(); + await whenDOMUpdated(); +}; + +const _resolveTaskPromise = () => { + if (!invalidatedWebComponents.isEmpty()) { + // More updates are pending. Resolve will be called again + return; + } + + if (renderTaskPromiseResolve) { + renderTaskPromiseResolve(); + renderTaskPromiseResolve = undefined; + renderTaskPromise = undefined; + } +}; + +const register = element => { + registeredElements.add(element); +}; + +const deregister = element => { + registeredElements.delete(element); +}; + +/** + * Re-renders all UI5 Elements on the page, with the option to specify filters to rerender only some components. + * + * Usage: + * reRenderAllUI5Elements() -> rerenders all components + * reRenderAllUI5Elements({tag: "ui5-button"}) -> re-renders only instances of ui5-button + * reRenderAllUI5Elements({rtlAware: true}) -> re-renders only rtlAware components + * reRenderAllUI5Elements({languageAware: true}) -> re-renders only languageAware components + * reRenderAllUI5Elements({rtlAware: true, languageAware: true}) -> re-renders components that are rtlAware or languageAware + * etc... + * + * @public + * @param {Object|undefined} filters - Object with keys that can be "rtlAware" or "languageAware" + */ +const reRenderAllUI5Elements = filters => { + registeredElements.forEach(element => { + const tag = element.constructor.getMetadata().getTag(); + const rtlAware = isRtlAware(element.constructor); + const languageAware = element.constructor.getMetadata().isLanguageAware(); + if (!filters || (filters.tag === tag) || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware)) { + renderDeferred(element); + } + }); +}; + +const attachBeforeComponentRender = listener => { + eventProvider.attachEvent("beforeComponentRender", listener); +}; + +const detachBeforeComponentRender = listener => { + eventProvider.detachEvent("beforeComponentRender", listener); +}; + +export { + renderDeferred, + renderImmediately, + cancelRender, + whenFinished, + register, + deregister, + reRenderAllUI5Elements, + attachBeforeComponentRender, + detachBeforeComponentRender, +}; diff --git a/packages/base/src/RenderScheduler.js b/packages/base/src/RenderScheduler.js index d111281273cb..3709da400fa0 100644 --- a/packages/base/src/RenderScheduler.js +++ b/packages/base/src/RenderScheduler.js @@ -1,179 +1,40 @@ -import EventProvider from "./EventProvider.js"; -import RenderQueue from "./RenderQueue.js"; -import { getAllRegisteredTags } from "./CustomElementsRegistry.js"; -import { isRtlAware } from "./locale/RTLAwareRegistry.js"; - -const registeredElements = new Set(); -const eventProvider = new EventProvider(); - -// Queue for invalidated web components -const invalidatedWebComponents = new RenderQueue(); - -let renderTaskPromise, - renderTaskPromiseResolve; - -let mutationObserverTimer; - -let queuePromise; +import { + renderDeferred, + renderImmediately, + whenFinished, +} from "./Render.js"; /** - * Class that manages the rendering/re-rendering of web components - * This is always asynchronous + * @deprecated Use the Render.js module instead */ class RenderScheduler { - constructor() { - throw new Error("Static class"); - } - /** * Schedules a render task (if not already scheduled) to render the component * * @param webComponent * @returns {Promise} + * @deprecated Use renderDeferred from the Render.js module instead */ static async renderDeferred(webComponent) { - // Enqueue the web component - invalidatedWebComponents.add(webComponent); - - // Schedule a rendering task - await RenderScheduler.scheduleRenderTask(); + await renderDeferred(webComponent); } /** * Renders a component synchronously * * @param webComponent + * @deprecated Use renderImmediately from the Render.js module instead */ static renderImmediately(webComponent) { - eventProvider.fireEvent("beforeComponentRender", webComponent); - webComponent._render(); + return renderImmediately(webComponent); } /** - * Cancels the rendering of a component, added to the queue with renderDeferred - * - * @param webComponent + * @deprecated Use whenFinished from the Render.js module instead + * @returns {Promise} */ - static cancelRender(webComponent) { - invalidatedWebComponents.remove(webComponent); - } - - /** - * Schedules a rendering task, if not scheduled already - */ - static async scheduleRenderTask() { - if (!queuePromise) { - queuePromise = new Promise(resolve => { - window.requestAnimationFrame(() => { - // Render all components in the queue - - // console.log(`--------------------RENDER TASK START------------------------------`); // eslint-disable-line - invalidatedWebComponents.process(RenderScheduler.renderImmediately); - // console.log(`--------------------RENDER TASK END------------------------------`); // eslint-disable-line - - // Resolve the promise so that callers of renderDeferred can continue - queuePromise = null; - resolve(); - - // Wait for Mutation observer before the render task is considered finished - if (!mutationObserverTimer) { - mutationObserverTimer = setTimeout(() => { - mutationObserverTimer = undefined; - if (invalidatedWebComponents.isEmpty()) { - RenderScheduler._resolveTaskPromise(); - } - }, 200); - } - }); - }); - } - - await queuePromise; - } - - /** - * return a promise that will be resolved once all invalidated web components are rendered - */ - static whenDOMUpdated() { - if (renderTaskPromise) { - return renderTaskPromise; - } - - renderTaskPromise = new Promise(resolve => { - renderTaskPromiseResolve = resolve; - window.requestAnimationFrame(() => { - if (invalidatedWebComponents.isEmpty()) { - renderTaskPromise = undefined; - resolve(); - } - }); - }); - - return renderTaskPromise; - } - - static whenAllCustomElementsAreDefined() { - const definedPromises = getAllRegisteredTags().map(tag => customElements.whenDefined(tag)); - return Promise.all(definedPromises); - } - static async whenFinished() { - await RenderScheduler.whenAllCustomElementsAreDefined(); - await RenderScheduler.whenDOMUpdated(); - } - - static _resolveTaskPromise() { - if (!invalidatedWebComponents.isEmpty()) { - // More updates are pending. Resolve will be called again - return; - } - - if (renderTaskPromiseResolve) { - renderTaskPromiseResolve.call(this); - renderTaskPromiseResolve = undefined; - renderTaskPromise = undefined; - } - } - - static register(element) { - registeredElements.add(element); - } - - static deregister(element) { - registeredElements.delete(element); - } - - /** - * Re-renders all UI5 Elements on the page, with the option to specify filters to rerender only some components. - * - * Usage: - * reRenderAllUI5Elements() -> rerenders all components - * reRenderAllUI5Elements({tag: "ui5-button"}) -> re-renders only instances of ui5-button - * reRenderAllUI5Elements({rtlAware: true}) -> re-renders only rtlAware components - * reRenderAllUI5Elements({languageAware: true}) -> re-renders only languageAware components - * reRenderAllUI5Elements({rtlAware: true, languageAware: true}) -> re-renders components that are rtlAware or languageAware - * etc... - * - * @public - * @param {Object|undefined} filters - Object with keys that can be "rtlAware" or "languageAware" - */ - static reRenderAllUI5Elements(filters) { - registeredElements.forEach(element => { - const tag = element.constructor.getMetadata().getTag(); - const rtlAware = isRtlAware(element.constructor); - const languageAware = element.constructor.getMetadata().isLanguageAware(); - if (!filters || (filters.tag === tag) || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware)) { - RenderScheduler.renderDeferred(element); - } - }); - } - - static attachBeforeComponentRender(listener) { - eventProvider.attachEvent("beforeComponentRender", listener); - } - - static detachBeforeComponentRender(listener) { - eventProvider.detachEvent("beforeComponentRender", listener); + await whenFinished(); } } diff --git a/packages/base/src/StaticAreaItem.js b/packages/base/src/StaticAreaItem.js index 8b849a38321e..0b3af22b28b3 100644 --- a/packages/base/src/StaticAreaItem.js +++ b/packages/base/src/StaticAreaItem.js @@ -1,5 +1,5 @@ import updateShadowRoot from "./updateShadowRoot.js"; -import RenderScheduler from "./RenderScheduler.js"; +import { whenFinished } from "./Render.js"; import getEffectiveContentDensity from "./util/getEffectiveContentDensity.js"; /** @@ -59,7 +59,7 @@ class StaticAreaItem extends HTMLElement { this._rendered = true; updateShadowRoot(this.ownerElement, true); } - await RenderScheduler.whenDOMUpdated(); // Wait for the content of the ui5-static-area-item to be rendered + await whenFinished(); // Wait for the content of the ui5-static-area-item to be rendered return this.shadowRoot; } diff --git a/packages/base/src/UI5Element.js b/packages/base/src/UI5Element.js index e74e6abde95c..fa17af2d4642 100644 --- a/packages/base/src/UI5Element.js +++ b/packages/base/src/UI5Element.js @@ -5,7 +5,13 @@ import EventProvider from "./EventProvider.js"; import getSingletonElementInstance from "./util/getSingletonElementInstance.js"; import "./StaticAreaItem.js"; import updateShadowRoot from "./updateShadowRoot.js"; -import RenderScheduler from "./RenderScheduler.js"; +import { + renderDeferred, + renderImmediately, + cancelRender, + register, + deregister, +} from "./Render.js"; import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js"; import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js"; import { skipOriginalEvent } from "./config/NoConflict.js"; @@ -40,7 +46,7 @@ function _invalidate(changeInfo) { this.onInvalidation(changeInfo); this._changedState.push(changeInfo); - RenderScheduler.renderDeferred(this); + renderDeferred(this); this._eventProvider.fireEvent("change", { ...changeInfo, target: this }); } @@ -119,8 +125,8 @@ class UI5Element extends HTMLElement { return; } - RenderScheduler.register(this); - RenderScheduler.renderImmediately(this); + register(this); + renderImmediately(this); this._domRefReadyPromise._deferredResolve(); this._fullyConnected = true; if (typeof this.onEnterDOM === "function") { @@ -143,7 +149,7 @@ class UI5Element extends HTMLElement { } if (needsShadowDOM) { - RenderScheduler.deregister(this); + deregister(this); if (this._fullyConnected) { if (typeof this.onExitDOM === "function") { this.onExitDOM(); @@ -156,7 +162,7 @@ class UI5Element extends HTMLElement { this.staticAreaItem.parentElement.removeChild(this.staticAreaItem); } - RenderScheduler.cancelRender(this); + cancelRender(this); } /** @@ -532,7 +538,7 @@ class UI5Element extends HTMLElement { onInvalidation(changeInfo) {} /** - * Do not call this method directly, only intended to be called by RenderScheduler.js + * Do not call this method directly, only intended to be called by js * @protected */ _render() { diff --git a/packages/base/src/config/Language.js b/packages/base/src/config/Language.js index 9486402ba18b..e749ec558b0a 100644 --- a/packages/base/src/config/Language.js +++ b/packages/base/src/config/Language.js @@ -3,7 +3,7 @@ import { getUseDefaultLanguage as getConfiguredUseDefaultLanguage, } from "../InitialConfiguration.js"; import { fireLanguageChange } from "../locale/languageChange.js"; -import RenderScheduler from "../RenderScheduler.js"; +import { reRenderAllUI5Elements, whenFinished } from "../Render.js"; let language; let useDefaultLanguage; @@ -34,8 +34,8 @@ const setLanguage = async newLanguage => { language = newLanguage; await fireLanguageChange(newLanguage); - RenderScheduler.reRenderAllUI5Elements({ languageAware: true }); - return RenderScheduler.whenFinished(); + reRenderAllUI5Elements({ languageAware: true }); + return whenFinished(); }; /** diff --git a/packages/base/src/delegate/ItemNavigation.js b/packages/base/src/delegate/ItemNavigation.js index c65da45e37f3..e6a780787c38 100644 --- a/packages/base/src/delegate/ItemNavigation.js +++ b/packages/base/src/delegate/ItemNavigation.js @@ -1,4 +1,4 @@ -import RenderScheduler from "../RenderScheduler.js"; +import { whenFinished } from "../Render.js"; import { isDown, isUp, @@ -109,7 +109,7 @@ class ItemNavigation extends EventProvider { event.preventDefault(); - await RenderScheduler.whenFinished(); + await whenFinished(); this.update(); this.focusCurrent(); diff --git a/packages/base/src/locale/applyDirection.js b/packages/base/src/locale/applyDirection.js index a27971c31a30..a532ccc935fe 100644 --- a/packages/base/src/locale/applyDirection.js +++ b/packages/base/src/locale/applyDirection.js @@ -1,4 +1,4 @@ -import RenderScheduler from "../RenderScheduler.js"; +import { reRenderAllUI5Elements, whenFinished } from "../Render.js"; import { fireDirectionChange } from "./directionChange.js"; /** @@ -11,8 +11,8 @@ import { fireDirectionChange } from "./directionChange.js"; const applyDirection = async () => { const listenersResults = fireDirectionChange(); await Promise.all(listenersResults); - RenderScheduler.reRenderAllUI5Elements({ rtlAware: true }); - return RenderScheduler.whenFinished(); + reRenderAllUI5Elements({ rtlAware: true }); + return whenFinished(); }; export default applyDirection; diff --git a/packages/base/src/theming/CustomStyle.js b/packages/base/src/theming/CustomStyle.js index f3bec1874743..3a1fb22bcf98 100644 --- a/packages/base/src/theming/CustomStyle.js +++ b/packages/base/src/theming/CustomStyle.js @@ -1,4 +1,4 @@ -import RenderScheduler from "../RenderScheduler.js"; +import { reRenderAllUI5Elements } from "../Render.js"; import EventProvider from "../EventProvider.js"; const eventProvider = new EventProvider(); @@ -25,7 +25,7 @@ const addCustomCSS = (tag, css) => { customCSSFor[tag].push(css); fireCustomCSSChange(tag); - RenderScheduler.reRenderAllUI5Elements({ tag }); + reRenderAllUI5Elements({ tag }); }; const getCustomCSS = tag => { diff --git a/packages/base/test/specs/UI5ElementInvalidation.js b/packages/base/test/specs/UI5ElementInvalidation.js index 44d9e95cb90d..5c6c1a8effd3 100644 --- a/packages/base/test/specs/UI5ElementInvalidation.js +++ b/packages/base/test/specs/UI5ElementInvalidation.js @@ -1,4 +1,5 @@ const assert = require("chai").assert; +const whenFinished = window["sap-ui-webcomponents-bundle"].whenFinished(); describe("Invalidation works", () => { browser.url("http://localhost:9191/test-resources/pages/AllTestElements.html"); @@ -19,7 +20,7 @@ describe("Invalidation works", () => { el.strProp = "new value"; el.boolProp = true; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidations); }); @@ -34,7 +35,7 @@ describe("Invalidation works", () => { const el = document.getElementById("gen"); el.strProp = text; - await window.RenderScheduler.whenFinished(); + await whenFinished(); let invalidations = 0; @@ -44,7 +45,7 @@ describe("Invalidation works", () => { el.strProp = text; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidations); }); @@ -60,7 +61,7 @@ describe("Invalidation works", () => { const el = document.getElementById("gen"); el.objectProp = obj; - await window.RenderScheduler.whenFinished(); + await whenFinished(); let invalidations = 0; @@ -70,7 +71,7 @@ describe("Invalidation works", () => { el.objectProp = otherObj; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidations); }); @@ -86,7 +87,7 @@ describe("Invalidation works", () => { const el = document.getElementById("gen"); el.multiProp = arr; - await window.RenderScheduler.whenFinished(); + await whenFinished(); let invalidations = 0; @@ -96,7 +97,7 @@ describe("Invalidation works", () => { el.multiProp = otherArr; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidations); }); @@ -120,7 +121,7 @@ describe("Invalidation works", () => { const div = document.createElement("div"); el.appendChild(div); - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidated); }); @@ -136,7 +137,7 @@ describe("Invalidation works", () => { const div = document.createElement("div"); el.appendChild(div); - await window.RenderScheduler.whenFinished(); + await whenFinished(); let invalidated = false; @@ -146,7 +147,7 @@ describe("Invalidation works", () => { el.removeChild(div); - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidated); }); @@ -160,7 +161,7 @@ describe("Invalidation works", () => { const el = document.getElementById("gen"); el.textContent = "test"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); // Number of invalidations may vary with children/slots count, so just check for invalidation let invalidated = false; @@ -171,7 +172,7 @@ describe("Invalidation works", () => { el.textContent = "test2"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidated); }); @@ -185,7 +186,7 @@ describe("Invalidation works", () => { const el = document.getElementById("gen"); el.textContent = "test"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); // Number of invalidations may vary with children/slots count, so just check for invalidation let invalidated = false; @@ -196,7 +197,7 @@ describe("Invalidation works", () => { el.childNodes[0].nodeValue = "test2"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(invalidated); }); @@ -228,7 +229,7 @@ describe("Invalidation works", () => { el.strProp = "new"; el.strProp = "newer"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(operations); }); diff --git a/packages/base/test/specs/UI5ElementLifecycle.js b/packages/base/test/specs/UI5ElementLifecycle.js index 225615ab022a..82015e7c69c5 100644 --- a/packages/base/test/specs/UI5ElementLifecycle.js +++ b/packages/base/test/specs/UI5ElementLifecycle.js @@ -1,4 +1,5 @@ const assert = require("chai").assert; +const whenFinished = window["sap-ui-webcomponents-bundle"].whenFinished(); describe("Lifecycle works", () => { browser.url("http://localhost:9191/test-resources/pages/AllTestElements.html"); @@ -20,7 +21,7 @@ describe("Lifecycle works", () => { }); document.body.appendChild(el); - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(calledCallbacks); }); @@ -40,7 +41,7 @@ describe("Lifecycle works", () => { const el = document.createElement("ui5-test-generic"); document.body.appendChild(el); - await window.RenderScheduler.whenFinished(); + await whenFinished(); el.strProp = "some string"; @@ -52,7 +53,7 @@ describe("Lifecycle works", () => { }; }); - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(calledCallbacks); }); @@ -80,11 +81,11 @@ describe("Lifecycle works", () => { document.body.appendChild(el); - await window.RenderScheduler.whenFinished(); // Must wait, otherwise onExitDOM won't be called + await whenFinished(); // Must wait, otherwise onExitDOM won't be called document.body.removeChild(el); - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(calledCallbacks); }); diff --git a/packages/base/test/specs/UI5ElementListenForChildPropChanges.spec.js b/packages/base/test/specs/UI5ElementListenForChildPropChanges.spec.js index 6fd1249dde35..a48a93fa24b9 100644 --- a/packages/base/test/specs/UI5ElementListenForChildPropChanges.spec.js +++ b/packages/base/test/specs/UI5ElementListenForChildPropChanges.spec.js @@ -1,4 +1,5 @@ const assert = require("chai").assert; +const whenFinished = window["sap-ui-webcomponents-bundle"].whenFinished(); describe("Metadata slot invalidateOnChildChange works", () => { browser.url("http://localhost:9191/test-resources/pages/AllTestElements.html"); @@ -17,7 +18,7 @@ describe("Metadata slot invalidateOnChildChange works", () => { child.prop1 = "a"; // child1(default slot) prop1 -> invalidates - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(parentInvalidated); }); @@ -39,7 +40,7 @@ describe("Metadata slot invalidateOnChildChange works", () => { child.prop2 = "b"; // child1(default slot) prop 2 -> does not - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(parentInvalidated); }); @@ -63,7 +64,7 @@ describe("Metadata slot invalidateOnChildChange works", () => { child.prop2 = "c"; child.prop3 = "c"; - await window.RenderScheduler.whenFinished(); + await whenFinished(); return done(parentInvalidatedCount); }); diff --git a/packages/fiori/src/UploadCollectionItem.js b/packages/fiori/src/UploadCollectionItem.js index 6b677e0ef077..383e202ed2d9 100644 --- a/packages/fiori/src/UploadCollectionItem.js +++ b/packages/fiori/src/UploadCollectionItem.js @@ -8,7 +8,7 @@ import ProgressIndicator from "@ui5/webcomponents/dist/ProgressIndicator.js"; import ListItem from "@ui5/webcomponents/dist/ListItem.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import getFileExtension from "@ui5/webcomponents-base/dist/util/getFileExtension.js"; -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { isEnter, isEscape, isSpace } from "@ui5/webcomponents-base/dist/Keys.js"; import UploadState from "./types/UploadState.js"; import "@ui5/webcomponents-icons/dist/refresh.js"; @@ -286,7 +286,7 @@ class UploadCollectionItem extends ListItem { const inp = this.shadowRoot.getElementById("ui5-uci-edit-input"); - await RenderScheduler.whenDOMUpdated(); + await whenFinished(); if (inp.getFocusDomRef()) { inp.getFocusDomRef().setSelectionRange(0, this._fileNameWithoutExtension.length); } diff --git a/packages/ie11/src/integrate.js b/packages/ie11/src/integrate.js index 691889b9d032..893f79b26e16 100644 --- a/packages/ie11/src/integrate.js +++ b/packages/ie11/src/integrate.js @@ -1,6 +1,6 @@ import { attachBoot } from "@ui5/webcomponents-base/dist/Boot.js"; import { attachThemeLoaded } from "@ui5/webcomponents-base/dist/theming/ThemeLoaded.js"; -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { attachBeforeComponentRender } from "@ui5/webcomponents-base/dist/Render.js"; import { setCreateObserverCallback, setDestroyObserverCallback } from "@ui5/webcomponents-base/dist/DOMObserver.js"; import whenPolyfillLoaded from "./whenPolyfillLoaded.js"; import createComponentStyleTag from "./theming/createComponentStyleTag.js"; @@ -13,7 +13,7 @@ attachBoot(whenPolyfillLoaded); attachThemeLoaded(runPonyfill); // Execute on each component render -RenderScheduler.attachBeforeComponentRender(createComponentStyleTag); +attachBeforeComponentRender(createComponentStyleTag); // Set the custom observer implementation for observe setCreateObserverCallback(window.ShadyDOM.observeChildren); diff --git a/packages/main/bundle.esm.js b/packages/main/bundle.esm.js index 851442ac981d..d352898adf18 100644 --- a/packages/main/bundle.esm.js +++ b/packages/main/bundle.esm.js @@ -91,8 +91,7 @@ import CustomListItem from "./dist/CustomListItem.js"; import GroupHeaderListItem from "./dist/GroupHeaderListItem.js"; // used in test pages -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; -window.RenderScheduler = RenderScheduler; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { isIE } from "@ui5/webcomponents-base/dist/Device.js"; window.isIE = isIE; // attached to the window object for testing purposes @@ -129,6 +128,7 @@ const testAssets = { attachThemeLoaded, detachThemeLoaded, getIconNames, + whenFinished, }; window["sap-ui-webcomponents-bundle"] = testAssets; diff --git a/packages/main/src/Calendar.js b/packages/main/src/Calendar.js index 098bbc2321ff..011e353ab448 100644 --- a/packages/main/src/Calendar.js +++ b/packages/main/src/Calendar.js @@ -1,5 +1,5 @@ import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js"; -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { isF4, isF4Shift, @@ -236,7 +236,7 @@ class Calendar extends CalendarPart { } async onAfterRendering() { - await RenderScheduler.whenFinished(); // Await for the current picker to render and then ask if it has previous/next pages + await whenFinished(); // Await for the current picker to render and then ask if it has previous/next pages this._previousButtonDisabled = !this._currentPickerDOM._hasPreviousPage(); this._nextButtonDisabled = !this._currentPickerDOM._hasNextPage(); } diff --git a/packages/main/src/DateRangePicker.js b/packages/main/src/DateRangePicker.js index cea854a3ecf1..eb324fe9eb64 100644 --- a/packages/main/src/DateRangePicker.js +++ b/packages/main/src/DateRangePicker.js @@ -1,4 +1,4 @@ -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js"; import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateBy.js"; import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js"; @@ -156,7 +156,7 @@ class DateRangePicker extends DatePicker { async _onInputSubmit(event) { const input = this._getInput(); const caretPos = input.getCaretPosition(); - await RenderScheduler.whenFinished(); + await whenFinished(); input.setCaretPosition(caretPos); // Return the caret on the previous position after rendering } @@ -240,7 +240,7 @@ class DateRangePicker extends DatePicker { } this._updateValueAndFireEvents(newValue, true, ["change", "value-changed"]); - await RenderScheduler.whenFinished(); + await whenFinished(); input.setCaretPosition(caretPos); // Return the caret to the previous (or the adjusted, if dates flipped) position after rendering } diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index f130e031ded0..40305a678c93 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -1,7 +1,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { isIE, isPhone, isSafari } from "@ui5/webcomponents-base/dist/Device.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; @@ -563,7 +563,7 @@ class Input extends UI5Element { preventFocusRestore: !this.hasSuggestionItemSelected, }); - RenderScheduler.whenFinished().then(async () => { + whenFinished().then(async () => { this._listWidth = await this.Suggestions._getListWidth(); }); diff --git a/packages/main/src/SegmentedButton.js b/packages/main/src/SegmentedButton.js index 56b303624cc2..2294db659f26 100644 --- a/packages/main/src/SegmentedButton.js +++ b/packages/main/src/SegmentedButton.js @@ -3,7 +3,7 @@ import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; +import { whenFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { isIE } from "@ui5/webcomponents-base/dist/Device.js"; import { SEGMENTEDBUTTON_ARIA_DESCRIPTION } from "./generated/i18n/i18n-defaults.js"; import ToggleButton from "./ToggleButton.js"; @@ -143,7 +143,7 @@ class SegmentedButton extends UI5Element { } async measureButtonsWidth() { - await RenderScheduler.whenDOMUpdated(); + await whenFinished(); this.prepareToMeasureButtons(); this.widths = this.buttons.map(button => { diff --git a/packages/main/test/pageobjects/DayPickerTestPage.js b/packages/main/test/pageobjects/DayPickerTestPage.js index 3a94147731f1..f437aaac35e3 100644 --- a/packages/main/test/pageobjects/DayPickerTestPage.js +++ b/packages/main/test/pageobjects/DayPickerTestPage.js @@ -5,7 +5,7 @@ class DayPickerTestHelper { get dayPickerRoot() { return browser.executeAsync(async (id, done) => { - await window.RenderScheduler.whenFinished(); + await window["sap-ui-webcomponents-bundle"].whenFinished(); const el = document.getElementById(id) .shadowRoot.querySelector(".ui5-dp-root"); diff --git a/packages/main/test/pages/Input_quickview.html b/packages/main/test/pages/Input_quickview.html index b5c0bb906b07..9c0f4632e1b5 100644 --- a/packages/main/test/pages/Input_quickview.html +++ b/packages/main/test/pages/Input_quickview.html @@ -57,7 +57,7 @@

Quick View sample

Test Quick View sample

- + @@ -95,22 +95,23 @@

Test Quick View sample