Diff
Modified: trunk/Websites/perf.webkit.org/ChangeLog (214279 => 214280)
--- trunk/Websites/perf.webkit.org/ChangeLog 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/ChangeLog 2017-03-22 22:50:57 UTC (rev 214280)
@@ -1,3 +1,46 @@
+2017-03-22 Ryosuke Niwa <rn...@webkit.org>
+
+ ComponentBase should enqueue itself to render when it becomes connected
+ https://bugs.webkit.org/show_bug.cgi?id=169905
+
+ Reviewed by Antti Koivisto.
+
+ When a component becomes connected to a document, enqueue itself to render automatically.
+ Also added the support for boolean attribute to ComponentBase.createElement.
+
+ * ReadMe.md: Added an instruction to raise the upload limit per r214065.
+ * browser-tests/component-base-tests.js: Added tests for the new behavior and createElement. Also moved
+ the tests related to enqueueToRenderOnResize out of defineElement tests.
+
+ * browser-tests/index.html:
+ (BrowsingContext.prototype.constructor): Override requestAnimationFrame so that the callback would be
+ involved immediately durign testing.
+
+ * public/v3/components/base.js:
+ (ComponentBase): Enqueue itself to render during construction if custom elements is not available.
+ (ComponentBase.defineElement):
+ (ComponentBase.defineElement.elementClass.prototype.connectedCallback): Enqueue itself to render when
+ the component's element became connected.
+ (ComponentBase.createElement): Use Array.isArray instead of instanceof to make it work with arrays made
+ in other realms (global objects) during testing. Added the support for boolean attributes. Setting an
+ attribute value to true would set the attribute, and setting it to false would not set the attribute.
+ (ComponentBase.useNativeCustomElements): Added. True iff window.customElements is defined.
+
+ * public/v3/components/chart-pane-base.js:
+ (ChartPaneBase.prototype.render): No longer need to call enqueueToRender on the commit log viewer.
+
+ * public/v3/components/commit-log-viewer.js:
+ (CommitLogViewer.prototype.render): No longer need to call enqueueToRender on the spinner icon.
+
+ * public/v3/models/time-series.js:
+ (TimeSeries): Made this a proper class declaration now that we don't include data.js after r213300.
+
+ * public/v3/pages/chart-pane.js:
+ (ChartPane.prototype._renderActionToolbar): No longer need to call enqueueToRender on the close icon.
+
+ * public/v3/pages/summary-page.js:
+ (SummaryPage.prototype._renderCell): No longer need to call enqueueToRender on the spinner icon.
+
2017-03-20 Ryosuke Niwa <rn...@webkit.org>
Delete another function that was supposed to be removed in the previous commit.
Modified: trunk/Websites/perf.webkit.org/ReadMe.md (214279 => 214280)
--- trunk/Websites/perf.webkit.org/ReadMe.md 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/ReadMe.md 2017-03-22 22:50:57 UTC (rev 214280)
@@ -84,6 +84,13 @@
Options Indexes MultiViews
php_flag zlib.output_compression on
+ 4. Increase the maximum upload size as needed for accepting custom roots:
+
+ <IfModule php5_module>
+ php_value upload_max_filesize 100M
+ php_value post_max_size 100M
+ </IfModule>
+
### Protecting the Administrative Pages to Prevent Execution of Arbitrary Code
By default, the application gives the administrative privilege to everyone. Anyone can add, remove, or edit tests,
Modified: trunk/Websites/perf.webkit.org/browser-tests/component-base-tests.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/browser-tests/component-base-tests.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/browser-tests/component-base-tests.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -18,6 +18,78 @@
});
}
+ it('must enqueue a connected component to render', () => {
+ const context = new BrowsingContext();
+ return context.importScripts(['instrumentation.js', 'components/base.js'], 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScripts(['instrumentation.js', 'components/base.js'], 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScripts(['instrumentation.js', 'components/base.js'], 'ComponentBase').then((ComponentBase) => {
+ 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);
+ });
+ });
+
describe('constructor', () => {
it('is a function', () => {
return new BrowsingContext().importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
@@ -406,6 +478,121 @@
});
});
+ describe('createElement()', () => {
+
+ it('should create an element of the specified name', () => {
+ const context = new BrowsingContext();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ const div = ComponentBase.createElement('div');
+ expect(div).to.be.a(context.global.HTMLDivElement);
+ });
+ });
+
+ it('should create an element with the specified attributes', () => {
+ const context = new BrowsingContext();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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');
+ expect(input.attributes[2].value).to.be('checked');
+ });
+ });
+
+ it('should create an element with the specified event handlers and attributes', () => {
+ const context = new BrowsingContext();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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();
+ return context.importScript('components/base.js', 'ComponentBase').then((ComponentBase) => {
+ 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');
+ });
+ });
+
+ });
+
describe('defineElement()', () => {
it('must define a custom element with a class of an appropriate name', () => {
@@ -466,52 +653,6 @@
});
});
- it('must enqueue a connected component to render upon a resize event if enqueueToRenderOnResize is true', () => {
- const context = new BrowsingContext();
- return context.importScripts(['instrumentation.js', 'components/base.js'], 'ComponentBase').then((ComponentBase) => {
- 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();
- return context.importScripts(['instrumentation.js', 'components/base.js'], 'ComponentBase').then((ComponentBase) => {
- 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);
- });
- });
-
});
});
Modified: trunk/Websites/perf.webkit.org/browser-tests/index.html (214279 => 214280)
--- trunk/Websites/perf.webkit.org/browser-tests/index.html 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/browser-tests/index.html 2017-03-22 22:50:57 UTC (rev 214280)
@@ -40,6 +40,9 @@
iframe.style.top = '0px';
BrowsingContext._iframes.push(iframe);
+ // Expedite calls to callbacks to make tests go faster.
+ iframe.contentWindow.requestAnimationFrame = (callback) => setTimeout(callback, 0);
+
this.iframe = iframe;
this.symbols = {};
this.global = this.iframe.contentWindow;
Modified: trunk/Websites/perf.webkit.org/public/v3/components/base.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/components/base.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/components/base.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -17,7 +17,9 @@
this._shadow = null;
this._actionCallbacks = new Map;
- if (!window.customElements && new.target.enqueueToRenderOnResize)
+ if (!ComponentBase.useNativeCustomElements)
+ this.enqueueToRender();
+ if (!ComponentBase.useNativeCustomElements && new.target.enqueueToRenderOnResize)
ComponentBase._connectedComponentToRenderOnResize(this);
}
@@ -174,7 +176,7 @@
const enqueueToRenderOnResize = elementInterface.enqueueToRenderOnResize;
- if (!window.customElements)
+ if (!ComponentBase.useNativeCustomElements)
return;
class elementClass extends HTMLElement {
@@ -194,6 +196,7 @@
connectedCallback()
{
+ this.component().enqueueToRender();
if (enqueueToRenderOnResize)
ComponentBase._connectedComponentToRenderOnResize(this.component());
}
@@ -215,7 +218,7 @@
static createElement(name, attributes, content)
{
var element = document.createElement(name);
- if (!content && (attributes instanceof Array || attributes instanceof Node
+ if (!content && (Array.isArray(attributes) || attributes instanceof Node
|| attributes instanceof ComponentBase || typeof(attributes) != 'object')) {
content = attributes;
attributes = {};
@@ -222,10 +225,12 @@
}
if (attributes) {
- for (var name in attributes) {
+ for (let name in attributes) {
if (name.startsWith('on'))
element.addEventListener(name.substring(2), attributes[name]);
- else
+ else if (attributes[name] === true)
+ element.setAttribute(name, name);
+ else if (attributes[name] !== false)
element.setAttribute(name, attributes[name]);
}
}
@@ -283,6 +288,7 @@
}
}
+ComponentBase.useNativeCustomElements = !!window.customElements;
ComponentBase._componentByName = new Map;
ComponentBase._componentByClass = new Map;
ComponentBase._currentlyConstructedByInterface = new Map;
Modified: trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -256,10 +256,9 @@
this._mainChartStatus.enqueueToRender();
var body = this.content().querySelector('.chart-pane-body');
- if (this._openRepository) {
+ if (this._openRepository)
body.classList.add('has-second-sidebar');
- this._commitLogViewer.enqueueToRender();
- } else
+ else
body.classList.remove('has-second-sidebar');
Instrumentation.endMeasuringTime('ChartPane', 'render');
Modified: trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -55,8 +55,6 @@
render()
{
- this.part('spinner').enqueueToRender();
-
const shouldShowRepositoryName = this._repository && (this._commits || this._fetchingPromise);
this.content('repository-name').textContent = shouldShowRepositoryName ? this._repository.name() : '';
this.content('spinner-container').style.display = this._fetchingPromise ? null : 'none';
Modified: trunk/Websites/perf.webkit.org/public/v3/models/time-series.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/models/time-series.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/models/time-series.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -1,8 +1,6 @@
'use strict';
-// v3 UI still relies on RunsData for associating metrics with units.
-// Use declartive syntax once that dependency has been removed.
-var TimeSeries = class {
+class TimeSeries {
constructor()
{
this._data = [];
Modified: trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -247,8 +247,6 @@
var link = ComponentBase.createLink;
var self = this;
- this.part('close').enqueueToRender();
-
if (this._chartsPage.canBreakdown(platform, metric)) {
actions.push(element('li', link('Breakdown', function () {
self._chartsPage.insertBreakdownPanesAfter(platform, metric, self);
Modified: trunk/Websites/perf.webkit.org/public/v3/pages/summary-page.js (214279 => 214280)
--- trunk/Websites/perf.webkit.org/public/v3/pages/summary-page.js 2017-03-22 22:25:09 UTC (rev 214279)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/summary-page.js 2017-03-22 22:50:57 UTC (rev 214280)
@@ -121,8 +121,6 @@
_renderCell(cell, spinner, anchor, ratioGraph, configurationGroup)
{
- spinner.enqueueToRender();
-
if (configurationGroup.isFetching())
cell.classList.add('fetching');
else