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;
|
|
|
|
}
|
|
|
|
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
class SomeComponent extends ComponentBase { }
|
|
|
|
if (options.htmlTemplate)
|
2017-01-19 22:58:46 +00:00
|
|
|
SomeComponent.htmlTemplate = () => { return '<div id="div" style="height: 10px;"></div>'; };
|
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; });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
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) => {
|
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) => {
|
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) => {
|
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);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
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) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(ComponentBase).to.be.a('function');
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
let callCount = 0;
|
|
|
|
class SomeComponent extends ComponentBase {
|
|
|
|
constructor() {
|
|
|
|
super('some-component');
|
|
|
|
callCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let instance = new SomeComponent;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instance).to.be.a(ComponentBase);
|
|
|
|
expect(instance).to.be.a(SomeComponent);
|
|
|
|
expect(callCount).to.be(1);
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('must not create shadow tree eagerly', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(false);
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
class SomeComponent extends ComponentBase { }
|
|
|
|
let instance = new SomeComponent('some-component');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instance.element()).to.be.a(context.global.HTMLElement);
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
class SomeComponent extends ComponentBase { }
|
|
|
|
let instance = new SomeComponent('some-component');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instance.element().component()).to.be(instance);
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('must not create shadow tree eagerly', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
|
|
|
instance.element();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(false);
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('content()', () => {
|
|
|
|
it('must create shadow tree', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
|
|
|
instance.content();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(true);
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('must return the same shadow tree each time it is called', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instance.content()).to.be(instance.content());
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
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) => {
|
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');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(part1.localName).to.be('div');
|
|
|
|
expect(part1.title).to.be('foo');
|
|
|
|
expect(instance.content('part2')).to.be(null);
|
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');
|
|
|
|
});
|
|
|
|
|
2018-06-28 22:14:39 +00:00
|
|
|
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');
|
|
|
|
});
|
2017-01-19 22:58:46 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('part()', () => {
|
|
|
|
it('must create shadow tree', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
|
|
|
instance.part('foo');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(true);
|
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) => {
|
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');
|
2017-02-17 05:36:05 +00:00
|
|
|
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);
|
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) => {
|
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);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
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);
|
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) => {
|
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);
|
|
|
|
});
|
|
|
|
});
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
|
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) => {
|
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();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCallCount).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
(new SomeComponent).enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCallCount).to.be(0);
|
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) => {
|
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);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
let instance = new SomeComponent;
|
|
|
|
instance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
instance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
(new SomeComponent).enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
const AnotherComponent = class extends ComponentBase { }
|
|
|
|
ComponentBase.defineElement('another-component', AnotherComponent);
|
|
|
|
(new AnotherComponent).enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
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) => {
|
2017-01-18 21:22:39 +00:00
|
|
|
let callback = null;
|
|
|
|
context.global.requestAnimationFrame = (newCallback) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(callback).to.be(null);
|
|
|
|
expect(newCallback).to.not.be(null);
|
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);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
const instance = new SomeComponent;
|
|
|
|
instance.enqueueToRender();
|
|
|
|
instance.enqueueToRender();
|
|
|
|
|
|
|
|
const anotherInstance = new SomeComponent;
|
|
|
|
anotherInstance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
callback();
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(2);
|
|
|
|
expect(renderCalls[0]).to.be(instance);
|
|
|
|
expect(renderCalls[1]).to.be(anotherInstance);
|
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) => {
|
2017-01-18 21:22:39 +00:00
|
|
|
let callback = null;
|
|
|
|
context.global.requestAnimationFrame = (newCallback) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(callback).to.be(null);
|
|
|
|
expect(newCallback).to.not.be(null);
|
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);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
const instance = new SomeComponent;
|
|
|
|
const anotherInstance = new SomeComponent;
|
|
|
|
instance.enqueueToRender();
|
|
|
|
instanceToEnqueue = anotherInstance;
|
|
|
|
callback();
|
|
|
|
callback = null;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(2);
|
|
|
|
expect(renderCalls[0]).to.be(instance);
|
|
|
|
expect(renderCalls[1]).to.be(anotherInstance);
|
2017-01-18 21:22:39 +00:00
|
|
|
renderCalls = [];
|
|
|
|
|
|
|
|
instance.enqueueToRender();
|
|
|
|
anotherInstance.enqueueToRender();
|
|
|
|
instanceToEnqueue = instance;
|
|
|
|
callback();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(3);
|
|
|
|
expect(renderCalls[0]).to.be(instance);
|
|
|
|
expect(renderCalls[1]).to.be(anotherInstance);
|
|
|
|
expect(renderCalls[2]).to.be(instance);
|
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) => {
|
2017-01-18 21:22:39 +00:00
|
|
|
let requestAnimationFrameCount = 0;
|
|
|
|
let callback = null;
|
|
|
|
context.global.requestAnimationFrame = (newCallback) => {
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(callback).to.be(null);
|
|
|
|
expect(newCallback).to.not.be(null);
|
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;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
instance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
anotherInstance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(0);
|
2017-01-18 21:22:39 +00:00
|
|
|
callback();
|
|
|
|
callback = null;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(2);
|
|
|
|
expect(renderCalls[0]).to.be(instance);
|
|
|
|
expect(renderCalls[1]).to.be(anotherInstance);
|
|
|
|
expect(requestAnimationFrameCount).to.be(1);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
|
|
|
anotherInstance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(2);
|
2017-01-18 21:22:39 +00:00
|
|
|
instance.enqueueToRender();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(requestAnimationFrameCount).to.be(2);
|
2017-01-18 21:22:39 +00:00
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(renderCalls.length).to.be(2);
|
2017-01-18 21:22:39 +00:00
|
|
|
callback();
|
|
|
|
callback = null;
|
2017-02-17 05:36:05 +00:00
|
|
|
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);
|
2017-01-18 21:22:39 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2017-01-16 00:12:22 +00:00
|
|
|
describe('render()', () => {
|
|
|
|
it('must create shadow tree', () => {
|
|
|
|
return createTestToCheckExistenceOfShadowTree((instance, hasShadowTree) => {
|
|
|
|
instance.render();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(true);
|
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();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(false);
|
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();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(true);
|
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();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(hasShadowTree()).to.be(true);
|
2017-01-16 00:12:22 +00:00
|
|
|
}, {htmlTemplate: false, cssTemplate: true});
|
|
|
|
});
|
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) => {
|
2017-01-19 22:58:46 +00:00
|
|
|
let didConstructShadowTreeCount = 0;
|
|
|
|
let htmlTemplateCount = 0;
|
|
|
|
|
|
|
|
class SomeComponent extends ComponentBase {
|
|
|
|
didConstructShadowTree()
|
|
|
|
{
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(this.content()).to.be.a(context.global.ShadowRoot);
|
2017-01-19 22:58:46 +00:00
|
|
|
didConstructShadowTreeCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static htmlTemplate()
|
|
|
|
{
|
|
|
|
htmlTemplateCount++;
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ComponentBase.defineElement('some-component', SomeComponent);
|
|
|
|
|
|
|
|
const instance = new SomeComponent;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(didConstructShadowTreeCount).to.be(0);
|
|
|
|
expect(htmlTemplateCount).to.be(0);
|
2017-01-19 22:58:46 +00:00
|
|
|
instance.render();
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(didConstructShadowTreeCount).to.be(1);
|
|
|
|
expect(htmlTemplateCount).to.be(1);
|
2017-01-19 22:58:46 +00:00
|
|
|
});
|
|
|
|
});
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
|
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) => {
|
2017-03-22 22:50:57 +00:00
|
|
|
const div = ComponentBase.createElement('div');
|
|
|
|
expect(div).to.be.a(context.global.HTMLDivElement);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-06-08 04:40:42 +00:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
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) => {
|
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('');
|
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) => {
|
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) => {
|
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) => {
|
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) => {
|
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) => {
|
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) => {
|
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');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
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) => {
|
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');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(elementClass).to.be.a('function');
|
|
|
|
expect(elementClass.name).to.be('SomeComponentElement');
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
let instances = [];
|
|
|
|
class SomeComponent extends ComponentBase {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
instances.push(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ComponentBase.defineElement('some-component', SomeComponent);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instances.length).to.be(0);
|
2017-01-16 00:12:22 +00:00
|
|
|
let element = context.document.createElement('some-component');
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instances.length).to.be(1);
|
2017-01-16 00:12:22 +00:00
|
|
|
|
2017-02-17 05:36:05 +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);
|
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) => {
|
2017-01-16 00:12:22 +00:00
|
|
|
let instances = [];
|
|
|
|
class SomeComponent extends ComponentBase {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
instances.push(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ComponentBase.defineElement('some-component', SomeComponent);
|
|
|
|
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instances.length).to.be(0);
|
2017-01-16 00:12:22 +00:00
|
|
|
let component = new SomeComponent;
|
2017-02-17 05:36:05 +00:00
|
|
|
expect(instances.length).to.be(1);
|
2017-01-16 00:12:22 +00:00
|
|
|
|
2017-02-17 05:36:05 +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);
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2018-06-28 22:14:39 +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);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-01-16 00:12:22 +00:00
|
|
|
});
|