<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214650] trunk/Websites/perf.webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214650">214650</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-30 19:11:32 -0700 (Thu, 30 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Modernize BuildbotSyncer and BuildbotTriggerable
https://bugs.webkit.org/show_bug.cgi?id=170310

Reviewed by Chris Dumez.

Modernized the code to use arrow functions and other modern idoms in ES2016.

* ReadMe.md: Added instructions on how to run tests, and moved the steps to configure postgres
above the steps to configure Apache since only the former is needed to run tests.
* tools/js/buildbot-syncer.js:
* tools/js/buildbot-triggerable.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
<li><a href="#trunkWebsitesperfwebkitorgReadMemd">trunk/Websites/perf.webkit.org/ReadMe.md</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolsjsbuildbotsyncerjs">trunk/Websites/perf.webkit.org/tools/js/buildbot-syncer.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolsjsbuildbottriggerablejs">trunk/Websites/perf.webkit.org/tools/js/buildbot-triggerable.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsitesperfwebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ChangeLog (214649 => 214650)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2017-03-31 02:08:07 UTC (rev 214649)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2017-03-31 02:11:32 UTC (rev 214650)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2017-03-30  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        Modernize BuildbotSyncer and BuildbotTriggerable
+        https://bugs.webkit.org/show_bug.cgi?id=170310
+
+        Reviewed by Chris Dumez.
+
+        Modernized the code to use arrow functions and other modern idoms in ES2016.
+
+        * ReadMe.md: Added instructions on how to run tests, and moved the steps to configure postgres
+        above the steps to configure Apache since only the former is needed to run tests.
+        * tools/js/buildbot-syncer.js:
+        * tools/js/buildbot-triggerable.js:
+
+2017-03-30  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
</ins><span class="cx">         Yet another build fix after r214502. Workaround webkit.org/b/169907 for now.
</span><span class="cx"> 
</span><span class="cx">         * public/v3/pages/analysis-task-page.js:
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgReadMemd"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ReadMe.md (214649 => 214650)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ReadMe.md        2017-03-31 02:08:07 UTC (rev 214649)
+++ trunk/Websites/perf.webkit.org/ReadMe.md        2017-03-31 02:11:32 UTC (rev 214650)
</span><span class="lines">@@ -37,6 +37,46 @@
</span><span class="cx"> The script caches remote server's responses under `public/data/remote-cache` and never revalidates them (to allow offline work).
</span><span class="cx"> If you needed the latest content, delete caches stored in this directory by running `tools/remote-cache-server.py reset`.
</span><span class="cx"> 
</span><ins>+## Running Tests
+
+There are three kinds of tests in directories of the same name: `unit-tests`, `server tests`, and `browser-tests`.
+
+ - `unit-tests`: These tests various models and common JS code used in v3 UI and tools. They mock JSON APIs and model object.
+ - `server-tests`: Server tests use a real Apache server in accordance with `testServer` in `config.json` and a Postgres database by the name of `testDatabaseName` specified in `config.json`. They're functional tests and may test both the backend database schema, PHP, and corresponding front-end code although many of them directly queries and modifies the database.
+ - `browser-tests`: These are tests to be ran inside a Web browser, and tests v3 UI's interaction with browser's DOM API.
+
+To run `unit-tests` and `server-tests`, simply run `./tools/run-tests.py` after installing dependencies and configuring the PostgreSQL.
+To run `browser-tests`, open `browser-tests/index.html` inside a Web browser.
+
+## Configuring PostgreSQL
+
+Run the following command to setup a Postgres server at `/Volumes/Data/perf.webkit.org/PostgresSQL` (or wherever you'd prefer):
+`python ./tools/setup-database.py /Volumes/Data/perf.webkit.org/PostgresSQL`
+
+It automatically retrieves the database name, the username, and the password from `config.json`.
+
+### Starting PostgreSQL
+
+The setup script automatically starts the database but you may need to run the following command to manually start the database after reboot.
+
+- Starting the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_ctl -D /Volumes/Data/perf.webkit.org/PostgresSQL -l /Volumes/Data/perf.webkit.org/PostgresSQL/logfile -o &quot;-k /Volumes/Data/perf.webkit.org/PostgresSQL&quot; start`
+- Stopping the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_ctl -D /Volumes/Data/perf.webkit.org/PostgresSQL -l /Volumes/Data/perf.webkit.org/PostgresSQL/logfile -o &quot;-k /Volumes/Data/perf.webkit.org/PostgresSQL&quot; stop`
+
+### Initializing the Database
+
+Run `database/init-database.sql` in psql as `webkit-perf-db-user`:
+`/Applications/Server.app/Contents/ServerRoot/usr/bin/psql webkit-perf-db -h localhost --username webkit-perf-db-user -f init-database.sql`
+
+### Making a Backup and Restoring
+
+Use `pg_dump` and `pg_restore` to backup and restore the database. If you're replicating the production database for development purposes, you may consider excluding `run_iterations` table, which takes up 2/3 of the storage space, to reduce the size of the database for your local copy. Adjust the number of concurrent processes to use by `--jobs` and adjust the compression level by `--compress` (0 is no compression, 9 is most compressed).
+
+- Making the fullbackup of the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump -h localhost webkit-perf-db --format=directory --file=&lt;path to backup directory&gt; --jobs=4 --no-owner --compress=7`
+
+- Making an abridged backup without `run_iterations` table: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump -h localhost webkit-perf-db --format=directory --file=&lt;path to backup directory&gt; --jobs=4 --no-owner --compress=7 --exclude-table=run_iterations`
+
+- Restoring the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_restore --format=directory --jobs=4 --no-owner --host localhost --username=webkit-perf-db-user &lt;path to backup directory&gt; --dbname=webkit-perf-db`
+    
</ins><span class="cx"> ## Configuring Apache
</span><span class="cx"> 
</span><span class="cx"> ### Instructions if you're using Server.app
</span><span class="lines">@@ -109,35 +149,6 @@
</span><span class="cx"> Require valid-user
</span><span class="cx"> ```
</span><span class="cx"> 
</span><del>-## Configuring PostgreSQL
-
-Run the following command to setup a Postgres server at `/Volumes/Data/perf.webkit.org/PostgresSQL` (or wherever you'd prefer):
-`python ./tools/setup-database.py /Volumes/Data/perf.webkit.org/PostgresSQL`
-
-It automatically retrieves the database name, the username, and the password from `config.json`.
-
-### Starting PostgreSQL
-
-The setup script automatically starts the database but you may need to run the following command to manually start the database after reboot.
-
-- Starting the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_ctl -D /Volumes/Data/perf.webkit.org/PostgresSQL -l /Volumes/Data/perf.webkit.org/PostgresSQL/logfile -o &quot;-k /Volumes/Data/perf.webkit.org/PostgresSQL&quot; start`
-- Stopping the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_ctl -D /Volumes/Data/perf.webkit.org/PostgresSQL -l /Volumes/Data/perf.webkit.org/PostgresSQL/logfile -o &quot;-k /Volumes/Data/perf.webkit.org/PostgresSQL&quot; stop`
-
-### Initializing the Database
-
-Run `database/init-database.sql` in psql as `webkit-perf-db-user`:
-`/Applications/Server.app/Contents/ServerRoot/usr/bin/psql webkit-perf-db -h localhost --username webkit-perf-db-user -f init-database.sql`
-
-### Making a Backup and Restoring
-
-Use `pg_dump` and `pg_restore` to backup and restore the database. If you're replicating the production database for development purposes, you may consider excluding `run_iterations` table, which takes up 2/3 of the storage space, to reduce the size of the database for your local copy. Adjust the number of concurrent processes to use by `--jobs` and adjust the compression level by `--compress` (0 is no compression, 9 is most compressed).
-
-- Making the fullbackup of the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump -h localhost webkit-perf-db --format=directory --file=&lt;path to backup directory&gt; --jobs=4 --no-owner --compress=7`
-
-- Making an abridged backup without `run_iterations` table: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_dump -h localhost webkit-perf-db --format=directory --file=&lt;path to backup directory&gt; --jobs=4 --no-owner --compress=7 --exclude-table=run_iterations`
-
-- Restoring the database: `/Applications/Server.app/Contents/ServerRoot/usr/bin/pg_restore --format=directory --jobs=4 --no-owner --host localhost --username=webkit-perf-db-user &lt;path to backup directory&gt; --dbname=webkit-perf-db`
-
</del><span class="cx"> ## Concepts
</span><span class="cx"> 
</span><span class="cx">  - **Test** - A test is a collection of metrics such as frame rate and malloced bytes. It can have a children and a parent and form a tree of tests.
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolsjsbuildbotsyncerjs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/js/buildbot-syncer.js (214649 => 214650)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/js/buildbot-syncer.js        2017-03-31 02:08:07 UTC (rev 214649)
+++ trunk/Websites/perf.webkit.org/tools/js/buildbot-syncer.js        2017-03-31 02:11:32 UTC (rev 214650)
</span><span class="lines">@@ -17,8 +17,8 @@
</span><span class="cx"> 
</span><span class="cx">         for (let propertyTuple of (rawData['properties'] || [])) {
</span><span class="cx">             // e.g. ['build_request_id', '16733', 'Force Build Form']
</span><del>-            let name = propertyTuple[0];
-            let value = propertyTuple[1];
</del><ins>+            const name = propertyTuple[0];
+            const value = propertyTuple[1];
</ins><span class="cx">             if (name == syncer._slavePropertyName)
</span><span class="cx">                 this._slaveName = value;
</span><span class="cx">             else if (name == syncer._buildRequestPropertyName)
</span><span class="lines">@@ -75,17 +75,13 @@
</span><span class="cx">     {
</span><span class="cx">         assert(test instanceof Test);
</span><span class="cx">         assert(platform instanceof Platform);
</span><del>-        this._testConfigurations.push({test: test, platform: platform, propertiesTemplate: propertiesTemplate});
</del><ins>+        this._testConfigurations.push({test, platform, propertiesTemplate});
</ins><span class="cx">     }
</span><span class="cx">     testConfigurations() { return this._testConfigurations; }
</span><span class="cx"> 
</span><span class="cx">     matchesConfiguration(request)
</span><span class="cx">     {
</span><del>-        for (let config of this._testConfigurations) {
-            if (config.platform == request.platform() &amp;&amp; config.test == request.test())
-                return true;
-        }
-        return false;
</del><ins>+        return this._testConfigurations.some((config) =&gt; config.platform == request.platform() &amp;&amp; config.test == request.test());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     scheduleRequest(newRequest, slaveName)
</span><span class="lines">@@ -140,10 +136,9 @@
</span><span class="cx"> 
</span><span class="cx">     pullBuildbot(count)
</span><span class="cx">     {
</span><del>-        let self = this;
-        return this._remote.getJSON(this.pathForPendingBuildsJSON()).then(function (content) {
-            let pendingEntries = content.map(function (entry) { return new BuildbotBuildEntry(self, entry); });
-            return self._pullRecentBuilds(count).then(function (entries) {
</del><ins>+        return this._remote.getJSON(this.pathForPendingBuildsJSON()).then((content) =&gt; {
+            let pendingEntries = content.map((entry) =&gt; new BuildbotBuildEntry(this, entry));
+            return this._pullRecentBuilds(count).then((entries) =&gt; {
</ins><span class="cx">                 let entryByRequest = {};
</span><span class="cx"> 
</span><span class="cx">                 for (let entry of pendingEntries)
</span><span class="lines">@@ -156,8 +151,8 @@
</span><span class="cx">                 for (let id in entryByRequest)
</span><span class="cx">                     entryList.push(entryByRequest[id]);
</span><span class="cx"> 
</span><del>-                self._entryList = entryList;
-                self._slavesWithNewRequests.clear();
</del><ins>+                this._entryList = entryList;
+                this._slavesWithNewRequests.clear();
</ins><span class="cx"> 
</span><span class="cx">                 return entryList;
</span><span class="cx">             });
</span><span class="lines">@@ -173,13 +168,12 @@
</span><span class="cx">         for (let i = 0; i &lt; count; i++)
</span><span class="cx">             selectedBuilds[i] = -i - 1;
</span><span class="cx"> 
</span><del>-        let self = this;
-        return this._remote.getJSON(this.pathForBuildJSON(selectedBuilds)).then(function (content) {
-            var entries = [];
</del><ins>+        return this._remote.getJSON(this.pathForBuildJSON(selectedBuilds)).then((content) =&gt; {
+            const entries = [];
</ins><span class="cx">             for (let index of selectedBuilds) {
</span><del>-                let entry = content[index];
</del><ins>+                const entry = content[index];
</ins><span class="cx">                 if (entry &amp;&amp; !entry['error'])
</span><del>-                    entries.push(new BuildbotBuildEntry(self, entry));
</del><ins>+                    entries.push(new BuildbotBuildEntry(this, entry));
</ins><span class="cx">             }
</span><span class="cx">             return entries;
</span><span class="cx">         });
</span><span class="lines">@@ -188,8 +182,7 @@
</span><span class="cx">     pathForPendingBuildsJSON() { return `/json/builders/${escape(this._builderName)}/pendingBuilds`; }
</span><span class="cx">     pathForBuildJSON(selectedBuilds)
</span><span class="cx">     {
</span><del>-        return `/json/builders/${escape(this._builderName)}/builds/?`
-            + selectedBuilds.map(function (number) { return 'select=' + number; }).join('&amp;');
</del><ins>+        return `/json/builders/${escape(this._builderName)}/builds/?` + selectedBuilds.map((number) =&gt; 'select=' + number).join('&amp;');
</ins><span class="cx">     }
</span><span class="cx">     pathForForceBuild() { return `/builders/${escape(this._builderName)}/force`; }
</span><span class="cx"> 
</span><span class="lines">@@ -214,14 +207,14 @@
</span><span class="cx">         }
</span><span class="cx">         assert(propertiesTemplate);
</span><span class="cx"> 
</span><del>-        let properties = {};
</del><ins>+        const properties = {};
</ins><span class="cx">         for (let key in propertiesTemplate) {
</span><del>-            let value = propertiesTemplate[key];
</del><ins>+            const value = propertiesTemplate[key];
</ins><span class="cx">             if (typeof(value) != 'object')
</span><span class="cx">                 properties[key] = value;
</span><span class="cx">             else if ('root' in value) {
</span><del>-                let repositoryName = value['root'];
-                let repository = repositoryByName[repositoryName];
</del><ins>+                const repositoryName = value['root'];
+                const repository = repositoryByName[repositoryName];
</ins><span class="cx">                 assert(repository, `&quot;${repositoryName}&quot; must be specified`);
</span><span class="cx">                 properties[key] = commitSet.revisionForRepository(repository);
</span><span class="cx">             } else if ('rootOptions' in value) {
</span><span class="lines">@@ -230,7 +223,7 @@
</span><span class="cx">                 properties[key] = commitSet.revisionForRepository(repositoryByName[filteredOptions[0]]);
</span><span class="cx">             }
</span><span class="cx">             else if ('rootsExcluding' in value) {
</span><del>-                let revisionSet = this._revisionSetFromCommitSetWithExclusionList(commitSet, value['rootsExcluding']);
</del><ins>+                const revisionSet = this._revisionSetFromCommitSetWithExclusionList(commitSet, value['rootsExcluding']);
</ins><span class="cx">                 properties[key] = JSON.stringify(revisionSet);
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -259,25 +252,25 @@
</span><span class="cx"> 
</span><span class="cx">     static _loadConfig(remote, config)
</span><span class="cx">     {
</span><del>-        let shared = config['shared'] || {};
-        let types = config['types'] || {};
-        let builders = config['builders'] || {};
</del><ins>+        const shared = config['shared'] || {};
+        const types = config['types'] || {};
+        const builders = config['builders'] || {};
</ins><span class="cx"> 
</span><span class="cx">         let syncerByBuilder = new Map;
</span><span class="cx">         for (let entry of config['configurations']) {
</span><del>-            let newConfig = {};
</del><ins>+            const newConfig = {};
</ins><span class="cx">             this._validateAndMergeConfig(newConfig, shared);
</span><span class="cx">             this._validateAndMergeConfig(newConfig, entry);
</span><span class="cx"> 
</span><del>-            let expandedConfigurations = this._expandTypesAndPlatforms(newConfig);
</del><ins>+            const expandedConfigurations = this._expandTypesAndPlatforms(newConfig);
</ins><span class="cx">             for (let config of expandedConfigurations) {
</span><span class="cx">                 if ('type' in config) {
</span><del>-                    let type = config['type'];
</del><ins>+                    const type = config['type'];
</ins><span class="cx">                     assert(type, `${type} is not a valid type in the configuration`);
</span><span class="cx">                     this._validateAndMergeConfig(config, types[type]);
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                let builder = entry['builder'];
</del><ins>+                const builder = entry['builder'];
</ins><span class="cx">                 if (builders[builder])
</span><span class="cx">                     this._validateAndMergeConfig(config, builders[builder]);
</span><span class="cx"> 
</span><span class="lines">@@ -290,7 +283,7 @@
</span><span class="cx"> 
</span><span class="cx">     static _expandTypesAndPlatforms(unresolvedConfig)
</span><span class="cx">     {
</span><del>-        let typeExpanded = [];
</del><ins>+        const typeExpanded = [];
</ins><span class="cx">         if ('types' in unresolvedConfig) {
</span><span class="cx">             for (let type of unresolvedConfig['types'])
</span><span class="cx">                 typeExpanded.push(this._validateAndMergeConfig({'type': type}, unresolvedConfig, 'types'));
</span><span class="lines">@@ -297,7 +290,7 @@
</span><span class="cx">         } else
</span><span class="cx">             typeExpanded.push(unresolvedConfig);
</span><span class="cx"> 
</span><del>-        let configurations = [];
</del><ins>+        const configurations = [];
</ins><span class="cx">         for (let config of typeExpanded) {
</span><span class="cx">             if ('platforms' in config) {
</span><span class="cx">                 for (let platform of config['platforms'])
</span><span class="lines">@@ -317,10 +310,10 @@
</span><span class="cx">         assert('properties' in newConfig, 'configuration must specify arguments to post on a builder');
</span><span class="cx">         assert('buildRequestArgument' in newConfig, 'configuration must specify buildRequestArgument');
</span><span class="cx"> 
</span><del>-        let test = Test.findByPath(newConfig.test);
</del><ins>+        const test = Test.findByPath(newConfig.test);
</ins><span class="cx">         assert(test, `${newConfig.test} is not a valid test path`);
</span><span class="cx"> 
</span><del>-        let platform = Platform.findByName(newConfig.platform);
</del><ins>+        const platform = Platform.findByName(newConfig.platform);
</ins><span class="cx">         assert(platform, `${newConfig.platform} is not a valid platform name`);
</span><span class="cx"> 
</span><span class="cx">         let syncer = syncerByBuilder.get(newConfig.builder);
</span><span class="lines">@@ -333,8 +326,8 @@
</span><span class="cx"> 
</span><span class="cx">     static _validateAndMergeConfig(config, valuesToMerge, excludedProperty)
</span><span class="cx">     {
</span><del>-        for (let name in valuesToMerge) {
-            let value = valuesToMerge[name];
</del><ins>+        for (const name in valuesToMerge) {
+            const value = valuesToMerge[name];
</ins><span class="cx">             if (name == excludedProperty)
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="lines">@@ -372,7 +365,7 @@
</span><span class="cx">     static _validateAndMergeProperties(properties, configArguments)
</span><span class="cx">     {
</span><span class="cx">         for (let name in configArguments) {
</span><del>-            let value = configArguments[name];
</del><ins>+            const value = configArguments[name];
</ins><span class="cx">             if (typeof(value) == 'string') {
</span><span class="cx">                 properties[name] = value;
</span><span class="cx">                 continue;
</span><span class="lines">@@ -379,7 +372,7 @@
</span><span class="cx">             }
</span><span class="cx">             assert.equal(typeof(value), 'object', 'A argument value must be either a string or a dictionary');
</span><span class="cx"> 
</span><del>-            let keys = Object.keys(value);
</del><ins>+            const keys = Object.keys(value);
</ins><span class="cx">             assert.equal(keys.length, 1, 'arguments value cannot contain more than one key');
</span><span class="cx">             let namedValue = value[keys[0]];
</span><span class="cx">             switch (keys[0]) {
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolsjsbuildbottriggerablejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/js/buildbot-triggerable.js (214649 => 214650)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/js/buildbot-triggerable.js        2017-03-31 02:08:07 UTC (rev 214649)
+++ trunk/Websites/perf.webkit.org/tools/js/buildbot-triggerable.js        2017-03-31 02:11:32 UTC (rev 214650)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx">         assert(typeof(slaveInfo.password) == 'string', 'slave password must be specified');
</span><span class="cx"> 
</span><span class="cx">         this._syncers = BuildbotSyncer._loadConfig(buildbotRemote, config);
</span><del>-        this._logger = logger || {log: function () { }, error: function () { }};
</del><ins>+        this._logger = logger || {log: () =&gt; { }, error: () =&gt; { }};
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     name() { return this._name; }
</span><span class="lines">@@ -48,30 +48,29 @@
</span><span class="cx">         let syncerList = this._syncers;
</span><span class="cx">         let buildReqeustsByGroup = new Map;
</span><span class="cx"> 
</span><del>-        let self = this;
</del><span class="cx">         this._logger.log(`Fetching build requests for ${this._name}...`);
</span><del>-        return BuildRequest.fetchForTriggerable(this._name).then(function (buildRequests) {
-            self._validateRequests(buildRequests);
</del><ins>+        return BuildRequest.fetchForTriggerable(this._name).then((buildRequests) =&gt; {
+            this._validateRequests(buildRequests);
</ins><span class="cx">             buildReqeustsByGroup = BuildbotTriggerable._testGroupMapForBuildRequests(buildRequests);
</span><del>-            return self._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
-        }).then(function (updates) {
-            self._logger.log('Scheduling builds');
-            let promistList = [];
-            let testGroupList = Array.from(buildReqeustsByGroup.values()).sort(function (a, b) { return a.groupOrder - b.groupOrder; });
-            for (let group of testGroupList) {
-                let promise = self._scheduleNextRequestInGroupIfSlaveIsAvailable(group, updates);
</del><ins>+            return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
+        }).then((updates) =&gt; {
+            this._logger.log('Scheduling builds');
+            const promistList = [];
+            const testGroupList = Array.from(buildReqeustsByGroup.values()).sort(function (a, b) { return a.groupOrder - b.groupOrder; });
+            for (const group of testGroupList) {
+                const promise = this._scheduleNextRequestInGroupIfSlaveIsAvailable(group, updates);
</ins><span class="cx">                 if (promise)
</span><span class="cx">                     promistList.push(promise);
</span><span class="cx">             }
</span><span class="cx">             return Promise.all(promistList);
</span><del>-        }).then(function () {
</del><ins>+        }).then(() =&gt; {
</ins><span class="cx">             // Pull all buildbots for the second time since the previous step may have scheduled more builds.
</span><del>-            return self._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
-        }).then(function (updates) {
</del><ins>+            return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
+        }).then((updates) =&gt; {
</ins><span class="cx">             // FIXME: Add a new API that just updates the requests.
</span><del>-            return self._remote.postJSONWithStatus(`/api/build-requests/${self._name}`, {
-                'slaveName': self._slaveInfo.name,
-                'slavePassword': self._slaveInfo.password,
</del><ins>+            return this._remote.postJSONWithStatus(`/api/build-requests/${this._name}`, {
+                'slaveName': this._slaveInfo.name,
+                'slavePassword': this._slaveInfo.password,
</ins><span class="cx">                 'buildRequestUpdates': updates});
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="lines">@@ -78,10 +77,10 @@
</span><span class="cx"> 
</span><span class="cx">     _validateRequests(buildRequests)
</span><span class="cx">     {
</span><del>-        let testPlatformPairs = {};
</del><ins>+        const testPlatformPairs = {};
</ins><span class="cx">         for (let request of buildRequests) {
</span><del>-            if (!this._syncers.some(function (syncer) { return syncer.matchesConfiguration(request); })) {
-                let key = request.platform().id + '-' + request.test().id();
</del><ins>+            if (!this._syncers.some((syncer) =&gt; syncer.matchesConfiguration(request))) {
+                const key = request.platform().id + '-' + request.test().id();
</ins><span class="cx">                 if (!(key in testPlatformPairs))
</span><span class="cx">                     this._logger.error(`No matching configuration for &quot;${request.test().fullName()}&quot; on &quot;${request.platform().name()}&quot;.`);                
</span><span class="cx">                 testPlatformPairs[key] = true;
</span><span class="lines">@@ -93,16 +92,15 @@
</span><span class="cx">     {
</span><span class="cx">         let updates = {};
</span><span class="cx">         let associatedRequests = new Set;
</span><del>-        let self = this;
-        return Promise.all(this._syncers.map(function (syncer) {
-            return syncer.pullBuildbot(self._lookbackCount).then(function (entryList) {
-                for (let entry of entryList) {
-                    let request = BuildRequest.findById(entry.buildRequestId());
</del><ins>+        return Promise.all(this._syncers.map((syncer) =&gt; {
+            return syncer.pullBuildbot(this._lookbackCount).then((entryList) =&gt; {
+                for (const entry of entryList) {
+                    const request = BuildRequest.findById(entry.buildRequestId());
</ins><span class="cx">                     if (!request)
</span><span class="cx">                         continue;
</span><span class="cx">                     associatedRequests.add(request);
</span><span class="cx"> 
</span><del>-                    let info = buildReqeustsByGroup.get(request.testGroupId());
</del><ins>+                    const info = buildReqeustsByGroup.get(request.testGroupId());
</ins><span class="cx">                     assert(!info.syncer || info.syncer == syncer);
</span><span class="cx">                     info.syncer = syncer;
</span><span class="cx">                     if (entry.slaveName()) {
</span><span class="lines">@@ -110,31 +108,31 @@
</span><span class="cx">                         info.slaveName = entry.slaveName();
</span><span class="cx">                     }
</span><span class="cx"> 
</span><del>-                    let newStatus = entry.buildRequestStatusIfUpdateIsNeeded(request);
</del><ins>+                    const newStatus = entry.buildRequestStatusIfUpdateIsNeeded(request);
</ins><span class="cx">                     if (newStatus) {
</span><del>-                        self._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to ${newStatus}`);
</del><ins>+                        this._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to ${newStatus}`);
</ins><span class="cx">                         updates[entry.buildRequestId()] = {status: newStatus, url: entry.url()};
</span><span class="cx">                     } else if (!request.statusUrl()) {
</span><del>-                        self._logger.log(`Setting the status URL of build request ${request.id()} to ${entry.url()}`);
</del><ins>+                        this._logger.log(`Setting the status URL of build request ${request.id()} to ${entry.url()}`);
</ins><span class="cx">                         updates[entry.buildRequestId()] = {status: request.status(), url: entry.url()};
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">             });
</span><del>-        })).then(function () {
-            for (let request of BuildRequest.all()) {
</del><ins>+        })).then(() =&gt; {
+            for (const request of BuildRequest.all()) {
</ins><span class="cx">                 if (request.hasStarted() &amp;&amp; !request.hasFinished() &amp;&amp; !associatedRequests.has(request)) {
</span><del>-                    self._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to failedIfNotCompleted`);
</del><ins>+                    this._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to failedIfNotCompleted`);
</ins><span class="cx">                     assert(!(request.id() in updates));
</span><span class="cx">                     updates[request.id()] = {status: 'failedIfNotCompleted'};
</span><span class="cx">                 }
</span><span class="cx">             }
</span><del>-        }).then(function () { return updates; });
</del><ins>+        }).then(() =&gt; updates);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _scheduleNextRequestInGroupIfSlaveIsAvailable(groupInfo, pendingUpdates)
</span><span class="cx">     {
</span><span class="cx">         let nextRequest = null;
</span><del>-        for (let request of groupInfo.requests) {
</del><ins>+        for (const request of groupInfo.requests) {
</ins><span class="cx">             if (request.isScheduled() || (request.id() in pendingUpdates &amp;&amp; pendingUpdates[request.id()]['status'] == 'scheduled'))
</span><span class="cx">                 break;
</span><span class="cx">             if (request.isPending() &amp;&amp; !(request.id() in pendingUpdates)) {
</span><span class="lines">@@ -157,6 +155,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (!syncer) {
</span><span class="cx">             for (syncer of this._syncers) {
</span><ins>+                // FIXME: This shouldn't be a new variable.
</ins><span class="cx">                 let promise = syncer.scheduleRequestInGroupIfAvailable(nextRequest);
</span><span class="cx">                 if (promise)
</span><span class="cx">                     break;
</span><span class="lines">@@ -174,7 +173,7 @@
</span><span class="cx"> 
</span><span class="cx">     static _testGroupMapForBuildRequests(buildRequests)
</span><span class="cx">     {
</span><del>-        let map = new Map;
</del><ins>+        const map = new Map;
</ins><span class="cx">         let groupOrder = 0;
</span><span class="cx">         for (let request of buildRequests) {
</span><span class="cx">             let groupId = request.testGroupId();
</span></span></pre>
</div>
</div>

</body>
</html>