Update to Speedometer 2.0 w/updated frameworks + new workloads
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 May 2017 21:16:51 +0000 (21:16 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 May 2017 21:16:51 +0000 (21:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170513

Patch by Addy Osmani <addyosmani@gmail.com> on 2017-05-16
Reviewed by Ryosuke Niwa.

Refresh test runner and fix apps to work with it.

* Speedometer/InteractiveRunner.html:
(parseQueryString): Adds support for startAutomatically query parameter.
* Speedometer/resources/tests.js:
(triggerEnter): Refactor event triggering behavior for tests.
* Speedometer/resources/todomvc/architecture-examples/angular/dist/index.html:
(CSS): Drop reference to extraneous stylesheet in Angular TodoMVC.
* Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.js:
* Speedometer/resources/todomvc/architecture-examples/emberjs/index.html:
(base): Enable Ember TodoMVC to be run from any directory/level.
* Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/memory.js:
(localStorageMemory): Correct import path and switch to window.localStorageMemory to fix Ember failures.
* Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/repo.js:
* Speedometer/resources/todomvc/architecture-examples/emberjs/tests/index.html:
* Speedometer/resources/todomvc/architecture-examples/jquery/index.html:
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/LICENSE: Added.
(LICENSE): Add missing metadata and LICENSE files as part of director.js package for jQuery TodoMVC
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/bower.json: Added.
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.js: Add missing
director.js dependency for jQuery TodoMVC implementation.
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.min.js: Added.
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/ender.js: Added.
* Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/package.json: Added.
* Speedometer/resources/todomvc/functional-prog-examples/elm/index.html: Fix path to built Elm TodoMVC scripts.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216946 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
PerformanceTests/ChangeLog
PerformanceTests/Speedometer/InteractiveRunner.html
PerformanceTests/Speedometer/resources/tests.js
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angular/dist/index.html
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.js
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/index.html
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/index.html
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/memory.js
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/repo.js
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/tests/index.html
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/index.html
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/LICENSE [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/bower.json [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.js [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.min.js [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/ender.js [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/package.json [new file with mode: 0644]
PerformanceTests/Speedometer/resources/todomvc/functional-prog-examples/elm/index.html

index 59e6048..a0c72fc 100644 (file)
@@ -1,3 +1,36 @@
+2017-05-16  Addy Osmani  <addyosmani@gmail.com>
+
+        Update to Speedometer 2.0 w/updated frameworks + new workloads
+        https://bugs.webkit.org/show_bug.cgi?id=170513
+
+        Reviewed by Ryosuke Niwa.
+
+        Refresh test runner and fix apps to work with it.
+
+        * Speedometer/InteractiveRunner.html:
+        (parseQueryString): Adds support for startAutomatically query parameter.
+        * Speedometer/resources/tests.js:
+        (triggerEnter): Refactor event triggering behavior for tests.
+        * Speedometer/resources/todomvc/architecture-examples/angular/dist/index.html:
+        (CSS): Drop reference to extraneous stylesheet in Angular TodoMVC.
+        * Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.js:
+        * Speedometer/resources/todomvc/architecture-examples/emberjs/index.html:
+        (base): Enable Ember TodoMVC to be run from any directory/level.
+        * Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/memory.js:
+        (localStorageMemory): Correct import path and switch to window.localStorageMemory to fix Ember failures.
+        * Speedometer/resources/todomvc/architecture-examples/emberjs/source/app/services/repo.js:
+        * Speedometer/resources/todomvc/architecture-examples/emberjs/tests/index.html:
+        * Speedometer/resources/todomvc/architecture-examples/jquery/index.html:
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/LICENSE: Added.
+        (LICENSE): Add missing metadata and LICENSE files as part of director.js package for jQuery TodoMVC
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/bower.json: Added.
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.js: Add missing 
+        director.js dependency for jQuery TodoMVC implementation.
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.min.js: Added.
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/ender.js: Added.
+        * Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/package.json: Added.
+        * Speedometer/resources/todomvc/functional-prog-examples/elm/index.html: Fix path to built Elm TodoMVC scripts.
+
 2017-05-12  Addy Osmani  <addyosmani@gmail.com>
 
         Speedometer: Add a React.js TodoMVC implementation
index 92076a4..7e5fe2a 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
-<title>DoYouEvenBench</title>
+<title>Speedometer 2.0 Interactive Runner</title>
 <script src="resources/benchmark-runner.js" defer></script>
 <script src="resources/tests.js" defer></script>
 <style>
@@ -66,13 +66,37 @@ function createUIForSuites(suites, onstep, onrun) {
 
     var button = document.createElement('button');
     button.textContent = 'Run';
+    button.id = 'runSuites';
     button.onclick = onrun;
     control.appendChild(button);
 
     return control;
 }
 
+var parseQueryString = (function (pairList) {
+    var pairs = {};
+    for (var i = 0; i < pairList.length; ++i) {
+        var keyValue = pairList[i].split('=', 2);
+        if (keyValue.length == 1)
+            pairs[keyValue[0]] = '';
+        else
+            pairs[keyValue[0]] = decodeURIComponent(keyValue[1].replace(/\+/g, ' '));
+    }
+    return pairs;
+})(window.location.search.substr(1).split('&'));
+
+function disableAllSuitesExcept(suiteName) {
+    Suites.forEach(function(element) {
+        if (element.name !== suiteName)
+            element.disabled = true;
+    });
+}
+
 function startTest() {
+    var queryParam = parseQueryString['suite'];
+    if (queryParam !== undefined)
+        disableAllSuitesExcept(queryParam);
+
     var runner = new BenchmarkRunner(Suites, {
         willRunTest: function (suite, test) {
             test.anchor.classList.add('running');
@@ -112,6 +136,9 @@ function startTest() {
     document.body.appendChild(createUIForSuites(Suites,
         function () { runner.step(currentState).then(function (state) { currentState = state; }); },
         function () { runner.runAllSteps(currentState); currentState = null; }));
+
+    if (parseQueryString['startAutomatically'] !== undefined)
+        document.getElementById('runSuites').click();
 }
 
 window.addEventListener('load', startTest);
index e6f239c..c60b8ec 100644 (file)
@@ -1,21 +1,31 @@
 var numberOfItemsToAdd = 100;
 var Suites = [];
+var ENTER_KEY_CODE = 13;
+
+var triggerEnter = function (element, type) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, true, true);
+    event.keyCode = ENTER_KEY_CODE;
+    event.which = ENTER_KEY_CODE;
+    event.key = 'ENTER';
+    element.dispatchEvent(event);
+}
 
 Suites.push({
     name: 'VanillaJS-TodoMVC',
     url: 'todomvc/vanilla-examples/vanillajs/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-        return runner.waitForElement('#new-todo').then(function (element) {
+        return runner.waitForElement('.new-todo').then(function (element) {
             element.focus();
             return element;
         });
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var todoController = contentWindow.todo.controller;
             for (var i = 0; i < numberOfItemsToAdd; i++) {
                 newTodo.value = 'Something to do ' + i;
-                todoController.addItem({keyCode: todoController.ENTER_KEY, target: newTodo});
+                newTodo.dispatchEvent(new Event('change'));
+                triggerEnter(newTodo, 'keypress');
             }
         }),
         new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
@@ -32,56 +42,84 @@ Suites.push({
 });
 
 Suites.push({
-    name: 'EmberJS-TodoMVC',
-    url: 'todomvc/architecture-examples/emberjs/index.html',
+    name: 'Vanilla-ES2015-TodoMVC',
+    url: 'todomvc/vanilla-examples/es2015/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-        return runner.waitForElement('#new-todo').then(function (element) {
+        return runner.waitForElement('.new-todo').then(function (element) {
             element.focus();
-            return {
-                views: contentWindow.Ember.View.views,
-                emberRun: contentWindow.Ember.run,
-            }
+            return element;
         });
     },
     tests: [
-        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (params) {
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
             for (var i = 0; i < numberOfItemsToAdd; i++) {
-                params.emberRun(function () { params.views["new-todo"].set('value', 'Something to do' + i); });
-                params.emberRun(function () { params.views["new-todo"].insertNewline(document.createEvent('Event')); });
+                newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('change'));
+                triggerEnter(newTodo, 'keypress');
             }
         }),
         new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
-            var checkboxes = contentDocument.querySelectorAll('.ember-checkbox');
-            for (var i = 0; i < checkboxes.length; i++) {
-                var view = params.views[checkboxes[i].id];
-                params.emberRun(function () { view.set('checked', true); });
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
+
+Suites.push({
+    name: 'Vanilla-ES2015-Babel-Webpack-TodoMVC',
+    url: 'todomvc/vanilla-examples/es2015-babel-webpack/dist/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('change'));
+                triggerEnter(newTodo, 'keypress');
             }
         }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
         new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
             var deleteButtons = contentDocument.querySelectorAll('.destroy');
             for (var i = 0; i < deleteButtons.length; i++)
-                params.emberRun(function () { deleteButtons[i].click(); });
+                deleteButtons[i].click();
         }),
     ]
 });
 
 Suites.push({
-    name: 'BackboneJS-TodoMVC',
-    url: 'todomvc/architecture-examples/backbone/index.html',
+    name: 'React-TodoMVC',
+    url: 'todomvc/architecture-examples/react/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-    contentWindow.Backbone.sync = function () {}
-        return runner.waitForElement('#new-todo').then(function (element) {
+        contentWindow.app.Utils.store = function () {}
+        return runner.waitForElement('.new-todo').then(function (element) {
             element.focus();
             return element;
         });
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var appView = contentWindow.appView;
-            var fakeEvent = {which: contentWindow.ENTER_KEY};
             for (var i = 0; i < numberOfItemsToAdd; i++) {
                 newTodo.value = 'Something to do ' + i;
-                appView.createOnEnter(fakeEvent);
+                newTodo.dispatchEvent(new Event('input', {
+                  bubbles: true,
+                  cancelable: true
+                }));
+                triggerEnter(newTodo, 'keydown');
             }
         }),
         new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
@@ -98,57 +136,89 @@ Suites.push({
 });
 
 Suites.push({
-    name: 'jQuery-TodoMVC',
-    url: 'todomvc/architecture-examples/jquery/index.html',
+    name: 'React-Redux-TodoMVC',
+    url: 'todomvc/architecture-examples/react-redux/dist/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-        return runner.waitForElement('#new-todo').then(function (element) {
+        return runner.waitForElement('.new-todo').then(function (element) {
             element.focus();
             return element;
         });
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var app = contentWindow.app;
-            var fakeEvent = {which: app.ENTER_KEY};
             for (var i = 0; i < numberOfItemsToAdd; i++) {
                 newTodo.value = 'Something to do ' + i;
-                app.create.call(newTodo, fakeEvent);
+                triggerEnter(newTodo, 'keydown');
             }
         }),
-        new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
-            var app = contentWindow.app;
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
             var checkboxes = contentDocument.querySelectorAll('.toggle');
-            var $ = contentWindow.$;
-
-            itemIndexToId = new Array(checkboxes.length);
             for (var i = 0; i < checkboxes.length; i++)
-                itemIndexToId[i] = $(checkboxes[i]).closest('li').data('id');
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
 
-            app.getTodo = function (element, callback) {
-                var self = this;
-                var id = itemIndexToId[this.currentItemIndex];
-                $.each(this.todos, function (j, val) {
-                    if (val.id === id) {
-                        callback.apply(self, arguments);
-                        return false;
-                    }
-                });
+Suites.push({
+    name: 'EmberJS-TodoMVC',
+    url: 'todomvc/architecture-examples/emberjs',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('#new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                triggerEnter(newTodo, 'keydown');
             }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
 
-            for (var i = 0; i < checkboxes.length; i++) {
-                app.currentItemIndex = i;
-                app.toggle.call(checkboxes[i]);
+Suites.push({
+    name: 'BackboneJS-TodoMVC',
+    url: 'todomvc/architecture-examples/backbone/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+    contentWindow.Backbone.sync = function () {}
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                triggerEnter(newTodo, 'keypress');
             }
         }),
+        new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
         new BenchmarkTestStep('DeletingAllItems', function (newTodo, contentWindow, contentDocument) {
-            contentDocument.querySelector('#clear-completed').click();
-            var app = contentWindow.app;
             var deleteButtons = contentDocument.querySelectorAll('.destroy');
-
-            for (var i = 0; i < deleteButtons.length; i++) {
-                app.currentItemIndex = i;
-                app.destroy.call(deleteButtons[i]);
-            }
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
         }),
     ]
 });
@@ -164,7 +234,6 @@ Suites.push({
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var todomvc = contentWindow.todomvc;
             var submitEvent = document.createEvent('Event');
             submitEvent.initEvent('submit', true, true);
             var inputEvent = document.createEvent('Event');
@@ -189,25 +258,56 @@ Suites.push({
 });
 
 Suites.push({
-    name: 'React-TodoMVC',
-    url: 'todomvc/labs/architecture-examples/react/index.html',
+    name: 'Angular2-TypeScript-TodoMVC',
+    url: 'todomvc/architecture-examples/angular/dist/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-        contentWindow.Utils.store = function () {}
-        return runner.waitForElement('#new-todo').then(function (element) {
+        return runner.waitForElement('.new-todo').then(function (element) {
             element.focus();
             return element;
         });
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var todomvc = contentWindow.todomvc;
             for (var i = 0; i < numberOfItemsToAdd; i++) {
                 newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('input', {
+                  bubbles: true,
+                  cancelable: true
+                }));
+                triggerEnter(newTodo, 'keyup');
+            }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
 
-                var keydownEvent = document.createEvent('Event');
-                keydownEvent.initEvent('keydown', true, true);
-                keydownEvent.which = 13; // VK_ENTER
-                newTodo.dispatchEvent(keydownEvent);
+Suites.push({
+    name: 'VueJS-TodoMVC',
+    url: 'todomvc/architecture-examples/vuejs-cli/dist/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('input', {
+                  bubbles: true,
+                  cancelable: true
+                }));
+                triggerEnter(newTodo, 'keyup');
             }
         }),
         new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
@@ -224,25 +324,19 @@ Suites.push({
 });
 
 Suites.push({
-    name: 'FlightJS-TodoMVC',
-    url: 'todomvc/dependency-examples/flight/index.html',
+    name: 'jQuery-TodoMVC',
+    url: 'todomvc/architecture-examples/jquery/index.html',
     prepare: function (runner, contentWindow, contentDocument) {
-        return runner.waitForElement('#appIsReady').then(function () {
-            var newTodo = contentDocument.querySelector('#new-todo');
-            newTodo.focus();
-            return newTodo;
-        });;
+        return runner.waitForElement('#new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
     },
     tests: [
         new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
-            var todomvc = contentWindow.todomvc;
             for (var i = 0; i < numberOfItemsToAdd; i++) {
                 newTodo.value = 'Something to do ' + i;
-
-                var keydownEvent = document.createEvent('Event');
-                keydownEvent.initEvent('keydown', true, true);
-                keydownEvent.which = 13; // VK_ENTER
-                newTodo.dispatchEvent(keydownEvent);
+                triggerEnter(newTodo, 'keyup');
             }
         }),
         new BenchmarkTestStep('CompletingAllItems', function (newTodo, contentWindow, contentDocument) {
@@ -256,6 +350,130 @@ Suites.push({
                 deleteButtons[i].click();
         }),
     ]
+})
+
+Suites.push({
+    name: 'Preact-TodoMVC',
+    url: 'todomvc/architecture-examples/preact/dist/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                triggerEnter(newTodo, 'keydown');
+            }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
+
+Suites.push({
+    name: 'Inferno-TodoMVC',
+    url: 'todomvc/architecture-examples/inferno/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('change', {
+                  bubbles: true,
+                  cancelable: true
+                }));
+                triggerEnter(newTodo, 'keydown');
+            }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
+
+Suites.push({
+    name: 'Elm-TodoMVC',
+    url: 'todomvc/functional-prog-examples/elm/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('.new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                newTodo.dispatchEvent(new Event('input', {
+                  bubbles: true,
+                  cancelable: true
+                }));
+                triggerEnter(newTodo, 'keydown');
+            }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
+});
+
+Suites.push({
+    name: 'Flight-TodoMVC',
+    url: 'todomvc/dependency-examples/flight/flight/index.html',
+    prepare: function (runner, contentWindow, contentDocument) {
+        return runner.waitForElement('#new-todo').then(function (element) {
+            element.focus();
+            return element;
+        });
+    },
+    tests: [
+        new BenchmarkTestStep('Adding' + numberOfItemsToAdd + 'Items', function (newTodo, contentWindow, contentDocument) {
+            for (var i = 0; i < numberOfItemsToAdd; i++) {
+                newTodo.value = 'Something to do ' + i;
+                triggerEnter(newTodo, 'keydown');
+            }
+        }),
+        new BenchmarkTestStep('CompletingAllItems', function (params, contentWindow, contentDocument) {
+            var checkboxes = contentDocument.querySelectorAll('.toggle');
+            for (var i = 0; i < checkboxes.length; i++)
+                checkboxes[i].click();
+        }),
+        new BenchmarkTestStep('DeletingItems', function (params, contentWindow, contentDocument) {
+            var deleteButtons = contentDocument.querySelectorAll('.destroy');
+            for (var i = 0; i < deleteButtons.length; i++)
+                deleteButtons[i].click();
+        }),
+    ]
 });
 
 var actionCount = 50;
index 76bdc86..3a1a9e2 100644 (file)
@@ -9,7 +9,7 @@
   <link rel="icon" type="image/x-icon" href="favicon.ico">
   <link rel="stylesheet" href="assets/css/todomvc-common.css">
   <link rel="stylesheet" href="assets/css/todomvc-app.css">
-<link href="styles.d41d8cd98f00b204e980.bundle.css" rel="stylesheet"/></head>
+</head>
 <body>
   <app-root>Loading...</app-root>
   <!-- Credits: Addy Osmani -->
index 619a004..7d4dfb3 100644 (file)
@@ -363,19 +363,15 @@ define('todomvc/services/memory', ['exports'], function (exports) {
       localStorageMemory.length = 0;
     };
 
-    if (typeof exports === 'object') {
-      module.exports = localStorageMemory;
-    } else {
-      root.localStorageMemory = localStorageMemory;
-    }
-  })(this);
+    root.localStorageMemory = localStorageMemory;
+  })(window);
 });
 define('todomvc/services/repo', ['exports', 'ember', 'todomvc/services/memory'], function (exports, _ember, _todomvcServicesMemory) {
     exports['default'] = _ember['default'].Service.extend({
         lastId: 0,
         data: null,
         findAll: function findAll() {
-            return this.get('data') || this.set('data', JSON.parse(_todomvcServicesMemory.getItem('todos') || '[]'));
+            return this.get('data') || this.set('data', JSON.parse(window.localStorageMemory.getItem('todos') || '[]'));
         },
 
         add: function add(attrs) {
@@ -391,7 +387,7 @@ define('todomvc/services/repo', ['exports', 'ember', 'todomvc/services/memory'],
         },
 
         persist: function persist() {
-            _todomvcServicesMemory.setItem('todos', JSON.stringify(this.get('data')));
+            window.localStorageMemory.setItem('todos', JSON.stringify(this.get('data')));
         }
     });
 });
@@ -1257,7 +1253,7 @@ catch(err) {
 /* jshint ignore:start */
 
 if (!runningTests) {
-  require("todomvc/app")["default"].create({"name":"todomvc","version":"0.0.0+5dbc5fb9"});
+  require("todomvc/app")["default"].create({"name":"todomvc","version":"0.0.0+"});
 }
 
 /* jshint ignore:end */
index 7e48c19..ed2a1cf 100644 (file)
@@ -6,21 +6,19 @@
     <title>Todomvc</title>
     <meta name="description" content="">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <base href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs" />
-    
-<meta name="todomvc/config/environment" content="%7B%22modulePrefix%22%3A%22todomvc%22%2C%22environment%22%3A%22development%22%2C%22baseURL%22%3Anull%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%7D%2C%22APP%22%3A%7B%22name%22%3A%22todomvc%22%2C%22version%22%3A%220.0.0+5dbc5fb9%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
+   
+<meta name="todomvc/config/environment" content="%7B%22modulePrefix%22%3A%22todomvc%22%2C%22environment%22%3A%22development%22%2C%22locationType%22%3A%22none%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%7D%2C%22APP%22%3A%7B%22name%22%3A%22todomvc%22%2C%22version%22%3A%220.0.0%202c3f8158%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
 
-    <link rel="stylesheet" href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/vendor.css">
-    <link rel="stylesheet" href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.css">
+    <link rel="stylesheet" href="assets/vendor.css">
 
     
   </head>
   <body>
     
 
-    <script src="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/vendor.js"></script>
-    <script src="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.js"></script>
+    <script src="assets/vendor.js"></script>
+    <script src="assets/todomvc.js"></script>
 
     
   </body>
-</html>
+</html>
\ No newline at end of file
index ba6f646..b1730fb 100644 (file)
@@ -6,19 +6,18 @@
     <title>Todomvc</title>
     <meta name="description" content="">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <base href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs" />
     {{content-for "head"}}
 
-    <link rel="stylesheet" href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/vendor.css">
-    <link rel="stylesheet" href="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.css">
+    <link rel="stylesheet" href="assets/vendor.css">
+    <link rel="stylesheet" href="assets/todomvc.css">
 
     {{content-for "head-footer"}}
   </head>
   <body>
     {{content-for "body"}}
 
-    <script src="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/vendor.js"></script>
-    <script src="/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/emberjs/assets/todomvc.js"></script>
+    <script src="assets/vendor.js"></script>
+    <script src="assets/todomvc.js"></script>
 
     {{content-for "body-footer"}}
   </body>
index 4b9d5af..74c5cdf 100644 (file)
@@ -74,9 +74,5 @@
     localStorageMemory.length = 0;
   };
 
-  if (typeof exports === 'object') {
-    module.exports = localStorageMemory;
-  } else {
     root.localStorageMemory = localStorageMemory;
-  }
-})(this);
+})(window);
index 0147ff3..cffa385 100644 (file)
@@ -1,12 +1,12 @@
 import Ember from 'ember';
-import * as localStorageMemory from './memory';
+import localStorageMemory from './memory';
 
 export default Ember.Service.extend({
     lastId: 0,
     data: null,
     findAll() {
         return this.get('data') ||
-            this.set('data', JSON.parse(localStorageMemory.getItem('todos') || '[]'));
+            this.set('data', JSON.parse(window.localStorageMemory.getItem('todos') || '[]'));
     },
 
     add(attrs) {
@@ -22,6 +22,6 @@ export default Ember.Service.extend({
     },
 
     persist() {
-        localStorageMemory.setItem('todos', JSON.stringify(this.get('data')));
+        window.localStorageMemory.setItem('todos', JSON.stringify(this.get('data')));
     }
 });
index e2a27c1..2ab218e 100644 (file)
@@ -8,7 +8,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
 
     <base href="/" />
-<meta name="todomvc/config/environment" content="%7B%22modulePrefix%22%3A%22todomvc%22%2C%22environment%22%3A%22test%22%2C%22baseURL%22%3A%22/%22%2C%22locationType%22%3A%22none%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%7D%2C%22APP%22%3A%7B%22LOG_ACTIVE_GENERATION%22%3Afalse%2C%22LOG_VIEW_LOOKUPS%22%3Afalse%2C%22rootElement%22%3A%22%23ember-testing%22%2C%22name%22%3A%22todomvc%22%2C%22version%22%3A%220.0.0+5dbc5fb9%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
+<meta name="todomvc/config/environment" content="%7B%22modulePrefix%22%3A%22todomvc%22%2C%22environment%22%3A%22test%22%2C%22baseURL%22%3A%22/%22%2C%22locationType%22%3A%22none%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%7D%2C%22APP%22%3A%7B%22LOG_ACTIVE_GENERATION%22%3Afalse%2C%22LOG_VIEW_LOOKUPS%22%3Afalse%2C%22rootElement%22%3A%22%23ember-testing%22%2C%22name%22%3A%22todomvc%22%2C%22version%22%3A%220.0.0+%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
     
 
     <link rel="stylesheet" href="assets/vendor.css">
index 414ac58..1cf803e 100644 (file)
@@ -55,7 +55,7 @@
         <!-- <script src="node_modules/todomvc-common/base.js"></script> -->
         <script src="node_modules/jquery/dist/jquery.js"></script>
         <script src="node_modules/handlebars/dist/handlebars.js"></script>
-        <script src="node_modules/director/build/director.js"></script>
+        <script src="node_modules/director/dist/director.js"></script>
         <script src="js/app.js"></script>
     </body>
 </html>
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/LICENSE b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/LICENSE
new file mode 100644 (file)
index 0000000..8a49810
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Charlie Robbins, Paolo Fragomeni, & the Contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/bower.json b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/bower.json
new file mode 100644 (file)
index 0000000..f939bb4
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "name": "director",
+  "version": "1.2.7",
+  "dependencies": {},
+  "main": "build/director.js",
+  "scripts": [
+    "build/director.js"
+  ]
+}
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.js b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.js
new file mode 100644 (file)
index 0000000..1038878
--- /dev/null
@@ -0,0 +1,725 @@
+
+
+//
+// Generated on Tue Dec 16 2014 12:13:47 GMT+0100 (CET) by Charlie Robbins, Paolo Fragomeni & the Contributors (Using Codesurgeon).
+// Version 1.2.6
+//
+
+(function (exports) {
+
+/*
+ * browser.js: Browser specific functionality for director.
+ *
+ * (C) 2011, Charlie Robbins, Paolo Fragomeni, & the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+var dloc = document.location;
+
+function dlocHashEmpty() {
+  // Non-IE browsers return '' when the address bar shows '#'; Director's logic
+  // assumes both mean empty.
+  return dloc.hash === '' || dloc.hash === '#';
+}
+
+var listener = {
+  mode: 'modern',
+  hash: dloc.hash,
+  history: false,
+
+  check: function () {
+    var h = dloc.hash;
+    if (h != this.hash) {
+      this.hash = h;
+      this.onHashChanged();
+    }
+  },
+
+  fire: function () {
+    if (this.mode === 'modern') {
+      this.history === true ? window.onpopstate() : window.onhashchange();
+    }
+    else {
+      this.onHashChanged();
+    }
+  },
+
+  init: function (fn, history) {
+    var self = this;
+    this.history = history;
+
+    if (!Router.listeners) {
+      Router.listeners = [];
+    }
+
+    function onchange(onChangeEvent) {
+      for (var i = 0, l = Router.listeners.length; i < l; i++) {
+        Router.listeners[i](onChangeEvent);
+      }
+    }
+
+    //note IE8 is being counted as 'modern' because it has the hashchange event
+    if ('onhashchange' in window && (document.documentMode === undefined
+      || document.documentMode > 7)) {
+      // At least for now HTML5 history is available for 'modern' browsers only
+      if (this.history === true) {
+        // There is an old bug in Chrome that causes onpopstate to fire even
+        // upon initial page load. Since the handler is run manually in init(),
+        // this would cause Chrome to run it twise. Currently the only
+        // workaround seems to be to set the handler after the initial page load
+        // http://code.google.com/p/chromium/issues/detail?id=63040
+        setTimeout(function() {
+          window.onpopstate = onchange;
+        }, 500);
+      }
+      else {
+        window.onhashchange = onchange;
+      }
+      this.mode = 'modern';
+    }
+    else {
+      //
+      // IE support, based on a concept by Erik Arvidson ...
+      //
+      var frame = document.createElement('iframe');
+      frame.id = 'state-frame';
+      frame.style.display = 'none';
+      document.body.appendChild(frame);
+      this.writeFrame('');
+
+      if ('onpropertychange' in document && 'attachEvent' in document) {
+        document.attachEvent('onpropertychange', function () {
+          if (event.propertyName === 'location') {
+            self.check();
+          }
+        });
+      }
+
+      window.setInterval(function () { self.check(); }, 50);
+
+      this.onHashChanged = onchange;
+      this.mode = 'legacy';
+    }
+
+    Router.listeners.push(fn);
+
+    return this.mode;
+  },
+
+  destroy: function (fn) {
+    if (!Router || !Router.listeners) {
+      return;
+    }
+
+    var listeners = Router.listeners;
+
+    for (var i = listeners.length - 1; i >= 0; i--) {
+      if (listeners[i] === fn) {
+        listeners.splice(i, 1);
+      }
+    }
+  },
+
+  setHash: function (s) {
+    // Mozilla always adds an entry to the history
+    if (this.mode === 'legacy') {
+      this.writeFrame(s);
+    }
+
+    if (this.history === true) {
+      window.history.pushState({}, document.title, s);
+      // Fire an onpopstate event manually since pushing does not obviously
+      // trigger the pop event.
+      this.fire();
+    } else {
+      dloc.hash = (s[0] === '/') ? s : '/' + s;
+    }
+    return this;
+  },
+
+  writeFrame: function (s) {
+    // IE support...
+    var f = document.getElementById('state-frame');
+    var d = f.contentDocument || f.contentWindow.document;
+    d.open();
+    d.write("<script>_hash = '" + s + "'; onload = parent.listener.syncHash;<script>");
+    d.close();
+  },
+
+  syncHash: function () {
+    // IE support...
+    var s = this._hash;
+    if (s != dloc.hash) {
+      dloc.hash = s;
+    }
+    return this;
+  },
+
+  onHashChanged: function () {}
+};
+
+var Router = exports.Router = function (routes) {
+  if (!(this instanceof Router)) return new Router(routes);
+
+  this.params   = {};
+  this.routes   = {};
+  this.methods  = ['on', 'once', 'after', 'before'];
+  this.scope    = [];
+  this._methods = {};
+
+  this._insert = this.insert;
+  this.insert = this.insertEx;
+
+  this.historySupport = (window.history != null ? window.history.pushState : null) != null
+
+  this.configure();
+  this.mount(routes || {});
+};
+
+Router.prototype.init = function (r) {
+  var self = this
+    , routeTo;
+  this.handler = function(onChangeEvent) {
+    var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;
+    var url = self.history === true ? self.getPath() : newURL.replace(/.*#/, '');
+    self.dispatch('on', url.charAt(0) === '/' ? url : '/' + url);
+  };
+
+  listener.init(this.handler, this.history);
+
+  if (this.history === false) {
+    if (dlocHashEmpty() && r) {
+      dloc.hash = r;
+    } else if (!dlocHashEmpty()) {
+      self.dispatch('on', '/' + dloc.hash.replace(/^(#\/|#|\/)/, ''));
+    }
+  }
+  else {
+    if (this.convert_hash_in_init) {
+      // Use hash as route
+      routeTo = dlocHashEmpty() && r ? r : !dlocHashEmpty() ? dloc.hash.replace(/^#/, '') : null;
+      if (routeTo) {
+        window.history.replaceState({}, document.title, routeTo);
+      }
+    }
+    else {
+      // Use canonical url
+      routeTo = this.getPath();
+    }
+
+    // Router has been initialized, but due to the chrome bug it will not
+    // yet actually route HTML5 history state changes. Thus, decide if should route.
+    if (routeTo || this.run_in_init === true) {
+      this.handler();
+    }
+  }
+
+  return this;
+};
+
+Router.prototype.explode = function () {
+  var v = this.history === true ? this.getPath() : dloc.hash;
+  if (v.charAt(1) === '/') { v=v.slice(1) }
+  return v.slice(1, v.length).split("/");
+};
+
+Router.prototype.setRoute = function (i, v, val) {
+  var url = this.explode();
+
+  if (typeof i === 'number' && typeof v === 'string') {
+    url[i] = v;
+  }
+  else if (typeof val === 'string') {
+    url.splice(i, v, s);
+  }
+  else {
+    url = [i];
+  }
+
+  listener.setHash(url.join('/'));
+  return url;
+};
+
+//
+// ### function insertEx(method, path, route, parent)
+// #### @method {string} Method to insert the specific `route`.
+// #### @path {Array} Parsed path to insert the `route` at.
+// #### @route {Array|function} Route handlers to insert.
+// #### @parent {Object} **Optional** Parent "routes" to insert into.
+// insert a callback that will only occur once per the matched route.
+//
+Router.prototype.insertEx = function(method, path, route, parent) {
+  if (method === "once") {
+    method = "on";
+    route = function(route) {
+      var once = false;
+      return function() {
+        if (once) return;
+        once = true;
+        return route.apply(this, arguments);
+      };
+    }(route);
+  }
+  return this._insert(method, path, route, parent);
+};
+
+Router.prototype.getRoute = function (v) {
+  var ret = v;
+
+  if (typeof v === "number") {
+    ret = this.explode()[v];
+  }
+  else if (typeof v === "string"){
+    var h = this.explode();
+    ret = h.indexOf(v);
+  }
+  else {
+    ret = this.explode();
+  }
+
+  return ret;
+};
+
+Router.prototype.destroy = function () {
+  listener.destroy(this.handler);
+  return this;
+};
+
+Router.prototype.getPath = function () {
+  var path = window.location.pathname;
+  if (path.substr(0, 1) !== '/') {
+    path = '/' + path;
+  }
+  return path;
+};
+function _every(arr, iterator) {
+  for (var i = 0; i < arr.length; i += 1) {
+    if (iterator(arr[i], i, arr) === false) {
+      return;
+    }
+  }
+}
+
+function _flatten(arr) {
+  var flat = [];
+  for (var i = 0, n = arr.length; i < n; i++) {
+    flat = flat.concat(arr[i]);
+  }
+  return flat;
+}
+
+function _asyncEverySeries(arr, iterator, callback) {
+  if (!arr.length) {
+    return callback();
+  }
+  var completed = 0;
+  (function iterate() {
+    iterator(arr[completed], function(err) {
+      if (err || err === false) {
+        callback(err);
+        callback = function() {};
+      } else {
+        completed += 1;
+        if (completed === arr.length) {
+          callback();
+        } else {
+          iterate();
+        }
+      }
+    });
+  })();
+}
+
+function paramifyString(str, params, mod) {
+  mod = str;
+  for (var param in params) {
+    if (params.hasOwnProperty(param)) {
+      mod = params[param](str);
+      if (mod !== str) {
+        break;
+      }
+    }
+  }
+  return mod === str ? "([._a-zA-Z0-9-%()]+)" : mod;
+}
+
+function regifyString(str, params) {
+  var matches, last = 0, out = "";
+  while (matches = str.substr(last).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/)) {
+    last = matches.index + matches[0].length;
+    matches[0] = matches[0].replace(/^\*/, "([_.()!\\ %@&a-zA-Z0-9-]+)");
+    out += str.substr(0, matches.index) + matches[0];
+  }
+  str = out += str.substr(last);
+  var captures = str.match(/:([^\/]+)/ig), capture, length;
+  if (captures) {
+    length = captures.length;
+    for (var i = 0; i < length; i++) {
+      capture = captures[i];
+      if (capture.slice(0, 2) === "::") {
+        str = capture.slice(1);
+      } else {
+        str = str.replace(capture, paramifyString(capture, params));
+      }
+    }
+  }
+  return str;
+}
+
+function terminator(routes, delimiter, start, stop) {
+  var last = 0, left = 0, right = 0, start = (start || "(").toString(), stop = (stop || ")").toString(), i;
+  for (i = 0; i < routes.length; i++) {
+    var chunk = routes[i];
+    if (chunk.indexOf(start, last) > chunk.indexOf(stop, last) || ~chunk.indexOf(start, last) && !~chunk.indexOf(stop, last) || !~chunk.indexOf(start, last) && ~chunk.indexOf(stop, last)) {
+      left = chunk.indexOf(start, last);
+      right = chunk.indexOf(stop, last);
+      if (~left && !~right || !~left && ~right) {
+        var tmp = routes.slice(0, (i || 1) + 1).join(delimiter);
+        routes = [ tmp ].concat(routes.slice((i || 1) + 1));
+      }
+      last = (right > left ? right : left) + 1;
+      i = 0;
+    } else {
+      last = 0;
+    }
+  }
+  return routes;
+}
+
+var QUERY_SEPARATOR = /\?.*/;
+
+Router.prototype.configure = function(options) {
+  options = options || {};
+  for (var i = 0; i < this.methods.length; i++) {
+    this._methods[this.methods[i]] = true;
+  }
+  this.recurse = options.recurse || this.recurse || false;
+  this.async = options.async || false;
+  this.delimiter = options.delimiter || "/";
+  this.strict = typeof options.strict === "undefined" ? true : options.strict;
+  this.notfound = options.notfound;
+  this.resource = options.resource;
+  this.history = options.html5history && this.historySupport || false;
+  this.run_in_init = this.history === true && options.run_handler_in_init !== false;
+  this.convert_hash_in_init = this.history === true && options.convert_hash_in_init !== false;
+  this.every = {
+    after: options.after || null,
+    before: options.before || null,
+    on: options.on || null
+  };
+  return this;
+};
+
+Router.prototype.param = function(token, matcher) {
+  if (token[0] !== ":") {
+    token = ":" + token;
+  }
+  var compiled = new RegExp(token, "g");
+  this.params[token] = function(str) {
+    return str.replace(compiled, matcher.source || matcher);
+  };
+  return this;
+};
+
+Router.prototype.on = Router.prototype.route = function(method, path, route) {
+  var self = this;
+  if (!route && typeof path == "function") {
+    route = path;
+    path = method;
+    method = "on";
+  }
+  if (Array.isArray(path)) {
+    return path.forEach(function(p) {
+      self.on(method, p, route);
+    });
+  }
+  if (path.source) {
+    path = path.source.replace(/\\\//ig, "/");
+  }
+  if (Array.isArray(method)) {
+    return method.forEach(function(m) {
+      self.on(m.toLowerCase(), path, route);
+    });
+  }
+  path = path.split(new RegExp(this.delimiter));
+  path = terminator(path, this.delimiter);
+  this.insert(method, this.scope.concat(path), route);
+};
+
+Router.prototype.path = function(path, routesFn) {
+  var self = this, length = this.scope.length;
+  if (path.source) {
+    path = path.source.replace(/\\\//ig, "/");
+  }
+  path = path.split(new RegExp(this.delimiter));
+  path = terminator(path, this.delimiter);
+  this.scope = this.scope.concat(path);
+  routesFn.call(this, this);
+  this.scope.splice(length, path.length);
+};
+
+Router.prototype.dispatch = function(method, path, callback) {
+  var self = this, fns = this.traverse(method, path.replace(QUERY_SEPARATOR, ""), this.routes, ""), invoked = this._invoked, after;
+  this._invoked = true;
+  if (!fns || fns.length === 0) {
+    this.last = [];
+    if (typeof this.notfound === "function") {
+      this.invoke([ this.notfound ], {
+        method: method,
+        path: path
+      }, callback);
+    }
+    return false;
+  }
+  if (this.recurse === "forward") {
+    fns = fns.reverse();
+  }
+  function updateAndInvoke() {
+    self.last = fns.after;
+    self.invoke(self.runlist(fns), self, callback);
+  }
+  after = this.every && this.every.after ? [ this.every.after ].concat(this.last) : [ this.last ];
+  if (after && after.length > 0 && invoked) {
+    if (this.async) {
+      this.invoke(after, this, updateAndInvoke);
+    } else {
+      this.invoke(after, this);
+      updateAndInvoke();
+    }
+    return true;
+  }
+  updateAndInvoke();
+  return true;
+};
+
+Router.prototype.invoke = function(fns, thisArg, callback) {
+  var self = this;
+  var apply;
+  if (this.async) {
+    apply = function(fn, next) {
+      if (Array.isArray(fn)) {
+        return _asyncEverySeries(fn, apply, next);
+      } else if (typeof fn == "function") {
+        fn.apply(thisArg, (fns.captures || []).concat(next));
+      }
+    };
+    _asyncEverySeries(fns, apply, function() {
+      if (callback) {
+        callback.apply(thisArg, arguments);
+      }
+    });
+  } else {
+    apply = function(fn) {
+      if (Array.isArray(fn)) {
+        return _every(fn, apply);
+      } else if (typeof fn === "function") {
+        return fn.apply(thisArg, fns.captures || []);
+      } else if (typeof fn === "string" && self.resource) {
+        self.resource[fn].apply(thisArg, fns.captures || []);
+      }
+    };
+    _every(fns, apply);
+  }
+};
+
+Router.prototype.traverse = function(method, path, routes, regexp, filter) {
+  var fns = [], current, exact, match, next, that;
+  function filterRoutes(routes) {
+    if (!filter) {
+      return routes;
+    }
+    function deepCopy(source) {
+      var result = [];
+      for (var i = 0; i < source.length; i++) {
+        result[i] = Array.isArray(source[i]) ? deepCopy(source[i]) : source[i];
+      }
+      return result;
+    }
+    function applyFilter(fns) {
+      for (var i = fns.length - 1; i >= 0; i--) {
+        if (Array.isArray(fns[i])) {
+          applyFilter(fns[i]);
+          if (fns[i].length === 0) {
+            fns.splice(i, 1);
+          }
+        } else {
+          if (!filter(fns[i])) {
+            fns.splice(i, 1);
+          }
+        }
+      }
+    }
+    var newRoutes = deepCopy(routes);
+    newRoutes.matched = routes.matched;
+    newRoutes.captures = routes.captures;
+    newRoutes.after = routes.after.filter(filter);
+    applyFilter(newRoutes);
+    return newRoutes;
+  }
+  if (path === this.delimiter && routes[method]) {
+    next = [ [ routes.before, routes[method] ].filter(Boolean) ];
+    next.after = [ routes.after ].filter(Boolean);
+    next.matched = true;
+    next.captures = [];
+    return filterRoutes(next);
+  }
+  for (var r in routes) {
+    if (routes.hasOwnProperty(r) && (!this._methods[r] || this._methods[r] && typeof routes[r] === "object" && !Array.isArray(routes[r]))) {
+      current = exact = regexp + this.delimiter + r;
+      if (!this.strict) {
+        exact += "[" + this.delimiter + "]?";
+      }
+      match = path.match(new RegExp("^" + exact));
+      if (!match) {
+        continue;
+      }
+      if (match[0] && match[0] == path && routes[r][method]) {
+        next = [ [ routes[r].before, routes[r][method] ].filter(Boolean) ];
+        next.after = [ routes[r].after ].filter(Boolean);
+        next.matched = true;
+        next.captures = match.slice(1);
+        if (this.recurse && routes === this.routes) {
+          next.push([ routes.before, routes.on ].filter(Boolean));
+          next.after = next.after.concat([ routes.after ].filter(Boolean));
+        }
+        return filterRoutes(next);
+      }
+      next = this.traverse(method, path, routes[r], current);
+      if (next.matched) {
+        if (next.length > 0) {
+          fns = fns.concat(next);
+        }
+        if (this.recurse) {
+          fns.push([ routes[r].before, routes[r].on ].filter(Boolean));
+          next.after = next.after.concat([ routes[r].after ].filter(Boolean));
+          if (routes === this.routes) {
+            fns.push([ routes["before"], routes["on"] ].filter(Boolean));
+            next.after = next.after.concat([ routes["after"] ].filter(Boolean));
+          }
+        }
+        fns.matched = true;
+        fns.captures = next.captures;
+        fns.after = next.after;
+        return filterRoutes(fns);
+      }
+    }
+  }
+  return false;
+};
+
+Router.prototype.insert = function(method, path, route, parent) {
+  var methodType, parentType, isArray, nested, part;
+  path = path.filter(function(p) {
+    return p && p.length > 0;
+  });
+  parent = parent || this.routes;
+  part = path.shift();
+  if (/\:|\*/.test(part) && !/\\d|\\w/.test(part)) {
+    part = regifyString(part, this.params);
+  }
+  if (path.length > 0) {
+    parent[part] = parent[part] || {};
+    return this.insert(method, path, route, parent[part]);
+  }
+  if (!part && !path.length && parent === this.routes) {
+    methodType = typeof parent[method];
+    switch (methodType) {
+     case "function":
+      parent[method] = [ parent[method], route ];
+      return;
+     case "object":
+      parent[method].push(route);
+      return;
+     case "undefined":
+      parent[method] = route;
+      return;
+    }
+    return;
+  }
+  parentType = typeof parent[part];
+  isArray = Array.isArray(parent[part]);
+  if (parent[part] && !isArray && parentType == "object") {
+    methodType = typeof parent[part][method];
+    switch (methodType) {
+     case "function":
+      parent[part][method] = [ parent[part][method], route ];
+      return;
+     case "object":
+      parent[part][method].push(route);
+      return;
+     case "undefined":
+      parent[part][method] = route;
+      return;
+    }
+  } else if (parentType == "undefined") {
+    nested = {};
+    nested[method] = route;
+    parent[part] = nested;
+    return;
+  }
+  throw new Error("Invalid route context: " + parentType);
+};
+
+
+
+Router.prototype.extend = function(methods) {
+  var self = this, len = methods.length, i;
+  function extend(method) {
+    self._methods[method] = true;
+    self[method] = function() {
+      var extra = arguments.length === 1 ? [ method, "" ] : [ method ];
+      self.on.apply(self, extra.concat(Array.prototype.slice.call(arguments)));
+    };
+  }
+  for (i = 0; i < len; i++) {
+    extend(methods[i]);
+  }
+};
+
+Router.prototype.runlist = function(fns) {
+  var runlist = this.every && this.every.before ? [ this.every.before ].concat(_flatten(fns)) : _flatten(fns);
+  if (this.every && this.every.on) {
+    runlist.push(this.every.on);
+  }
+  runlist.captures = fns.captures;
+  runlist.source = fns.source;
+  return runlist;
+};
+
+Router.prototype.mount = function(routes, path) {
+  if (!routes || typeof routes !== "object" || Array.isArray(routes)) {
+    return;
+  }
+  var self = this;
+  path = path || [];
+  if (!Array.isArray(path)) {
+    path = path.split(self.delimiter);
+  }
+  function insertOrMount(route, local) {
+    var rename = route, parts = route.split(self.delimiter), routeType = typeof routes[route], isRoute = parts[0] === "" || !self._methods[parts[0]], event = isRoute ? "on" : rename;
+    if (isRoute) {
+      rename = rename.slice((rename.match(new RegExp("^" + self.delimiter)) || [ "" ])[0].length);
+      parts.shift();
+    }
+    if (isRoute && routeType === "object" && !Array.isArray(routes[route])) {
+      local = local.concat(parts);
+      self.mount(routes[route], local);
+      return;
+    }
+    if (isRoute) {
+      local = local.concat(rename.split(self.delimiter));
+      local = terminator(local, self.delimiter);
+    }
+    self.insert(event, local, routes[route]);
+  }
+  for (var route in routes) {
+    if (routes.hasOwnProperty(route)) {
+      insertOrMount(route, path.slice(0));
+    }
+  }
+};
+
+
+
+}(typeof exports === "object" ? exports : window));
\ No newline at end of file
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.min.js b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/director.min.js
new file mode 100644 (file)
index 0000000..c956af4
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+//
+// Generated on Tue Dec 16 2014 12:13:47 GMT+0100 (CET) by Charlie Robbins, Paolo Fragomeni & the Contributors (Using Codesurgeon).
+// Version 1.2.6
+//
+(function(a){function k(a,b,c,d){var e=0,f=0,g=0,c=(c||"(").toString(),d=(d||")").toString(),h;for(h=0;h<a.length;h++){var i=a[h];if(i.indexOf(c,e)>i.indexOf(d,e)||~i.indexOf(c,e)&&!~i.indexOf(d,e)||!~i.indexOf(c,e)&&~i.indexOf(d,e)){f=i.indexOf(c,e),g=i.indexOf(d,e);if(~f&&!~g||!~f&&~g){var j=a.slice(0,(h||1)+1).join(b);a=[j].concat(a.slice((h||1)+1))}e=(g>f?g:f)+1,h=0}else e=0}return a}function j(a,b){var c,d=0,e="";while(c=a.substr(d).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/))d=c.index+c[0].length,c[0]=c[0].replace(/^\*/,"([_.()!\\ %@&a-zA-Z0-9-]+)"),e+=a.substr(0,c.index)+c[0];a=e+=a.substr(d);var f=a.match(/:([^\/]+)/ig),g,h;if(f){h=f.length;for(var j=0;j<h;j++)g=f[j],g.slice(0,2)==="::"?a=g.slice(1):a=a.replace(g,i(g,b))}return a}function i(a,b,c){c=a;for(var d in b)if(b.hasOwnProperty(d)){c=b[d](a);if(c!==a)break}return c===a?"([._a-zA-Z0-9-%()]+)":c}function h(a,b,c){if(!a.length)return c();var d=0;(function e(){b(a[d],function(b){b||b===!1?(c(b),c=function(){}):(d+=1,d===a.length?c():e())})})()}function g(a){var b=[];for(var c=0,d=a.length;c<d;c++)b=b.concat(a[c]);return b}function f(a,b){for(var c=0;c<a.length;c+=1)if(b(a[c],c,a)===!1)return}function c(){return b.hash===""||b.hash==="#"}var b=document.location,d={mode:"modern",hash:b.hash,history:!1,check:function(){var a=b.hash;a!=this.hash&&(this.hash=a,this.onHashChanged())},fire:function(){this.mode==="modern"?this.history===!0?window.onpopstate():window.onhashchange():this.onHashChanged()},init:function(a,b){function d(a){for(var b=0,c=e.listeners.length;b<c;b++)e.listeners[b](a)}var c=this;this.history=b,e.listeners||(e.listeners=[]);if("onhashchange"in window&&(document.documentMode===undefined||document.documentMode>7))this.history===!0?setTimeout(function(){window.onpopstate=d},500):window.onhashchange=d,this.mode="modern";else{var f=document.createElement("iframe");f.id="state-frame",f.style.display="none",document.body.appendChild(f),this.writeFrame(""),"onpropertychange"in document&&"attachEvent"in document&&document.attachEvent("onpropertychange",function(){event.propertyName==="location"&&c.check()}),window.setInterval(function(){c.check()},50),this.onHashChanged=d,this.mode="legacy"}e.listeners.push(a);return this.mode},destroy:function(a){if(!!e&&!!e.listeners){var b=e.listeners;for(var c=b.length-1;c>=0;c--)b[c]===a&&b.splice(c,1)}},setHash:function(a){this.mode==="legacy"&&this.writeFrame(a),this.history===!0?(window.history.pushState({},document.title,a),this.fire()):b.hash=a[0]==="/"?a:"/"+a;return this},writeFrame:function(a){var b=document.getElementById("state-frame"),c=b.contentDocument||b.contentWindow.document;c.open(),c.write("<script>_hash = '"+a+"'; onload = parent.listener.syncHash;<script>"),c.close()},syncHash:function(){var a=this._hash;a!=b.hash&&(b.hash=a);return this},onHashChanged:function(){}},e=a.Router=function(a){if(this instanceof e)this.params={},this.routes={},this.methods=["on","once","after","before"],this.scope=[],this._methods={},this._insert=this.insert,this.insert=this.insertEx,this.historySupport=(window.history!=null?window.history.pushState:null)!=null,this.configure(),this.mount(a||{});else return new e(a)};e.prototype.init=function(a){var e=this,f;this.handler=function(a){var b=a&&a.newURL||window.location.hash,c=e.history===!0?e.getPath():b.replace(/.*#/,"");e.dispatch("on",c.charAt(0)==="/"?c:"/"+c)},d.init(this.handler,this.history),this.history===!1?c()&&a?b.hash=a:c()||e.dispatch("on","/"+b.hash.replace(/^(#\/|#|\/)/,"")):(this.convert_hash_in_init?(f=c()&&a?a:c()?null:b.hash.replace(/^#/,""),f&&window.history.replaceState({},document.title,f)):f=this.getPath(),(f||this.run_in_init===!0)&&this.handler());return this},e.prototype.explode=function(){var a=this.history===!0?this.getPath():b.hash;a.charAt(1)==="/"&&(a=a.slice(1));return a.slice(1,a.length).split("/")},e.prototype.setRoute=function(a,b,c){var e=this.explode();typeof a=="number"&&typeof b=="string"?e[a]=b:typeof c=="string"?e.splice(a,b,s):e=[a],d.setHash(e.join("/"));return e},e.prototype.insertEx=function(a,b,c,d){a==="once"&&(a="on",c=function(a){var b=!1;return function(){if(!b){b=!0;return a.apply(this,arguments)}}}(c));return this._insert(a,b,c,d)},e.prototype.getRoute=function(a){var b=a;if(typeof a=="number")b=this.explode()[a];else if(typeof a=="string"){var c=this.explode();b=c.indexOf(a)}else b=this.explode();return b},e.prototype.destroy=function(){d.destroy(this.handler);return this},e.prototype.getPath=function(){var a=window.location.pathname;a.substr(0,1)!=="/"&&(a="/"+a);return a};var l=/\?.*/;e.prototype.configure=function(a){a=a||{};for(var b=0;b<this.methods.length;b++)this._methods[this.methods[b]]=!0;this.recurse=a.recurse||this.recurse||!1,this.async=a.async||!1,this.delimiter=a.delimiter||"/",this.strict=typeof a.strict=="undefined"?!0:a.strict,this.notfound=a.notfound,this.resource=a.resource,this.history=a.html5history&&this.historySupport||!1,this.run_in_init=this.history===!0&&a.run_handler_in_init!==!1,this.convert_hash_in_init=this.history===!0&&a.convert_hash_in_init!==!1,this.every={after:a.after||null,before:a.before||null,on:a.on||null};return this},e.prototype.param=function(a,b){a[0]!==":"&&(a=":"+a);var c=new RegExp(a,"g");this.params[a]=function(a){return a.replace(c,b.source||b)};return this},e.prototype.on=e.prototype.route=function(a,b,c){var d=this;!c&&typeof b=="function"&&(c=b,b=a,a="on");if(Array.isArray(b))return b.forEach(function(b){d.on(a,b,c)});b.source&&(b=b.source.replace(/\\\//ig,"/"));if(Array.isArray(a))return a.forEach(function(a){d.on(a.toLowerCase(),b,c)});b=b.split(new RegExp(this.delimiter)),b=k(b,this.delimiter),this.insert(a,this.scope.concat(b),c)},e.prototype.path=function(a,b){var c=this,d=this.scope.length;a.source&&(a=a.source.replace(/\\\//ig,"/")),a=a.split(new RegExp(this.delimiter)),a=k(a,this.delimiter),this.scope=this.scope.concat(a),b.call(this,this),this.scope.splice(d,a.length)},e.prototype.dispatch=function(a,b,c){function h(){d.last=e.after,d.invoke(d.runlist(e),d,c)}var d=this,e=this.traverse(a,b.replace(l,""),this.routes,""),f=this._invoked,g;this._invoked=!0;if(!e||e.length===0){this.last=[],typeof this.notfound=="function"&&this.invoke([this.notfound],{method:a,path:b},c);return!1}this.recurse==="forward"&&(e=e.reverse()),g=this.every&&this.every.after?[this.every.after].concat(this.last):[this.last];if(g&&g.length>0&&f){this.async?this.invoke(g,this,h):(this.invoke(g,this),h());return!0}h();return!0},e.prototype.invoke=function(a,b,c){var d=this,e;this.async?(e=function(c,d){if(Array.isArray(c))return h(c,e,d);typeof c=="function"&&c.apply(b,(a.captures||[]).concat(d))},h(a,e,function(){c&&c.apply(b,arguments)})):(e=function(c){if(Array.isArray(c))return f(c,e);if(typeof c=="function")return c.apply(b,a.captures||[]);typeof c=="string"&&d.resource&&d.resource[c].apply(b,a.captures||[])},f(a,e))},e.prototype.traverse=function(a,b,c,d,e){function l(a){function c(a){for(var b=a.length-1;b>=0;b--)Array.isArray(a[b])?(c(a[b]),a[b].length===0&&a.splice(b,1)):e(a[b])||a.splice(b,1)}function b(a){var c=[];for(var d=0;d<a.length;d++)c[d]=Array.isArray(a[d])?b(a[d]):a[d];return c}if(!e)return a;var d=b(a);d.matched=a.matched,d.captures=a.captures,d.after=a.after.filter(e),c(d);return d}var f=[],g,h,i,j,k;if(b===this.delimiter&&c[a]){j=[[c.before,c[a]].filter(Boolean)],j.after=[c.after].filter(Boolean),j.matched=!0,j.captures=[];return l(j)}for(var m in c)if(c.hasOwnProperty(m)&&(!this._methods[m]||this._methods[m]&&typeof c[m]=="object"&&!Array.isArray(c[m]))){g=h=d+this.delimiter+m,this.strict||(h+="["+this.delimiter+"]?"),i=b.match(new RegExp("^"+h));if(!i)continue;if(i[0]&&i[0]==b&&c[m][a]){j=[[c[m].before,c[m][a]].filter(Boolean)],j.after=[c[m].after].filter(Boolean),j.matched=!0,j.captures=i.slice(1),this.recurse&&c===this.routes&&(j.push([c.before,c.on].filter(Boolean)),j.after=j.after.concat([c.after].filter(Boolean)));return l(j)}j=this.traverse(a,b,c[m],g);if(j.matched){j.length>0&&(f=f.concat(j)),this.recurse&&(f.push([c[m].before,c[m].on].filter(Boolean)),j.after=j.after.concat([c[m].after].filter(Boolean)),c===this.routes&&(f.push([c.before,c.on].filter(Boolean)),j.after=j.after.concat([c.after].filter(Boolean)))),f.matched=!0,f.captures=j.captures,f.after=j.after;return l(f)}}return!1},e.prototype.insert=function(a,b,c,d){var e,f,g,h,i;b=b.filter(function(a){return a&&a.length>0}),d=d||this.routes,i=b.shift(),/\:|\*/.test(i)&&!/\\d|\\w/.test(i)&&(i=j(i,this.params));if(b.length>0){d[i]=d[i]||{};return this.insert(a,b,c,d[i])}{if(!!i||!!b.length||d!==this.routes){f=typeof d[i],g=Array.isArray(d[i]);if(d[i]&&!g&&f=="object"){e=typeof d[i][a];switch(e){case"function":d[i][a]=[d[i][a],c];return;case"object":d[i][a].push(c);return;case"undefined":d[i][a]=c;return}}else if(f=="undefined"){h={},h[a]=c,d[i]=h;return}throw new Error("Invalid route context: "+f)}e=typeof d[a];switch(e){case"function":d[a]=[d[a],c];return;case"object":d[a].push(c);return;case"undefined":d[a]=c;return}}},e.prototype.extend=function(a){function e(a){b._methods[a]=!0,b[a]=function(){var c=arguments.length===1?[a,""]:[a];b.on.apply(b,c.concat(Array.prototype.slice.call(arguments)))}}var b=this,c=a.length,d;for(d=0;d<c;d++)e(a[d])},e.prototype.runlist=function(a){var b=this.every&&this.every.before?[this.every.before].concat(g(a)):g(a);this.every&&this.every.on&&b.push(this.every.on),b.captures=a.captures,b.source=a.source;return b},e.prototype.mount=function(a,b){function d(b,d){var e=b,f=b.split(c.delimiter),g=typeof a[b],h=f[0]===""||!c._methods[f[0]],i=h?"on":e;h&&(e=e.slice((e.match(new RegExp("^"+c.delimiter))||[""])[0].length),f.shift());h&&g==="object"&&!Array.isArray(a[b])?(d=d.concat(f),c.mount(a[b],d)):(h&&(d=d.concat(e.split(c.delimiter)),d=k(d,c.delimiter)),c.insert(i,d,a[b]))}if(!!a&&typeof a=="object"&&!Array.isArray(a)){var c=this;b=b||[],Array.isArray(b)||(b=b.split(c.delimiter));for(var e in a)a.hasOwnProperty(e)&&d(e,b.slice(0))}}})(typeof exports=="object"?exports:window)
\ No newline at end of file
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/ender.js b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/dist/ender.js
new file mode 100644 (file)
index 0000000..fe3ebc4
--- /dev/null
@@ -0,0 +1,3 @@
+$.ender({
+  router: Router
+});
diff --git a/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/package.json b/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/jquery/node_modules/director/package.json
new file mode 100644 (file)
index 0000000..10bd296
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  "name": "director",
+  "description": "A client Side/Server Side Router",
+  "author": "Charlie Robbins <charlie.robbins@gmail.com>",
+  "version": "1.2.8",
+  "maintainers": [
+    "hij1nx <paolo@nodejitsu.com>",
+    "beaugunderson <beau@beaugunderson.com>"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/flatiron/director.git"
+  },
+  "keywords": [
+    "URL",
+    "router",
+    "http",
+    "cli",
+    "flatiron",
+    "client side",
+    "ender"
+  ],
+  "devDependencies": {
+    "api-easy": "0.4.x",
+    "codesurgeon": "https://github.com/hij1nx/codesurgeon/tarball/master",
+    "colors": "1.0.x",
+    "qunitjs": "1.9.x",
+    "request": "2.49.x",
+    "uglify-js": "2.4.x",
+    "vows": "0.8.0"
+  },
+  "ender": "./build/ender.js",
+  "browserify": "./build/director",
+  "main": "./lib/director",
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "vows test/server/*/*-test.js --spec"
+  }
+}
index 9514c4c..99134a2 100644 (file)
@@ -16,7 +16,7 @@
 </head>
 
 <body>
-<script src="build/elm.js"></script>
+<script src="dist/elm.js"></script>
 <script>
     (function () {
         // var result = localStorage.getItem('elm-todo-model');