karma-benchpress
Version:
Karma plugin to run angular-benchpress benchmarks.
1,677 lines (1,495 loc) • 569 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var di = require('di');
var Measure = require('./Measure');
var RunState = require('./RunState');
var Statistics = require('./Statistics');
var Steps = require('./Steps');
function Aggregator (measure, runState, statistics, steps) {
this._measure = measure;
this._runState = runState;
this._statistics = statistics;
this._steps = steps.all();
this.timesPerAction = {};
}
Aggregator.prototype.trimSamples = function(times) {
var delta = times.length - this._runState.numSamples;
if (delta > 0) {
return times.slice(delta);
}
return times;
};
Aggregator.prototype.getTimesPerAction = function(name) {
if (this.timesPerAction[name]) return this.timesPerAction[name];
var tpa = this.timesPerAction[name] = {
name: name,
nextEntry: 0
};
_.each(this._measure.characteristics, function(c) {
tpa[c] = {
recent: undefined,
history: [],
avg: {},
min: Number.MAX_VALUE,
max: Number.MIN_VALUE
};
});
return tpa;
};
Aggregator.prototype.updateTimes = function(tpa, index, reference, recentTime) {
var curTpa = tpa[reference];
curTpa.recent = recentTime;
curTpa.history[index] = recentTime;
curTpa.history = this.trimSamples(curTpa.history);
curTpa.min = Math.min(curTpa.min, recentTime);
curTpa.max = Math.max(curTpa.max, recentTime);
};
Aggregator.prototype.calcStats = function() {
var stats = {};
var self = this;
this._steps.forEach(function(bs) {
var recentResult = self._runState.recentResult[bs.name],
tpa = self.getTimesPerAction(bs.name);
tpa.description = bs.description;
_.each(self._measure.characteristics, function(c) {
self.updateTimes(tpa, tpa.nextEntry, c, recentResult[c]);
var mean = self._statistics.getMean(tpa[c].history);
var stdDev = self._statistics.calculateStandardDeviation(tpa[c].history, mean);
tpa[c].avg = {
mean: mean,
stdDev: stdDev,
coefficientOfVariation: self._statistics.calculateCoefficientOfVariation(stdDev, mean)
};
});
// Start over samples when hits the max set by numSamples
tpa.nextEntry++;
tpa.nextEntry %= self._runState.numSamples;
stats[bs.name] = tpa;
});
return stats;
};
di.annotate(Aggregator, new di.Inject(Measure, RunState, Statistics, Steps));
module.exports = Aggregator;
},{"./Measure":8,"./RunState":9,"./Statistics":11,"./Steps":12,"di":24}],2:[function(require,module,exports){
var di = require('di');
var Aggregator = require('./Aggregator');
var Globals = require('./Globals');
var Logger = require('./Logger');
var Runner = require('./Runner');
var RunState = require('./RunState');
var Rx = require('rx');
var Steps = require('./Steps');
var Utils = require('./Utils');
function AutoRunner(aggregator,globals,logger,runner,runState,steps,utils){
this._aggregator = aggregator;
this._globals = globals;
this._logger = logger;
this._runner = runner;
this._runState = runState;
this._utils = utils;
this._steps = steps;
}
AutoRunner.prototype.bootstrap = function() {
var parsed = this._utils.parseSearch(this._globals._window.location.search)
this._runState.setDefault(parsed);
if (parsed['__bpAutoClose__'] === 'true') {
this._runState.headless = true;
}
};
AutoRunner.prototype.ready = function () {
this._globals._window.setTimeout(function() {
this.runBenchmark(this._runState);
}.bind(this));
};
AutoRunner.prototype.runBenchmark = function(config) {
this.runAllTests().subscribe(function(update) {
this._logger.write(update);
}.bind(this), null, function() {
if (this._runState.headless === true) {
var benchpressComplete = new Event('benchpressComplete');
benchpressComplete.result = this.stats;
this._globals._window.dispatchEvent(benchpressComplete);
this._globals._window.close();
}
}.bind(this));
};
AutoRunner.prototype.runAllTests = function (iterations) {
this.subject = this.subject || new Rx.Subject();
iterations = typeof iterations === 'number' ? iterations : this._runState.iterations;
if (iterations--) {
this._steps.all().forEach(function(bs) {
var testResults = this._runner.runTimedTest(bs);
this._runState.recentResult[bs.name] = testResults;
this.subject.onNext({step: bs.name, results: testResults})
}.bind(this));
this.stats = this._aggregator.calcStats();
window.requestAnimationFrame(function() {
this.runAllTests(iterations);
}.bind(this));
}
else {
this.stats = this._aggregator.calcStats();
this.subject.onCompleted();
this.subject.dispose();
delete this.subject;
}
return this.subject;
};
di.annotate(AutoRunner, new di.Inject(Aggregator,Globals,Logger,Runner,RunState,Steps,Utils));
module.exports = AutoRunner;
},{"./Aggregator":1,"./Globals":5,"./Logger":7,"./RunState":9,"./Runner":10,"./Steps":12,"./Utils":13,"di":24,"rx":29}],3:[function(require,module,exports){
function ClientScripts () {
this._scripts = [];
}
ClientScripts.prototype.all = function() {
return this._scripts;
}
ClientScripts.prototype.shiftOne = function() {
return this._scripts.shift();
};
ClientScripts.prototype.add = function(script) {
this._scripts.push(script);
};
ClientScripts.prototype.addMany = function(scripts) {
this._scripts.push.apply(this._scripts, scripts);
}
module.exports = ClientScripts;
},{}],4:[function(require,module,exports){
var di = require('di');
var ClientScripts = require('./ClientScripts');
var Globals = require('./Globals');
var RunState = require('./RunState');
var Rx = require('rx');
var Utils = require('./Utils');
function Document(globals, runState, scripts, utils) {
this._utils = utils;
this._scripts = scripts;
this._globals = globals;
this._runState = runState;
this.loadNextScript = this.loadNextScript.bind(this);
}
Document.prototype.setAutoRun = function(val) {
this.autoRunner = val;
};
Document.prototype.addSampleRange = function() {
this.sampleRange = this.container().querySelector('#sampleRange');
if (this.sampleRange) {
this.sampleRange.value = Math.max(this._runState.numSamples, 1);
this.sampleRange.addEventListener('input', this.onSampleInputChanged.bind(this));
}
};
Document.prototype.onSampleInputChanged = function (evt) {
var value = evt.target.value;
this._runState.numSamples = parseInt(value, 10);
};
Document.prototype.container = function() {
if (!this._container) {
this._container = document.querySelector('#benchmarkContainer');
}
return this._container;
};
Document.prototype.addInfo = function() {
this.infoDiv = this.container().querySelector('div.info');
if (this.infoDiv) {
this.infoTemplate = _.template(this.container().querySelector('#infoTemplate').innerHTML);
}
};
Document.prototype.loadNextScript = function() {
var params = this._utils.parseSearch(this._globals._window.location.search);
var config = this._scripts.shiftOne();
if (!config) return;
if (config.id) {
if (params[config.id]) {
config.src = params[config.id];
}
this.addScriptToUI(config);
}
var tag = document.createElement('script');
tag.setAttribute('src', config.src);
tag.onload = this.loadNextScript;
document.body.appendChild(tag);
};
Document.prototype.openTab = function (id) {
var divs = this._container.querySelectorAll('.tab-pane');
for (var i=0;i<divs.length;i++) {
divs[i].style.display = 'none';
}
this._container.querySelector('.nav-tabs li.active').classList.remove('active');
this._container.querySelector(id).style.display = 'block';
this._container.querySelector('[href="' + id + '"]').parentElement.classList.add('active');
}
Document.prototype.addScriptToUI = function(config) {
if (!this._scriptsContainer) return;
var compiled = this._scriptTemplate(config);
this._scriptsContainer.innerHTML += compiled;
};
//Deprecated
Document.prototype.getParams = function() {
return this._utils.parseSearch(this._globals._window.location.search);
};
Document.prototype.addScriptsContainer = function() {
if (!this.container()) return;
this._scriptsContainer = this.container().querySelector('table.scripts tbody');
this._scriptTemplate = _.template(this.container().querySelector('#scriptTemplate').innerHTML);
};
Document.prototype.onDOMContentLoaded = function() {
if (!this.container() || this.autoRunner) return;
this.addSampleRange();
this.addInfo();
this.addScriptsContainer();
this.loopBtn = document.querySelector('.loopBtn');
this.onceBtn = document.querySelector('.onceBtn');
this.twentyFiveBtn = document.querySelector('.twentyFiveBtn');
};
Document.prototype.observeBtns = function () {
if (!this.btnObserver) this.btnObserver = Rx.Observable.
fromEvent(document.querySelectorAll('.bp-btn'), 'click');
return this.btnObserver;
}
Document.prototype.writeReport = function(reportContent) {
this.infoDiv.innerHTML = reportContent;
};
di.annotate(Document, new di.Inject(Globals, RunState, ClientScripts, Utils));
module.exports = Document;
},{"./ClientScripts":3,"./Globals":5,"./RunState":9,"./Utils":13,"di":24,"rx":29}],5:[function(require,module,exports){
function Globals() {
this._window = window;
}
module.exports = Globals;
},{}],6:[function(require,module,exports){
var di = require('di');
var Aggregator = require('./Aggregator');
var Document = require('./Document');
var Measure = require('./Measure');
var RunState = require('./RunState');
var Statistics = require('./Statistics');
var Steps = require('./Steps');
var _ = require('underscore');
function Report(aggregator, doc, measure, runState, statistics, steps) {
this._aggregator = aggregator;
this._doc = doc;
this._measure = measure;
this._runState = runState;
this._statistics = statistics;
this._steps = steps.all();
}
Report.prototype.generatePartial = function(model) {
return this._doc.infoTemplate(model);
};
Report.prototype.getMarkup = function(stats) {
var report = '';
Object.keys(stats).forEach(function(key) {
report += this.generatePartial(stats[key]);
}.bind(this));
return report;
};
di.annotate(Report, new di.Inject(Aggregator, Document, Measure, RunState, Statistics, Steps));
module.exports = Report;
},{"./Aggregator":1,"./Document":4,"./Measure":8,"./RunState":9,"./Statistics":11,"./Steps":12,"di":24,"underscore":30}],7:[function(require,module,exports){
function Logger() {
}
Logger.prototype.write = function(ln) {
console.log(ln);
};
module.exports = Logger;
},{}],8:[function(require,module,exports){
function Measure(){
this.characteristics = ['gcTime','testTime','garbageCount','retainedCount'];
};
Measure.prototype.numMilliseconds = function() {
if (window.performance != null && typeof window.performance.now == 'function') {
return window.performance.now();
} else if (window.performance != null && typeof window.performance.webkitNow == 'function') {
return window.performance.webkitNow();
} else {
console.log('using Date.now');
return Date.now();
}
};
module.exports = Measure;
},{}],9:[function(require,module,exports){
function RunState() {
this.defaults = {
iterations: 25,
numSamples: 20
};
this.iterations = 25;
this.numSamples = 20;
this.recentResult = {};
};
RunState.prototype.setIterations = function(i) {
this.iterations = i;
};
RunState.prototype.resetIterations = function() {
this.iterations = this.defaults.iterations;
};
RunState.prototype.setDefault = function(defaults) {
['iterations','numSamples'].forEach(function(prop) {
var propVal = parseInt(defaults[prop],10);
if (typeof propVal === 'number' && !isNaN(propVal)) {
this[prop] = propVal;
this.defaults[prop] = propVal;
}
else if (typeof defaults[prop] !== 'undefined') {
throw new Error(prop + ' must be of type number, got: ' + typeof defaults[prop]);
}
}.bind(this));
};
module.exports = RunState;
},{}],10:[function(require,module,exports){
var di = require('di');
var Aggregator = require('./Aggregator');
var Document = require('./Document');
var Globals = require('./Globals');
var Measure = require('./Measure');
var Report = require('./HtmlReport');
var RunState = require('./RunState');
var Steps = require('./Steps');
var Rx = require('rx');
function Runner (aggregator, doc, globals, measure, report, runState, steps) {
this._aggregator = aggregator;
this._doc = doc;
this._globals = globals;
this._measure = measure;
this._steps = steps;
this._runState = runState;
this._report = report;
this.reportMarkup = '';
}
Runner.prototype.bootstrap = function() {
this._btnSubscription = this._doc.observeBtns().subscribe(this.onBtnClick.bind(this));
};
Runner.prototype.ready = function () {
//No-op. API symmetry to AutoRunner
};
Runner.prototype.onBtnClick = function(e) {
switch (e && e.target && e.target.textContent) {
case 'Loop':
this.loopBenchmark();
break;
case 'Once':
this.onceBenchmark();
break;
case 'Loop 25x':
this.twentyFiveBenchmark();
break;
case 'Profile':
this.profile();
break;
case 'Pause':
this._runState.setIterations(0);
this._doc.loopBtn.innerText = 'Loop';
break;
default:
throw new Error('Could not find handler');
}
};
Runner.prototype.loopBenchmark = function (notify) {
this._runState.setIterations(-1);
notify && notify({status: 'done', runType: 'loop'})
this._doc.loopBtn.innerText = 'Pause';
this.runAllTests();
};
Runner.prototype.onceBenchmark = function() {
this._runState.setIterations(1);
this._doc.onceBtn.innerText = '...';
this.runAllTests(function() {
this._doc.onceBtn.innerText = 'Once';
}.bind(this));
};
Runner.prototype.twentyFiveBenchmark = function() {
var twentyFiveBtn = this._doc.twentyFiveBtn;
this._runState.setIterations(25);
twentyFiveBtn.innerText = 'Looping...';
this.runAllTests(function() {
twentyFiveBtn.innerText = 'Loop 25x';
}, 5);
};
Runner.prototype.runAllTests = function (done) {
var self = this;
if (this._runState.iterations--) {
this._steps.all().forEach(function(bs) {
var testResults = self.runTimedTest(bs);
self._runState.recentResult[bs.name] = testResults;
});
var stats = this._aggregator.calcStats();
this.reportMarkup = this._report.getMarkup(stats);
this._doc.writeReport(this.reportMarkup);
window.requestAnimationFrame(function() {
self.runAllTests(done);
});
}
else {
this._doc.writeReport(this.reportMarkup);
this._runState.resetIterations();
done && done();
}
};
Runner.prototype.profile = function() {
console.profile();
this.onceBenchmark();
console.profileEnd();
};
Runner.prototype.runTimedTest = function (bs) {
var startTime,
endTime,
startGCTime,
endGCTime,
retainedMemory,
garbage,
beforeHeap,
afterHeap,
finalHeap;
if (typeof this._globals._window.gc === 'function') {
this._globals._window.gc();
}
if (window.performance && window.performance.memory) {
beforeHeap = performance.memory.usedJSHeapSize;
}
startTime = this._measure.numMilliseconds();
bs.fn();
endTime = this._measure.numMilliseconds() - startTime;
if (window.performance && window.performance.memory) {
afterHeap = performance.memory.usedJSHeapSize;
}
startGCTime = this._measure.numMilliseconds();
if (typeof window.gc === 'function') {
window.gc();
}
endGCTime = this._measure.numMilliseconds() - startGCTime;
if (window.performance && window.performance.memory) {
finalHeap = performance.memory.usedJSHeapSize;
garbage = Math.abs(finalHeap - afterHeap);
retainedMemory = finalHeap - beforeHeap;
}
return {
testTime: endTime,
gcTime: endGCTime || 0,
beforeHeap: beforeHeap || 0,
garbageCount: garbage || 0,
retainedCount: retainedMemory || 0
};
};
di.annotate(Runner, new di.Inject(Aggregator, Document, Globals, Measure, Report, RunState, Steps));
module.exports = Runner;
},{"./Aggregator":1,"./Document":4,"./Globals":5,"./HtmlReport":6,"./Measure":8,"./RunState":9,"./Steps":12,"di":24,"rx":29}],11:[function(require,module,exports){
var di = require('di');
function Statistics() {
//Taken from z-table where confidence is 95%
this.criticalValue = 1.96
}
Statistics.prototype.getMean = function (sample) {
var total = 0;
sample.forEach(function(x) { total += x; });
return total / sample.length;
};
Statistics.prototype.calculateConfidenceInterval = function(standardDeviation, sampleSize) {
var standardError = standardDeviation / Math.sqrt(sampleSize);
return this.criticalValue * standardError;
};
Statistics.prototype.calculateRelativeMarginOfError = function(marginOfError, mean) {
/*
* Converts absolute margin of error to a relative margin of error by
* converting it to a percentage of the mean.
*/
return (marginOfError / mean);
};
Statistics.prototype.calculateCoefficientOfVariation = function(standardDeviation, mean) {
return standardDeviation / mean;
};
Statistics.prototype.calculateStandardDeviation = function(sample, mean) {
var deviation = 0;
sample.forEach(function(x) {
deviation += Math.pow(x - mean, 2);
});
deviation = deviation / (sample.length -1);
deviation = Math.sqrt(deviation);
return deviation;
};
// di.annotate(Statistics, new di.Inject())
module.exports = Statistics;
},{"di":24}],12:[function(require,module,exports){
function Steps() {
this._steps = [];
};
Steps.prototype.all = function () {
return this._steps;
};
Steps.prototype.add = function (step) {
this._steps.push(step);
};
module.exports = Steps;
},{}],13:[function(require,module,exports){
function Utils() {}
Utils.prototype.parseSearch = function (search) {
var parsed = {};
var tuples = search.replace(/^\?/, '').split('&');
tuples.forEach(function(pair) {
var keyVal = pair.split('=');
parsed[keyVal[0]] = keyVal[1];
});
return parsed;
};
module.exports = Utils;
},{}],14:[function(require,module,exports){
var di = require('di');
var Utils = require('./Utils');
var Globals = require('./Globals');
function Variables(utils, globals) {
this.variables = [];
this._utils = utils;
this._globals = globals;
}
Variables.prototype._setPendingFromSearch = function() {
if (this._pending === undefined) {
this._pending = this._utils.
parseSearch(this._globals._window.location.search).variable;
}
};
Variables.prototype._autoSelectPending = function() {
if (this._pending !== null && this._pending !== undefined) {
return this.select(this._pending);
var reduced = this.variables.reduce(function(prev, curr) {
prev[curr.value] = curr;
return prev;
}, {});
this.selected = reduced[this._pending];
}
};
Variables.prototype.add = function (variable) {
this._setPendingFromSearch();
this.variables.push(variable);
this._autoSelectPending();
};
Variables.prototype.addMany = function (varArr) {
this._setPendingFromSearch();
this.variables.push.apply(this.variables, varArr);
this._autoSelectPending();
};
Variables.prototype.select = function (val) {
this.selected = this.variables.reduce(function(prev, curr) {
prev[curr.value] = curr;
return prev;
}, {})[val];
if (this.selected !== undefined) this._pending = null;
};
di.annotate(Variables, new di.Inject(Utils, Globals))
module.exports = Variables;
},{"./Globals":5,"./Utils":13,"di":24}],15:[function(require,module,exports){
var di = require('di');
var ClientScripts = require('./ClientScripts');
var Document = require('./Document');
var Globals = require('./Globals');
var Measure = require('./Measure');
var Report = require('./HtmlReport');
var AutoRunner = require('./AutoRunner');
var Statistics = require('./Statistics');
var Steps = require('./Steps');
var Variables = require('./Variables');
//Benchpress Facade
function AutoBenchPress (doc, globals, measure, report, runner, scripts, statistics, steps, variables) {
doc.setAutoRun(true);
// Left benchmarkSteps on global for backwards-compatibility
//Deprecated
window.benchmarkSteps = this.steps = steps.all();
this._scripts = scripts;
this.runner = runner;
//Deprecated
this.scripts = scripts.all();
this.doc = doc;
this.variables = variables;
//Legacy Support
this.Document = doc;
this.Measure = measure;
this.Runner = runner;
this.Report = report;
this.Statistics = statistics;
if (globals._window) globals._window.addEventListener('DOMContentLoaded', function(e) {
doc.onDOMContentLoaded.call(doc);
runner.bootstrap();
}.bind(this));
}
di.annotate(AutoBenchPress, new di.Inject(Document, Globals, Measure, Report, AutoRunner, ClientScripts, Statistics, Steps, Variables))
var injector = new di.Injector([]);
window.bp = injector.get(AutoBenchPress);
module.exports = AutoBenchPress;
},{"./AutoRunner":2,"./ClientScripts":3,"./Document":4,"./Globals":5,"./HtmlReport":6,"./Measure":8,"./Statistics":11,"./Steps":12,"./Variables":14,"di":24}],16:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node 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.
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
if (!isNumber(n) || n < 0 || isNaN(n))
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(isObject(this._events.error) && !this._events.error.length)) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
}
throw TypeError('Uncaught, unspecified "error" event.');
}
}
handler = this._events[type];
if (isUndefined(handler))
return false;
if (isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
handler.apply(this, args);
}
} else if (isObject(handler)) {
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);
else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
var m;
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!isFunction(listener))
throw TypeError('listener must be a function');
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}
listeners = this._events[type];
if (isFunction(listeners)) {
this.removeListener(type, listeners);
} else {
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.listenerCount = function(emitter, type) {
var ret;
if (!emitter._events || !emitter._events[type])
ret = 0;
else if (isFunction(emitter._events[type]))
ret = 1;
else
ret = emitter._events[type].length;
return ret;
};
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isUndefined(arg) {
return arg === void 0;
}
},{}],17:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],18:[function(require,module,exports){
"use strict";
var __moduleName = "annotations";
var isFunction = $traceurRuntime.assertObject(require('./util')).isFunction;
var SuperConstructor = function SuperConstructor() {};
($traceurRuntime.createClass)(SuperConstructor, {}, {});
var TransientScope = function TransientScope() {};
($traceurRuntime.createClass)(TransientScope, {}, {});
var Inject = function Inject() {
for (var tokens = [],
$__5 = 0; $__5 < arguments.length; $__5++)
tokens[$__5] = arguments[$__5];
this.tokens = tokens;
this.isPromise = false;
this.isLazy = false;
};
($traceurRuntime.createClass)(Inject, {}, {});
var InjectPromise = function InjectPromise() {
for (var tokens = [],
$__6 = 0; $__6 < arguments.length; $__6++)
tokens[$__6] = arguments[$__6];
this.tokens = tokens;
this.isPromise = true;
this.isLazy = false;
};
($traceurRuntime.createClass)(InjectPromise, {}, {}, Inject);
var InjectLazy = function InjectLazy() {
for (var tokens = [],
$__7 = 0; $__7 < arguments.length; $__7++)
tokens[$__7] = arguments[$__7];
this.tokens = tokens;
this.isPromise = false;
this.isLazy = true;
};
($traceurRuntime.createClass)(InjectLazy, {}, {}, Inject);
var Provide = function Provide(token) {
this.token = token;
this.isPromise = false;
};
($traceurRuntime.createClass)(Provide, {}, {});
var ProvidePromise = function ProvidePromise(token) {
this.token = token;
this.isPromise = true;
};
($traceurRuntime.createClass)(ProvidePromise, {}, {}, Provide);
function annotate(fn, annotation) {
fn.annotations = fn.annotations || [];
fn.annotations.push(annotation);
}
function hasAnnotation(fn, annotationClass) {
if (!fn.annotations || fn.annotations.length === 0) {
return false;
}
for (var $__1 = fn.annotations[Symbol.iterator](),
$__2; !($__2 = $__1.next()).done; ) {
var annotation = $__2.value;
{
if (annotation instanceof annotationClass) {
return true;
}
}
}
return false;
}
function readAnnotations(fn) {
var collectedAnnotations = {
provide: {
token: null,
isPromise: false
},
params: []
};
if (fn.annotations && fn.annotations.length) {
for (var $__1 = fn.annotations[Symbol.iterator](),
$__2; !($__2 = $__1.next()).done; ) {
var annotation = $__2.value;
{
if (annotation instanceof Inject) {
collectedAnnotations.params = annotation.tokens.map((function(token) {
return {
token: token,
isPromise: annotation.isPromise,
isLazy: annotation.isLazy
};
}));
}
if (annotation instanceof Provide) {
collectedAnnotations.provide.token = annotation.token;
collectedAnnotations.provide.isPromise = annotation.isPromise;
}
}
}
}
if (fn.parameters) {
fn.parameters.forEach((function(param, idx) {
for (var $__3 = param[Symbol.iterator](),
$__4; !($__4 = $__3.next()).done; ) {
var paramAnnotation = $__4.value;
{
if (isFunction(paramAnnotation) && !collectedAnnotations.params[idx]) {
collectedAnnotations.params[idx] = {
token: paramAnnotation,
isPromise: false,
isLazy: false
};
} else if (paramAnnotation instanceof Inject) {
collectedAnnotations.params[idx] = {
token: paramAnnotation.tokens[0],
isPromise: paramAnnotation.isPromise,
isLazy: paramAnnotation.isLazy
};
}
}
}
}));
}
return collectedAnnotations;
}
;
module.exports = {
get annotate() {
return annotate;
},
get hasAnnotation() {
return hasAnnotation;
},
get readAnnotations() {
return readAnnotations;
},
get SuperConstructor() {
return SuperConstructor;
},
get TransientScope() {
return TransientScope;
},
get Inject() {
return Inject;
},
get InjectPromise() {
return InjectPromise;
},
get InjectLazy() {
return InjectLazy;
},
get Provide() {
return Provide;
},
get ProvidePromise() {
return ProvidePromise;
},
__esModule: true
};
},{"./util":23}],19:[function(require,module,exports){
"use strict";
var __moduleName = "index";
var $__injector__ = require('./injector');
var $__annotations__ = require('./annotations');
module.exports = {
get Injector() {
return $__injector__.Injector;
},
get annotate() {
return $__annotations__.annotate;
},
get Inject() {
return $__annotations__.Inject;
},
get InjectPromise() {
return $__annotations__.InjectPromise;
},
get Provide() {
return $__annotations__.Provide;
},
get ProvidePromise() {
return $__annotations__.ProvidePromise;
},
get SuperConstructor() {
return $__annotations__.SuperConstructor;
},
get TransientScope() {
return $__annotations__.TransientScope;
},
__esModule: true
};
},{"./annotations":18,"./injector":20}],20:[function(require,module,exports){
"use strict";
var __moduleName = "injector";
var $__4 = $traceurRuntime.assertObject(require('./annotations')),
annotate = $__4.annotate,
readAnnotations = $__4.readAnnotations,
hasAnnotation = $__4.hasAnnotation,
ProvideAnnotation = $__4.Provide,
TransientScopeAnnotation = $__4.TransientScope;
var $__4 = $traceurRuntime.assertObject(require('./util')),
isFunction = $__4.isFunction,
toString = $__4.toString;
var getUniqueId = $traceurRuntime.assertObject(require('./profiler')).getUniqueId;
var createProviderFromFnOrClass = $traceurRuntime.assertObject(require('./providers')).createProviderFromFnOrClass;
function constructResolvingMessage(resolving) {
var token = arguments[1] !== (void 0) ? arguments[1] : null;
if (token) {
resolving.push(token);
}
if (resolving.length > 1) {
return (" (" + resolving.map(toString).join(' -> ') + ")");
}
return '';
}
var Injector = function Injector() {
var modules = arguments[0] !== (void 0) ? arguments[0] : [];
var parentInjector = arguments[1] !== (void 0) ? arguments[1] : null;
var providers = arguments[2] !== (void 0) ? arguments[2] : new Map();
this.cache = new Map();
this.providers = providers;
this.parent = parentInjector;
this.id = getUniqueId();
this._loadModules(modules);
};
var $Injector = Injector;
($traceurRuntime.createClass)(Injector, {
_collectProvidersWithAnnotation: function(annotationClass, collectedProviders) {
this.providers.forEach((function(provider, token) {
if (!collectedProviders.has(token) && hasAnnotation(provider.provider, annotationClass)) {
collectedProviders.set(token, provider);
}
}));
if (this.parent) {
this.parent._collectProvidersWithAnnotation(annotationClass, collectedProviders);
}
},
_loadModules: function(modules) {
var $__0 = this;
for (var $__2 = modules[Symbol.iterator](),
$__3; !($__3 = $__2.next()).done; ) {
var module = $__3.value;
{
if (isFunction(module)) {
this._loadFnOrClass(module);
continue;
}
Object.keys(module).forEach((function(key) {
if (isFunction(module[key])) {
$__0._loadFnOrClass(module[key], key);
}
}));
}
}
},
_loadFnOrClass: function(fnOrClass, key) {
var annotations = readAnnotations(fnOrClass);
var token = annotations.provide.token || key || fnOrClass;
var provider = createProviderFromFnOrClass(fnOrClass, annotations);
this.providers.set(token, provider);
},
_hasProviderFor: function(token) {
if (this.providers.has(token)) {
return true;
}
if (this.parent) {
return this.parent._hasProviderFor(token);
}
return false;
},
get: function(token) {
var resolving = arguments[1] !== (void 0) ? arguments[1] : [];
var wantPromise = arguments[2] !== (void 0) ? arguments[2] : false;
var wantLazy = arguments[3] !== (void 0) ? arguments[3] : false;
var $__0 = this;
var resolvingMsg = '';
var instance;
var injector = this;
if (token === $Injector) {
if (wantPromise) {
return Promise.resolve(this);
}
return this;
}
if (wantLazy) {
return function createLazyInstance() {
var lazyInjector = injector;
if (arguments.length) {
var locals = [];
var args = arguments;
for (var i = 0; i < args.length; i += 2) {
locals.push((function(ii) {
var fn = function createLocalInstance() {
return args[ii + 1];
};
annotate(fn, new ProvideAnnotation(args[ii]));
return fn;
})(i));
}
lazyInjector = injector.createChild(locals);
}
return lazyInjector.get(token, resolving, wantPromise, false);
};
}
if (this.cache.has(token)) {
instance = this.cache.get(token);
if (this.providers.get(token).isPromise) {
if (!wantPromise) {
resolvingMsg = constructResolvingMessage(resolving, token);
throw new Error(("Cannot instantiate " + toString(token) + " synchronously. It is provided as a promise!" + resolvingMsg));
}
} else {
if (wantPromise) {
return Promise.resolve(instance);
}
}
return instance;
}
var provider = this.providers.get(token);
if (!provider && isFunction(token) && !this._hasProviderFor(token)) {
provider = createProviderFromFnOrClass(token, readAnnotations(token));
this.providers.set(token, provider);
}
if (!provider) {
if (!this.parent) {
resolvingMsg = constructResolvingMessage(resolving, token);
console.log('bad token', token);
throw new Error(("No provider for " + token + "!" + resolvingMsg));
}
return this.parent.get(token, resolving, wantPromise, wantLazy);
}
if (resolving.indexOf(token) !== -1) {
resolvingMsg = constructResolvingMessage(resolving, token);
throw new Error(("Cannot instantiate cyclic dependency!" + resolvingMsg));
}
resolving.push(token);
var delayingInstantiation = wantPromise && provider.params.some((function(param) {
return !param.isPromise;
}));
var args = provider.params.map((function(param) {
if (delayingInstantiation) {
return $__0.get(param.token, resolving, true, param.isLazy);
}
return $__0.get(param.token, resolving, param.isPromise, param.isLazy);
}));
if (delayingInstantiation) {
var delayedResolving = resolving.slice();
resolving.pop();
return Promise.all(args).then(function(args) {
try {
instance = provider.create(args);
} catch (e) {
resolvingMsg = constructResolvingMessage(delayedResolving);
var originalMsg = 'ORIGINAL ERROR: ' + e.message;
e.message = ("Error during instantiation of " + toString(token) + "!" + resolvingMsg + "\n" + originalMsg);
throw e;
}
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) {
injector.cache.set(token, instance);
}
return instance;
});
}
try {
instance = provider.create(args);
} catch (e) {
resolvingMsg = constructResolvingMessage(resolving);
var originalMsg = 'ORIGINAL ERROR: ' + e.message;
e.message = ("Error during instantiation of " + toString(token) + "!" + resolvingMsg + "\n" + originalMsg);
throw e;
}
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) {
this.cache.set(token, instance);
}
if (!wantPromise && provider.isPromise) {
resolvingMsg = constructResolvingMessage(resolving);
throw new Error(("Cannot instantiate " + toString(token) + " synchronously. It is provided as a promise!" + resolvingMsg));
}
if (wantPromise && !provider.isPromise) {
instance = Promise.resolve(instance);
}
resolving.pop();
return instance;
},
getPromise: function(token) {
return this.get(token, [], true);
},
createChild: function() {
var modules = arguments[0] !== (void 0) ? arguments[0] : [];
var forceNewInstancesOf = arguments[1] !== (void 0) ? arguments[1] : [];
var forcedProviders = new Map();
for (var $__2 = forceNewInstancesOf[Symbol.iterator](),
$__3; !($__3 = $__2.next()).done; ) {
var annotation = $__3.value;
{
this._collectProvidersWithAnnotation(annotation, forcedProviders);
}
}
return new $Injector(modules, this, forcedProviders);
},
dump: function() {
var $__0 = this;
var serialized = {
id: this.id,
parent_id: this.parent ? this.parent.id : null,
providers: {}
};
Object.keys(this.providers).forEach((function(token) {
serialized.providers[token] = {
name: token,
dependencies: $__0.providers[token].params
};
}));
return serialized;
}
}, {});
;
module.exports = {
get Injector() {
return Injector;
},
__esModule: true
};
},{"./annotations":18,"./profiler":21,"./providers":22,"./util":23}],21:[function(require,module,exports){
"use strict";
var __moduleName = "profiler";
var globalCounter = 0;
function getUniqueId() {
return ++globalCounter;
}
;
module.exports = {
get getUniqueId() {
return getUniqueId;
},
__esModule: true
};
},{}],22:[function(require,module,exports){
"use strict";
var __moduleName = "providers";
var $__3 = $traceurRuntime.assertObject(require('./annotations')),
SuperConstructorAnnotation = $__3.SuperConstructor,
readAnnotations = $__3.readAnnotations;
var $__3 = $traceurRuntime.assertObject(require('./util')),
isClass = $__3.isClass,
isFunction = $__3.isFunction,
isObject = $__3.isObject,
toString = $__3.toString;
var EmptyFunction = Object.getPrototypeOf(Function);
var ClassProvider = function ClassProvider(clazz, params, isPromise) {
this.provider = clazz;
this.isPromise = isPromise;
this.params = [];
this.constructors = [];
this._flattenParams(clazz, params);
this.constructors.unshift([clazz, 0, this.params.length - 1]);
};
($traceurRuntime.createClass)(ClassProvider, {
_flattenParams: function(constructor, params) {
var SuperConstructor;
var constructorInfo;
for (var $__1 = params[Symbol.iterator](),
$__2; !($__2 = $__1.next()).done; ) {
var param = $__2.value;
{
if (param.token === SuperConstructorAnnotation) {
SuperConstructor = Object.getPrototypeOf(constructor);
if (SuperConstructor === EmptyFunction) {
throw new Error((toString(constructor) + " does not have a parent constructor. Only classes with a parent can ask for SuperConstructor!"));
}
constructorInfo = [SuperConstructor, this.params.length];
this.constructors.push(constructorInfo);
this._flattenParams(SuperConstructor, readAnnotations(SuperConstructor).params);
constructorInfo.push(this.params.length - 1);
} else {
this.params.push(param);
}
}
}
},
_createConstructor: function(currentConstructorIdx, context, allArguments) {
var constructorInfo = this.constructors[currentConstructorIdx];
var nextConstructorInfo = this.constructors[currentConstructorIdx + 1];
var argsForCurrentConstructor;
if (nextConstructorInfo) {
argsForCurrentConstructor = allArguments.slice(constructorInfo[1], nextConstructorInfo[1]).concat([this._createConstructor(currentConstructorIdx + 1, context, allArguments)]).concat(allArguments.slice(nextConstructorInfo[2] + 1, constructorInfo[2] + 1));
} else {
argsForCurrentConstructor = allArguments.slice(constructorInfo[1], constructorInfo[2] + 1);
}
return function InjectedAndBoundSuperConstructor() {
return constructorInfo[0].apply(context, argsForCurrentConstructor);
};
},
create: function(args) {
var context = Object.create(this.provider.prototype);
var constructor = this._createConstructor(0, context, args);
var returnedValue = constructor();
if (isFunction(returnedValue) || isObject(returnedValue)) {
return returnedValue;
}
return context;
}
}, {});
var FactoryProvider = function FactoryProvider(factoryFunction, params, isPromise) {
this.provider = factoryFunction;
this.params = params;
this.isPromise = isPromise;
for (var $__1 = params[Symbol.iterator](),
$__2; !($__2 = $__1.next()).done; ) {
var param = $__2.value;
{
if (param.token === SuperConstructorAnnotation) {
throw new Error((toString(factoryFunction) + " is not a class. Only classes with a parent can ask for SuperConstructor!"));
}
}
}
};
($traceurRuntime.createClass)(FactoryProvider, {create: function(args) {
return this.provider.apply(undefined, args);
}}, {});
function createProviderFromFnOrClass(fnOrClass, annotations) {
if (isClass(fnOrClass)) {
return new ClassProvider(fnOrClass, annotations.params, annotations.provide.isPromise);
}
return new FactoryProvider(fnOrClass, annotations.params, annotations.provide.isPromise);
}
module.exports = {
get createProviderFromFnOrClass() {
return createProviderFromFnOrClass;
},
__esModule: true
};
},{"./annotations":18,"./util":23}],23:[function(require,module,exports){
"use strict";
var __moduleName = "util";
function isUpperCase(char) {
return char.toUpperCase() === char;
}
function isClass(clsOrFunction) {
if (clsOrFunction.name) {
return isUpperCase(clsOrFunction.name.charAt(0));
}
return Object.keys(clsOrFunction.prototype).length > 0;
}
function isFunction(value) {
return typeof value === 'function';
}
function isObject(value) {
return typeof value === 'object';
}
function toString(token) {
if (typeof token === 'string') {
return token;
}
if (token.name) {
return token.name;
}
return token.toString();
}
;
module.exports = {
get isUpperCase() {
return isUpperCase;
},
get isClass() {
return isClass;
},
get isFunction() {
return isFunction;
},
get isObject() {
return isObject;
},
get toString() {
return toString;
},
__esModule: true
};
},{}],24:[function(require,module,exports){
// This is the file that gets included when you use "di" module in Node.js.
// Include Traceur runtime.
require('traceur/bin/traceur-runtime');
// Node.js has to be run with --harmony_collections to support ES6 Map.
// If not defined, i