haikuwebkit/Websites/perf.webkit.org/browser-tests/component-base-tests.js

748 lines
33 KiB
JavaScript
Raw Permalink Normal View History

Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
describe('ComponentBase', function() {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
async function importComponentBase(context)
{
const [Instrumentation, CommonComponentBase, ComponentBase] = await context.importScripts(
['instrumentation.js', '../shared/common-component-base.js', 'components/base.js'],
'Instrumentation', 'CommonComponentBase', 'ComponentBase');
return ComponentBase;
}
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
function createTestToCheckExistenceOfShadowTree(callback, options = {htmlTemplate: false, cssTemplate: true})
{
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
class SomeComponent extends ComponentBase { }
if (options.htmlTemplate)
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
SomeComponent.htmlTemplate = () => { return '<div id="div" style="height: 10px;"></div>'; };
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
if (options.cssTemplate)
SomeComponent.cssTemplate = () => { return ':host { height: 10px; }'; };
let instance = new SomeComponent('some-component');
instance.element().style.display = 'block';
context.document.body.appendChild(instance.element());
return callback(instance, () => { return instance.element().offsetHeight == 10; });
});
}
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
it('must enqueue a connected component to render', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
let renderCall = 0;
class SomeComponent extends ComponentBase {
render() { renderCall++; }
}
ComponentBase.defineElement('some-component', SomeComponent);
let requestAnimationFrameCount = 0;
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
callback = newCallback;
requestAnimationFrameCount++;
}
expect(requestAnimationFrameCount).to.be(0);
const instance = new SomeComponent;
context.document.body.appendChild(instance.element());
expect(requestAnimationFrameCount).to.be(1);
callback();
expect(renderCall).to.be(1);
expect(requestAnimationFrameCount).to.be(1);
});
});
it('must enqueue a connected component to render upon a resize event if enqueueToRenderOnResize is true', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
class SomeComponent extends ComponentBase {
static get enqueueToRenderOnResize() { return true; }
}
ComponentBase.defineElement('some-component', SomeComponent);
let requestAnimationFrameCount = 0;
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
callback = newCallback;
requestAnimationFrameCount++;
}
expect(requestAnimationFrameCount).to.be(0);
const instance = new SomeComponent;
context.global.dispatchEvent(new Event('resize'));
context.document.body.appendChild(instance.element());
context.global.dispatchEvent(new Event('resize'));
expect(requestAnimationFrameCount).to.be(1);
});
});
it('must not enqueue a disconnected component to render upon a resize event if enqueueToRenderOnResize is true', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
class SomeComponent extends ComponentBase {
static get enqueueToRenderOnResize() { return true; }
}
ComponentBase.defineElement('some-component', SomeComponent);
let requestAnimationFrameCount = 0;
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
callback = newCallback;
requestAnimationFrameCount++;
}
const instance = new SomeComponent;
expect(requestAnimationFrameCount).to.be(0);
context.global.dispatchEvent(new Event('resize'));
expect(requestAnimationFrameCount).to.be(0);
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
describe('constructor', () => {
it('is a function', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
expect(ComponentBase).to.be.a('function');
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('can be instantiated', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
let callCount = 0;
class SomeComponent extends ComponentBase {
constructor() {
super('some-component');
callCount++;
}
}
let instance = new SomeComponent;
expect(instance).to.be.a(ComponentBase);
expect(instance).to.be.a(SomeComponent);
expect(callCount).to.be(1);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must not create shadow tree eagerly', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
expect(hasShadowTree()).to.be(false);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
});
describe('element()', () => {
it('must return an element', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
class SomeComponent extends ComponentBase { }
let instance = new SomeComponent('some-component');
expect(instance.element()).to.be.a(context.global.HTMLElement);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must return an element whose component() matches the component', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
const context = new BrowsingContext();
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
class SomeComponent extends ComponentBase { }
let instance = new SomeComponent('some-component');
expect(instance.element().component()).to.be(instance);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must not create shadow tree eagerly', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.element();
expect(hasShadowTree()).to.be(false);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
});
describe('content()', () => {
it('must create shadow tree', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.content();
expect(hasShadowTree()).to.be(true);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must return the same shadow tree each time it is called', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
expect(instance.content()).to.be(instance.content());
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
it('must return the element matching the id if an id is specified', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
class SomeComponent extends ComponentBase {
static htmlTemplate() { return '<div id="part1" title="foo"></div><div id="part1"></div>'; }
}
ComponentBase.defineElement('some-component', SomeComponent);
const instance = new SomeComponent;
const part1 = instance.content('part1');
expect(part1.localName).to.be('div');
expect(part1.title).to.be('foo');
expect(instance.content('part2')).to.be(null);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
});
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
it('it must create DOM tree from contentTemplate', async () => {
const context = new BrowsingContext();
const ComponentBase = await importComponentBase(context);
class SomeComponent extends ComponentBase { };
SomeComponent.contentTemplate = ['div', {id: 'container'}, 'hello, world'];
const instance = new SomeComponent('some-component');
const container = instance.content('container');
expect(container).to.be.a(context.global.HTMLDivElement);
expect(container.textContent).to.be('hello, world');
});
it('it must create content using derived class content template', async () => {
const context = new BrowsingContext();
const ComponentBase = await importComponentBase(context);
class BaseClass extends ComponentBase { };
BaseClass.contentTemplate = ['div', {id: 'container'}, 'base-class'];
const baseInstance = new BaseClass('base-class');
class DerivedClass extends BaseClass {};
DerivedClass.contentTemplate = ['div', {id: 'container'}, 'derived-class'];
const derivedInstance = new DerivedClass('derived-class');
const baseContainer = baseInstance.content('container');
expect(baseContainer).to.be.a(context.global.HTMLDivElement);
expect(baseContainer.textContent).to.be('base-class');
const derivedContainer = derivedInstance.content('container');
expect(derivedContainer).to.be.a(context.global.HTMLDivElement);
expect(derivedContainer.textContent).to.be('derived-class');
});
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
it('it must create stylsheet from styleTemplate', async () => {
const context = new BrowsingContext();
const ComponentBase = await importComponentBase(context);
class SomeComponent extends ComponentBase { };
SomeComponent.contentTemplate = ['span', 'hello, world'];
SomeComponent.styleTemplate = {':host': {'font-weight': 'bold'}};
const instance = new SomeComponent('some-component');
context.document.body.append(instance.element());
expect(context.global.getComputedStyle(instance.content().firstChild).fontWeight).to.be('bold');
});
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
describe('part()', () => {
it('must create shadow tree', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.part('foo');
expect(hasShadowTree()).to.be(true);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
});
it('must return the component matching the id if an id is specified', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
class SomeComponent extends ComponentBase { }
ComponentBase.defineElement('some-component', SomeComponent);
class OtherComponent extends ComponentBase {
static htmlTemplate() { return '<some-component id="foo"></some-component>'; }
}
ComponentBase.defineElement('other-component', OtherComponent);
const otherComponent = new OtherComponent;
const someComponent = otherComponent.part('foo');
expect(someComponent).to.be.a(SomeComponent);
expect(someComponent.element().id).to.be('foo');
expect(otherComponent.part('foo')).to.be(someComponent);
expect(otherComponent.part('bar')).to.be(null);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
});
});
describe('dispatchAction()', () => {
it('must invoke a callback specified in listenToAction', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
class SomeComponent extends ComponentBase { }
ComponentBase.defineElement('some-component', SomeComponent);
const instance = new SomeComponent;
const calls = [];
instance.listenToAction('action', (...args) => {
calls.push(args);
});
const object = {'foo': 1};
instance.dispatchAction('action', 'bar', object, 5);
expect(calls.length).to.be(1);
expect(calls[0][0]).to.be('bar');
expect(calls[0][1]).to.be(object);
expect(calls[0][2]).to.be(5);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
});
it('must not do anything when there are no callbacks', () => {
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(new BrowsingContext()).then((ComponentBase) => {
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
class SomeComponent extends ComponentBase { }
ComponentBase.defineElement('some-component', SomeComponent);
const object = {'foo': 1};
(new SomeComponent).dispatchAction('action', 'bar', object, 5);
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
describe('enqueueToRender()', () => {
it('must not immediately call render()', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
context.global.requestAnimationFrame = () => {}
let renderCallCount = 0;
const SomeComponent = class extends ComponentBase {
render() { renderCallCount++; }
}
ComponentBase.defineElement('some-component', SomeComponent);
(new SomeComponent).enqueueToRender();
expect(renderCallCount).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
(new SomeComponent).enqueueToRender();
expect(renderCallCount).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
});
});
it('must request an animation frame exactly once', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
let requestAnimationFrameCount = 0;
context.global.requestAnimationFrame = () => { requestAnimationFrameCount++; }
const SomeComponent = class extends ComponentBase { }
ComponentBase.defineElement('some-component', SomeComponent);
expect(requestAnimationFrameCount).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
let instance = new SomeComponent;
instance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
instance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
(new SomeComponent).enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
const AnotherComponent = class extends ComponentBase { }
ComponentBase.defineElement('another-component', AnotherComponent);
(new AnotherComponent).enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
});
});
it('must invoke render() when the callback to requestAnimationFrame is called', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
expect(callback).to.be(null);
expect(newCallback).to.not.be(null);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback = newCallback;
}
let renderCalls = [];
const SomeComponent = class extends ComponentBase {
render() {
renderCalls.push(this);
}
}
ComponentBase.defineElement('some-component', SomeComponent);
expect(renderCalls.length).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
const instance = new SomeComponent;
instance.enqueueToRender();
instance.enqueueToRender();
const anotherInstance = new SomeComponent;
anotherInstance.enqueueToRender();
expect(renderCalls.length).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback();
expect(renderCalls.length).to.be(2);
expect(renderCalls[0]).to.be(instance);
expect(renderCalls[1]).to.be(anotherInstance);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
});
});
it('must immediately invoke render() on a component enqueued inside another render() call', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
expect(callback).to.be(null);
expect(newCallback).to.not.be(null);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback = newCallback;
}
let renderCalls = [];
let instanceToEnqueue = null;
const SomeComponent = class extends ComponentBase {
render() {
renderCalls.push(this);
if (instanceToEnqueue)
instanceToEnqueue.enqueueToRender();
instanceToEnqueue = null;
}
}
ComponentBase.defineElement('some-component', SomeComponent);
expect(renderCalls.length).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
const instance = new SomeComponent;
const anotherInstance = new SomeComponent;
instance.enqueueToRender();
instanceToEnqueue = anotherInstance;
callback();
callback = null;
expect(renderCalls.length).to.be(2);
expect(renderCalls[0]).to.be(instance);
expect(renderCalls[1]).to.be(anotherInstance);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
renderCalls = [];
instance.enqueueToRender();
anotherInstance.enqueueToRender();
instanceToEnqueue = instance;
callback();
expect(renderCalls.length).to.be(3);
expect(renderCalls[0]).to.be(instance);
expect(renderCalls[1]).to.be(anotherInstance);
expect(renderCalls[2]).to.be(instance);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
});
});
it('must request a new animation frame once it exited the callback from requestAnimationFrame', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
let requestAnimationFrameCount = 0;
let callback = null;
context.global.requestAnimationFrame = (newCallback) => {
expect(callback).to.be(null);
expect(newCallback).to.not.be(null);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback = newCallback;
requestAnimationFrameCount++;
}
let renderCalls = [];
const SomeComponent = class extends ComponentBase {
render() { renderCalls.push(this); }
}
ComponentBase.defineElement('some-component', SomeComponent);
const instance = new SomeComponent;
const anotherInstance = new SomeComponent;
expect(requestAnimationFrameCount).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
instance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
anotherInstance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
expect(renderCalls.length).to.be(0);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback();
callback = null;
expect(renderCalls.length).to.be(2);
expect(renderCalls[0]).to.be(instance);
expect(renderCalls[1]).to.be(anotherInstance);
expect(requestAnimationFrameCount).to.be(1);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
anotherInstance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(2);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
instance.enqueueToRender();
expect(requestAnimationFrameCount).to.be(2);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
expect(renderCalls.length).to.be(2);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
callback();
callback = null;
expect(renderCalls.length).to.be(4);
expect(renderCalls[0]).to.be(instance);
expect(renderCalls[1]).to.be(anotherInstance);
expect(renderCalls[2]).to.be(anotherInstance);
expect(renderCalls[3]).to.be(instance);
expect(requestAnimationFrameCount).to.be(2);
Make calls to render() functions async https://bugs.webkit.org/show_bug.cgi?id=167151 Reviewed by Andreas Kling. Make calls to render() async by coalescing calls inside enqueueToRender(), which has been renamed from updateRendering(). We now queue up all the components and wait until the next animation frame to invoke render() on all those components. This reduces render() calls in the summary page of our internal dashboard by 15x from ~9400 to ~600 by eliminating pathological O(n^2) behavior between render() calls. Consolidated TimeSeriesChart's enqueueRender into this newly added feature of ComponentBase along with the support to call render() on a resize event. New implementation makes use of connectedCallback and disconnectedCallback to avoid the work when the component is not in a document tree. The rest of the patch concerns with renaming updateRendering to enqueueToRender and fixing a few minor bugs that I encountered while working on this patch. * browser-tests/component-base-tests.js: Added tests for ComponentBase.enqueueToRender(). * browser-tests/index.html: (BrowserContext.prototype.importScripts): Renamed from importScript; Now supports loading multiple scripts. (BrowserContext.prototype.importScript): Added. (BrowserContext): Removed the unused createWithScripts. * public/v3/components/analysis-results-viewer.js: (AnalysisResultsViewer.prototype._expandBetween): * public/v3/components/bar-graph-group.js: (BarGraphGroup.prototype.updateGroupRendering): * public/v3/components/base.js: (ComponentBase): When the browser doesn't support custom elements and (ComponentBase.prototype.enqueueToRender): Renamed from updateRendering. Queues up the component to call render() instead of immediately invoking it. (ComponentBase.renderingTimerDidFire): Call render(). Since render() function often calls enqueueToRender on child components, go ahead and invoke render() on any components enqueued during render() calls. (ComponentBase._connectedComponentToRenderOnResize): Added. (ComponentBase._disconnectedComponentToRenderOnResize): Added. (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Added. This is an optimization to avoid the work when the component is not in the document; e.g. because the entire page component has been detached from the document. The old implementation in TimeSeriesChart was not doing this. (ComponentBase.defineElement.elementClass.prototype.disconnectedCallback): Added. (ComponentBase): Replaced unused static variables with _componentsToRender and _componentsToRenderOnResize. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.fetchAnalysisTasks): (ChartPaneBase.prototype.didUpdateAnnotations): Added. Addresses the bug that the annotation bars in the charts shown an an analysis task doesn't update its color when the state is updated in the UI. (ChartPaneBase.prototype._mainSelectionDidZoom): (ChartPaneBase.prototype._updateStatus): (ChartPaneBase.prototype._requestOpeningCommitViewer): (ChartPaneBase.prototype._keyup): (ChartPaneBase.prototype.render): * public/v3/components/commit-log-viewer.js: * public/v3/components/customizable-test-group-form.js: (CustomizableTestGroupForm): (CustomizableTestGroupForm.prototype._customize): * public/v3/components/editable-text.js: (EditableText.prototype._didUpdate): * public/v3/components/interactive-time-series-chart.js: * public/v3/components/pane-selector.js: (PaneSelector.prototype._selectedItem): * public/v3/components/time-series-chart.js: (TimeSeriesChart): Removed the logic to update upon resize. See _connectedComponentToRenderOnResize above. (TimeSeriesChart.prototype.get enqueueToRenderOnResize): Added. Returns true. (TimeSeriesChart.prototype.enqueueToRender): Deleted. (TimeSeriesChart._renderEnqueuedCharts): Deleted. (TimeSeriesChart): Call ComponentBase.defineElement to make this a proper component so that the logic in connectedCallback to update upon resize event would work. * public/v3/instrumentation.js: (Instrumentation.dumpStatistics): Sort results by the key names. * public/v3/models/time-series.js: (TimeSeries.prototype.values): Added. This method was never ported to v3 in r198462, and broke the feature to show moving averages, etc... on the charts page. * public/v3/pages/analysis-category-page.js: (AnalysisCategoryPage.prototype.open): (AnalysisCategoryPage.prototype.updateFromSerializedState): (AnalysisCategoryPage.prototype.filterDidChange): (AnalysisCategoryPage.prototype.render): * public/v3/pages/analysis-task-page.js: (AnalysisTaskChartPane.prototype._updateStatus): (AnalysisTaskPage.prototype.updateFromSerializedState): (AnalysisTaskPage.prototype._didFetchTask): (AnalysisTaskPage.prototype._didFetchRelatedAnalysisTasks): (AnalysisTaskPage.prototype._didFetchMeasurement): (AnalysisTaskPage.prototype._didFetchTestGroups): (AnalysisTaskPage.prototype._showAllTestGroups): (AnalysisTaskPage.prototype._didFetchAnalysisResults): (AnalysisTaskPage.prototype.render): (AnalysisTaskPage.prototype._renderTestGroupList.): (AnalysisTaskPage.prototype._renderTestGroupList): (AnalysisTaskPage.prototype._createTestGroupListItem): (AnalysisTaskPage.prototype._showTestGroup): (AnalysisTaskPage.prototype._didStartEditingTaskName): (AnalysisTaskPage.prototype._updateTaskName): (AnalysisTaskPage.prototype._updateTestGroupName): (AnalysisTaskPage.prototype._hideCurrentTestGroup): (AnalysisTaskPage.prototype._updateChangeType): Fixed the bug that we were never updating annotation bars in the main chart by calling didUpdateAnnotations. (AnalysisTaskPage.prototype._associateBug): (AnalysisTaskPage.prototype._dissociateBug): (AnalysisTaskPage.prototype._associateCommit): (AnalysisTaskPage.prototype._dissociateCommit): (AnalysisTaskPage.prototype._chartSelectionDidChange): (AnalysisTaskPage.prototype._selectedRowInAnalysisResultsViewer): * public/v3/pages/build-request-queue-page.js: (BuildRequestQueuePage.prototype.open.): (BuildRequestQueuePage.prototype.open): * public/v3/pages/chart-pane.js: (ChartPane.prototype.setOpenRepository): (ChartPane.prototype._renderTrendLinePopover): Fixed a race condition. Insert a select element as needed before trying to assign the current value on it. (ChartPane.prototype._trendLineTypeDidChange): (ChartPane.prototype._updateTrendLine): * public/v3/pages/charts-page.js: (ChartsPage.prototype.updateFromSerializedState): (ChartsPage.prototype._updateDomainsFromSerializedState): (ChartsPage.prototype.setNumberOfDaysFromToolbar): (ChartsPage.prototype._didMutatePaneList): (ChartsPage.prototype.render): * public/v3/pages/charts-toolbar.js: (ChartsToolbar.prototype.render): * public/v3/pages/create-analysis-task-page.js: (CreateAnalysisTaskPage.prototype.updateFromSerializedState): * public/v3/pages/dashboard-page.js: (DashboardPage.prototype.updateFromSerializedState): (DashboardPage.prototype._fetchedData): * public/v3/pages/heading.js: (Heading.prototype.render): * public/v3/pages/page-with-heading.js: (PageWithHeading.prototype.render): * public/v3/pages/page.js: (Page.prototype.open): * public/v3/pages/summary-page.js: (SummaryPage.prototype.open): (SummaryPage.prototype.this._renderQueue.push): (SummaryPage): (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184216@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-18 21:22:39 +00:00
});
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
describe('render()', () => {
it('must create shadow tree', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.render();
expect(hasShadowTree()).to.be(true);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must not create shadow tree when neither htmlTemplate nor cssTemplate are present', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.render();
expect(hasShadowTree()).to.be(false);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
}, {htmlTemplate: false, cssTemplate: false});
});
it('must create shadow tree when htmlTemplate is present and cssTemplate is not', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.render();
expect(hasShadowTree()).to.be(true);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
}, {htmlTemplate: true, cssTemplate: false});
});
it('must create shadow tree when cssTemplate is present and htmlTemplate is not', () => {
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
instance.render();
expect(hasShadowTree()).to.be(true);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
}, {htmlTemplate: false, cssTemplate: true});
});
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
it('must invoke didConstructShadowTree after creating the shadow tree', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
let didConstructShadowTreeCount = 0;
let htmlTemplateCount = 0;
class SomeComponent extends ComponentBase {
didConstructShadowTree()
{
expect(this.content()).to.be.a(context.global.ShadowRoot);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
didConstructShadowTreeCount++;
}
static htmlTemplate()
{
htmlTemplateCount++;
return '';
}
}
ComponentBase.defineElement('some-component', SomeComponent);
const instance = new SomeComponent;
expect(didConstructShadowTreeCount).to.be(0);
expect(htmlTemplateCount).to.be(0);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
instance.render();
expect(didConstructShadowTreeCount).to.be(1);
expect(htmlTemplateCount).to.be(1);
Add a mechanism to dispatch and listen to an action https://bugs.webkit.org/show_bug.cgi?id=167191 Reviewed by Antti Koivisto. Added the notion of an action to components. Like DOM events, it can be dispatched or listen to. Also added ComponentBase.prototype.part which finds a sub-component inside a component's shadow tree, and made ComponentBase.prototype.content take an id to find an element that matches it. * browser-tests/close-button-tests.js: Added. Tests for CloseButton. * browser-tests/component-base-tests.js: Added tests for ComponentBase's part(~), content(id), dispatchEvent. * browser-tests/index.html: * public/v3/components/base.js: (ComponentBase): Added this._actionCallbacks, which is a map of an action name to a callback to be invoked. (ComponentBase.prototype.content): Return an element of the given id if one is specified. (ComponentBase.prototype.part): Find a component whose element has the matching id. (ComponentBase.prototype.dispatchAction): Added. (ComponentBase.prototype.listenToAction): Added. (ComponentBase.prototype._ensureShadowTree): Call didConstructShadowTree. (ComponentBase.prototype.didConstructShadowTree): Added. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Copy attributes when instantiating an element for a component when the browser doesn't support custom elements API. (ComponentBase.createLink): (ComponentBase.prototype.createEventHandler): Added. (ComponentBase.createEventHandler): Renamed from createActionHandler. * public/v3/components/button-base.js: (ButtonBase.prototype.didConstructShadowTree): Added. Dispatch "activate" action when the button is clicked. (ButtonBase.prototype.setCallback): Deleted. (ButtonBase.htmlTemplate): Use id instead of class so that this.content() can find it. (ButtonBase.cssTemplate): Updated style rules. * public/v3/pages/chart-pane.js: (ChartPane): (ChartPane.prototype.didConstructShadowTree): Added. Listen to "activate" action on the close button. (ChartPane.prototype.render): Fixed a bug that we were never calling enqueueToRender on the close button. (ChartPane.htmlTemplate): Add the id on the close button. Canonical link: https://commits.webkit.org/184266@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-19 22:58:46 +00:00
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
describe('createElement()', () => {
it('should create an element of the specified name', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const div = ComponentBase.createElement('div');
expect(div).to.be.a(context.global.HTMLDivElement);
});
});
it('should allow to create an element with attributes to be null or undefined', () => {
const context = new BrowsingContext();
return importComponentBase(context).then((ComponentBase) => {
const input = ComponentBase.createElement('input', {'title': null, 'required': undefined});
expect(input).to.be.a(context.global.HTMLInputElement);
expect(input.attributes.length).to.be(2);
expect(input.attributes[0].localName).to.be('title');
expect(input.attributes[0].value).to.be('null');
expect(input.attributes[1].localName).to.be('required');
expect(input.attributes[1].value).to.be('undefined');
});
});
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
it('should create an element with the specified attributes', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const input = ComponentBase.createElement('input', {'title': 'hi', 'id': 'foo', 'required': false, 'checked': true});
expect(input).to.be.a(context.global.HTMLInputElement);
expect(input.attributes.length).to.be(3);
expect(input.attributes[0].localName).to.be('title');
expect(input.attributes[0].value).to.be('hi');
expect(input.attributes[1].localName).to.be('id');
expect(input.attributes[1].value).to.be('foo');
expect(input.attributes[2].localName).to.be('checked');
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
expect(input.attributes[2].value).to.be('');
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
});
});
it('should create an element with the specified event handlers and attributes', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
let clickCount = 0;
const div = ComponentBase.createElement('div', {'title': 'hi', 'onclick': () => clickCount++});
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(1);
expect(div.attributes[0].localName).to.be('title');
expect(div.attributes[0].value).to.be('hi');
expect(clickCount).to.be(0);
div.click();
expect(clickCount).to.be(1);
});
});
it('should create an element with the specified children when there is no attribute specified', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const element = ComponentBase.createElement;
const span = element('span');
const div = element('div', [span, 'hi']);
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(0);
expect(div.childNodes.length).to.be(2);
expect(div.childNodes[0]).to.be(span);
expect(div.childNodes[1]).to.be.a(context.global.Text);
expect(div.childNodes[1].data).to.be('hi');
});
});
it('should create an element with the specified children when the second argument is a span', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const element = ComponentBase.createElement;
const span = element('span');
const div = element('div', span);
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(0);
expect(div.childNodes.length).to.be(1);
expect(div.childNodes[0]).to.be(span);
});
});
it('should create an element with the specified children when the second argument is a Text node', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const element = ComponentBase.createElement;
const text = context.document.createTextNode('hi');
const div = element('div', text);
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(0);
expect(div.childNodes.length).to.be(1);
expect(div.childNodes[0]).to.be(text);
});
});
it('should create an element with the specified children when the second argument is a component', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
class SomeComponent extends ComponentBase { };
ComponentBase.defineElement('some-component', SomeComponent);
const element = ComponentBase.createElement;
const component = new SomeComponent;
const div = element('div', component);
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(0);
expect(div.childNodes.length).to.be(1);
expect(div.childNodes[0]).to.be(component.element());
});
});
it('should create an element with the specified attributes and children', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
ComponentBase should enqueue itself to render when it becomes connected https://bugs.webkit.org/show_bug.cgi?id=169905 Reviewed by Antti Koivisto. When a component becomes connected to a document, enqueue itself to render automatically. Also added the support for boolean attribute to ComponentBase.createElement. * ReadMe.md: Added an instruction to raise the upload limit per r214065. * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved the tests related to enqueueToRenderOnResize out of defineElement tests. * browser-tests/index.html: (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be involved immediately durign testing. * public/v3/components/base.js: (ComponentBase): Enqueue itself to render during construction if custom elements is not available. (ComponentBase.defineElement): (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when the component's element became connected. (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made in other realms (global objects) during testing. Added the support for boolean attributes. Setting an attribute value to true would set the attribute, and setting it to false would not set the attribute. (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined. * public/v3/components/chart-pane-base.js: (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer. * public/v3/components/commit-log-viewer.js: (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon. * public/v3/models/time-series.js: (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300. * public/v3/pages/chart-pane.js: (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon. * public/v3/pages/summary-page.js: (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon. Canonical link: https://commits.webkit.org/186907@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214280 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-03-22 22:50:57 +00:00
const element = ComponentBase.createElement;
const span = element('span');
const div = element('div', {'lang': 'en'}, [span, 'hi']);
expect(div).to.be.a(context.global.HTMLDivElement);
expect(div.attributes.length).to.be(1);
expect(div.attributes[0].localName).to.be('lang');
expect(div.attributes[0].value).to.be('en');
expect(div.childNodes.length).to.be(2);
expect(div.childNodes[0]).to.be(span);
expect(div.childNodes[1]).to.be.a(context.global.Text);
expect(div.childNodes[1].data).to.be('hi');
});
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
describe('defineElement()', () => {
it('must define a custom element with a class of an appropriate name', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
class SomeComponent extends ComponentBase { }
ComponentBase.defineElement('some-component', SomeComponent);
let elementClass = context.global.customElements.get('some-component');
expect(elementClass).to.be.a('function');
expect(elementClass.name).to.be('SomeComponentElement');
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must define a custom element that can be instantiated via document.createElement', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
let instances = [];
class SomeComponent extends ComponentBase {
constructor() {
super();
instances.push(this);
}
}
ComponentBase.defineElement('some-component', SomeComponent);
expect(instances.length).to.be(0);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
let element = context.document.createElement('some-component');
expect(instances.length).to.be(1);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
expect(element).to.be.a(context.global.HTMLElement);
expect(element.component()).to.be(instances[0]);
expect(instances[0].element()).to.be(element);
expect(instances.length).to.be(1);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
it('must define a custom element that can be instantiated via new', () => {
const context = new BrowsingContext();
Add the basic support for writing components in node.js https://bugs.webkit.org/show_bug.cgi?id=186299 Reviewed by Antti Koivisto. Add the basic support for writing components in node.js for generating rich email notifications. To do this, this patch introduces MarkupComponentBase and MarkupPage which implement similar API to ComponentBase and Page classes of v3 UI code. This enables us to share code between frontend and the backend in the future. Because there is no support for declarative custom elements or shadow root in HTML, MarkupComponentBase uses a similar but distinct concept of "content" tree to represent the "DOM" tree for a component. When generating the HTML, MarkupComponentBase and MarkupPage collectively transforms stylesheets and flattens the tree into a single HTML. In order to keep this flatteneing logic simple, MarkupComponentBase only supports a very small subset of CSS selectors to select elements by their local names and class names. Specifically, each class name and element name based selectors are replaced by a globally unique class name based selector, and each element which matches the selector is applied of the same globally unique class name. The transformation is applied when constructing the "content" tree as well as calls to renderReplace. Because much of v3 frontend code relies on DOM API, this patch also implements the simplest form of a fake DOM API as MarkupNode, MarkupParentNode, MarkupElement, and MarkupText. In order to avoid reimplementing HTML & CSS parsers, this patch introduces the concept of content and style templates to ComponentBase which are JSON alternatives to HTML & CSS template strings which can be used in both frontend & backend. * browser-tests/close-button-tests.js: Include CommonComponentBase. * browser-tests/commit-log-viewer-tests.js: Ditto. * browser-tests/component-base-tests.js: Ditto. Added a test cases for content & style templates. (async.importComponentBase): Added. * browser-tests/editable-text-tests.js: Include CommonComponentBase. * browser-tests/index.html: * browser-tests/markup-page-tests.js: Added. * browser-tests/page-router-tests.js: Include CommonComponentBase. * browser-tests/page-tests.js: Ditto. * browser-tests/test-group-form-tests.js: Ditto. * public/shared/common-component-base.js: Added. (CommonComponentBase): Extracted out of ComponentBase. (CommonComponentBase.prototype.renderReplace): Added. (CommonComponentBase.renderReplace): Moved from ComponentBase. (CommonComponentBase.prototype._recursivelyUpgradeUnknownElements): Moved and renamed from ComponentBase's _recursivelyReplaceUnknownElementsByComponents. (CommonComponentBase.prototype._upgradeUnknownElement): Extracted out of the same function. (CommonComponentBase._constructStylesheetFromTemplate): Added. (CommonComponentBase._constructNodeTreeFromTemplate): Added. (CommonComponentBase.prototype.createElement): Added. (CommonComponentBase.createElement): Moved from ComponentBase. (CommonComponentBase._addContentToElement): Moved from ComponentBase. (CommonComponentBase.prototype.createLink): Added. (CommonComponentBase.createLink): Moved from ComponentBase. (CommonComponentBase._context): Added. Set to document in a browser and MarkupDocument in node.js. (CommonComponentBase._isNode): Added. Set to a function which does instanceof Node/MarkupNode check. (CommonComponentBase._baseClass): Added. Set to ComponentBase or MarkupComponentBase. * public/v3/components/base.js: (ComponentBase): (ComponentBase.prototype._ensureShadowTree): Added the support for the content and style templates. Also avoid parsing the html template each time a component is instantiated by caching the result. * public/v3/index.html: * tools/js/markup-component.js: Added. (MarkupDocument): Added. A fake Document. (MarkupDocument.prototype.createContentRoot): A substitude for attachShadow. (MarkupDocument.prototype.createElement): (MarkupDocument.prototype.createTextNode): (MarkupDocument.prototype._idForClone): (MarkupDocument.prototype.reset): (MarkupDocument.prototype.markup): (MarkupDocument.prototype.escapeAttributeValue): (MarkupDocument.prototype.escapeNodeData): (MarkupNode): Added. A fake Node. Each node gets an unique ID. (MarkupNode.prototype._markup): (MarkupNode.prototype.clone): Implemented by the leave class. (MarkupNode.prototype._cloneNodeData): (MarkupNode.prototype.remove): (MarkupParentNode): Added. An equivalent of ContainerNode in WebCore. (MarkupParentNode.prototype.get childNodes): (MarkupParentNode.prototype._cloneNodeData): (MarkupParentNode.prototype.appendChild): (MarkupParentNode.prototype.removeChild): (MarkupParentNode.prototype.removeAllChildren): (MarkupParentNode.prototype.replaceChild): (MarkupContentRoot): Added. Used like a shadow tree. (MarkupContentRoot.prototype._markup): Added. (MarkupElement): Added. A fake Element. It also implements a subset of IDL attributes implemented by subclasses such as HTMLInputElement for simplicity. (MarkupElement.prototype.get id): Added. (MarkupElement.prototype.get localName): Added. (MarkupElement.prototype.clone): Added. (MarkupElement.prototype.appendChild): Added. (MarkupElement.prototype.addEventListener): Added. (MarkupElement.prototype.setAttribute): Added. (MarkupElement.prototype.getAttribute): Added. (MarkupElement.prototype.get attributes): Added. (MarkupElement.prototype.get textContent): Added. (MarkupElement.prototype.set textContent): Added. (MarkupElement.prototype._serializeStyle): Added. (MarkupElement.prototype._markup): Added. Flattens the tree with content tree like copy & paste so this can't be used to implement innerHTML. (MarkupElement.prototype.get value): Added. (MarkupElement.prototype.set value): Added. (MarkupElement.prototype.get style): Added. Returns a fake writeonly CSSStyleDeclaration. (MarkupElement.prototype.set style): Added. (MarkupElement.get selfClosingNames): Added. A small list of self-closing tags for the HTML generation. (MarkupText): Added. (MarkupText.prototype.clone): Added. (MarkupText.prototype._markup): Added. (MarkupText.prototype.get data): Added. (MarkupText.prototype.set data): Added. (MarkupComponentBase): Added. (MarkupComponentBase.prototype.element): Added. Like ComponentBase's element. (MarkupComponentBase.prototype.content): Added. Like ComponentBase's content. (MarkupComponentBase.prototype._findElementRecursivelyById): Added. A fake getElementById. (MarkupComponentBase.prototype.render): Added. Like ComponentBase's render. (MarkupComponentBase.prototype.runRenderLoop): Added. In ComponentBase, we use requestAnimationFrame. In MarkupComponentBase, we keep rendering until the queue drains empty. (MarkupComponentBase.prototype.renderReplace): Added. Like ComponentBase's renderReplace but applies the transformation of classes to workaround the lack of shadow tree support in scriptless HTML. (MarkupComponentBase.prototype._applyStyleOverrides): Added. Recursively applies the transformation. (MarkupComponentBase.prototype._ensureContentTree): Added. Like ComponentBase's _ensureShadowTree. (MarkupComponentBase.reset): Added. (MarkupComponentBase._parseTemplates): Added. Parses the content & style templates, and generates the transformed fake DOM tree and stylesheet text whereby selectors in each component is modified to be unique across all components. The function to apply the necessary changes to an element is saved in the global map of components, and later used in renderReplace via _applyStyleOverrides. (MarkupComponentBase.defineElement): Added. Like ComponentBase's defineElement. (MarkupComponentBase.prototype.createEventHandler): Added. (MarkupComponentBase.createEventHandler): Added. (MarkupPage): Added. The top-level component responsible for generating a DOCTYPE, head, and body. (MarkupPage.prototype.pageTitle): Added. (MarkupPage.prototype.content): Added. Overrides the one in MarkupComponentBase to return what would be the content of the body element as opposed to the html element for the connivance of subclasses, and to match the behavior of the frontend Page class. (MarkupPage.prototype.render): Added. (MarkupPage.prototype._updateComponentsStylesheet): Added. Concatenates the transformed stylesheet of all components used. (MarkupPage.get contentTemplate): Added. (MarkupPage.prototype.generateMarkup): Added. Enqueues the page to render, spin the render loop, and generates the HTML. We enqueue the page twice in order to invoke _updateComponentsStylesheet after all subcomponent had finished rendering. * unit-tests/markup-component-base-tests.js: Added. * unit-tests/markup-element-tests.js: Added. (.createElement): Added. * unit-tests/markup-page-tests.js: Added. Canonical link: https://commits.webkit.org/201761@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232588 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-07 18:25:35 +00:00
return importComponentBase(context).then((ComponentBase) => {
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
let instances = [];
class SomeComponent extends ComponentBase {
constructor() {
super();
instances.push(this);
}
}
ComponentBase.defineElement('some-component', SomeComponent);
expect(instances.length).to.be(0);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
let component = new SomeComponent;
expect(instances.length).to.be(1);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
expect(component).to.be(instances[0]);
expect(component.element()).to.be.a(context.global.HTMLElement);
expect(component.element().component()).to.be(component);
expect(instances.length).to.be(1);
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});
});
});
describe('_ensureShadowTree', () => {
it('should parse derived component after parsing base component', async () => {
const context = new BrowsingContext();
const ComponentBase = await importComponentBase(context);
class DerivedComponent extends ComponentBase {};
const baseInstance = new ComponentBase;
expect(ComponentBase.hasOwnProperty('_parsed')).to.be(false);
expect(DerivedComponent.hasOwnProperty('_parsed')).to.be(false);
baseInstance._ensureShadowTree();
expect(ComponentBase.hasOwnProperty('_parsed')).to.be(true);
expect(DerivedComponent.hasOwnProperty('_parsed')).to.be(false);
expect(!!ComponentBase._parsed).to.be(true);
expect(!!DerivedComponent._parsed).to.be(true);
const derivedInstance = new DerivedComponent;
derivedInstance._ensureShadowTree();
expect(ComponentBase.hasOwnProperty('_parsed')).to.be(true);
expect(DerivedComponent.hasOwnProperty('_parsed')).to.be(true);
expect(!!ComponentBase._parsed).to.be(true);
expect(!!DerivedComponent._parsed).to.be(true);
});
});
Adopt custom elements API in perf dashboard https://bugs.webkit.org/show_bug.cgi?id=167045 Reviewed by Darin Adler. Adopt custom elements API in ComponentBase, and create the shadow tree lazily in content() and render() instead of eagerly creating it inside the constructor. For now, create a separate element class for each component in ComponentBase.defineElement instead of making ComponentBase inherit from HTMLElement to preserve the semantics we have as well as to test the boundaries of what custom elements API allows for framework authors. In order to ensure one-to-one correspondence between elements and their components, we use a static map, ComponentBase._currentlyConstructedByInterface, to remember which element or component is being created and use that in custom element's constructor to update element.component() and this._element. Also dropped the support for not having attachShadow as we've shipped this feature in Safari 10. Finally, added tests to be ran inside a browser to test the front end code in browser-tests. * browser-tests/component-base-tests.js: Added. Basic tests for ComponentBase. * browser-tests/index.html: Added. * public/v3/components/base.js: (ComponentBase): Don't create the shadow tree. Use the currently constructed element as this._element if there is one (the custom element's constructor is getting called). Otherwise create a new element but store this component in the map to avoid creating a new component in the custom element's constructor. (ComponentBase.prototype.content): Lazily create the shadow tree now. (ComponentBase.prototype.render): Ditto. (ComponentBase.prototype._ensureShadowTree): Renamed from _constructShadowTree. Dropped the support for not having shadow DOM API. This is now required. Also use importNode instead of cloneNode in cloning the template content since the latter would not get upgraded. (ComponentBase.prototype._recursivelyReplaceUnknownElementsByComponents): Modernized the code. Don't re-create a component if its element had already been upgraded by its custom element constructor. (ComponentBase.defineElement): Add this component to the static maps. _componentByName is used by _recursivelyReplaceUnknownElementsByComponents to instantiate new components in the browsers that don't support custom elements API and _componentByClass is used by ComponentBase's constructor to lookup the element name. The latter should go away once all components fully adopt ComponentBase.defineElement. (ComponentBase.defineElement.elementClass): A class to define a custom element for the component. We need to reconfigure the property since class's name is not writable but configurable. * public/v3/components/button-base.js: (ButtonBase.htmlTemplate): Added. Extracted the common code from CloseButton and WarningIcon. (ButtonBase.buttonContent): Added. An abstract method overridden by CloseButton and WarningIcon. (ButtonBase.sizeFactor): Added. Overridden by WarningIcon. (ButtonBase.cssTemplate): Updated to use :host. * public/v3/components/close-button.js: (CloseButton.buttonContent): Renamed from htmlTemplate. * public/v3/components/spinner-icon.js: (SpinnerIcon.cssTemplate): Removed webkit prefixed properties, and updated it to animate stroke instead of opacity to reduce the power usage. (SpinnerIcon.htmlTemplate): Factored stroke, stroke-width, and stroke-linecap into cssTemplate. * public/v3/components/warning-icon.js: (WarningIcon.cssTemplate): Deleted. (WarningIcon.sizeFactor): Added. (WarningIcon.buttonContent): Renamed from htmlTemplate. * public/v3/pages/summary-page.js: (SummaryPage._constructRatioGraph): Fixed a bug that we were not never calling spinner.updateRendering(). (SummaryPage.prototype._renderCell): Canonical link: https://commits.webkit.org/184156@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210783 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-01-16 00:12:22 +00:00
});