pax_global_header00006660000000000000000000000064130665134320014515gustar00rootroot0000000000000052 comment=061282627fdb7867d560729ca34b710fe8c48464 benchmark.js-2.1.4/000077500000000000000000000000001306651343200140665ustar00rootroot00000000000000benchmark.js-2.1.4/.gitattributes000066400000000000000000000000141306651343200167540ustar00rootroot00000000000000* text=auto benchmark.js-2.1.4/.github/000077500000000000000000000000001306651343200154265ustar00rootroot00000000000000benchmark.js-2.1.4/.github/CONTRIBUTING.md000066400000000000000000000031071306651343200176600ustar00rootroot00000000000000# Contributing to Benchmark.js If you’d like to contribute a feature or bug fix, you can [fork](https://help.github.com/articles/fork-a-repo/) Benchmark.js, commit your changes, and [send a pull request](https://help.github.com/articles/using-pull-requests/). Please make sure to [search the issue tracker](https://github.com/bestiejs/benchmark.js/issues) first; your issue may have already been discussed or fixed in `master`. ## Tests Include updated unit tests in the `test` directory as part of your pull request. Before running the unit tests you’ll need to install, `npm i`, [development dependencies](https://docs.npmjs.com/files/package.json#devdependencies). Run unit tests from the command-line via `node test/test`, or open `test/index.html` in a web browser. The `test/run-test.sh` script attempts to run the tests in [Node.js](https://nodejs.org/) and [PhantomJS](http://phantomjs.org/) before running them in your default browser. ## Coding Guidelines In addition to the following guidelines, please follow the conventions already established in the code. - **Spacing**:
Use two spaces for indentation. No tabs. - **Naming**:
Keep variable and method names concise and descriptive. - **Quotes**:
Single-quoted strings are preferred to double-quoted strings; however, please use a double-quoted string if the value contains a single-quote character to avoid unnecessary escaping. - **Comments**:
Please use single-line comments to annotate significant additions, and [JSDoc-style](http://www.2ality.com/2011/08/jsdoc-intro.html) comments for new methods. benchmark.js-2.1.4/.gitignore000066400000000000000000000000651306651343200160570ustar00rootroot00000000000000.coveralls.yml .DS_Store *.log coverage node_modules benchmark.js-2.1.4/.travis.yml000066400000000000000000000030211306651343200161730ustar00rootroot00000000000000language: node_js sudo: false node_js: - 6 cache: directories: - ~/.npm - ~/.yarn-cache - travis_phantomjs env: global: - BIN=node ISTANBUL=false - secure: XOINlYZG3DYXq5agQXvkad2MfnOO/+z40fn37RKfNuxNI5veBK7tPRcCIQ998o+NyVTpyd3NZhqkowCxAL8bp4HJ81SesRKQSaXoSzgV7CnloxLxcduiiRJ6lnxFGgCbpqyLxZHWr0mQugcLhs5nhiZ5Dnw6dZxYX/oKKvOomZA= matrix: - - ISTANBUL=true - BIN=phantomjs matrix: include: - node_js: 4 env: git: depth: 10 branches: only: - master before_install: # Upgrade PhantomJS. - | export PHANTOMJS_VERSION=2.1.1 export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then rm -rf $PWD/travis_phantomjs mkdir -p $PWD/travis_phantomjs wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 tar -xvf phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs fi phantomjs -v # Use exact Node version. - nvm use $TRAVIS_NODE_VERSION # Setup package managers. - npm set loglevel error - npm set progress false - npm i -g yarn@0.16.1 - yarn -V install: # Install packages. - yarn script: - | if [ $ISTANBUL = true ]; then istanbul cover -x "**/vendor/**" --report lcovonly ./test/test.js && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage else cd ./test $BIN ./test.js fi benchmark.js-2.1.4/LICENSE000066400000000000000000000022751306651343200151010ustar00rootroot00000000000000Copyright 2010-2016 Mathias Bynens Based on JSLitmus.js, copyright Robert Kieffer Modified by John-David Dalton 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. benchmark.js-2.1.4/README.md000066400000000000000000000041721306651343200153510ustar00rootroot00000000000000# Benchmark.js v2.1.4 A [robust](https://mathiasbynens.be/notes/javascript-benchmarking "Bulletproof JavaScript benchmarks") benchmarking library that supports high-resolution timers & returns statistically significant results. As seen on [jsPerf](https://jsperf.com/). ## Documentation * [API Documentation](https://benchmarkjs.com/docs) ## Download * [Development source](https://raw.githubusercontent.com/bestiejs/benchmark.js/2.1.4/benchmark.js) ## Installation Benchmark.js’ only hard dependency is [lodash](https://lodash.com/). Include [platform.js](https://mths.be/platform) to populate [Benchmark.platform](https://benchmarkjs.com/docs#platform). In a browser: ```html ``` In an AMD loader: ```js require({ 'paths': { 'benchmark': 'path/to/benchmark', 'lodash': 'path/to/lodash', 'platform': 'path/to/platform' } }, ['benchmark'], function(Benchmark) {/*…*/}); ``` Using npm: ```shell $ npm i --save benchmark ``` In Node.js: ```js var Benchmark = require('benchmark'); ``` Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons: ```shell npm i --save microtime ``` Usage example: ```js var suite = new Benchmark.Suite; // add tests suite.add('RegExp#test', function() { /o/.test('Hello World!'); }) .add('String#indexOf', function() { 'Hello World!'.indexOf('o') > -1; }) // add listeners .on('cycle', function(event) { console.log(String(event.target)); }) .on('complete', function() { console.log('Fastest is ' + this.filter('fastest').map('name')); }) // run async .run({ 'async': true }); // logs: // => RegExp#test x 4,161,532 +-0.99% (59 cycles) // => String#indexOf x 6,139,623 +-1.00% (131 cycles) // => Fastest is String#indexOf ``` ## Support Tested in Chrome 54-55, Firefox 49-50, IE 11, Edge 14, Safari 9-10, Node.js 6-7, & PhantomJS 2.1.1. ## BestieJS Benchmark.js is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, & plenty of documentation. benchmark.js-2.1.4/benchmark.js000066400000000000000000002506311306651343200163650ustar00rootroot00000000000000/*! * Benchmark.js * Copyright 2010-2016 Mathias Bynens * Based on JSLitmus.js, copyright Robert Kieffer * Modified by John-David Dalton * Available under MIT license */ ;(function() { 'use strict'; /** Used as a safe reference for `undefined` in pre ES5 environments. */ var undefined; /** Used to determine if values are of the language type Object. */ var objectTypes = { 'function': true, 'object': true }; /** Used as a reference to the global object. */ var root = (objectTypes[typeof window] && window) || this; /** Detect free variable `define`. */ var freeDefine = typeof define == 'function' && typeof define.amd == 'object' && define.amd && define; /** Detect free variable `exports`. */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; /** Detect free variable `module`. */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } /** Detect free variable `require`. */ var freeRequire = typeof require == 'function' && require; /** Used to assign each benchmark an incremented id. */ var counter = 0; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; /** Used to detect primitive types. */ var rePrimitive = /^(?:boolean|number|string|undefined)$/; /** Used to make every compiled test unique. */ var uidCounter = 0; /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'Date', 'Function', 'Math', 'Object', 'RegExp', 'String', '_', 'clearTimeout', 'chrome', 'chromium', 'document', 'navigator', 'phantom', 'platform', 'process', 'runtime', 'setTimeout' ]; /** Used to avoid hz of Infinity. */ var divisors = { '1': 4096, '2': 512, '3': 64, '4': 8, '5': 0 }; /** * T-Distribution two-tailed critical values for 95% confidence. * For more info see http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm. */ var tTable = { '1': 12.706, '2': 4.303, '3': 3.182, '4': 2.776, '5': 2.571, '6': 2.447, '7': 2.365, '8': 2.306, '9': 2.262, '10': 2.228, '11': 2.201, '12': 2.179, '13': 2.16, '14': 2.145, '15': 2.131, '16': 2.12, '17': 2.11, '18': 2.101, '19': 2.093, '20': 2.086, '21': 2.08, '22': 2.074, '23': 2.069, '24': 2.064, '25': 2.06, '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042, 'infinity': 1.96 }; /** * Critical Mann-Whitney U-values for 95% confidence. * For more info see http://www.saburchill.com/IBbiology/stats/003.html. */ var uTable = { '5': [0, 1, 2], '6': [1, 2, 3, 5], '7': [1, 3, 5, 6, 8], '8': [2, 4, 6, 8, 10, 13], '9': [2, 4, 7, 10, 12, 15, 17], '10': [3, 5, 8, 11, 14, 17, 20, 23], '11': [3, 6, 9, 13, 16, 19, 23, 26, 30], '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37], '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45], '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55], '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64], '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75], '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87], '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99], '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113], '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127], '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142], '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158], '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175], '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192], '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211], '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230], '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250], '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272], '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294], '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317] }; /*--------------------------------------------------------------------------*/ /** * Create a new `Benchmark` function using the given `context` object. * * @static * @memberOf Benchmark * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `Benchmark` function. */ function runInContext(context) { // Exit early if unable to acquire lodash. var _ = context && context._ || require('lodash') || root._; if (!_) { Benchmark.runInContext = runInContext; return Benchmark; } // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. // See http://es5.github.io/#x11.1.5. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; /** Native constructor references. */ var Array = context.Array, Date = context.Date, Function = context.Function, Math = context.Math, Object = context.Object, RegExp = context.RegExp, String = context.String; /** Used for `Array` and `Object` method references. */ var arrayRef = [], objectProto = Object.prototype; /** Native method shortcuts. */ var abs = Math.abs, clearTimeout = context.clearTimeout, floor = Math.floor, log = Math.log, max = Math.max, min = Math.min, pow = Math.pow, push = arrayRef.push, setTimeout = context.setTimeout, shift = arrayRef.shift, slice = arrayRef.slice, sqrt = Math.sqrt, toString = objectProto.toString, unshift = arrayRef.unshift; /** Used to avoid inclusion in Browserified bundles. */ var req = require; /** Detect DOM document object. */ var doc = isHostType(context, 'document') && context.document; /** Used to access Wade Simmons' Node.js `microtime` module. */ var microtimeObject = req('microtime'); /** Used to access Node.js's high resolution timer. */ var processObject = isHostType(context, 'process') && context.process; /** Used to prevent a `removeChild` memory leak in IE < 9. */ var trash = doc && doc.createElement('div'); /** Used to integrity check compiled tests. */ var uid = 'uid' + _.now(); /** Used to avoid infinite recursion when methods call each other. */ var calledBy = {}; /** * An object used to flag environments/features. * * @static * @memberOf Benchmark * @type Object */ var support = {}; (function() { /** * Detect if running in a browser environment. * * @memberOf Benchmark.support * @type boolean */ support.browser = doc && isHostType(context, 'navigator') && !isHostType(context, 'phantom'); /** * Detect if the Timers API exists. * * @memberOf Benchmark.support * @type boolean */ support.timeout = isHostType(context, 'setTimeout') && isHostType(context, 'clearTimeout'); /** * Detect if function decompilation is support. * * @name decompilation * @memberOf Benchmark.support * @type boolean */ try { // Safari 2.x removes commas in object literals from `Function#toString` results. // See http://webk.it/11609 for more details. // Firefox 3.6 and Opera 9.25 strip grouping parentheses from `Function#toString` results. // See http://bugzil.la/559438 for more details. support.decompilation = Function( ('return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')') // Avoid issues with code added by Istanbul. .replace(/__cov__[^;]+;/g, '') )()(0).x === '1'; } catch(e) { support.decompilation = false; } }()); /** * Timer object used by `clock()` and `Deferred#resolve`. * * @private * @type Object */ var timer = { /** * The timer namespace object or constructor. * * @private * @memberOf timer * @type {Function|Object} */ 'ns': Date, /** * Starts the deferred timer. * * @private * @memberOf timer * @param {Object} deferred The deferred instance. */ 'start': null, // Lazy defined in `clock()`. /** * Stops the deferred timer. * * @private * @memberOf timer * @param {Object} deferred The deferred instance. */ 'stop': null // Lazy defined in `clock()`. }; /*------------------------------------------------------------------------*/ /** * The Benchmark constructor. * * Note: The Benchmark constructor exposes a handful of lodash methods to * make working with arrays, collections, and objects easier. The lodash * methods are: * [`each/forEach`](https://lodash.com/docs#forEach), [`forOwn`](https://lodash.com/docs#forOwn), * [`has`](https://lodash.com/docs#has), [`indexOf`](https://lodash.com/docs#indexOf), * [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce) * * @constructor * @param {string} name A name to identify the benchmark. * @param {Function|string} fn The test to benchmark. * @param {Object} [options={}] Options object. * @example * * // basic usage (the `new` operator is optional) * var bench = new Benchmark(fn); * * // or using a name first * var bench = new Benchmark('foo', fn); * * // or with options * var bench = new Benchmark('foo', fn, { * * // displayed by `Benchmark#toString` if `name` is not available * 'id': 'xyz', * * // called when the benchmark starts running * 'onStart': onStart, * * // called after each run cycle * 'onCycle': onCycle, * * // called when aborted * 'onAbort': onAbort, * * // called when a test errors * 'onError': onError, * * // called when reset * 'onReset': onReset, * * // called when the benchmark completes running * 'onComplete': onComplete, * * // compiled/called before the test loop * 'setup': setup, * * // compiled/called after the test loop * 'teardown': teardown * }); * * // or name and options * var bench = new Benchmark('foo', { * * // a flag to indicate the benchmark is deferred * 'defer': true, * * // benchmark test function * 'fn': function(deferred) { * // call `Deferred#resolve` when the deferred test is finished * deferred.resolve(); * } * }); * * // or options only * var bench = new Benchmark({ * * // benchmark name * 'name': 'foo', * * // benchmark test as a string * 'fn': '[1,2,3,4].sort()' * }); * * // a test's `this` binding is set to the benchmark instance * var bench = new Benchmark('foo', function() { * 'My name is '.concat(this.name); // "My name is foo" * }); */ function Benchmark(name, fn, options) { var bench = this; // Allow instance creation without the `new` operator. if (!(bench instanceof Benchmark)) { return new Benchmark(name, fn, options); } // Juggle arguments. if (_.isPlainObject(name)) { // 1 argument (options). options = name; } else if (_.isFunction(name)) { // 2 arguments (fn, options). options = fn; fn = name; } else if (_.isPlainObject(fn)) { // 2 arguments (name, options). options = fn; fn = null; bench.name = name; } else { // 3 arguments (name, fn [, options]). bench.name = name; } setOptions(bench, options); bench.id || (bench.id = ++counter); bench.fn == null && (bench.fn = fn); bench.stats = cloneDeep(bench.stats); bench.times = cloneDeep(bench.times); } /** * The Deferred constructor. * * @constructor * @memberOf Benchmark * @param {Object} clone The cloned benchmark instance. */ function Deferred(clone) { var deferred = this; if (!(deferred instanceof Deferred)) { return new Deferred(clone); } deferred.benchmark = clone; clock(deferred); } /** * The Event constructor. * * @constructor * @memberOf Benchmark * @param {Object|string} type The event type. */ function Event(type) { var event = this; if (type instanceof Event) { return type; } return (event instanceof Event) ? _.assign(event, { 'timeStamp': _.now() }, typeof type == 'string' ? { 'type': type } : type) : new Event(type); } /** * The Suite constructor. * * Note: Each Suite instance has a handful of wrapped lodash methods to * make working with Suites easier. The wrapped lodash methods are: * [`each/forEach`](https://lodash.com/docs#forEach), [`indexOf`](https://lodash.com/docs#indexOf), * [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce) * * @constructor * @memberOf Benchmark * @param {string} name A name to identify the suite. * @param {Object} [options={}] Options object. * @example * * // basic usage (the `new` operator is optional) * var suite = new Benchmark.Suite; * * // or using a name first * var suite = new Benchmark.Suite('foo'); * * // or with options * var suite = new Benchmark.Suite('foo', { * * // called when the suite starts running * 'onStart': onStart, * * // called between running benchmarks * 'onCycle': onCycle, * * // called when aborted * 'onAbort': onAbort, * * // called when a test errors * 'onError': onError, * * // called when reset * 'onReset': onReset, * * // called when the suite completes running * 'onComplete': onComplete * }); */ function Suite(name, options) { var suite = this; // Allow instance creation without the `new` operator. if (!(suite instanceof Suite)) { return new Suite(name, options); } // Juggle arguments. if (_.isPlainObject(name)) { // 1 argument (options). options = name; } else { // 2 arguments (name [, options]). suite.name = name; } setOptions(suite, options); } /*------------------------------------------------------------------------*/ /** * A specialized version of `_.cloneDeep` which only clones arrays and plain * objects assigning all other values by reference. * * @private * @param {*} value The value to clone. * @returns {*} The cloned value. */ var cloneDeep = _.partial(_.cloneDeepWith, _, function(value) { // Only clone primitives, arrays, and plain objects. if (!_.isArray(value) && !_.isPlainObject(value)) { return value; } }); /** * Creates a function from the given arguments string and body. * * @private * @param {string} args The comma separated function arguments. * @param {string} body The function body. * @returns {Function} The new function. */ function createFunction() { // Lazy define. createFunction = function(args, body) { var result, anchor = freeDefine ? freeDefine.amd : Benchmark, prop = uid + 'createFunction'; runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}'); result = anchor[prop]; delete anchor[prop]; return result; }; // Fix JaegerMonkey bug. // For more information see http://bugzil.la/639720. createFunction = support.browser && (createFunction('', 'return"' + uid + '"') || _.noop)() == uid ? createFunction : Function; return createFunction.apply(null, arguments); } /** * Delay the execution of a function based on the benchmark's `delay` property. * * @private * @param {Object} bench The benchmark instance. * @param {Object} fn The function to execute. */ function delay(bench, fn) { bench._timerId = _.delay(fn, bench.delay * 1e3); } /** * Destroys the given element. * * @private * @param {Element} element The element to destroy. */ function destroyElement(element) { trash.appendChild(element); trash.innerHTML = ''; } /** * Gets the name of the first argument from a function's source. * * @private * @param {Function} fn The function. * @returns {string} The argument name. */ function getFirstArgument(fn) { return (!_.has(fn, 'toString') && (/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || ''; } /** * Computes the arithmetic mean of a sample. * * @private * @param {Array} sample The sample. * @returns {number} The mean. */ function getMean(sample) { return (_.reduce(sample, function(sum, x) { return sum + x; }) / sample.length) || 0; } /** * Gets the source code of a function. * * @private * @param {Function} fn The function. * @returns {string} The function's source code. */ function getSource(fn) { var result = ''; if (isStringable(fn)) { result = String(fn); } else if (support.decompilation) { // Escape the `{` for Firefox 1. result = _.result(/^[^{]+\{([\s\S]*)\}\s*$/.exec(fn), 1); } // Trim string. result = (result || '').replace(/^\s+|\s+$/g, ''); // Detect strings containing only the "use strict" directive. return /^(?:\/\*+[\w\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result) ? '' : result; } /** * Checks if an object is of the specified class. * * @private * @param {*} value The value to check. * @param {string} name The name of the class. * @returns {boolean} Returns `true` if the value is of the specified class, else `false`. */ function isClassOf(value, name) { return value != null && toString.call(value) == '[object ' + name + ']'; } /** * Host objects can return type values that are different from their actual * data type. The objects we are concerned with usually return non-primitive * types of "object", "function", or "unknown". * * @private * @param {*} object The owner of the property. * @param {string} property The property to check. * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. */ function isHostType(object, property) { if (object == null) { return false; } var type = typeof object[property]; return !rePrimitive.test(type) && (type != 'object' || !!object[property]); } /** * Checks if a value can be safely coerced to a string. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if the value can be coerced, else `false`. */ function isStringable(value) { return _.isString(value) || (_.has(value, 'toString') && _.isFunction(value.toString)); } /** * A wrapper around `require` to suppress `module missing` errors. * * @private * @param {string} id The module id. * @returns {*} The exported module or `null`. */ function require(id) { try { var result = freeExports && freeRequire(id); } catch(e) {} return result || null; } /** * Runs a snippet of JavaScript via script injection. * * @private * @param {string} code The code to run. */ function runScript(code) { var anchor = freeDefine ? define.amd : Benchmark, script = doc.createElement('script'), sibling = doc.getElementsByTagName('script')[0], parent = sibling.parentNode, prop = uid + 'runScript', prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();'; // Firefox 2.0.0.2 cannot use script injection as intended because it executes // asynchronously, but that's OK because script injection is only used to avoid // the previously commented JaegerMonkey bug. try { // Remove the inserted script *before* running the code to avoid differences // in the expected script element count/order of the document. script.appendChild(doc.createTextNode(prefix + code)); anchor[prop] = function() { destroyElement(script); }; } catch(e) { parent = parent.cloneNode(false); sibling = null; script.text = code; } parent.insertBefore(script, sibling); delete anchor[prop]; } /** * A helper function for setting options/event handlers. * * @private * @param {Object} object The benchmark or suite instance. * @param {Object} [options={}] Options object. */ function setOptions(object, options) { options = object.options = _.assign({}, cloneDeep(object.constructor.options), cloneDeep(options)); _.forOwn(options, function(value, key) { if (value != null) { // Add event listeners. if (/^on[A-Z]/.test(key)) { _.each(key.split(' '), function(key) { object.on(key.slice(2).toLowerCase(), value); }); } else if (!_.has(object, key)) { object[key] = cloneDeep(value); } } }); } /*------------------------------------------------------------------------*/ /** * Handles cycling/completing the deferred benchmark. * * @memberOf Benchmark.Deferred */ function resolve() { var deferred = this, clone = deferred.benchmark, bench = clone._original; if (bench.aborted) { // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete. deferred.teardown(); clone.running = false; cycle(deferred); } else if (++deferred.cycles < clone.count) { clone.compiled.call(deferred, context, timer); } else { timer.stop(deferred); deferred.teardown(); delay(clone, function() { cycle(deferred); }); } } /*------------------------------------------------------------------------*/ /** * A generic `Array#filter` like method. * * @static * @memberOf Benchmark * @param {Array} array The array to iterate over. * @param {Function|string} callback The function/alias called per iteration. * @returns {Array} A new array of values that passed callback filter. * @example * * // get odd numbers * Benchmark.filter([1, 2, 3, 4, 5], function(n) { * return n % 2; * }); // -> [1, 3, 5]; * * // get fastest benchmarks * Benchmark.filter(benches, 'fastest'); * * // get slowest benchmarks * Benchmark.filter(benches, 'slowest'); * * // get benchmarks that completed without erroring * Benchmark.filter(benches, 'successful'); */ function filter(array, callback) { if (callback === 'successful') { // Callback to exclude those that are errored, unrun, or have hz of Infinity. callback = function(bench) { return bench.cycles && _.isFinite(bench.hz) && !bench.error; }; } else if (callback === 'fastest' || callback === 'slowest') { // Get successful, sort by period + margin of error, and filter fastest/slowest. var result = filter(array, 'successful').sort(function(a, b) { a = a.stats; b = b.stats; return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback === 'fastest' ? 1 : -1); }); return _.filter(result, function(bench) { return result[0].compare(bench) == 0; }); } return _.filter(array, callback); } /** * Converts a number to a more readable comma-separated string representation. * * @static * @memberOf Benchmark * @param {number} number The number to convert. * @returns {string} The more readable string representation. */ function formatNumber(number) { number = String(number).split('.'); return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') + (number[1] ? '.' + number[1] : ''); } /** * Invokes a method on all items in an array. * * @static * @memberOf Benchmark * @param {Array} benches Array of benchmarks to iterate over. * @param {Object|string} name The name of the method to invoke OR options object. * @param {...*} [args] Arguments to invoke the method with. * @returns {Array} A new array of values returned from each method invoked. * @example * * // invoke `reset` on all benchmarks * Benchmark.invoke(benches, 'reset'); * * // invoke `emit` with arguments * Benchmark.invoke(benches, 'emit', 'complete', listener); * * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks * Benchmark.invoke(benches, { * * // invoke the `run` method * 'name': 'run', * * // pass a single argument * 'args': true, * * // treat as queue, removing benchmarks from front of `benches` until empty * 'queued': true, * * // called before any benchmarks have been invoked. * 'onStart': onStart, * * // called between invoking benchmarks * 'onCycle': onCycle, * * // called after all benchmarks have been invoked. * 'onComplete': onComplete * }); */ function invoke(benches, name) { var args, bench, queued, index = -1, eventProps = { 'currentTarget': benches }, options = { 'onStart': _.noop, 'onCycle': _.noop, 'onComplete': _.noop }, result = _.toArray(benches); /** * Invokes the method of the current object and if synchronous, fetches the next. */ function execute() { var listeners, async = isAsync(bench); if (async) { // Use `getNext` as the first listener. bench.on('complete', getNext); listeners = bench.events.complete; listeners.splice(0, 0, listeners.pop()); } // Execute method. result[index] = _.isFunction(bench && bench[name]) ? bench[name].apply(bench, args) : undefined; // If synchronous return `true` until finished. return !async && getNext(); } /** * Fetches the next bench or executes `onComplete` callback. */ function getNext(event) { var cycleEvent, last = bench, async = isAsync(last); if (async) { last.off('complete', getNext); last.emit('complete'); } // Emit "cycle" event. eventProps.type = 'cycle'; eventProps.target = last; cycleEvent = Event(eventProps); options.onCycle.call(benches, cycleEvent); // Choose next benchmark if not exiting early. if (!cycleEvent.aborted && raiseIndex() !== false) { bench = queued ? benches[0] : result[index]; if (isAsync(bench)) { delay(bench, execute); } else if (async) { // Resume execution if previously asynchronous but now synchronous. while (execute()) {} } else { // Continue synchronous execution. return true; } } else { // Emit "complete" event. eventProps.type = 'complete'; options.onComplete.call(benches, Event(eventProps)); } // When used as a listener `event.aborted = true` will cancel the rest of // the "complete" listeners because they were already called above and when // used as part of `getNext` the `return false` will exit the execution while-loop. if (event) { event.aborted = true; } else { return false; } } /** * Checks if invoking `Benchmark#run` with asynchronous cycles. */ function isAsync(object) { // Avoid using `instanceof` here because of IE memory leak issues with host objects. var async = args[0] && args[0].async; return name == 'run' && (object instanceof Benchmark) && ((async == null ? object.options.async : async) && support.timeout || object.defer); } /** * Raises `index` to the next defined index or returns `false`. */ function raiseIndex() { index++; // If queued remove the previous bench. if (queued && index > 0) { shift.call(benches); } // If we reached the last index then return `false`. return (queued ? benches.length : index < result.length) ? index : (index = false); } // Juggle arguments. if (_.isString(name)) { // 2 arguments (array, name). args = slice.call(arguments, 2); } else { // 2 arguments (array, options). options = _.assign(options, name); name = options.name; args = _.isArray(args = 'args' in options ? options.args : []) ? args : [args]; queued = options.queued; } // Start iterating over the array. if (raiseIndex() !== false) { // Emit "start" event. bench = result[index]; eventProps.type = 'start'; eventProps.target = bench; options.onStart.call(benches, Event(eventProps)); // End early if the suite was aborted in an "onStart" listener. if (name == 'run' && (benches instanceof Suite) && benches.aborted) { // Emit "cycle" event. eventProps.type = 'cycle'; options.onCycle.call(benches, Event(eventProps)); // Emit "complete" event. eventProps.type = 'complete'; options.onComplete.call(benches, Event(eventProps)); } // Start method execution. else { if (isAsync(bench)) { delay(bench, execute); } else { while (execute()) {} } } } return result; } /** * Creates a string of joined array values or object key-value pairs. * * @static * @memberOf Benchmark * @param {Array|Object} object The object to operate on. * @param {string} [separator1=','] The separator used between key-value pairs. * @param {string} [separator2=': '] The separator used between keys and values. * @returns {string} The joined result. */ function join(object, separator1, separator2) { var result = [], length = (object = Object(object)).length, arrayLike = length === length >>> 0; separator2 || (separator2 = ': '); _.each(object, function(value, key) { result.push(arrayLike ? value : key + separator2 + value); }); return result.join(separator1 || ','); } /*------------------------------------------------------------------------*/ /** * Aborts all benchmarks in the suite. * * @name abort * @memberOf Benchmark.Suite * @returns {Object} The suite instance. */ function abortSuite() { var event, suite = this, resetting = calledBy.resetSuite; if (suite.running) { event = Event('abort'); suite.emit(event); if (!event.cancelled || resetting) { // Avoid infinite recursion. calledBy.abortSuite = true; suite.reset(); delete calledBy.abortSuite; if (!resetting) { suite.aborted = true; invoke(suite, 'abort'); } } } return suite; } /** * Adds a test to the benchmark suite. * * @memberOf Benchmark.Suite * @param {string} name A name to identify the benchmark. * @param {Function|string} fn The test to benchmark. * @param {Object} [options={}] Options object. * @returns {Object} The suite instance. * @example * * // basic usage * suite.add(fn); * * // or using a name first * suite.add('foo', fn); * * // or with options * suite.add('foo', fn, { * 'onCycle': onCycle, * 'onComplete': onComplete * }); * * // or name and options * suite.add('foo', { * 'fn': fn, * 'onCycle': onCycle, * 'onComplete': onComplete * }); * * // or options only * suite.add({ * 'name': 'foo', * 'fn': fn, * 'onCycle': onCycle, * 'onComplete': onComplete * }); */ function add(name, fn, options) { var suite = this, bench = new Benchmark(name, fn, options), event = Event({ 'type': 'add', 'target': bench }); if (suite.emit(event), !event.cancelled) { suite.push(bench); } return suite; } /** * Creates a new suite with cloned benchmarks. * * @name clone * @memberOf Benchmark.Suite * @param {Object} options Options object to overwrite cloned options. * @returns {Object} The new suite instance. */ function cloneSuite(options) { var suite = this, result = new suite.constructor(_.assign({}, suite.options, options)); // Copy own properties. _.forOwn(suite, function(value, key) { if (!_.has(result, key)) { result[key] = _.isFunction(_.get(value, 'clone')) ? value.clone() : cloneDeep(value); } }); return result; } /** * An `Array#filter` like method. * * @name filter * @memberOf Benchmark.Suite * @param {Function|string} callback The function/alias called per iteration. * @returns {Object} A new suite of benchmarks that passed callback filter. */ function filterSuite(callback) { var suite = this, result = new suite.constructor(suite.options); result.push.apply(result, filter(suite, callback)); return result; } /** * Resets all benchmarks in the suite. * * @name reset * @memberOf Benchmark.Suite * @returns {Object} The suite instance. */ function resetSuite() { var event, suite = this, aborting = calledBy.abortSuite; if (suite.running && !aborting) { // No worries, `resetSuite()` is called within `abortSuite()`. calledBy.resetSuite = true; suite.abort(); delete calledBy.resetSuite; } // Reset if the state has changed. else if ((suite.aborted || suite.running) && (suite.emit(event = Event('reset')), !event.cancelled)) { suite.aborted = suite.running = false; if (!aborting) { invoke(suite, 'reset'); } } return suite; } /** * Runs the suite. * * @name run * @memberOf Benchmark.Suite * @param {Object} [options={}] Options object. * @returns {Object} The suite instance. * @example * * // basic usage * suite.run(); * * // or with options * suite.run({ 'async': true, 'queued': true }); */ function runSuite(options) { var suite = this; suite.reset(); suite.running = true; options || (options = {}); invoke(suite, { 'name': 'run', 'args': options, 'queued': options.queued, 'onStart': function(event) { suite.emit(event); }, 'onCycle': function(event) { var bench = event.target; if (bench.error) { suite.emit({ 'type': 'error', 'target': bench }); } suite.emit(event); event.aborted = suite.aborted; }, 'onComplete': function(event) { suite.running = false; suite.emit(event); } }); return suite; } /*------------------------------------------------------------------------*/ /** * Executes all registered listeners of the specified event type. * * @memberOf Benchmark, Benchmark.Suite * @param {Object|string} type The event type or object. * @param {...*} [args] Arguments to invoke the listener with. * @returns {*} Returns the return value of the last listener executed. */ function emit(type) { var listeners, object = this, event = Event(type), events = object.events, args = (arguments[0] = event, arguments); event.currentTarget || (event.currentTarget = object); event.target || (event.target = object); delete event.result; if (events && (listeners = _.has(events, event.type) && events[event.type])) { _.each(listeners.slice(), function(listener) { if ((event.result = listener.apply(object, args)) === false) { event.cancelled = true; } return !event.aborted; }); } return event.result; } /** * Returns an array of event listeners for a given type that can be manipulated * to add or remove listeners. * * @memberOf Benchmark, Benchmark.Suite * @param {string} type The event type. * @returns {Array} The listeners array. */ function listeners(type) { var object = this, events = object.events || (object.events = {}); return _.has(events, type) ? events[type] : (events[type] = []); } /** * Unregisters a listener for the specified event type(s), * or unregisters all listeners for the specified event type(s), * or unregisters all listeners for all event types. * * @memberOf Benchmark, Benchmark.Suite * @param {string} [type] The event type. * @param {Function} [listener] The function to unregister. * @returns {Object} The current instance. * @example * * // unregister a listener for an event type * bench.off('cycle', listener); * * // unregister a listener for multiple event types * bench.off('start cycle', listener); * * // unregister all listeners for an event type * bench.off('cycle'); * * // unregister all listeners for multiple event types * bench.off('start cycle complete'); * * // unregister all listeners for all event types * bench.off(); */ function off(type, listener) { var object = this, events = object.events; if (!events) { return object; } _.each(type ? type.split(' ') : events, function(listeners, type) { var index; if (typeof listeners == 'string') { type = listeners; listeners = _.has(events, type) && events[type]; } if (listeners) { if (listener) { index = _.indexOf(listeners, listener); if (index > -1) { listeners.splice(index, 1); } } else { listeners.length = 0; } } }); return object; } /** * Registers a listener for the specified event type(s). * * @memberOf Benchmark, Benchmark.Suite * @param {string} type The event type. * @param {Function} listener The function to register. * @returns {Object} The current instance. * @example * * // register a listener for an event type * bench.on('cycle', listener); * * // register a listener for multiple event types * bench.on('start cycle', listener); */ function on(type, listener) { var object = this, events = object.events || (object.events = {}); _.each(type.split(' '), function(type) { (_.has(events, type) ? events[type] : (events[type] = []) ).push(listener); }); return object; } /*------------------------------------------------------------------------*/ /** * Aborts the benchmark without recording times. * * @memberOf Benchmark * @returns {Object} The benchmark instance. */ function abort() { var event, bench = this, resetting = calledBy.reset; if (bench.running) { event = Event('abort'); bench.emit(event); if (!event.cancelled || resetting) { // Avoid infinite recursion. calledBy.abort = true; bench.reset(); delete calledBy.abort; if (support.timeout) { clearTimeout(bench._timerId); delete bench._timerId; } if (!resetting) { bench.aborted = true; bench.running = false; } } } return bench; } /** * Creates a new benchmark using the same test and options. * * @memberOf Benchmark * @param {Object} options Options object to overwrite cloned options. * @returns {Object} The new benchmark instance. * @example * * var bizarro = bench.clone({ * 'name': 'doppelganger' * }); */ function clone(options) { var bench = this, result = new bench.constructor(_.assign({}, bench, options)); // Correct the `options` object. result.options = _.assign({}, cloneDeep(bench.options), cloneDeep(options)); // Copy own custom properties. _.forOwn(bench, function(value, key) { if (!_.has(result, key)) { result[key] = cloneDeep(value); } }); return result; } /** * Determines if a benchmark is faster than another. * * @memberOf Benchmark * @param {Object} other The benchmark to compare. * @returns {number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate. */ function compare(other) { var bench = this; // Exit early if comparing the same benchmark. if (bench == other) { return 0; } var critical, zStat, sample1 = bench.stats.sample, sample2 = other.stats.sample, size1 = sample1.length, size2 = sample2.length, maxSize = max(size1, size2), minSize = min(size1, size2), u1 = getU(sample1, sample2), u2 = getU(sample2, sample1), u = min(u1, u2); function getScore(xA, sampleB) { return _.reduce(sampleB, function(total, xB) { return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5); }, 0); } function getU(sampleA, sampleB) { return _.reduce(sampleA, function(total, xA) { return total + getScore(xA, sampleB); }, 0); } function getZ(u) { return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12); } // Reject the null hypothesis the two samples come from the // same population (i.e. have the same median) if... if (size1 + size2 > 30) { // ...the z-stat is greater than 1.96 or less than -1.96 // http://www.statisticslectures.com/topics/mannwhitneyu/ zStat = getZ(u); return abs(zStat) > 1.96 ? (u == u1 ? 1 : -1) : 0; } // ...the U value is less than or equal the critical U value. critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3]; return u <= critical ? (u == u1 ? 1 : -1) : 0; } /** * Reset properties and abort if running. * * @memberOf Benchmark * @returns {Object} The benchmark instance. */ function reset() { var bench = this; if (bench.running && !calledBy.abort) { // No worries, `reset()` is called within `abort()`. calledBy.reset = true; bench.abort(); delete calledBy.reset; return bench; } var event, index = 0, changes = [], queue = []; // A non-recursive solution to check if properties have changed. // For more information see http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4. var data = { 'destination': bench, 'source': _.assign({}, cloneDeep(bench.constructor.prototype), cloneDeep(bench.options)) }; do { _.forOwn(data.source, function(value, key) { var changed, destination = data.destination, currValue = destination[key]; // Skip pseudo private properties and event listeners. if (/^_|^events$|^on[A-Z]/.test(key)) { return; } if (_.isObjectLike(value)) { if (_.isArray(value)) { // Check if an array value has changed to a non-array value. if (!_.isArray(currValue)) { changed = true; currValue = []; } // Check if an array has changed its length. if (currValue.length != value.length) { changed = true; currValue = currValue.slice(0, value.length); currValue.length = value.length; } } // Check if an object has changed to a non-object value. else if (!_.isObjectLike(currValue)) { changed = true; currValue = {}; } // Register a changed object. if (changed) { changes.push({ 'destination': destination, 'key': key, 'value': currValue }); } queue.push({ 'destination': currValue, 'source': value }); } // Register a changed primitive. else if (!_.eq(currValue, value) && value !== undefined) { changes.push({ 'destination': destination, 'key': key, 'value': value }); } }); } while ((data = queue[index++])); // If changed emit the `reset` event and if it isn't cancelled reset the benchmark. if (changes.length && (bench.emit(event = Event('reset')), !event.cancelled)) { _.each(changes, function(data) { data.destination[data.key] = data.value; }); } return bench; } /** * Displays relevant benchmark information when coerced to a string. * * @name toString * @memberOf Benchmark * @returns {string} A string representation of the benchmark instance. */ function toStringBench() { var bench = this, error = bench.error, hz = bench.hz, id = bench.id, stats = bench.stats, size = stats.sample.length, pm = '\xb1', result = bench.name || (_.isNaN(id) ? id : ''); if (error) { var errorStr; if (!_.isObject(error)) { errorStr = String(error); } else if (!_.isError(Error)) { errorStr = join(error); } else { // Error#name and Error#message properties are non-enumerable. errorStr = join(_.assign({ 'name': error.name, 'message': error.message }, error)); } result += ': ' + errorStr; } else { result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm + stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)'; } return result; } /*------------------------------------------------------------------------*/ /** * Clocks the time taken to execute a test per cycle (secs). * * @private * @param {Object} bench The benchmark instance. * @returns {number} The time taken. */ function clock() { var options = Benchmark.options, templateData = {}, timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }]; // Lazy define for hi-res timers. clock = function(clone) { var deferred; if (clone instanceof Deferred) { deferred = clone; clone = deferred.benchmark; } var bench = clone._original, stringable = isStringable(bench.fn), count = bench.count = clone.count, decompilable = stringable || (support.decompilation && (clone.setup !== _.noop || clone.teardown !== _.noop)), id = bench.id, name = bench.name || (typeof id == 'number' ? '' : id), result = 0; // Init `minTime` if needed. clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime); // Compile in setup/teardown functions and the test loop. // Create a new compiled test, instead of using the cached `bench.compiled`, // to avoid potential engine optimizations enabled over the life of the test. var funcBody = deferred ? 'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;' + // When `deferred.cycles` is `0` then... 'if(!d#.cycles){' + // set `deferred.fn`, 'd#.fn=function(){var ${fnArg}=d#;if(typeof f#=="function"){try{${fn}\n}catch(e#){f#(d#)}}else{${fn}\n}};' + // set `deferred.teardown`, 'd#.teardown=function(){d#.cycles=0;if(typeof td#=="function"){try{${teardown}\n}catch(e#){td#()}}else{${teardown}\n}};' + // execute the benchmark's `setup`, 'if(typeof su#=="function"){try{${setup}\n}catch(e#){su#()}}else{${setup}\n};' + // start timer, 't#.start(d#);' + // and then execute `deferred.fn` and return a dummy object. '}d#.fn();return{uid:"${uid}"}' : 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\n${begin};' + 'while(i#--){${fn}\n}${end};${teardown}\nreturn{elapsed:r#,uid:"${uid}"}'; var compiled = bench.compiled = clone.compiled = createCompiled(bench, decompilable, deferred, funcBody), isEmpty = !(templateData.fn || stringable); try { if (isEmpty) { // Firefox may remove dead code from `Function#toString` results. // For more information see http://bugzil.la/536085. throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.'); } else if (!deferred) { // Pretest to determine if compiled code exits early, usually by a // rogue `return` statement, by checking for a return object with the uid. bench.count = 1; compiled = decompilable && (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled; bench.count = count; } } catch(e) { compiled = null; clone.error = e || new Error(String(e)); bench.count = count; } // Fallback when a test exits early or errors during pretest. if (!compiled && !deferred && !isEmpty) { funcBody = ( stringable || (decompilable && !clone.error) ? 'function f#(){${fn}\n}var r#,s#,m#=this,i#=m#.count' : 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count' ) + ',n#=t#.ns;${setup}\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};' + 'delete m#.f#;${teardown}\nreturn{elapsed:r#}'; compiled = createCompiled(bench, decompilable, deferred, funcBody); try { // Pretest one more time to check for errors. bench.count = 1; compiled.call(bench, context, timer); bench.count = count; delete clone.error; } catch(e) { bench.count = count; if (!clone.error) { clone.error = e || new Error(String(e)); } } } // If no errors run the full test loop. if (!clone.error) { compiled = bench.compiled = clone.compiled = createCompiled(bench, decompilable, deferred, funcBody); result = compiled.call(deferred || bench, context, timer).elapsed; } return result; }; /*----------------------------------------------------------------------*/ /** * Creates a compiled function from the given function `body`. */ function createCompiled(bench, decompilable, deferred, body) { var fn = bench.fn, fnArg = deferred ? getFirstArgument(fn) || 'deferred' : ''; templateData.uid = uid + uidCounter++; _.assign(templateData, { 'setup': decompilable ? getSource(bench.setup) : interpolate('m#.setup()'), 'fn': decompilable ? getSource(fn) : interpolate('m#.fn(' + fnArg + ')'), 'fnArg': fnArg, 'teardown': decompilable ? getSource(bench.teardown) : interpolate('m#.teardown()') }); // Use API of chosen timer. if (timer.unit == 'ns') { _.assign(templateData, { 'begin': interpolate('s#=n#()'), 'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)') }); } else if (timer.unit == 'us') { if (timer.ns.stop) { _.assign(templateData, { 'begin': interpolate('s#=n#.start()'), 'end': interpolate('r#=n#.microseconds()/1e6') }); } else { _.assign(templateData, { 'begin': interpolate('s#=n#()'), 'end': interpolate('r#=(n#()-s#)/1e6') }); } } else if (timer.ns.now) { _.assign(templateData, { 'begin': interpolate('s#=n#.now()'), 'end': interpolate('r#=(n#.now()-s#)/1e3') }); } else { _.assign(templateData, { 'begin': interpolate('s#=new n#().getTime()'), 'end': interpolate('r#=(new n#().getTime()-s#)/1e3') }); } // Define `timer` methods. timer.start = createFunction( interpolate('o#'), interpolate('var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#') ); timer.stop = createFunction( interpolate('o#'), interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#') ); // Create compiled test. return createFunction( interpolate('window,t#'), 'var global = window, clearTimeout = global.clearTimeout, setTimeout = global.setTimeout;\n' + interpolate(body) ); } /** * Gets the current timer's minimum resolution (secs). */ function getRes(unit) { var measured, begin, count = 30, divisor = 1e3, ns = timer.ns, sample = []; // Get average smallest measurable time. while (count--) { if (unit == 'us') { divisor = 1e6; if (ns.stop) { ns.start(); while (!(measured = ns.microseconds())) {} } else { begin = ns(); while (!(measured = ns() - begin)) {} } } else if (unit == 'ns') { divisor = 1e9; begin = (begin = ns())[0] + (begin[1] / divisor); while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) {} divisor = 1; } else if (ns.now) { begin = ns.now(); while (!(measured = ns.now() - begin)) {} } else { begin = new ns().getTime(); while (!(measured = new ns().getTime() - begin)) {} } // Check for broken timers. if (measured > 0) { sample.push(measured); } else { sample.push(Infinity); break; } } // Convert to seconds. return getMean(sample) / divisor; } /** * Interpolates a given template string. */ function interpolate(string) { // Replaces all occurrences of `#` with a unique number and template tokens with content. return _.template(string.replace(/\#/g, /\d+/.exec(templateData.uid)))(templateData); } /*----------------------------------------------------------------------*/ // Detect Chrome's microsecond timer: // enable benchmarking via the --enable-benchmarking command // line switch in at least Chrome 7 to use chrome.Interval try { if ((timer.ns = new (context.chrome || context.chromium).Interval)) { timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); } } catch(e) {} // Detect Node.js's nanosecond resolution timer available in Node.js >= 0.8. if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') { timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' }); } // Detect Wade Simmons' Node.js `microtime` module. if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') { timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); } // Pick timer with highest resolution. timer = _.minBy(timers, 'res'); // Error if there are no working timers. if (timer.res == Infinity) { throw new Error('Benchmark.js was unable to find a working timer.'); } // Resolve time span required to achieve a percent uncertainty of at most 1%. // For more information see http://spiff.rit.edu/classes/phys273/uncert/uncert.html. options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05)); return clock.apply(null, arguments); } /*------------------------------------------------------------------------*/ /** * Computes stats on benchmark results. * * @private * @param {Object} bench The benchmark instance. * @param {Object} options The options object. */ function compute(bench, options) { options || (options = {}); var async = options.async, elapsed = 0, initCount = bench.initCount, minSamples = bench.minSamples, queue = [], sample = bench.stats.sample; /** * Adds a clone to the queue. */ function enqueue() { queue.push(_.assign(bench.clone(), { '_original': bench, 'events': { 'abort': [update], 'cycle': [update], 'error': [update], 'start': [update] } })); } /** * Updates the clone/original benchmarks to keep their data in sync. */ function update(event) { var clone = this, type = event.type; if (bench.running) { if (type == 'start') { // Note: `clone.minTime` prop is inited in `clock()`. clone.count = bench.initCount; } else { if (type == 'error') { bench.error = clone.error; } if (type == 'abort') { bench.abort(); bench.emit('cycle'); } else { event.currentTarget = event.target = bench; bench.emit(event); } } } else if (bench.aborted) { // Clear abort listeners to avoid triggering bench's abort/cycle again. clone.events.abort.length = 0; clone.abort(); } } /** * Determines if more clones should be queued or if cycling should stop. */ function evaluate(event) { var critical, df, mean, moe, rme, sd, sem, variance, clone = event.target, done = bench.aborted, now = _.now(), size = sample.push(clone.times.period), maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime, times = bench.times, varOf = function(sum, x) { return sum + pow(x - mean, 2); }; // Exit early for aborted or unclockable tests. if (done || clone.hz == Infinity) { maxedOut = !(size = sample.length = queue.length = 0); } if (!done) { // Compute the sample mean (estimate of the population mean). mean = getMean(sample); // Compute the sample variance (estimate of the population variance). variance = _.reduce(sample, varOf, 0) / (size - 1) || 0; // Compute the sample standard deviation (estimate of the population standard deviation). sd = sqrt(variance); // Compute the standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean). sem = sd / sqrt(size); // Compute the degrees of freedom. df = size - 1; // Compute the critical value. critical = tTable[Math.round(df) || 1] || tTable.infinity; // Compute the margin of error. moe = sem * critical; // Compute the relative margin of error. rme = (moe / mean) * 100 || 0; _.assign(bench.stats, { 'deviation': sd, 'mean': mean, 'moe': moe, 'rme': rme, 'sem': sem, 'variance': variance }); // Abort the cycle loop when the minimum sample size has been collected // and the elapsed time exceeds the maximum time allowed per benchmark. // We don't count cycle delays toward the max time because delays may be // increased by browsers that clamp timeouts for inactive tabs. For more // information see https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs. if (maxedOut) { // Reset the `initCount` in case the benchmark is rerun. bench.initCount = initCount; bench.running = false; done = true; times.elapsed = (now - times.timeStamp) / 1e3; } if (bench.hz != Infinity) { bench.hz = 1 / mean; times.cycle = mean * bench.count; times.period = mean; } } // If time permits, increase sample size to reduce the margin of error. if (queue.length < 2 && !maxedOut) { enqueue(); } // Abort the `invoke` cycle when done. event.aborted = done; } // Init queue and begin. enqueue(); invoke(queue, { 'name': 'run', 'args': { 'async': async }, 'queued': true, 'onCycle': evaluate, 'onComplete': function() { bench.emit('complete'); } }); } /*------------------------------------------------------------------------*/ /** * Cycles a benchmark until a run `count` can be established. * * @private * @param {Object} clone The cloned benchmark instance. * @param {Object} options The options object. */ function cycle(clone, options) { options || (options = {}); var deferred; if (clone instanceof Deferred) { deferred = clone; clone = clone.benchmark; } var clocked, cycles, divisor, event, minTime, period, async = options.async, bench = clone._original, count = clone.count, times = clone.times; // Continue, if not aborted between cycles. if (clone.running) { // `minTime` is set to `Benchmark.options.minTime` in `clock()`. cycles = ++clone.cycles; clocked = deferred ? deferred.elapsed : clock(clone); minTime = clone.minTime; if (cycles > bench.cycles) { bench.cycles = cycles; } if (clone.error) { event = Event('error'); event.message = clone.error; clone.emit(event); if (!event.cancelled) { clone.abort(); } } } // Continue, if not errored. if (clone.running) { // Compute the time taken to complete last test cycle. bench.times.cycle = times.cycle = clocked; // Compute the seconds per operation. period = bench.times.period = times.period = clocked / count; // Compute the ops per second. bench.hz = clone.hz = 1 / period; // Avoid working our way up to this next time. bench.initCount = clone.initCount = count; // Do we need to do another cycle? clone.running = clocked < minTime; if (clone.running) { // Tests may clock at `0` when `initCount` is a small number, // to avoid that we set its count to something a bit higher. if (!clocked && (divisor = divisors[clone.cycles]) != null) { count = floor(4e6 / divisor); } // Calculate how many more iterations it will take to achieve the `minTime`. if (count <= clone.count) { count += Math.ceil((minTime - clocked) / period); } clone.running = count != Infinity; } } // Should we exit early? event = Event('cycle'); clone.emit(event); if (event.aborted) { clone.abort(); } // Figure out what to do next. if (clone.running) { // Start a new cycle. clone.count = count; if (deferred) { clone.compiled.call(deferred, context, timer); } else if (async) { delay(clone, function() { cycle(clone, options); }); } else { cycle(clone); } } else { // Fix TraceMonkey bug associated with clock fallbacks. // For more information see http://bugzil.la/509069. if (support.browser) { runScript(uid + '=1;delete ' + uid); } // We're done. clone.emit('complete'); } } /*------------------------------------------------------------------------*/ /** * Runs the benchmark. * * @memberOf Benchmark * @param {Object} [options={}] Options object. * @returns {Object} The benchmark instance. * @example * * // basic usage * bench.run(); * * // or with options * bench.run({ 'async': true }); */ function run(options) { var bench = this, event = Event('start'); // Set `running` to `false` so `reset()` won't call `abort()`. bench.running = false; bench.reset(); bench.running = true; bench.count = bench.initCount; bench.times.timeStamp = _.now(); bench.emit(event); if (!event.cancelled) { options = { 'async': ((options = options && options.async) == null ? bench.async : options) && support.timeout }; // For clones created within `compute()`. if (bench._original) { if (bench.defer) { Deferred(bench); } else { cycle(bench, options); } } // For original benchmarks. else { compute(bench, options); } } return bench; } /*------------------------------------------------------------------------*/ // Firefox 1 erroneously defines variable and argument names of functions on // the function itself as non-configurable properties with `undefined` values. // The bugginess continues as the `Benchmark` constructor has an argument // named `options` and Firefox 1 will not assign a value to `Benchmark.options`, // making it non-writable in the process, unless it is the first property // assigned by for-in loop of `_.assign()`. _.assign(Benchmark, { /** * The default options copied by benchmark instances. * * @static * @memberOf Benchmark * @type Object */ 'options': { /** * A flag to indicate that benchmark cycles will execute asynchronously * by default. * * @memberOf Benchmark.options * @type boolean */ 'async': false, /** * A flag to indicate that the benchmark clock is deferred. * * @memberOf Benchmark.options * @type boolean */ 'defer': false, /** * The delay between test cycles (secs). * @memberOf Benchmark.options * @type number */ 'delay': 0.005, /** * Displayed by `Benchmark#toString` when a `name` is not available * (auto-generated if absent). * * @memberOf Benchmark.options * @type string */ 'id': undefined, /** * The default number of times to execute a test on a benchmark's first cycle. * * @memberOf Benchmark.options * @type number */ 'initCount': 1, /** * The maximum time a benchmark is allowed to run before finishing (secs). * * Note: Cycle delays aren't counted toward the maximum time. * * @memberOf Benchmark.options * @type number */ 'maxTime': 5, /** * The minimum sample size required to perform statistical analysis. * * @memberOf Benchmark.options * @type number */ 'minSamples': 5, /** * The time needed to reduce the percent uncertainty of measurement to 1% (secs). * * @memberOf Benchmark.options * @type number */ 'minTime': 0, /** * The name of the benchmark. * * @memberOf Benchmark.options * @type string */ 'name': undefined, /** * An event listener called when the benchmark is aborted. * * @memberOf Benchmark.options * @type Function */ 'onAbort': undefined, /** * An event listener called when the benchmark completes running. * * @memberOf Benchmark.options * @type Function */ 'onComplete': undefined, /** * An event listener called after each run cycle. * * @memberOf Benchmark.options * @type Function */ 'onCycle': undefined, /** * An event listener called when a test errors. * * @memberOf Benchmark.options * @type Function */ 'onError': undefined, /** * An event listener called when the benchmark is reset. * * @memberOf Benchmark.options * @type Function */ 'onReset': undefined, /** * An event listener called when the benchmark starts running. * * @memberOf Benchmark.options * @type Function */ 'onStart': undefined }, /** * Platform object with properties describing things like browser name, * version, and operating system. See [`platform.js`](https://mths.be/platform). * * @static * @memberOf Benchmark * @type Object */ 'platform': context.platform || require('platform') || ({ 'description': context.navigator && context.navigator.userAgent || null, 'layout': null, 'product': null, 'name': null, 'manufacturer': null, 'os': null, 'prerelease': null, 'version': null, 'toString': function() { return this.description || ''; } }), /** * The semantic version number. * * @static * @memberOf Benchmark * @type string */ 'version': '2.1.4' }); _.assign(Benchmark, { 'filter': filter, 'formatNumber': formatNumber, 'invoke': invoke, 'join': join, 'runInContext': runInContext, 'support': support }); // Add lodash methods to Benchmark. _.each(['each', 'forEach', 'forOwn', 'has', 'indexOf', 'map', 'reduce'], function(methodName) { Benchmark[methodName] = _[methodName]; }); /*------------------------------------------------------------------------*/ _.assign(Benchmark.prototype, { /** * The number of times a test was executed. * * @memberOf Benchmark * @type number */ 'count': 0, /** * The number of cycles performed while benchmarking. * * @memberOf Benchmark * @type number */ 'cycles': 0, /** * The number of executions per second. * * @memberOf Benchmark * @type number */ 'hz': 0, /** * The compiled test function. * * @memberOf Benchmark * @type {Function|string} */ 'compiled': undefined, /** * The error object if the test failed. * * @memberOf Benchmark * @type Object */ 'error': undefined, /** * The test to benchmark. * * @memberOf Benchmark * @type {Function|string} */ 'fn': undefined, /** * A flag to indicate if the benchmark is aborted. * * @memberOf Benchmark * @type boolean */ 'aborted': false, /** * A flag to indicate if the benchmark is running. * * @memberOf Benchmark * @type boolean */ 'running': false, /** * Compiled into the test and executed immediately **before** the test loop. * * @memberOf Benchmark * @type {Function|string} * @example * * // basic usage * var bench = Benchmark({ * 'setup': function() { * var c = this.count, * element = document.getElementById('container'); * while (c--) { * element.appendChild(document.createElement('div')); * } * }, * 'fn': function() { * element.removeChild(element.lastChild); * } * }); * * // compiles to something like: * var c = this.count, * element = document.getElementById('container'); * while (c--) { * element.appendChild(document.createElement('div')); * } * var start = new Date; * while (count--) { * element.removeChild(element.lastChild); * } * var end = new Date - start; * * // or using strings * var bench = Benchmark({ * 'setup': '\ * var a = 0;\n\ * (function() {\n\ * (function() {\n\ * (function() {', * 'fn': 'a += 1;', * 'teardown': '\ * }())\n\ * }())\n\ * }())' * }); * * // compiles to something like: * var a = 0; * (function() { * (function() { * (function() { * var start = new Date; * while (count--) { * a += 1; * } * var end = new Date - start; * }()) * }()) * }()) */ 'setup': _.noop, /** * Compiled into the test and executed immediately **after** the test loop. * * @memberOf Benchmark * @type {Function|string} */ 'teardown': _.noop, /** * An object of stats including mean, margin or error, and standard deviation. * * @memberOf Benchmark * @type Object */ 'stats': { /** * The margin of error. * * @memberOf Benchmark#stats * @type number */ 'moe': 0, /** * The relative margin of error (expressed as a percentage of the mean). * * @memberOf Benchmark#stats * @type number */ 'rme': 0, /** * The standard error of the mean. * * @memberOf Benchmark#stats * @type number */ 'sem': 0, /** * The sample standard deviation. * * @memberOf Benchmark#stats * @type number */ 'deviation': 0, /** * The sample arithmetic mean (secs). * * @memberOf Benchmark#stats * @type number */ 'mean': 0, /** * The array of sampled periods. * * @memberOf Benchmark#stats * @type Array */ 'sample': [], /** * The sample variance. * * @memberOf Benchmark#stats * @type number */ 'variance': 0 }, /** * An object of timing data including cycle, elapsed, period, start, and stop. * * @memberOf Benchmark * @type Object */ 'times': { /** * The time taken to complete the last cycle (secs). * * @memberOf Benchmark#times * @type number */ 'cycle': 0, /** * The time taken to complete the benchmark (secs). * * @memberOf Benchmark#times * @type number */ 'elapsed': 0, /** * The time taken to execute the test once (secs). * * @memberOf Benchmark#times * @type number */ 'period': 0, /** * A timestamp of when the benchmark started (ms). * * @memberOf Benchmark#times * @type number */ 'timeStamp': 0 } }); _.assign(Benchmark.prototype, { 'abort': abort, 'clone': clone, 'compare': compare, 'emit': emit, 'listeners': listeners, 'off': off, 'on': on, 'reset': reset, 'run': run, 'toString': toStringBench }); /*------------------------------------------------------------------------*/ _.assign(Deferred.prototype, { /** * The deferred benchmark instance. * * @memberOf Benchmark.Deferred * @type Object */ 'benchmark': null, /** * The number of deferred cycles performed while benchmarking. * * @memberOf Benchmark.Deferred * @type number */ 'cycles': 0, /** * The time taken to complete the deferred benchmark (secs). * * @memberOf Benchmark.Deferred * @type number */ 'elapsed': 0, /** * A timestamp of when the deferred benchmark started (ms). * * @memberOf Benchmark.Deferred * @type number */ 'timeStamp': 0 }); _.assign(Deferred.prototype, { 'resolve': resolve }); /*------------------------------------------------------------------------*/ _.assign(Event.prototype, { /** * A flag to indicate if the emitters listener iteration is aborted. * * @memberOf Benchmark.Event * @type boolean */ 'aborted': false, /** * A flag to indicate if the default action is cancelled. * * @memberOf Benchmark.Event * @type boolean */ 'cancelled': false, /** * The object whose listeners are currently being processed. * * @memberOf Benchmark.Event * @type Object */ 'currentTarget': undefined, /** * The return value of the last executed listener. * * @memberOf Benchmark.Event * @type Mixed */ 'result': undefined, /** * The object to which the event was originally emitted. * * @memberOf Benchmark.Event * @type Object */ 'target': undefined, /** * A timestamp of when the event was created (ms). * * @memberOf Benchmark.Event * @type number */ 'timeStamp': 0, /** * The event type. * * @memberOf Benchmark.Event * @type string */ 'type': '' }); /*------------------------------------------------------------------------*/ /** * The default options copied by suite instances. * * @static * @memberOf Benchmark.Suite * @type Object */ Suite.options = { /** * The name of the suite. * * @memberOf Benchmark.Suite.options * @type string */ 'name': undefined }; /*------------------------------------------------------------------------*/ _.assign(Suite.prototype, { /** * The number of benchmarks in the suite. * * @memberOf Benchmark.Suite * @type number */ 'length': 0, /** * A flag to indicate if the suite is aborted. * * @memberOf Benchmark.Suite * @type boolean */ 'aborted': false, /** * A flag to indicate if the suite is running. * * @memberOf Benchmark.Suite * @type boolean */ 'running': false }); _.assign(Suite.prototype, { 'abort': abortSuite, 'add': add, 'clone': cloneSuite, 'emit': emit, 'filter': filterSuite, 'join': arrayRef.join, 'listeners': listeners, 'off': off, 'on': on, 'pop': arrayRef.pop, 'push': push, 'reset': resetSuite, 'run': runSuite, 'reverse': arrayRef.reverse, 'shift': shift, 'slice': slice, 'sort': arrayRef.sort, 'splice': arrayRef.splice, 'unshift': unshift }); /*------------------------------------------------------------------------*/ // Expose Deferred, Event, and Suite. _.assign(Benchmark, { 'Deferred': Deferred, 'Event': Event, 'Suite': Suite }); /*------------------------------------------------------------------------*/ // Add lodash methods as Suite methods. _.each(['each', 'forEach', 'indexOf', 'map', 'reduce'], function(methodName) { var func = _[methodName]; Suite.prototype[methodName] = function() { var args = [this]; push.apply(args, arguments); return func.apply(_, args); }; }); // Avoid array-like object bugs with `Array#shift` and `Array#splice` // in Firefox < 10 and IE < 9. _.each(['pop', 'shift', 'splice'], function(methodName) { var func = arrayRef[methodName]; Suite.prototype[methodName] = function() { var value = this, result = func.apply(value, arguments); if (value.length === 0) { delete value[0]; } return result; }; }); // Avoid buggy `Array#unshift` in IE < 8 which doesn't return the new // length of the array. Suite.prototype.unshift = function() { var value = this; unshift.apply(value, arguments); return value.length; }; return Benchmark; } /*--------------------------------------------------------------------------*/ // Export Benchmark. // Some AMD build optimizers, like r.js, check for condition patterns like the following: if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { // Define as an anonymous module so, through path mapping, it can be aliased. define(['lodash', 'platform'], function(_, platform) { return runInContext({ '_': _, 'platform': platform }); }); } else { var Benchmark = runInContext(); // Check for `exports` after `define` in case a build optimizer adds an `exports` object. if (freeExports && freeModule) { // Export for Node.js. if (moduleExports) { (freeModule.exports = Benchmark).Benchmark = Benchmark; } // Export for CommonJS support. freeExports.Benchmark = Benchmark; } else { // Export to the global object. root.Benchmark = Benchmark; } } }.call(this)); benchmark.js-2.1.4/doc/000077500000000000000000000000001306651343200146335ustar00rootroot00000000000000benchmark.js-2.1.4/doc/README.md000066400000000000000000001202071306651343200161140ustar00rootroot00000000000000# Benchmark.js v2.1.4 ## `Methods` * `Benchmark` * `Benchmark.Deferred` * `Benchmark.Deferred.prototype.resolve` * `Benchmark.Event` * `Benchmark.Suite` * `Benchmark.Suite.prototype.abort` * `Benchmark.Suite.prototype.add` * `Benchmark.Suite.prototype.clone` * `Benchmark.Suite.prototype.filter` * `Benchmark.Suite.prototype.reset` * `Benchmark.Suite.prototype.run` * `Benchmark.filter` * `Benchmark.formatNumber` * `Benchmark.invoke` * `Benchmark.join` * `Benchmark.runInContext` * `Benchmark.prototype.abort` * `Benchmark.prototype.clone` * `Benchmark.prototype.compare` * `Benchmark.prototype.emit` * `Benchmark.prototype.listeners` * `Benchmark.prototype.off` * `Benchmark.prototype.on` * `Benchmark.prototype.reset` * `Benchmark.prototype.run` * `Benchmark.prototype.toString` ## `Properties` * `Benchmark.Deferred.prototype.benchmark` * `Benchmark.Deferred.prototype.cycles` * `Benchmark.Deferred.prototype.elapsed` * `Benchmark.Deferred.prototype.timeStamp` * `Benchmark.Event.prototype.aborted` * `Benchmark.Event.prototype.cancelled` * `Benchmark.Event.prototype.currentTarget` * `Benchmark.Event.prototype.result` * `Benchmark.Event.prototype.target` * `Benchmark.Event.prototype.timeStamp` * `Benchmark.Event.prototype.type` * `Benchmark.Suite.options` * `Benchmark.Suite.options.name` * `Benchmark.Suite.prototype.aborted` * `Benchmark.Suite.prototype.length` * `Benchmark.Suite.prototype.running` * `Benchmark.options` * `Benchmark.options.async` * `Benchmark.options.defer` * `Benchmark.options.delay` * `Benchmark.options.id` * `Benchmark.options.initCount` * `Benchmark.options.maxTime` * `Benchmark.options.minSamples` * `Benchmark.options.minTime` * `Benchmark.options.name` * `Benchmark.options.onAbort` * `Benchmark.options.onComplete` * `Benchmark.options.onCycle` * `Benchmark.options.onError` * `Benchmark.options.onReset` * `Benchmark.options.onStart` * `Benchmark.platform` * `Benchmark.support` * `Benchmark.support.browser` * `Benchmark.version` * `Benchmark.prototype.aborted` * `Benchmark.prototype.compiled` * `Benchmark.prototype.count` * `Benchmark.prototype.cycles` * `Benchmark.support.decompilation` * `Benchmark.prototype.error` * `Benchmark.prototype.fn` * `Benchmark.prototype.hz` * `Benchmark.prototype.running` * `Benchmark.prototype.setup` * `Benchmark.prototype.stats` * `Benchmark.prototype.teardown` * `Benchmark.support.timeout` * `Benchmark.prototype.times` * `Benchmark#stats.deviation` * `Benchmark#stats.mean` * `Benchmark#stats.moe` * `Benchmark#stats.rme` * `Benchmark#stats.sample` * `Benchmark#stats.sem` * `Benchmark#stats.variance` * `Benchmark#times.cycle` * `Benchmark#times.elapsed` * `Benchmark#times.period` * `Benchmark#times.timeStamp` ## `Methods`

Benchmark(name, fn, [options={}])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L356 "View in source") [Ⓣ][1] The Benchmark constructor.

Note: The Benchmark constructor exposes a handful of lodash methods to make working with arrays, collections, and objects easier. The lodash methods are:
[`each/forEach`](https://lodash.com/docs#forEach), [`forOwn`](https://lodash.com/docs#forOwn), [`has`](https://lodash.com/docs#has), [`indexOf`](https://lodash.com/docs#indexOf), [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce) #### Arguments 1. `name` *(string)*: A name to identify the benchmark. 2. `fn` *(Function|string)*: The test to benchmark. 3. `[options={}]` *(Object)*: Options object. #### Example ```js // basic usage (the `new` operator is optional) var bench = new Benchmark(fn); // or using a name first var bench = new Benchmark('foo', fn); // or with options var bench = new Benchmark('foo', fn, { // displayed by `Benchmark#toString` if `name` is not available 'id': 'xyz', // called when the benchmark starts running 'onStart': onStart, // called after each run cycle 'onCycle': onCycle, // called when aborted 'onAbort': onAbort, // called when a test errors 'onError': onError, // called when reset 'onReset': onReset, // called when the benchmark completes running 'onComplete': onComplete, // compiled/called before the test loop 'setup': setup, // compiled/called after the test loop 'teardown': teardown }); // or name and options var bench = new Benchmark('foo', { // a flag to indicate the benchmark is deferred 'defer': true, // benchmark test function 'fn': function(deferred) { // call `Deferred#resolve` when the deferred test is finished deferred.resolve(); } }); // or options only var bench = new Benchmark({ // benchmark name 'name': 'foo', // benchmark test as a string 'fn': '[1,2,3,4].sort()' }); // a test's `this` binding is set to the benchmark instance var bench = new Benchmark('foo', function() { 'My name is '.concat(this.name); // "My name is foo" }); ``` ---

Benchmark.Deferred(clone)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L399 "View in source") [Ⓣ][1] The Deferred constructor. #### Arguments 1. `clone` *(Object)*: The cloned benchmark instance. ---

Benchmark.Deferred.prototype.resolve()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L716 "View in source") [Ⓣ][1] Handles cycling/completing the deferred benchmark. ---

Benchmark.Event(type)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L415 "View in source") [Ⓣ][1] The Event constructor. #### Arguments 1. `type` *(Object|string)*: The event type. ---

Benchmark.Suite(name, [options={}])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L467 "View in source") [Ⓣ][1] The Suite constructor.

Note: Each Suite instance has a handful of wrapped lodash methods to make working with Suites easier. The wrapped lodash methods are:
[`each/forEach`](https://lodash.com/docs#forEach), [`indexOf`](https://lodash.com/docs#indexOf), [`map`](https://lodash.com/docs#map), and [`reduce`](https://lodash.com/docs#reduce) #### Arguments 1. `name` *(string)*: A name to identify the suite. 2. `[options={}]` *(Object)*: Options object. #### Example ```js // basic usage (the `new` operator is optional) var suite = new Benchmark.Suite; // or using a name first var suite = new Benchmark.Suite('foo'); // or with options var suite = new Benchmark.Suite('foo', { // called when the suite starts running 'onStart': onStart, // called between running benchmarks 'onCycle': onCycle, // called when aborted 'onAbort': onAbort, // called when a test errors 'onError': onError, // called when reset 'onReset': onReset, // called when the suite completes running 'onComplete': onComplete }); ``` ---

Benchmark.Suite.prototype.abort()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1008 "View in source") [Ⓣ][1] Aborts all benchmarks in the suite. #### Returns *(Object)*: The suite instance. ---

Benchmark.Suite.prototype.add(name, fn, [options={}])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1068 "View in source") [Ⓣ][1] Adds a test to the benchmark suite. #### Arguments 1. `name` *(string)*: A name to identify the benchmark. 2. `fn` *(Function|string)*: The test to benchmark. 3. `[options={}]` *(Object)*: Options object. #### Returns *(Object)*: The suite instance. #### Example ```js // basic usage suite.add(fn); // or using a name first suite.add('foo', fn); // or with options suite.add('foo', fn, { 'onCycle': onCycle, 'onComplete': onComplete }); // or name and options suite.add('foo', { 'fn': fn, 'onCycle': onCycle, 'onComplete': onComplete }); // or options only suite.add({ 'name': 'foo', 'fn': fn, 'onCycle': onCycle, 'onComplete': onComplete }); ``` ---

Benchmark.Suite.prototype.clone(options)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1087 "View in source") [Ⓣ][1] Creates a new suite with cloned benchmarks. #### Arguments 1. `options` *(Object)*: Options object to overwrite cloned options. #### Returns *(Object)*: The new suite instance. ---

Benchmark.Suite.prototype.filter(callback)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1110 "View in source") [Ⓣ][1] An `Array#filter` like method. #### Arguments 1. `callback` *(Function|string)*: The function/alias called per iteration. #### Returns *(Object)*: A new suite of benchmarks that passed callback filter. ---

Benchmark.Suite.prototype.reset()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1125 "View in source") [Ⓣ][1] Resets all benchmarks in the suite. #### Returns *(Object)*: The suite instance. ---

Benchmark.Suite.prototype.run([options={}])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1162 "View in source") [Ⓣ][1] Runs the suite. #### Arguments 1. `[options={}]` *(Object)*: Options object. #### Returns *(Object)*: The suite instance. #### Example ```js // basic usage suite.run(); // or with options suite.run({ 'async': true, 'queued': true }); ``` ---

Benchmark.filter(array, callback)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L763 "View in source") [Ⓣ][1] A generic `Array#filter` like method. #### Arguments 1. `array` *(Array)*: The array to iterate over. 2. `callback` *(Function|string)*: The function/alias called per iteration. #### Returns *(Array)*: A new array of values that passed callback filter. #### Example ```js // get odd numbers Benchmark.filter([1, 2, 3, 4, 5], function(n) { return n % 2; }); // -> [1, 3, 5]; // get fastest benchmarks Benchmark.filter(benches, 'fastest'); // get slowest benchmarks Benchmark.filter(benches, 'slowest'); // get benchmarks that completed without erroring Benchmark.filter(benches, 'successful'); ``` ---

Benchmark.formatNumber(number)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L792 "View in source") [Ⓣ][1] Converts a number to a more readable comma-separated string representation. #### Arguments 1. `number` *(number)*: The number to convert. #### Returns *(string)*: The more readable string representation. ---

Benchmark.invoke(benches, name, [args])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L837 "View in source") [Ⓣ][1] Invokes a method on all items in an array. #### Arguments 1. `benches` *(Array)*: Array of benchmarks to iterate over. 2. `name` *(Object|string)*: The name of the method to invoke OR options object. 3. `[args]` *(...*)*: Arguments to invoke the method with. #### Returns *(Array)*: A new array of values returned from each method invoked. #### Example ```js // invoke `reset` on all benchmarks Benchmark.invoke(benches, 'reset'); // invoke `emit` with arguments Benchmark.invoke(benches, 'emit', 'complete', listener); // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks Benchmark.invoke(benches, { // invoke the `run` method 'name': 'run', // pass a single argument 'args': true, // treat as queue, removing benchmarks from front of `benches` until empty 'queued': true, // called before any benchmarks have been invoked. 'onStart': onStart, // called between invoking benchmarks 'onCycle': onCycle, // called after all benchmarks have been invoked. 'onComplete': onComplete }); ``` ---

Benchmark.join(object, [separator1=','], [separator2=': '])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L987 "View in source") [Ⓣ][1] Creates a string of joined array values or object key-value pairs. #### Arguments 1. `object` *(Array|Object)*: The object to operate on. 2. `[separator1=',']` *(string)*: The separator used between key-value pairs. 3. `[separator2=': ']` *(string)*: The separator used between keys and values. #### Returns *(string)*: The joined result. ---

Benchmark.runInContext([context=root])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L125 "View in source") [Ⓣ][1] Create a new `Benchmark` function using the given `context` object. #### Arguments 1. `[context=root]` *(Object)*: The context object. #### Returns *(Function)*: Returns a new `Benchmark` function. ---

Benchmark.prototype.abort()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1328 "View in source") [Ⓣ][1] Aborts the benchmark without recording times. #### Returns *(Object)*: The benchmark instance. ---

Benchmark.prototype.clone(options)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1367 "View in source") [Ⓣ][1] Creates a new benchmark using the same test and options. #### Arguments 1. `options` *(Object)*: Options object to overwrite cloned options. #### Returns *(Object)*: The new benchmark instance. #### Example ```js var bizarro = bench.clone({ 'name': 'doppelganger' }); ``` ---

Benchmark.prototype.compare(other)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1391 "View in source") [Ⓣ][1] Determines if a benchmark is faster than another. #### Arguments 1. `other` *(Object)*: The benchmark to compare. #### Returns *(number)*: Returns `-1` if slower, `1` if faster, and `0` if indeterminate. ---

Benchmark.prototype.emit(type, [args])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1202 "View in source") [Ⓣ][1] Executes all registered listeners of the specified event type. #### Arguments 1. `type` *(Object|string)*: The event type or object. 2. `[args]` *(...*)*: Arguments to invoke the listener with. #### Returns *(*)*: Returns the return value of the last listener executed. ---

Benchmark.prototype.listeners(type)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1232 "View in source") [Ⓣ][1] Returns an array of event listeners for a given type that can be manipulated to add or remove listeners. #### Arguments 1. `type` *(string)*: The event type. #### Returns *(Array)*: The listeners array. ---

Benchmark.prototype.off([type], [listener])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1265 "View in source") [Ⓣ][1] Unregisters a listener for the specified event type(s), or unregisters all listeners for the specified event type(s), or unregisters all listeners for all event types. #### Arguments 1. `[type]` *(string)*: The event type. 2. `[listener]` *(Function)*: The function to unregister. #### Returns *(Object)*: The current instance. #### Example ```js // unregister a listener for an event type bench.off('cycle', listener); // unregister a listener for multiple event types bench.off('start cycle', listener); // unregister all listeners for an event type bench.off('cycle'); // unregister all listeners for multiple event types bench.off('start cycle complete'); // unregister all listeners for all event types bench.off(); ``` ---

Benchmark.prototype.on(type, listener)

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1307 "View in source") [Ⓣ][1] Registers a listener for the specified event type(s). #### Arguments 1. `type` *(string)*: The event type. 2. `listener` *(Function)*: The function to register. #### Returns *(Object)*: The current instance. #### Example ```js // register a listener for an event type bench.on('cycle', listener); // register a listener for multiple event types bench.on('start cycle', listener); ``` ---

Benchmark.prototype.reset()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1444 "View in source") [Ⓣ][1] Reset properties and abort if running. #### Returns *(Object)*: The benchmark instance. ---

Benchmark.prototype.run([options={}])

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2093 "View in source") [Ⓣ][1] Runs the benchmark. #### Arguments 1. `[options={}]` *(Object)*: Options object. #### Returns *(Object)*: The benchmark instance. #### Example ```js // basic usage bench.run(); // or with options bench.run({ 'async': true }); ``` ---

Benchmark.prototype.toString()

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L1525 "View in source") [Ⓣ][1] Displays relevant benchmark information when coerced to a string. #### Returns *(string)*: A string representation of the benchmark instance. --- ## `Properties`

Benchmark.Deferred.prototype.benchmark

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2583 "View in source") [Ⓣ][1] The deferred benchmark instance. ---

Benchmark.Deferred.prototype.cycles

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2591 "View in source") [Ⓣ][1] The number of deferred cycles performed while benchmarking. ---

Benchmark.Deferred.prototype.elapsed

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2599 "View in source") [Ⓣ][1] The time taken to complete the deferred benchmark *(secs)*. ---

Benchmark.Deferred.prototype.timeStamp

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2607 "View in source") [Ⓣ][1] A timestamp of when the deferred benchmark started *(ms)*. ---

Benchmark.Event.prototype.aborted

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2624 "View in source") [Ⓣ][1] A flag to indicate if the emitters listener iteration is aborted. ---

Benchmark.Event.prototype.cancelled

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2632 "View in source") [Ⓣ][1] A flag to indicate if the default action is cancelled. ---

Benchmark.Event.prototype.currentTarget

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2640 "View in source") [Ⓣ][1] The object whose listeners are currently being processed. ---

Benchmark.Event.prototype.result

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2648 "View in source") [Ⓣ][1] The return value of the last executed listener. ---

Benchmark.Event.prototype.target

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2656 "View in source") [Ⓣ][1] The object to which the event was originally emitted. ---

Benchmark.Event.prototype.timeStamp

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2664 "View in source") [Ⓣ][1] A timestamp of when the event was created *(ms)*. ---

Benchmark.Event.prototype.type

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2672 "View in source") [Ⓣ][1] The event type. ---

Benchmark.Suite.options

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2684 "View in source") [Ⓣ][1] The default options copied by suite instances. ---

Benchmark.Suite.options.name

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2692 "View in source") [Ⓣ][1] The name of the suite. ---

Benchmark.Suite.prototype.aborted

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2713 "View in source") [Ⓣ][1] A flag to indicate if the suite is aborted. ---

Benchmark.Suite.prototype.length

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2705 "View in source") [Ⓣ][1] The number of benchmarks in the suite. ---

Benchmark.Suite.prototype.running

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2721 "View in source") [Ⓣ][1] A flag to indicate if the suite is running. ---

Benchmark.options

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2142 "View in source") [Ⓣ][1] The default options copied by benchmark instances. ---

Benchmark.options.async

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2151 "View in source") [Ⓣ][1] A flag to indicate that benchmark cycles will execute asynchronously by default. ---

Benchmark.options.defer

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2159 "View in source") [Ⓣ][1] A flag to indicate that the benchmark clock is deferred. ---

Benchmark.options.delay

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2166 "View in source") [Ⓣ][1] The delay between test cycles *(secs)*. ---

Benchmark.options.id

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2175 "View in source") [Ⓣ][1] Displayed by `Benchmark#toString` when a `name` is not available *(auto-generated if absent)*. ---

Benchmark.options.initCount

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2183 "View in source") [Ⓣ][1] The default number of times to execute a test on a benchmark's first cycle. ---

Benchmark.options.maxTime

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2193 "View in source") [Ⓣ][1] The maximum time a benchmark is allowed to run before finishing *(secs)*.

Note: Cycle delays aren't counted toward the maximum time. ---

Benchmark.options.minSamples

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2201 "View in source") [Ⓣ][1] The minimum sample size required to perform statistical analysis. ---

Benchmark.options.minTime

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2209 "View in source") [Ⓣ][1] The time needed to reduce the percent uncertainty of measurement to `1`% *(secs)*. ---

Benchmark.options.name

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2217 "View in source") [Ⓣ][1] The name of the benchmark. ---

Benchmark.options.onAbort

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2225 "View in source") [Ⓣ][1] An event listener called when the benchmark is aborted. ---

Benchmark.options.onComplete

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2233 "View in source") [Ⓣ][1] An event listener called when the benchmark completes running. ---

Benchmark.options.onCycle

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2241 "View in source") [Ⓣ][1] An event listener called after each run cycle. ---

Benchmark.options.onError

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2249 "View in source") [Ⓣ][1] An event listener called when a test errors. ---

Benchmark.options.onReset

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2257 "View in source") [Ⓣ][1] An event listener called when the benchmark is reset. ---

Benchmark.options.onStart

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2265 "View in source") [Ⓣ][1] An event listener called when the benchmark starts running. ---

Benchmark.platform

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2276 "View in source") [Ⓣ][1] Platform object with properties describing things like browser name, version, and operating system. See [`platform.js`](https://mths.be/platform). ---

Benchmark.support

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L195 "View in source") [Ⓣ][1] An object used to flag environments/features. ---

Benchmark.support.browser

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L205 "View in source") [Ⓣ][1] Detect if running in a browser environment. ---

Benchmark.version

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2297 "View in source") [Ⓣ][1] The semantic version number. ---

Benchmark.prototype.aborted

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2372 "View in source") [Ⓣ][1] A flag to indicate if the benchmark is aborted. ---

Benchmark.prototype.compiled

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2348 "View in source") [Ⓣ][1] The compiled test function. ---

Benchmark.prototype.count

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2324 "View in source") [Ⓣ][1] The number of times a test was executed. ---

Benchmark.prototype.cycles

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2332 "View in source") [Ⓣ][1] The number of cycles performed while benchmarking. ---

Benchmark.support.decompilation

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L222 "View in source") [Ⓣ][1] Detect if function decompilation is support. ---

Benchmark.prototype.error

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2356 "View in source") [Ⓣ][1] The error object if the test failed. ---

Benchmark.prototype.fn

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2364 "View in source") [Ⓣ][1] The test to benchmark. ---

Benchmark.prototype.hz

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2340 "View in source") [Ⓣ][1] The number of executions per second. ---

Benchmark.prototype.running

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2380 "View in source") [Ⓣ][1] A flag to indicate if the benchmark is running. ---

Benchmark.prototype.setup

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2443 "View in source") [Ⓣ][1] Compiled into the test and executed immediately **before** the test loop. #### Example ```js // basic usage var bench = Benchmark({ 'setup': function() { var c = this.count, element = document.getElementById('container'); while (c--) { element.appendChild(document.createElement('div')); } }, 'fn': function() { element.removeChild(element.lastChild); } }); // compiles to something like: var c = this.count, element = document.getElementById('container'); while (c--) { element.appendChild(document.createElement('div')); } var start = new Date; while (count--) { element.removeChild(element.lastChild); } var end = new Date - start; // or using strings var bench = Benchmark({ 'setup': '\ var a = 0;\n\ (function() {\n\ (function() {\n\ (function() {', 'fn': 'a += 1;', 'teardown': '\ }())\n\ }())\n\ }())' }); // compiles to something like: var a = 0; (function() { (function() { (function() { var start = new Date; while (count--) { a += 1; } var end = new Date - start; }()) }()) }()) ``` ---

Benchmark.prototype.stats

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2459 "View in source") [Ⓣ][1] An object of stats including mean, margin or error, and standard deviation. ---

Benchmark.prototype.teardown

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2451 "View in source") [Ⓣ][1] Compiled into the test and executed immediately **after** the test loop. ---

Benchmark.support.timeout

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L213 "View in source") [Ⓣ][1] Detect if the Timers API exists. ---

Benchmark.prototype.times

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2524 "View in source") [Ⓣ][1] An object of timing data including cycle, elapsed, period, start, and stop. ---

Benchmark#stats.deviation

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2491 "View in source") [Ⓣ][1] The sample standard deviation. ---

Benchmark#stats.mean

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2499 "View in source") [Ⓣ][1] The sample arithmetic mean *(secs)*. ---

Benchmark#stats.moe

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2467 "View in source") [Ⓣ][1] The margin of error. ---

Benchmark#stats.rme

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2475 "View in source") [Ⓣ][1] The relative margin of error *(expressed as a percentage of the mean)*. ---

Benchmark#stats.sample

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2507 "View in source") [Ⓣ][1] The array of sampled periods. ---

Benchmark#stats.sem

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2483 "View in source") [Ⓣ][1] The standard error of the mean. ---

Benchmark#stats.variance

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2515 "View in source") [Ⓣ][1] The sample variance. ---

Benchmark#times.cycle

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2532 "View in source") [Ⓣ][1] The time taken to complete the last cycle *(secs)*. ---

Benchmark#times.elapsed

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2540 "View in source") [Ⓣ][1] The time taken to complete the benchmark *(secs)*. ---

Benchmark#times.period

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2548 "View in source") [Ⓣ][1] The time taken to execute the test once *(secs)*. ---

Benchmark#times.timeStamp

[Ⓢ](https://github.com/bestiejs/benchmark.js/blob/2.1.4/benchmark.js#L2556 "View in source") [Ⓣ][1] A timestamp of when the benchmark started *(ms)*. --- [1]: #methods "Jump back to the TOC." benchmark.js-2.1.4/example/000077500000000000000000000000001306651343200155215ustar00rootroot00000000000000benchmark.js-2.1.4/example/jsperf/000077500000000000000000000000001306651343200170125ustar00rootroot00000000000000benchmark.js-2.1.4/example/jsperf/index.html000066400000000000000000000303351306651343200210130ustar00rootroot00000000000000 Benchmark.js test page | jsPerf

Benchmark.js test page

JavaScript performance comparison

Test case created by Mathias and last updated

Info

This is just a test document for Benchmark.js.

Preparation code

<div>Lorem ipsum</div>
<script>
  var arr = [1, 5, 4, 2, 3];

  function init() {
    window.console && console.log('init called');
  }
</script>
<script>
Benchmark.prototype.setup = function() {
  window.foo = 42;
  var x = arr;
};

Benchmark.prototype.teardown = function() {
  window.foo = 24;
};
</script>

Preparation code output

Lorem ipsum

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Testing in
Test Ops/sec
Normal
x.sort(function(a, b) {
  return a - b;
});
Exit Early
x.sort(function(a, b) {
  return a - b;
});
return;
Async
// async test
setTimeout(function() {
  deferred.resolve();
}, 10);
Error
x.foo(); // unknown method
Comments
// comments at start
x.reverse().sort(function(a, b) {
  return a - b;
});
// comments at end

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 comments

Add a comment

benchmark.js-2.1.4/example/jsperf/main.css000066400000000000000000000215421306651343200204540ustar00rootroot00000000000000html, body, h1, h2, h3, fieldset, #faq, #faq dt, #faq dd { margin: 0; padding: 0; border: 0; } table, p, ul, h1, h2, h3, #error-info, form div, #faq, .bs-rt { margin-bottom: 1em; } button, input, textarea, a, .bs-rt { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } html, input, textarea, button { font: 1em/1.5 sans-serif; } html { background: #c4c4c4; height: 100%; } body { background: #fff; border: solid #aaa; border-width: 0 1px; width: 60em; padding: 0 2.5em; margin: 0 auto; min-height: 100%; } a { color: #357ab0; padding: .2em; } a:hover, a:focus { text-decoration: none; } blockquote { margin: 0 0 1em; border-left: 5px solid #b4b4b4; padding-left: .5em; } table { width: 100%; border-collapse: collapse; } thead th, button:hover, button:focus, .submit:hover, .submit:focus, a:hover, a:focus, #comments .meta a:hover, #comments .meta a:focus, li.current a:hover, li.current a:focus, form h3, #comments .owner .meta { background: #1a6ab9; background-image: -moz-linear-gradient(top, #6ca5dd, #1a6ab9); background-image: -o-linear-gradient(top, #6ca5dd, #1a6ab9); background-image: -webkit-gradient(linear, left top, left bottom, from(#6ca5dd), to(#1a6ab9)); background-image: -webkit-linear-gradient(#6ca5dd, #1a6ab9); background-image: linear-gradient(top, #6ca5dd, #1a6ab9); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#6ca5dd', EndColorStr='#1a6ab9'); color: #fff; } caption, #comments .meta { background: #bcbcbc; background-image: -moz-linear-gradient(top, #d0d0d0, #a7a7a7); background-image: -o-linear-gradient(top, #d0d0d0, #a7a7a7); background-image: -webkit-gradient(linear, left top, left bottom, from(#d0d0d0), to(#a7a7a7)); background-image: -webkit-linear-gradient(#d0d0d0, #a7a7a7); background-image: linear-gradient(top, #d0d0d0, #a7a7a7); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#d0d0d0', EndColorStr='#a7a7a7'); color: #555; } thead th, caption { font-weight: bold; } .js tbody th:hover, .js tbody th:focus { text-decoration: underline; cursor: pointer; } tbody th, td { border: solid #b4b4b4; border-width: 0 1px 1px 0; } tbody th { background: #dde4ea; min-width: 100px; } tbody th div { max-width: 200px; word-wrap: break-word; overflow: auto; } td.results { text-align: center; border-right: 0; } .results span, small { display: block; font-size: .8em; } td, th, caption { padding: .2em .5em; } td.fastest { background: #9cee82; } tr:last-child td, tr:last-child th { border-bottom: 0; } td.slowest, td.error, .invalid { background: pink; } /* needs its own rule because of buggy IE */ :focus:invalid { background: pink; } td.error { text-transform: uppercase; font-weight: bold; } button, .submit { padding: .35em .5em; cursor: pointer; color: #000; border: 1px solid #999; background: #dadada; background-image: -moz-linear-gradient(top, #ebebeb, #b8b8b8); background-image: -o-linear-gradient(top, #ebebeb, #b8b8b8); background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#b8b8b8)); background-image: -webkit-linear-gradient(top, #ebebeb, #b8b8b8); background-image: linear-gradient(top, #ebebeb, #b8b8b8); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ebebeb', EndColorStr='#b8b8b8'); } a:hover span, a:focus span, #comments .owner .meta a { color: #fff; } #controls, #run, .buttons { float: right; } button:hover, button:focus, .submit:hover, .submit:focus { border-color: #357ab0 } #add-buttons button { padding: .15em .4em; font-size: 11px; font-weight: bold; } form label { float: left; width: 14em; cursor: pointer; text-align: right; margin-right: 1em; padding: .4em; } label.inline { float: none; padding: 0; margin: 0; } label[for="visible"], label[for$="][defer]"] { position: relative; top: -.37em; } label span { display: block; font-size: 90%; color: #b4b4b4; } label em { color: red; font-style: normal; } .js #advanced { display: none; } #show-advanced { display: none; } .js #show-advanced { display: block; } section { display: block; border-top: 1px solid #ccc; padding-top: 2em; margin: 2em 0; } textarea { resize: vertical; height: 15em; width: 42.6em; *width: 42.4em; /* IE < 8 */ } input, textarea { border: 1px solid #b4b4b4; padding: .4em; } #visible { /* checkboxes, for IE */ border: 0; padding: 0; } form h2, form h3, form h4, p.error, .preview, #add-libraries, #add-buttons { padding-left: 250px; display: block; } hgroup h2, #controls, #firebug, #java { display: none; } pre { width: 100%; overflow: auto; } table #results-1 { width: 100px; } table pre { *padding: 1.5em 0; /* IE < 8 */ *overflow-y: hidden; /* IE < 8 */ } table pre, table td.code { width: 650px; } mark { background: #ff9; padding: .2em .1em; } h1, h2, h3, h4 { font-weight: bold; font-size: 1em; } h1 { padding-top: 1em; font-size: 1.4em; } form h3 { padding-top: .2em; padding-bottom: .2em; } h1 em { font-style: normal; } h1 strong { font-style: italic; font-family: Monaco, 'Lucida Console', monospace; } li.current a { background: #90ee85; } #donate { display: block; background: #ffffdc; border: 1px solid #faa700; padding: 1em; } #donate h1 { padding-top: 0; font-size: 16px; } #paypal { text-align: center; } footer { display: block; margin-top: 2em; padding: .5em 0 1.5em; border-top: 2px solid #c4c4c4; } #add-test { margin-right: .3em; } #bs-chart { overflow: auto; } #bs-chart-frame { height: 240px; width: 100%; } #bs-logo { margin: 0; } #bs-logo span, applet { position: absolute; left: -9999em; } #bs-logo a { display: block; width: 232px; height: 39px; filter: none; background: url(https://www.browserscope.org/static/img/logo.png) 0 0 no-repeat; } #bs-ua { padding: .5em .5em 0; color: #555; } #bs-results .bs-rt { font-size: 10pt; padding: .5em; background: #ddd; } #bs-results td { border: 1px solid #ddd; padding: .4em; white-space: nowrap; } #bs-results .rt-ua-cur { font-style: italic; font-weight: bold; } #bs-results .bs-rt-message { padding: 3em; text-align: center; font-weight: bold; color: #555; } #bs-results .google-visualization-table-tr-head td { white-space: normal; } #controls { margin-top: -3.35em; } #comments h1 { padding: 0; } #comments .meta img { position: absolute; left: 0; top: 0; margin: 0; } #comments .meta img { top: 2px; left: 2px; } #comments .meta { padding-left: 35px; margin-top: 0; width: 923px; line-height: 30px; } #comments .meta a { font-weight: bold; color: #555; } #comments article div { padding: 0 1em 0; } #comments article { display: block; border: 1px solid #b4b4b4; position: relative; margin-bottom: 1em; } /* needs its own rule (cannot be grouped with `tbody th`) because of buggy IE */ #comments article:target { background: #dde4ea; } #error-info.show, .meta strong, #firebug strong, #java strong, #status strong { background: pink; border: 1px solid #b00b00; padding: .4em; } #error-info.show { padding: .5em 1em; } #error-info, code, samp, var, textarea, #slug { font-family: Monaco, monospace; font-size: .9em; } #java strong { background: #ffffdc; border: 1px solid #faa700; } #slug { font-size: 1em; } #faq dt { margin-top: 1em; font-weight: bold; } #faq dt a { display: none; } #faq dt:hover a { display: inline; } #faq dt:target, #faq dt:target + dd { background: #90ee85; margin: 0 -.8em; padding: 0 .8em; } #faq dt:target + dd { padding-bottom: .5em; margin-bottom: -.5em; } #faq dt:target { margin-top: .5em; padding-top: .5em; } #firebug, #java, #status { margin: 0 0 1em; padding: .3em 0; } #prep-code pre { max-height: 500px; overflow: auto; } #controls.show, #firebug.show, #java.show { display: block; } .co1, .co2, .coMULTI { font-style: italic; } .error { color: #b00b00; } .imp { color: red; } .kw1, .kw3 { color: #006; } .kw2 { color: #036; } .co1, .coMULTI { color: #060; } .co2 { color: #096; } .es0 { color: #009; } .br0 { color: #090; } .sy0 { color: #393; } .st0 { color: #36c; } .nu0 { color: #c00; } .me1 { color: #606; } /* < 1051px */ @media (max-width: 1050px) { table pre, table td.code { width: 550px; } } /* < 1041px */ @media (max-width: 1040px) { body { margin: 0; border: 0; } body, #comments .meta { width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } } /* < 801px */ @media (max-width: 800px) { table pre, table td.code { width: 450px; } } /* < 681px */ @media (max-width: 680px) { table pre, table td.code { width: 350px; } } /* < 651px */ @media (max-width: 650px) { table pre, table td.code { width: 200px; } } benchmark.js-2.1.4/example/jsperf/ui.js000066400000000000000000000475271306651343200200040ustar00rootroot00000000000000/*! * ui.js * Copyright Mathias Bynens * Modified by John-David Dalton * Available under MIT license */ (function(window, document) { /** Cache of error messages */ var errors = []; /** Google Analytics account id */ var gaId = ''; /** Cache of event handlers */ var handlers = {}; /** A flag to indicate that the page has loaded */ var pageLoaded = false; /** Benchmark results element id prefix (e.g. `results-1`) */ var prefix = 'results-'; /** The element responsible for scrolling the page (assumes ui.js is just before ) */ var scrollEl = document.body; /** Used to resolve a value's internal [[Class]] */ var toString = {}.toString; /** Namespace */ var ui = new Benchmark.Suite; /** Object containing various CSS class names */ var classNames = { // used for error styles 'error': 'error', // used to make content visible 'show': 'show', // used to reset result styles 'results': 'results' }; /** Used to flag environments/features */ var has = { // used for pre-populating form fields 'localStorage': !!function() { try { return !localStorage.getItem(+new Date); } catch(e) {} }(), // used to distinguish between a regular test page and an embedded chart 'runner': !!$('runner') }; /** Object containing various text messages */ var texts = { // inner text for the various run button states 'run': { 'again': 'Run again', 'ready': 'Run tests', 'running': 'Stop running' }, // common status values 'status': { 'again': 'Done. Ready to run again.', 'ready': 'Ready to run.' } }; /** The options object for Benchmark.Suite#run */ var runOptions = { 'async': true, 'queued': true }; /** API shortcuts */ var filter = Benchmark.filter, formatNumber = Benchmark.formatNumber, join = Benchmark.join; /*--------------------------------------------------------------------------*/ handlers.benchmark = { /** * The onCycle callback, used for onStart as well, assigned to new benchmarks. * * @private */ 'cycle': function() { var bench = this, size = bench.stats.sample.length; if (!bench.aborted) { setStatus(bench.name + ' × ' + formatNumber(bench.count) + ' (' + size + ' sample' + (size == 1 ? '' : 's') + ')'); } }, /** * The onStart callback assigned to new benchmarks. * * @private */ 'start': function() { // call user provided init() function if (isFunction(window.init)) { init(); } } }; handlers.button = { /** * The "run" button click event handler used to run or abort the benchmarks. * * @private */ 'run': function() { var stopped = !ui.running; ui.abort(); ui.length = 0; if (stopped) { logError({ 'clear': true }); ui.push.apply(ui, _.filter(ui.benchmarks, function(bench) { return !bench.error && bench.reset(); })); ui.run(runOptions); } } }; handlers.title = { /** * The title table cell click event handler used to run the corresponding benchmark. * * @private * @param {Object} event The event object. */ 'click': function(event) { event || (event = window.event); var id, index, target = event.target || event.srcElement; while (target && !(id = target.id)) { target = target.parentNode; } index = id && --id.split('-')[1] || 0; ui.push(ui.benchmarks[index].reset()); ui.running ? ui.render(index) : ui.run(runOptions); }, /** * The title cell keyup event handler used to simulate a mouse click when hitting the ENTER key. * * @private * @param {Object} event The event object. */ 'keyup': function(event) { if (13 == (event || window.event).keyCode) { handlers.title.click(event); } } }; handlers.window = { /** * The window hashchange event handler supported by Chrome 5+, Firefox 3.6+, and IE8+. * * @private */ 'hashchange': function() { ui.parseHash(); var scrollTop, params = ui.params, chart = params.chart, filterBy = params.filterby; if (pageLoaded) { // configure browserscope ui.browserscope.postable = has.runner && !('nopost' in params); // configure chart renderer if (chart || filterBy) { scrollTop = $('results').offsetTop; ui.browserscope.render({ 'chart': chart, 'filterBy': filterBy }); } if (has.runner) { // call user provided init() function if (isFunction(window.init)) { init(); } // auto-run if ('run' in params) { scrollTop = $('runner').offsetTop; setTimeout(handlers.button.run, 1); } // scroll to the relevant section if (scrollTop) { scrollEl.scrollTop = scrollTop; } } } }, /** * The window load event handler used to initialize the UI. * * @private */ 'load': function() { // only for pages with a comment form if (has.runner) { // init the ui addClass('controls', classNames.show); addListener('run', 'click', handlers.button.run); setHTML('run', texts.run.ready); setStatus(texts.status.ready); // prefill author details if (has.localStorage) { _.each([$('author'), $('author-email'), $('author-url')], function(element) { element.value = localStorage[element.id] || ''; element.oninput = element.onkeydown = function(event) { event && event.type < 'k' && (element.onkeydown = null); localStorage[element.id] = element.value; }; }); } // show warning when Firebug is enabled (avoids showing for Firebug Lite) try { // Firebug 1.9 no longer has `console.firebug` if (console.firebug || /firebug/i.test(console.table())) { addClass('firebug', classNames.show); } } catch(e) {} } // clear length so tests can be manually queued ui.length = 0; // evaluate hash values after all other "load" events have fired _.defer(function() { pageLoaded = true; handlers.window.hashchange(); }); } }; /*--------------------------------------------------------------------------*/ /** * Shortcut for document.getElementById(). * * @private * @param {Element|string} id The id of the element to retrieve. * @returns {Element} The element, if found, or null. */ function $(id) { return typeof id == 'string' ? document.getElementById(id) : id; } /** * Adds a CSS class name to an element's className property. * * @private * @param {Element|string} element The element or id of the element. * @param {string} className The class name. * @returns {Element} The element. */ function addClass(element, className) { if ((element = $(element)) && !hasClass(element, className)) { element.className += (element.className ? ' ' : '') + className; } return element; } /** * Registers an event listener on an element. * * @private * @param {Element|string} element The element or id of the element. * @param {string} eventName The name of the event. * @param {Function} handler The event handler. * @returns {Element} The element. */ function addListener(element, eventName, handler) { if ((element = $(element))) { if (typeof element.addEventListener != 'undefined') { element.addEventListener(eventName, handler, false); } else if (typeof element.attachEvent != 'undefined') { element.attachEvent('on' + eventName, handler); } } return element; } /** * Appends to an element's innerHTML property. * * @private * @param {Element|string} element The element or id of the element. * @param {string} html The HTML to append. * @returns {Element} The element. */ function appendHTML(element, html) { if ((element = $(element)) && html != null) { element.innerHTML += html; } return element; } /** * Shortcut for document.createElement(). * * @private * @param {string} tag The tag name of the element to create. * @returns {Element} A new element of the given tag name. */ function createElement(tagName) { return document.createElement(tagName); } /** * Checks if an element is assigned the given class name. * * @private * @param {Element|string} element The element or id of the element. * @param {string} className The class name. * @returns {boolean} If assigned the class name return true, else false. */ function hasClass(element, className) { return !!(element = $(element)) && (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1; } /** * Set an element's innerHTML property. * * @private * @param {Element|string} element The element or id of the element. * @param {string} html The HTML to set. * @returns {Element} The element. */ function setHTML(element, html) { if ((element = $(element))) { element.innerHTML = html == null ? '' : html; } return element; } /*--------------------------------------------------------------------------*/ /** * Gets the Hz, i.e. operations per second, of `bench` adjusted for the * margin of error. * * @private * @param {Object} bench The benchmark object. * @returns {number} Returns the adjusted Hz. */ function getHz(bench) { return 1 / (bench.stats.mean + bench.stats.moe); } /** * Checks if a value has an internal [[Class]] of Function. * * @private * @param {Mixed} value The value to check. * @returns {boolean} Returns `true` if the value is a function, else `false`. */ function isFunction(value) { return toString.call(value) == '[object Function]'; } /** * Appends to or clears the error log. * * @private * @param {string|Object} text The text to append or options object. */ function logError(text) { var table, div = $('error-info'), options = {}; // juggle arguments if (typeof text == 'object' && text) { options = text; text = options.text; } else if (arguments.length) { options.text = text; } if (!div) { table = $('test-table'); div = createElement('div'); div.id = 'error-info'; table.parentNode.insertBefore(div, table.nextSibling); } if (options.clear) { div.className = div.innerHTML = ''; errors.length = 0; } if ('text' in options && _.indexOf(errors, text) < 0) { errors.push(text); addClass(div, classNames.show); appendHTML(div, text); } } /** * Sets the status text. * * @private * @param {string} text The text to write to the status. */ function setStatus(text) { setHTML('status', text); } /*--------------------------------------------------------------------------*/ /** * Parses the window.location.hash value into an object assigned to `ui.params`. * * @static * @memberOf ui * @returns {Object} The suite instance. */ function parseHash() { var me = this, hashes = location.hash.slice(1).split('&'), params = me.params || (me.params = {}); // remove old params _.forOwn(params, function(value, key) { delete params[key]; }); // add new params _.each(hashes[0] && hashes, function(value) { value = value.split('='); params[value[0].toLowerCase()] = (value[1] || '').toLowerCase(); }); return me; } /** * Renders the results table cell of the corresponding benchmark(s). * * @static * @memberOf ui * @param {number} [index] The index of the benchmark to render. * @returns {Object} The suite instance. */ function render(index) { _.each(index == null ? (index = 0, ui.benchmarks) : [ui.benchmarks[index]], function(bench) { var parsed, cell = $(prefix + (++index)), error = bench.error, hz = bench.hz; // reset title and class cell.title = ''; cell.className = classNames.results; // status: error if (error) { setHTML(cell, 'Error'); addClass(cell, classNames.error); parsed = join(error, '
  • '); logError('

    ' + error + '.

    ' + (parsed ? '
    • ' + parsed + '
    ' : '')); } else { // status: running if (bench.running) { setHTML(cell, 'running…'); } // status: completed else if (bench.cycles) { // obscure details until the suite has completed if (ui.running) { setHTML(cell, 'completed'); } else { cell.title = 'Ran ' + formatNumber(bench.count) + ' times in ' + bench.times.cycle.toFixed(3) + ' seconds.'; setHTML(cell, formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ±' + bench.stats.rme.toFixed(2) + '%'); } } else { // status: pending if (ui.running && ui.indexOf(bench) > -1) { setHTML(cell, 'pending…'); } // status: ready else { setHTML(cell, 'ready'); } } } }); return ui; } /*--------------------------------------------------------------------------*/ ui.on('add', function(event) { var bench = event.target, index = ui.benchmarks.length, id = index + 1, title = $('title-' + id); ui.benchmarks.push(bench); if (has.runner) { title.tabIndex = 0; title.title = 'Click to run this test again.'; addListener(title, 'click', handlers.title.click); addListener(title, 'keyup', handlers.title.keyup); bench.on('start', handlers.benchmark.start); bench.on('start cycle', handlers.benchmark.cycle); ui.render(index); } }) .on('start cycle', function() { ui.render(); setHTML('run', texts.run.running); }) .on('complete', function() { var benches = filter(ui.benchmarks, 'successful'), fastest = filter(benches, 'fastest'), slowest = filter(benches, 'slowest'); ui.render(); setHTML('run', texts.run.again); setStatus(texts.status.again); // highlight result cells _.each(benches, function(bench) { var cell = $(prefix + (_.indexOf(ui.benchmarks, bench) + 1)), fastestHz = getHz(fastest[0]), hz = getHz(bench), percent = (1 - (hz / fastestHz)) * 100, span = cell.getElementsByTagName('span')[0], text = 'fastest'; if (_.indexOf(fastest, bench) > -1) { // mark fastest addClass(cell, text); } else { text = isFinite(hz) ? formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + '% slower' : ''; // mark slowest if (_.indexOf(slowest, bench) > -1) { addClass(cell, 'slowest'); } } // write ranking if (span) { setHTML(span, text); } else { appendHTML(cell, '' + text + ''); } }); ui.browserscope.post(); }); /*--------------------------------------------------------------------------*/ /** * An array of benchmarks created from test cases. * * @memberOf ui * @type Array */ ui.benchmarks = []; /** * The parsed query parameters of the pages url hash. * * @memberOf ui * @type Object */ ui.params = {}; // parse query params into ui.params hash ui.parseHash = parseHash; // (re)render the results of one or more benchmarks ui.render = render; /*--------------------------------------------------------------------------*/ // expose window.ui = ui; // don't let users alert, confirm, prompt, or open new windows window.alert = window.confirm = window.prompt = window.open = function() {}; // parse hash query params when it changes addListener(window, 'hashchange', handlers.window.hashchange); // bootstrap onload addListener(window, 'load', handlers.window.load); // parse location hash string ui.parseHash(); // provide a simple UI for toggling between chart types and filtering results // (assumes ui.js is just before ) (function() { var sibling = $('bs-results'), p = createElement('p'); p.innerHTML = 'Chart type: bar, ' + 'column, line, pie, ' + 'table
    ' + 'Filter: popular, ' + 'all, desktop, family, ' + 'major, minor, mobile, ' + 'prerelease'; sibling.parentNode.insertBefore(p, sibling); // use DOM0 event handler to simplify canceling the default action $('charts').onclick = $('filters').onclick = function(event) { event || (event = window.event); var target = event.target || event.srcElement; if (target.href || (target = target.parentNode).href) { ui.browserscope.render( target.parentNode.id == 'charts' ? { 'chart': target.innerHTML } : { 'filterBy': target.innerHTML } ); } // cancel the default action return false; }; }()); /*--------------------------------------------------------------------------*/ // fork for runner or embedded chart if (has.runner) { // detect the scroll element (function() { var scrollTop, div = document.createElement('div'), body = document.body, bodyStyle = body.style, bodyHeight = bodyStyle.height, html = document.documentElement, htmlStyle = html.style, htmlHeight = htmlStyle.height; bodyStyle.height = htmlStyle.height = 'auto'; div.style.cssText = 'display:block;height:9001px;'; body.insertBefore(div, body.firstChild); scrollTop = html.scrollTop; // set `scrollEl` that's used in `handlers.window.hashchange()` if (html.clientWidth !== 0 && ++html.scrollTop && html.scrollTop == scrollTop + 1) { scrollEl = html; } body.removeChild(div); bodyStyle.height = bodyHeight; htmlStyle.height = htmlHeight; html.scrollTop = scrollTop; }()); // catch and display errors from the "preparation code" window.onerror = function(message, fileName, lineNumber) { logError('

    ' + message + '.

    • ' + join({ 'message': message, 'fileName': fileName, 'lineNumber': lineNumber }, '
    • ') + '
    '); scrollEl.scrollTop = $('error-info').offsetTop; }; } else { // short circuit unusable methods ui.render = function() {}; ui.off('start cycle complete'); setTimeout(function() { ui.off(); ui.browserscope.post = function() {}; _.invokeMap(ui.benchmarks, 'off'); }, 1); } /*--------------------------------------------------------------------------*/ // optimized asynchronous Google Analytics snippet based on // https://mathiasbynens.be/notes/async-analytics-snippet if (gaId) { (function() { var script = createElement('script'), sibling = document.getElementsByTagName('script')[0]; window._gaq = [['_setAccount', gaId], ['_trackPageview']]; script.src = 'https://www.google-analytics.com/ga.js'; sibling.parentNode.insertBefore(script, sibling); }()); } }(this, document)); benchmark.js-2.1.4/index.js000077500000000000000000000000501306651343200155310ustar00rootroot00000000000000module.exports = require('./benchmark');benchmark.js-2.1.4/package.json000066400000000000000000000024101306651343200163510ustar00rootroot00000000000000{ "name": "benchmark", "version": "2.1.4", "description": "A benchmarking library that supports high-resolution timers & returns statistically significant results.", "homepage": "https://benchmarkjs.com/", "license": "MIT", "main": "benchmark.js", "keywords": "benchmark, performance, speed", "author": "Mathias Bynens (https://mathiasbynens.be/)", "contributors": [ "Mathias Bynens (https://mathiasbynens.be/)", "John-David Dalton (http://allyoucanleet.com/)", "Kit Cambridge (http://kitcambridge.be/)" ], "repository": "bestiejs/benchmark.js", "scripts": { "doc": "docdown benchmark.js doc/README.md style=github title=\"Benchmark.js v${npm_package_version}\" toc=categories url=https://github.com/bestiejs/benchmark.js/blob/${npm_package_version}/benchmark.js", "test": "node test/test" }, "dependencies": { "lodash": "^4.17.4", "platform": "^1.3.3" }, "devDependencies": { "coveralls": "^2.12.0", "docdown": "~0.7.2", "istanbul": "0.4.5", "qunit-extras": "^3.0.0", "qunitjs": "^2.2.1", "requirejs": "^2.3.3" }, "files": [ "benchmark.js" ] } benchmark.js-2.1.4/plugin/000077500000000000000000000000001306651343200153645ustar00rootroot00000000000000benchmark.js-2.1.4/plugin/ui.browserscope.js000066400000000000000000001041541306651343200210600ustar00rootroot00000000000000(function(window, document) { /** Cache used by various methods */ var cache = { 'counter': 0, 'lastAction': 'load', 'lastChart': 'bar', 'lastFilterBy': 'all', 'responses': { /* 'all': null, 'desktop': null, 'major': null, ... */ }, 'timers': { /* 'load': null, 'post': null, ... */ } }; /** * Used to filter Browserscope results by browser category. * * @see https://www.browserscope.org/user/tests/howto#urlparams */ var filterMap = { 'all': 3, 'desktop': 'top-d', 'family': 0, 'major': 1, 'minor': 2, 'mobile': 'top-m', 'popular': 'top', 'prerelease': 'top-d-e' }; /** * The doctype used in the creation of iframes so Browserscope * detects the correct IE compat mode. */ var doctype = /css/i.test(document.compatMode) ? '' : ''; /** * The `uaToken` is prepended to the value of the data cell of the Google * visualization data table object that matches the user's browser name. After * the chart is rendered the element containing the `uaToken` is assigned the * `ui.browserscope.uaClass` class name to allow for the creation of a visual * indicator to help the user more easily find their browser's results. */ var uaToken = '\u2028'; /** Math shortcuts */ var floor = Math.floor, max = Math.max, min = Math.min; /** Utility shortcuts */ var filter = Benchmark.filter, formatNumber = Benchmark.formatNumber; /*--------------------------------------------------------------------------*/ /** * Registers an event listener. * * @private * @param {Element} element The element. * @param {string} eventName The name of the event to listen to. * @param {Function} handler The event handler. * @returns {Element} The element. */ function addListener(element, eventName, handler) { if ((element = typeof element == 'string' ? query(element)[0] : element)) { if (typeof element.addEventListener != 'undefined') { element.addEventListener(eventName, handler, false); } else if (typeof element.attachEvent != 'undefined') { element.attachEvent('on' + eventName, handler); } } return element; } /** * Shortcut for `document.createElement()`. * * @private * @param {string} tagName The tag name of the element to create. * @param {string} name A name to assign to the element. * @param {Document|Element} context The document object used to create the element. * @returns {Element} Returns a new element. */ function createElement(tagName, name, context) { var result; name && name.nodeType && (context = name, name = ''); context = context ? context.ownerDocument || context : document; name || (name = ''); try { // set name attribute for IE6/7 result = context.createElement('<' + tagName + ' name="' + name + '">'); } catch(e) { (result = context.createElement(tagName)).name = name; } return result; } /** * Creates a new style element. * * @private * @param {string} cssText The css text of the style element. * @param {Document|Element} context The document object used to create the element. * @returns {Element} Returns the new style element. */ function createStyleSheet(cssText, context) { // use a text node, "x", to work around innerHTML issues with style elements // https://msdn.microsoft.com/en-us/library/ms533897.aspx var div = createElement('div', context); div.innerHTML = 'x'; return div.lastChild; } /** * Gets the text content of an element. * * @private * @param {Element} element The element. * @param {Document|Element} context The element whose descendants are queried. * @returns {string} The text content of the element. */ function getText(element, context) { element = query(element, context)[0]; return element && (element.textContent || element.innerText) || ''; } /** * Injects a script into the document. * * @private * @param {string} src The external script source. * @param {Object} sibling The element to inject the script after. * @param {Document} context The document object used to create the script element. * @returns {Object} The new script element. */ function loadScript(src, sibling, context) { if (sibling) { context = sibling.ownerDocument; if (!context) { context = sibling; sibling = query('script', context).pop(); } } if (!sibling) { sibling = query('*', context).pop(); } var script = createElement('script', context); script.src = src; return sibling.parentNode.insertBefore(script, sibling.nextSibling); } /** * Queries the document for elements by id or tagName. * * @private * @param {string} selector The css selector to match. * @param {Document|Element} context The element whose descendants are queried. * @returns {Array} The array of results. */ function query(selector, context) { var result = []; selector || (selector = ''); context = typeof context == 'string' ? query(context)[0] : context || document; if (selector.nodeType) { result = [selector]; } else if (context) { _.each(selector.split(','), function(selector) { _.each(/^#/.test(selector) ? [context.getElementById(selector.slice(1))] : context.getElementsByTagName(selector), function(node) { result.push(node); }); }); } return result; } /** * Set an element's innerHTML property. * * @private * @param {Element} element The element. * @param {string} html The HTML to set. * @param {Object} object The template object used to modify the html. * @returns {Element} The element. */ function setHTML(element, html, object) { if ((element = query(element)[0])) { element.innerHTML = _.template(html)(object || {}); } return element; } /** * Displays a message in the "results" element. * * @private * @param {string} text The text to display. * @param {Object} object The template object used to modify the text. */ function setMessage(text, object) { var me = ui.browserscope, cont = me.container; if (cont) { cont.className = 'bs-rt-message'; setHTML(cont, text, object); } } /*--------------------------------------------------------------------------*/ /** * Adds a style sheet to the current chart and assigns the `ui.browserscope.uaClass` * class name to the chart element containing the user's browser name. * * @private * @returns {boolean} Returns `true` if the operation succeeded, else `false`. */ function addChartStyle() { var me = ui.browserscope, cssText = [], uaClass = me.uaClass; var win = me.chartWindow, doc = win.document, iframe = query('iframe', me.container)[0]; // the chart container may be an iframe in older browsers var chartContainer = iframe ? win.frames[iframe.name].document : query('#bs-chart', doc)[0]; var chartNodes = query('text,textpath', chartContainer), context = iframe ? chartContainer : doc, result = false; if (iframe && chartNodes.length) { // extract CSS rules for `uaClass` _.each(query('link,style', doc), function(node) { // avoid access denied errors on external style sheets // outside the same origin policy try { var sheet = node.sheet || node.styleSheet; _.each(sheet.cssRules || sheet.rules, function(rule) { if ((rule.selectorText || rule.cssText).indexOf('.' + uaClass) > -1) { cssText.push(rule.style && rule.style.cssText || /[^{}]*(?=})/.exec(rule.cssText) || ''); } }); } catch(e) {} }); // insert custom style sheet query('head', context)[0].appendChild( createStyleSheet('.' + uaClass + '{' + cssText.join(';') + '}', context)); } // scan chart elements for a match _.some(chartNodes, function(node) { var nextSibling; if ((node.string || getText(node)).charAt(0) != uaToken) { return false; } // for VML if (node.string) { // IE requires reinserting the element to render correctly node.className = uaClass; nextSibling = node.nextSibling; node.parentNode.insertBefore(node.removeNode(), nextSibling); } // for SVG else { node.setAttribute('class', uaClass); } return (result = true); }); return result; } /** * A simple data object cloning utility. * * @private * @param {Mixed} data The data object to clone. * @returns {Mixed} The cloned data object. */ function cloneData(data) { var fn, ctor, result = data; if (_.isArray(data)) { result = _.map(data, cloneData); } else if (data === Object(data)) { ctor = data.constructor; result = ctor == Object ? {} : (fn = function(){}, fn.prototype = ctor.prototype, new fn); _.forOwn(data, function(value, key) { result[key] = cloneData(value); }); } return result; } /** * Creates a Browserscope results object. * * @private * @returns {Object|null} Browserscope results object or null. */ function createSnapshot() { // clone benches, exclude those that are errored, unrun, or have hz of Infinity var benches = _.invokeMap(filter(ui.benchmarks, 'successful'), 'clone'), fastest = filter(benches, 'fastest'), slowest = filter(benches, 'slowest'); var neither = _.filter(benches, function(bench) { return _.indexOf(fastest, bench) + _.indexOf(slowest, bench) == -2; }); function merge(destination, source) { destination.count = source.count; destination.cycles = source.cycles; destination.hz = source.hz; destination.stats = _.extend({}, source.stats); } // normalize results on slowest in each category _.each(fastest.concat(slowest), function(bench) { merge(bench, _.indexOf(fastest, bench) > -1 ? fastest[fastest.length - 1] : slowest[0]); }); // sort slowest to fastest // (a larger `mean` indicates a slower benchmark) neither.sort(function(a, b) { a = a.stats; b = b.stats; return (a.mean + a.moe > b.mean + b.moe) ? -1 : 1; }); // normalize the leftover benchmarks _.reduce(neither, function(prev, bench) { // if the previous slower benchmark is indistinguishable from // the current then use the previous benchmark's values if (prev.compare(bench) == 0) { merge(bench, prev); } return bench; }); // append benchmark ids for duplicate names or names with no alphanumeric/space characters // and use the upper limit of the confidence interval to compute a lower hz // to avoid recording inflated results caused by a high margin or error return _.reduce(benches, function(result, bench, key) { var stats = bench.stats; result || (result = {}); key = toLabel(bench.name); result[key && !_.has(result, key) ? key : key + bench.id ] = floor(1 / (stats.mean + stats.moe)); return result; }, null); } /** * Retrieves the "cells" array from a given Google visualization data row object. * * @private * @param {Object} object The data row object. * @returns {Array} An array of cell objects. */ function getDataCells(object) { // resolve cells by duck typing because of munged property names var result = []; _.forOwn(object, function(value) { return !(_.isArray(value) && (result = value)); }); // remove empty entries which occur when not all the tests are recorded return _.compact(result); } /** * Retrieves the "labels" array from a given Google visualization data table object. * * @private * @param {Object} object The data table object. * @returns {Array} An array of label objects. */ function getDataLabels(object) { var result = [], labelMap = {}; // resolve labels by duck typing because of munged property names _.forOwn(object, function(value) { return !(_.isArray(value) && 0 in value && 'type' in value[0] && (result = value)); }); // create a data map of labels to names _.each(ui.benchmarks, function(bench) { var key = toLabel(bench.name); labelMap[key && !_.has(labelMap, key) ? key : key + bench.id ] = bench.name; }); // replace Browserscope's basic labels with benchmark names return _.each(result, function(cell) { var name = labelMap[cell.label]; name && (cell.label = name); }); } /** * Retrieves the "rows" array from a given Google visualization data table object. * * @private * @param {Object} object The data table object. * @returns {Array} An array of row objects. */ function getDataRows(object) { var name, me = ui.browserscope, filterBy = cache.lastFilterBy, bsUa = query('#bs-ua', me.chartWindow.document)[0], browserName = toBrowserName(getText(query('strong', bsUa)[0]), filterBy), uaClass = me.uaClass, result = []; // resolve rows by duck typing because of munged property names _.forOwn(object, function(value, key) { return !(_.isArray(value) && 0 in value && !('type' in value[0]) && (name = key, result = value)); }); // remove empty rows and set the `p.className` on the browser // name cell that matches the user's browser name if (result.length) { result = object[name] = _.filter(result, function(value) { var cells = getDataCells(value), first = cells[0], second = cells[1]; // cells[0] is the browser name cell so instead we check cells[1] // for the presence of ops/sec data to determine if a row is empty or not if (first && second && second.f) { delete first.p.className; if (browserName == toBrowserName(first.f, filterBy)) { first.p.className = uaClass; } return true; } }); } return result; } /** * Executes a callback at a given delay interval until it returns `false`. * * @private * @param {Function} callback The function called every poll interval. * @param {number} delay The delay between callback calls (secs). */ function poll(callback, delay) { function poller(init) { if (init || callback() !== false) { setTimeout(poller, delay * 1e3); } } poller(true); } /** * Cleans up the last action and sets the current action. * * @private * @param {string} action The current action. */ function setAction(action) { clearTimeout(cache.timers[cache.lastAction]); cache.lastAction = action; } /** * Converts the browser name version number to the format allowed by the * specified filter. * * @private * @param {string} name The full browser name . * @param {string} filterBy The filter formating rules to apply. * @returns {string} The converted browser name. */ function toBrowserName(name, filterBy) { name || (name = ''); if (filterBy == 'all') { // truncate something like 1.0.0 to 1 name = name.replace(/(\d+)[.0]+$/, '$1'); } else if (filterBy == 'family') { // truncate something like XYZ 1.2 to XYZ name = name.replace(/[.\d\s]+$/, ''); } else if (/minor|popular/.test(filterBy) && /\d+(?:\.[1-9])+$/.test(name)) { // truncate something like 1.2.3 to 1.2 name = name.replace(/(\d+\.[1-9])(\.[.\d]+$)/, '$1'); } else { // truncate something like 1.0 to 1 or 1.2.3 to 1 but leave something like 1.2 alone name = name.replace(/(\d+)(?:(\.[1-9]$)|(\.[.\d]+$))/, '$1$2'); } return name; } /** * Replaces non-alphanumeric characters with spaces because Browserscope labels * can only contain alphanumeric characters and spaces. * * @private * @param {string} text The text to be converted. * @returns {string} The Browserscope safe label text. * @see https://code.google.com/p/browserscope/issues/detail?id=271 */ function toLabel(text) { return (text || '').replace(/[^a-z0-9]+/gi, ' '); } /** * Updates the `ui.browserscope.chartFrame` height based on the height of its content. * * @private */ function updateChartFrameHeight() { var me = ui.browserscope, doc = me.chartWindow.document, docEl = doc.documentElement, body = doc.body; me.chartFrame.style.height = max( docEl.clientHeight, docEl.offsetHeight, body.offsetHeight, docEl.scrollHeight, body.scrollHeight ) + 'px'; } /*--------------------------------------------------------------------------*/ /** * Loads Browserscope's cumulative results table. * * @static * @memberOf ui.browserscope * @param {Object} options The options object. */ function load(options) { options || (options = {}); var fired, me = ui.browserscope, cont = me.container, filterBy = cache.lastFilterBy = options.filterBy || cache.lastFilterBy, google = me.chartWindow.google, responses = cache.responses, response = cache.responses[filterBy], visualization = google && google.visualization; function onComplete(response) { var lastResponse = responses[filterBy]; if (!fired) { // set the fired flag to avoid Google's own timeout fired = true; // render if the filter is still the same, else cache the result if (filterBy == cache.lastFilterBy) { me.render({ 'force': true, 'response': lastResponse || response }); } else if(!lastResponse && response && !response.isError()) { responses[filterBy] = response; } } } // set last action in case the load fails and a retry is needed setAction('load'); if (!cont || !visualization || !visualization.Query || response) { // exit early if there is no container element or the response is cached // and retry if the visualization library hasn't loaded yet setMessage(''); cont && onComplete(response); } else if (!ui.running) { // set our own load timeout to display an error message and retry loading cache.timers.load = setTimeout(onComplete, me.timings.timeout * 1e3); // set "loading" message and attempt to load Browserscope data setMessage(me.texts.loading); // request Browserscope chart data and pass it to `google.visualization.Query.setResponse()` (new visualization.Query( 'https://www.browserscope.org/gviz_table_data?category=usertest_' + me.key + '&v=' + filterMap[filterBy], { 'sendMethod': 'scriptInjection' } )) .send(onComplete); } } /** * Creates a Browserscope beacon and posts the benchmark results. * * @static * @memberOf ui.browserscope */ function post() { var me = ui.browserscope, key = me.key, snapshot = createSnapshot(); // set last action in case the post fails and a retry is needed setAction('post'); if (key && snapshot && me.postable && !ui.running && !/Simulator/i.test(Benchmark.platform)) { var win = me.chartWindow, doc = win.document, name = 'browserscope-' + cache.counter++, iframe = createElement('iframe', name, doc); // create new beacon doc.body.appendChild(iframe); iframe.style.display = 'none'; // expose results snapshot me.snapshot = snapshot; // set "posting" message and attempt to post the results snapshot setMessage(me.texts.post); // Note: We originally created an iframe to avoid Browserscope's old limit // of one beacon per page load. It's currently used to implement custom // request timeout and retry routines. var idoc = win.frames[name].document; idoc.write(_.template( '${doctype} benchmark.js-2.1.4/test/run-test.sh000066400000000000000000000002361306651343200171630ustar00rootroot00000000000000cd "$(dirname "$0")" for cmd in phantomjs node; do echo "Testing in $cmd..." $cmd test.js echo "" done echo "Testing in a browser..." open index.html benchmark.js-2.1.4/test/test.js000066400000000000000000001154441306651343200163730ustar00rootroot00000000000000;(function() { /** Used as a safe reference for `undefined` in pre ES5 environments. */ var undefined; /** Used as a reference to the global object. */ var root = (typeof global == 'object' && global) || this; /** Method and object shortcuts. */ var phantom = root.phantom, amd = root.define && define.amd, document = !phantom && root.document, slice = Array.prototype.slice; /** Load libraries. */ var _ = root._ || require('lodash'), Benchmark = root.Benchmark || require('../benchmark.js'), QUnit = root.QUnit || require('qunit-extras'); /** Used to create dummy benchmarks for comparisons. */ var benchData = { 'hz': 1000, 'count': 10, 'cycles': 1, 'stats': { 'deviation': 0, 'mean': 1, 'moe': 0, 'rme': 0, 'sample': [1, 1, 1, 1, 1], 'sem': 0, 'variance': 0 } }; // Init Benchmark.options.minTime. Benchmark(function() { throw 0; }).run(); // Set a shorter max time. Benchmark.options.maxTime = Benchmark.options.minTime * 5; /*--------------------------------------------------------------------------*/ /** * Skips a given number of tests with a passing result. * * @private * @param {Object} assert The QUnit assert object. * @param {number} [count=1] The number of tests to skip. */ function skipTest(assert, count) { count || (count = 1); while (count--) { assert.ok(true, 'test skipped'); } } /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark'); (function() { QUnit.test('should support loading Benchmark.js as a module', function(assert) { if (amd) { assert.strictEqual((benchmarkModule || {}).version, Benchmark.version); } else { skipTest(assert); } }); QUnit.test('should support loading Platform.js as a module', function(assert) { if (amd) { var platform = (benchmarkModule || {}).platform || {}, name = platform.name; assert.ok(typeof name == 'string' || name === null); } else { skipTest(assert); } }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark constructor'); (function() { QUnit.test('should create a new instance when called without the `new` operator', function(assert) { assert.ok(Benchmark() instanceof Benchmark); }); QUnit.test('should support passing an options object', function(assert) { var bench = Benchmark({ 'name': 'foo', 'fn': function() {} }); assert.ok(bench.fn && bench.name == 'foo'); }); QUnit.test('should support passing a "name" and "fn" argument', function(assert) { var bench = Benchmark('foo', function() {}); assert.ok(bench.fn && bench.name == 'foo'); }); QUnit.test('should support passing a "name" argument and an options object', function(assert) { var bench = Benchmark('foo', { 'fn': function() {} }); assert.ok(bench.fn && bench.name == 'foo'); }); QUnit.test('should support passing a "name" argument and an options object', function(assert) { var bench = Benchmark('foo', function() {}, { 'id': 'bar' }); assert.ok(bench.fn && bench.name == 'foo' && bench.id == 'bar'); }); QUnit.test('should support passing an empty string for the "fn" options property', function(assert) { var bench = Benchmark({ 'fn': '' }).run(); assert.ok(!bench.error); }); QUnit.test('should detect dead code', function(assert) { var bench = Benchmark(function() {}).run(); assert.ok(/setup\(\)/.test(bench.compiled) ? !bench.error : bench.error); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark compilation'); (function() { QUnit.test('should compile using the default "toString" method', function(assert) { var bench = Benchmark({ 'setup': function() { var a = 1; }, 'fn': function() { throw a; }, 'teardown': function() { a = 2; } }).run(); var compiled = bench.compiled; if (/setup\(\)/.test(compiled)) { skipTest(assert); } else { assert.ok(/var a\s*=\s*1/.test(compiled) && /throw a/.test(compiled) && /a\s*=\s*2/.test(compiled)); } }); QUnit.test('should compile using a custom "toString" method', function(assert) { var bench = Benchmark({ 'setup': function() {}, 'fn': function() {}, 'teardown': function() {} }); bench.setup.toString = function() { return 'var a = 1;' }; bench.fn.toString = function() { return 'throw a;' }; bench.teardown.toString = function() { return 'a = 2;' }; bench.run(); var compiled = bench.compiled; if (/setup\(\)/.test(compiled)) { skipTest(assert); } else { assert.ok(/var a\s*=\s*1/.test(compiled) && /throw a/.test(compiled) && /a\s*=\s*2/.test(compiled)); } }); QUnit.test('should compile using a string value', function(assert) { var bench = Benchmark({ 'setup': 'var a = 1;', 'fn': 'throw a;', 'teardown': 'a = 2;' }).run(); var compiled = bench.compiled; if (/setup\(\)/.test(compiled)) { skipTest(assert); } else { assert.ok(/var a\s*=\s*1/.test(compiled) && /throw a/.test(compiled) && /a\s*=\s*2/.test(compiled)); } }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark test binding'); (function() { var count = 0; var tests = { 'inlined "setup", "fn", and "teardown"': ( 'if(/ops/.test(this))this._fn=true;' ), 'called "fn" and inlined "setup"/"teardown" reached by error': function() { count++; if (/ops/.test(this)) { this._fn = true; } }, 'called "fn" and inlined "setup"/"teardown" reached by `return` statement': function() { if (/ops/.test(this)) { this._fn = true; } return; } }; _.forOwn(tests, function(fn, title) { QUnit.test('should have correct binding for ' + title, function(assert) { var bench = Benchmark({ 'setup': 'if(/ops/.test(this))this._setup=true;', 'fn': fn, 'teardown': 'if(/ops/.test(this))this._teardown=true;', 'onCycle': function() { this.abort(); } }).run(); var compiled = bench.compiled; if (/setup\(\)/.test(compiled)) { skipTest(assert, 3); } else { assert.ok(bench._setup, 'correct binding for "setup"'); assert.ok(bench._fn, 'correct binding for "fn"'); assert.ok(bench._teardown, 'correct binding for "teardown"'); } }); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.filter'); (function() { var objects = { 'array': ['a', 'b', 'c', ''], 'array-like-object': { '0': 'a', '1': 'b', '2': 'c', '3': '', 'length': 4 } }; _.forOwn(objects, function(object, key) { QUnit.test('should providee the correct arguments when passing an ' + key, function(assert) { var args; Benchmark.filter(object, function() { args || (args = slice.call(arguments)); }); assert.deepEqual(args, ['a', 0, object]); }); QUnit.test('should return correct result when passing an ' + key, function(assert) { var actual = Benchmark.filter(object, function(value, index) { return index > 0; }); assert.deepEqual(actual, ['b', 'c', '']); }); }); QUnit.test('should correctly detect the fastest/slowest benchmark for small sample sizes', function(assert) { var data = _.cloneDeep(benchData), bench = Benchmark(data); var other = Benchmark(_.merge(data, { 'hz': 500, 'stats': { 'mean': 2, 'sample': [2, 2, 2, 2, 2] } })); var actual = Benchmark.filter([bench, other], 'fastest'); assert.deepEqual(actual, [bench], 'correctly detects the fastest'); actual = Benchmark.filter([bench, other], 'slowest'); assert.deepEqual(actual, [other], 'correctly detects the slowest'); }); QUnit.test('should correctly detect the fastest/slowest benchmark for large sample sizes', function(assert) { var data = _.cloneDeep(benchData); var bench = Benchmark(_.merge(data, { 'stats': { 'sample': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] } })); var other = Benchmark(_.merge(data, { 'hz': 500, 'stats': { 'mean': 2, 'sample': [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] } })); var actual = Benchmark.filter([bench, other], 'fastest'); assert.deepEqual(actual, [bench], 'correctly detects the fastest'); actual = Benchmark.filter([bench, other], 'slowest'); assert.deepEqual(actual, [other], 'correctly detects the slowest'); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.formatNumber'); (function() { QUnit.test('should format a million correctly', function(assert) { assert.strictEqual(Benchmark.formatNumber(1e6), '1,000,000'); }); QUnit.test('should format less than 100 correctly', function(assert) { assert.strictEqual(Benchmark.formatNumber(23), '23'); }); QUnit.test('should format numbers with decimal values correctly', function(assert) { assert.strictEqual(Benchmark.formatNumber(1234.56), '1,234.56'); }); QUnit.test('should format negative numbers correctly', function(assert) { assert.strictEqual(Benchmark.formatNumber(-1234.56), '-1,234.56'); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.invoke'); (function() { var objects = { 'array': ['a', ['b'], 'c', null], 'array-like-object': { '0': 'a', '1': ['b'], '2': 'c', '3': null, 'length': 4 } }; _.forOwn(objects, function(object, key) { QUnit.test('should return the correct result when passing an ' + key, function(assert) { var actual = Benchmark.invoke(object, 'concat'); assert.deepEqual(actual, ['a', ['b'], 'c', undefined]); }); QUnit.test('should provide the correct arguments to the invoked method when passing an ' + key, function(assert) { var actual = Benchmark.invoke(object, 'concat', 'x', 'y', 'z'); assert.deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined]); }); QUnit.test('should handle options object with callbacks correctly when passing an ' + key, function(assert) { function callback() { callbacks.push(slice.call(arguments)); } var callbacks = []; var actual = Benchmark.invoke(object, { 'name': 'concat', 'args': ['x', 'y', 'z'], 'onStart': callback, 'onCycle': callback, 'onComplete': callback }); assert.deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined]); assert.strictEqual(callbacks[0].length, 1); assert.strictEqual(callbacks[0][0].target, 'a'); assert.deepEqual(callbacks[0][0].currentTarget, object); assert.strictEqual(callbacks[0][0].type, 'start'); assert.strictEqual(callbacks[1][0].type, 'cycle'); assert.strictEqual(callbacks[5][0].type, 'complete'); }); QUnit.test('should support queuing when passing an ' + key, function(assert) { var lengths = []; var actual = Benchmark.invoke(object, { 'name': 'concat', 'queued': true, 'args': 'x', 'onCycle': function() { lengths.push(object.length); } }); assert.deepEqual(lengths, [4, 3, 2, 1]); assert.deepEqual(actual, ['ax', ['b', 'x'], 'cx', undefined]); }); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.join'); (function() { var objects = { 'array': ['a', 'b', ''], 'array-like-object': { '0': 'a', '1': 'b', '2': '', 'length': 3 }, 'object': { 'a': '0', 'b': '1', '': '2' } }; _.forOwn(objects, function(object, key) { QUnit.test('should join correctly using the default separator when passing an ' + key, function(assert) { assert.strictEqual(Benchmark.join(object), key == 'object' ? 'a: 0,b: 1,: 2' : 'a,b,'); }); QUnit.test('should join correctly using a custom separator when passing an ' + key, function(assert) { assert.strictEqual(Benchmark.join(object, '+', '@'), key == 'object' ? 'a@0+b@1+@2' : 'a+b+'); }); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark#clone'); (function() { var bench = Benchmark(function() { this.count += 0; }).run(); QUnit.test('should return the correct result passing no arguments', function(assert) { var clone = bench.clone(); assert.deepEqual(clone, bench); assert.ok(clone.stats != bench.stats && clone.times != bench.times && clone.options != bench.options); }); QUnit.test('should return the correct result passing a data object', function(assert) { var clone = bench.clone({ 'fn': '', 'name': 'foo' }); assert.ok(clone.fn === '' && clone.options.fn === ''); assert.ok(clone.name == 'foo' && clone.options.name == 'foo'); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark#compare'); (function() { QUnit.test('should return `0` when compared to itself', function(assert) { var bench = Benchmark(benchData); assert.strictEqual(bench.compare(bench), 0); }); QUnit.test('should correctly detect the faster benchmark for small sample sizes', function(assert) { var data = _.cloneDeep(benchData), bench = Benchmark(data); var other = Benchmark(_.merge(data, { 'hz': 500, 'stats': { 'mean': 2, 'sample': [2, 2, 2, 2, 2] } })); assert.strictEqual(bench.compare(other), 1); assert.strictEqual(other.compare(bench), -1); }); QUnit.test('should correctly detect the faster benchmark for large sample sizes', function(assert) { var data = _.cloneDeep(benchData); var bench = Benchmark(_.merge(data, { 'stats': { 'sample': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] } })); var other = Benchmark(_.merge(data, { 'hz': 500, 'stats': { 'mean': 2, 'sample': [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] } })); assert.strictEqual(bench.compare(other), 1); assert.strictEqual(other.compare(bench), -1); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark#reset'); (function() { QUnit.test('should not reset default event handlers', function(assert) { var handler = function() {}; Benchmark.options.onStart = handler; var bench = Benchmark(), clone = bench.clone({ 'events': { 'cycle': [function() {}] } }); clone.reset(); assert.deepEqual(clone.events, { 'start': [handler] }); delete Benchmark.options.onStart; }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark#run'); (function() { var data = { 'onComplete': 0, 'onCycle': 0, 'onStart': 0 }; var bench = Benchmark({ 'fn': function() { this.count += 0; }, 'onStart': function() { data.onStart++; }, 'onComplete': function() { data.onComplete++; } }) .run(); QUnit.test('should not trigger event handlers by internal benchmark clones', function(assert) { assert.strictEqual(data.onStart, 1); assert.strictEqual(data.onComplete, 1); }); }()); /*--------------------------------------------------------------------------*/ _.forOwn({ 'Benchmark': Benchmark, 'Benchmark.Suite': Benchmark.Suite }, function(Constructor, namespace) { QUnit.module(namespace + '#emit'); (function() { QUnit.test('should emit passed arguments', function(assert) { var args, object = Constructor(); object.on('args', function() { args = slice.call(arguments, 1); }); object.emit('args', 'a', 'b', 'c'); assert.deepEqual(args, ['a', 'b', 'c']); }); QUnit.test('should emit with no listeners', function(assert) { var event = Benchmark.Event('empty'), object = Constructor(); object.emit(event); assert.strictEqual(event.cancelled, false); }); QUnit.test('should emit with an event type of "toString"', function(assert) { var event = Benchmark.Event('toString'), object = Constructor(); object.emit(event); assert.strictEqual(event.cancelled, false); }); QUnit.test('should returns the last listeners returned value', function(assert) { var event = Benchmark.Event('result'), object = Constructor(); object.on('result', function() { return 'x'; }); object.on('result', function() { return 'y'; }); assert.strictEqual(object.emit(event), 'y'); }); QUnit.test('should abort the emitters listener iteration when `event.aborted` is `true`', function(assert) { var event = Benchmark.Event('aborted'), object = Constructor(); object.on('aborted', function(event) { event.aborted = true; return false; }); object.on('aborted', function(event) { // should not get here event.aborted = false; return true; }); assert.strictEqual(object.emit(event), false); assert.strictEqual(event.aborted, true); }); QUnit.test('should cancel the event if a listener explicitly returns `false`', function(assert) { var event = Benchmark.Event('cancel'), object = Constructor(); object.on('cancel', function() { return false; }); object.on('cancel', function() { return true; }); object.emit(event); assert.strictEqual(event.cancelled, true); }); QUnit.test('should use a shallow clone of the listeners when emitting', function(assert) { var event, listener2 = function(eventObject) { eventObject.listener2 = true }, object = Constructor(); object.on('shallowclone', function(eventObject) { event = eventObject; object.off(event.type, listener2); }) .on('shallowclone', listener2) .emit('shallowclone'); assert.ok(event.listener2); }); QUnit.test('should emit a custom event object', function(assert) { var event = Benchmark.Event('custom'), object = Constructor(); object.on('custom', function(eventObject) { eventObject.touched = true; }); object.emit(event); assert.ok(event.touched); }); QUnit.test('should set `event.result` correctly', function(assert) { var event = Benchmark.Event('result'), object = Constructor(); object.on('result', function() { return 'x'; }); object.emit(event); assert.strictEqual(event.result, 'x'); }); QUnit.test('should correctly set `event.type`', function(assert) { var event, object = Constructor(); object.on('type', function(eventObj) { event = eventObj; }); object.emit('type'); assert.strictEqual(event.type, 'type'); }); }()); /*------------------------------------------------------------------------*/ QUnit.module(namespace + '#listeners'); (function() { QUnit.test('should return the correct listeners', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); assert.deepEqual(object.listeners('x'), [listener]); }); QUnit.test('should return an array and initializes previously uninitialized listeners', function(assert) { var object = Constructor(); assert.deepEqual(object.listeners('x'), []); assert.deepEqual(object.events, { 'x': [] }); }); }()); /*------------------------------------------------------------------------*/ QUnit.module(namespace + '#off'); (function() { QUnit.test('should return the benchmark', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); assert.strictEqual(object.off('x', listener), object); }); QUnit.test('should ignore inherited properties of the event cache', function(assert) { var Dummy = function() {}, listener = function() {}, object = Constructor(); Dummy.prototype.x = [listener]; object.events = new Dummy; object.off('x', listener); assert.deepEqual(object.events.x, [listener]); }); QUnit.test('should handle an event type and listener', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); object.off('x', listener); assert.deepEqual(object.events.x, []); }); QUnit.test('should handle unregistering duplicate listeners', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); object.on('x', listener); var events = object.events; object.off('x', listener); assert.deepEqual(events.x, [listener]); object.off('x', listener); assert.deepEqual(events.x, []); }); QUnit.test('should handle a non-registered listener', function(assert) { var object = Constructor(); object.off('x', function() {}); assert.strictEqual(object.events, undefined); }); QUnit.test('should handle space separated event type and listener', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); object.on('y', listener); var events = object.events; object.off('x y', listener); assert.deepEqual(events.x, []); assert.deepEqual(events.y, []); }); QUnit.test('should handle space separated event type and no listener', function(assert) { var listener1 = function() {}, listener2 = function() {}, object = Constructor(); object.on('x', listener1); object.on('y', listener2); var events = object.events; object.off('x y'); assert.deepEqual(events.x, []); assert.deepEqual(events.y, []); }); QUnit.test('should handle no arguments', function(assert) { var listener1 = function() {}, listener2 = function() {}, listener3 = function() {}, object = Constructor(); object.on('x', listener1); object.on('y', listener2); object.on('z', listener3); var events = object.events; object.off(); assert.deepEqual(events.x, []); assert.deepEqual(events.y, []); assert.deepEqual(events.z, []); }); }()); /*------------------------------------------------------------------------*/ QUnit.module(namespace + '#on'); (function() { QUnit.test('should return the benchmark', function(assert) { var listener = function() {}, object = Constructor(); assert.strictEqual(object.on('x', listener), object); }); QUnit.test('should ignore inherited properties of the event cache', function(assert) { var Dummy = function() {}, listener1 = function() {}, listener2 = function() {}, object = Constructor(); Dummy.prototype.x = [listener1]; object.events = new Dummy; object.on('x', listener2); assert.deepEqual(object.events.x, [listener2]); }); QUnit.test('should handle an event type and listener', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); assert.deepEqual(object.events.x, [listener]); }); QUnit.test('should handle registering duplicate listeners', function(assert) { var listener = function() {}, object = Constructor(); object.on('x', listener); object.on('x', listener); assert.deepEqual(object.events.x, [listener, listener]); }); QUnit.test('should handle space separated event type and listener', function(assert) { var listener = function() {}, object = Constructor(); object.on('x y', listener); var events = object.events; assert.deepEqual(events.x, [listener]); assert.deepEqual(events.y, [listener]); }); }()); }); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite#abort'); (function() { QUnit.test('should ignore abort calls when the suite isn\'t running', function(assert) { var fired = false; var suite = Benchmark.Suite('suite', { 'onAbort': function() { fired = true; } }); suite.add('foo', function() {}); suite.abort(); assert.strictEqual(fired, false); }); QUnit.test('should ignore abort calls from `Benchmark.Suite#reset` when the suite isn\'t running', function(assert) { var fired = false; var suite = Benchmark.Suite('suite', { 'onAbort': function() { fired = true; } }); suite.add('foo', function() {}); suite.reset(); assert.strictEqual(fired, false); }); QUnit.test('should emit an abort event when running', function(assert) { var done = assert.async(); var fired = false; Benchmark.Suite({ 'onAbort': function() { fired = true; } }) .on('start', function() { this.abort(); }) .on('complete', function() { assert.ok(fired); done(); }) .add(function(){}) .run({ 'async': true }); }); QUnit.test('should emit an abort event after calling `Benchmark.Suite#reset`', function(assert) { var done = assert.async(); var fired = false; Benchmark.Suite({ 'onAbort': function() { fired = true; } }) .on('start', function() { this.reset(); }) .on('complete', function() { assert.ok(fired); done(); }) .add(function(){}) .run({ 'async': true }); }); QUnit.test('should abort deferred benchmark', function(assert) { var done = assert.async(); var fired = false, suite = Benchmark.Suite(); suite.on('complete', function() { assert.strictEqual(fired, false); done(); }) .add('a', { 'defer': true, 'fn': function(deferred) { // avoid test inlining suite.name; // delay resolve setTimeout(function() { deferred.resolve(); suite.abort(); }, 10); } }) .add('b', { 'defer': true, 'fn': function(deferred) { // avoid test inlining suite.name; // delay resolve setTimeout(function() { deferred.resolve(); fired = true; }, 10); } }) .run(); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite#reverse'); (function() { QUnit.test('should reverses the element order', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 1; suite.length = 2; var actual = suite.reverse(); assert.strictEqual(actual, suite); assert.deepEqual(slice.call(actual), [1, 0]); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite#shift'); (function() { QUnit.test('should remove the first element', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 1; suite.length = 2; var actual = suite.shift(); assert.strictEqual(actual, 0); assert.deepEqual(slice.call(suite), [1]); }); QUnit.test('should shift an object with no elements', function(assert) { var suite = Benchmark.Suite(), actual = suite.shift(); assert.strictEqual(actual, undefined); assert.deepEqual(slice.call(suite), []); }); QUnit.test('should have no elements when length is `0` after shift', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite.length = 1; suite.shift(); // ensure element is removed assert.strictEqual('0' in suite, false); assert.strictEqual(suite.length, 0); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite#splice'); (function() { QUnit.test('should work with positive `start` argument', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 3; suite.length = 2; var actual = suite.splice(1, 0, 1, 2); assert.deepEqual(actual, []); assert.deepEqual(slice.call(suite), [0, 1, 2, 3]); }); QUnit.test('should work with positive `start` and `deleteCount` arguments', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 3; suite.length = 2; var actual = suite.splice(1, 1, 1, 2); assert.deepEqual(actual, [3]); assert.deepEqual(slice.call(suite), [0, 1, 2]); }); QUnit.test('should work with `deleteCount` values exceeding length', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 3; suite.length = 2; var actual = suite.splice(1, 10, 1, 2); assert.deepEqual(actual, [3]); assert.deepEqual(slice.call(suite), [0, 1, 2]); }); QUnit.test('should work with negative `start` and `deleteCount` arguments', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 3; suite.length = 2; var actual = suite.splice(-1, -1, 1, 2); assert.deepEqual(actual, []); assert.deepEqual(slice.call(suite), [0, 1, 2, 3]); }); QUnit.test('should work with an extreme negative `deleteCount` value', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite[1] = 3; suite.length = 2; var actual = suite.splice(0, -10, 1, 2); assert.deepEqual(actual, []); assert.deepEqual(slice.call(suite), [1, 2, 0, 3]); }); QUnit.test('should have no elements when length is `0` after splice', function(assert) { var suite = Benchmark.Suite(); suite[0] = 0; suite.length = 1 suite.splice(0, 1); // ensure element is removed assert.strictEqual('0' in suite, false); assert.strictEqual(suite.length, 0); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite#unshift'); (function() { QUnit.test('should add a first element', function(assert) { var suite = Benchmark.Suite(); suite[0] = 1; suite.length = 1; var actual = suite.unshift(0); assert.strictEqual(actual, 2); assert.deepEqual(slice.call(suite), [0, 1]); }); QUnit.test('should add multiple elements to the front', function(assert) { var suite = Benchmark.Suite(); suite[0] = 3; suite.length = 1; var actual = suite.unshift(0, 1, 2); assert.strictEqual(actual, 4); assert.deepEqual(slice.call(suite), [0, 1, 2, 3]); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite filtered results onComplete'); (function() { var count = 0, suite = Benchmark.Suite(); suite.add('a', function() { for (var i = 0; i < 1e5; i++) { count++; } }) .add('b', function() { for (var i = 0; i < 1e6; i++) { count++; } }) .add('c', function() { throw new TypeError; }); QUnit.test('should filter by fastest', function(assert) { var done = assert.async(); suite.on('complete', function() { suite.off(); assert.deepEqual(this.filter('fastest').map('name'), ['a']); done(); }) .run({ 'async': true }); }); QUnit.test('should filter by slowest', function(assert) { var done = assert.async(); suite.on('complete', function() { suite.off(); assert.deepEqual(this.filter('slowest').map('name'), ['b']); done(); }) .run({ 'async': true }); }); QUnit.test('should filter by successful', function(assert) { var done = assert.async(); suite.on('complete', function() { suite.off(); assert.deepEqual(this.filter('successful').map('name'), ['a', 'b']); done(); }) .run({ 'async': true }); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Benchmark.Suite event flow'); (function() { var events = [], callback = function(event) { events.push(event); }; var suite = Benchmark.Suite('suite', { 'onAdd': callback, 'onAbort': callback, 'onClone': callback, 'onError': callback, 'onStart': callback, 'onCycle': callback, 'onComplete': callback, 'onReset': callback }) .add('bench', function() { throw null; }, { 'onAbort': callback, 'onClone': callback, 'onError': callback, 'onStart': callback, 'onCycle': callback, 'onComplete': callback, 'onReset': callback }) .run({ 'async': false }); // first Suite#onAdd QUnit.test('should emit the suite "add" event first', function(assert) { var event = events[0]; assert.ok(event.type == 'add' && event.currentTarget.name == 'suite' && event.target.name == 'bench'); }); // next we start the Suite because no reset was needed QUnit.test('should emit the suite "start" event', function(assert) { var event = events[1]; assert.ok(event.type == 'start' && event.currentTarget.name == 'suite' && event.target.name == 'bench'); }); // and so start the first benchmark QUnit.test('should emit the benchmark "start" event', function(assert) { var event = events[2]; assert.ok(event.type == 'start' && event.currentTarget.name == 'bench'); }); // oh no! we abort because of an error QUnit.test('should emit the benchmark "error" event', function(assert) { var event = events[3]; assert.ok(event.type == 'error' && event.currentTarget.name == 'bench'); }); // benchmark error triggered QUnit.test('should emit the benchmark "abort" event', function(assert) { var event = events[4]; assert.ok(event.type == 'abort' && event.currentTarget.name == 'bench'); }); // we reset the benchmark as part of the abort QUnit.test('should emit the benchmark "reset" event', function(assert) { var event = events[5]; assert.ok(event.type == 'reset' && event.currentTarget.name == 'bench'); }); // benchmark is cycle is finished QUnit.test('should emit the benchmark "cycle" event', function(assert) { var event = events[6]; assert.ok(event.type == 'cycle' && event.currentTarget.name == 'bench'); }); // benchmark is complete QUnit.test('should emit the benchmark "complete" event', function(assert) { var event = events[7]; assert.ok(event.type == 'complete' && event.currentTarget.name == 'bench'); }); // the benchmark error triggers a Suite error QUnit.test('should emit the suite "error" event', function(assert) { var event = events[8]; assert.ok(event.type == 'error' && event.currentTarget.name == 'suite' && event.target.name == 'bench'); }); // the Suite cycle finishes QUnit.test('should emit the suite "cycle" event', function(assert) { var event = events[9]; assert.ok(event.type == 'cycle' && event.currentTarget.name == 'suite' && event.target.name == 'bench'); }); // the Suite completes QUnit.test('should emit the suite "complete" event', function(assert) { var event = events[10]; assert.ok(event.type == 'complete' && event.currentTarget.name == 'suite' && event.target.name == 'bench'); }); QUnit.test('should emit all expected events', function(assert) { assert.ok(events.length == 11); }); }()); /*--------------------------------------------------------------------------*/ QUnit.module('Deferred benchmarks'); (function() { QUnit.test('should run a deferred benchmark correctly', function(assert) { var done = assert.async(); Benchmark(function(deferred) { setTimeout(function() { deferred.resolve(); }, 1e3); }, { 'defer': true, 'onComplete': function() { assert.strictEqual(this.hz.toFixed(0), '1'); done(); } }) .run(); }); QUnit.test('should run with string values for "fn", "setup", and "teardown"', function(assert) { var done = assert.async(); Benchmark({ 'defer': true, 'setup': 'var x = [3, 2, 1];', 'fn': 'setTimeout(function() { x.sort(); deferred.resolve(); }, 10);', 'teardown': 'x.length = 0;', 'onComplete': function() { assert.ok(true); done(); } }) .run(); }); QUnit.test('should execute "setup", "fn", and "teardown" in correct order', function(assert) { var done = assert.async(); var fired = []; Benchmark({ 'defer': true, 'setup': function() { fired.push('setup'); }, 'fn': function(deferred) { fired.push('fn'); setTimeout(function() { deferred.resolve(); }, 10); }, 'teardown': function() { fired.push('teardown'); }, 'onComplete': function() { var actual = fired.join().replace(/(fn,)+/g, '$1').replace(/(setup,fn,teardown(?:,|$))+/, '$1'); assert.strictEqual(actual, 'setup,fn,teardown'); done(); } }) .run(); }); }()); /*--------------------------------------------------------------------------*/ QUnit.config.asyncRetries = 10; QUnit.config.hidepassed = true; if (!document) { QUnit.config.noglobals = true; QUnit.load(); QUnit.start(); } }.call(this)); benchmark.js-2.1.4/yarn.lock000066400000000000000000000610031306651343200157110ustar00rootroot00000000000000# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 abbrev@1, abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" dependencies: kind-of "^3.0.2" longest "^1.0.1" repeat-string "^1.5.2" amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" dependencies: sprintf-js "~1.0.2" asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" async@1.x, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" dependencies: tweetnacl "^0.14.3" boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" dependencies: hoek "2.x.x" brace-expansion@^1.0.0: version "1.1.6" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" dependencies: balanced-match "^0.4.1" concat-map "0.0.1" camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" caseless@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" chalk@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" has-ansi "^2.0.0" strip-ansi "^3.0.0" supports-color "^2.0.0" cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" dependencies: center-align "^0.1.1" right-align "^0.1.1" wordwrap "0.0.2" combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: delayed-stream "~1.0.0" commander@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: graceful-readlink ">= 1.0.0" concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" coveralls@^2.12.0: version "2.12.0" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.12.0.tgz#b3d064108e29728385b56e42fc2d119f43e0e517" dependencies: js-yaml "3.6.1" lcov-parse "0.0.10" log-driver "1.2.5" minimist "1.2.0" request "2.79.0" cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" dependencies: boom "2.x.x" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" decamelize@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" docdown@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/docdown/-/docdown-0.7.2.tgz#f8c68f5836974860e5bb1802bcac52ba8a3ff677" dependencies: doctrine "^2.0.0" lodash "^4.17.2" doctrine@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" dependencies: esutils "^2.0.2" isarray "^1.0.0" ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" dependencies: jsbn "~0.1.0" escape-string-regexp@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" dependencies: esprima "^2.7.1" estraverse "^1.9.1" esutils "^2.0.2" optionator "^0.8.1" optionalDependencies: source-map "~0.2.0" esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" esprima@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" extend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" extsprintf@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" form-data@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" dependencies: asynckit "^0.4.0" combined-stream "^1.0.5" mime-types "^2.1.12" generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" generate-object-property@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" dependencies: is-property "^1.0.0" getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" dependencies: assert-plus "^1.0.0" glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" dependencies: inflight "^1.0.4" inherits "2" minimatch "2 || 3" once "^1.3.0" path-is-absolute "^1.0.0" "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" handlebars@^4.0.1: version "4.0.6" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7" dependencies: async "^1.4.0" optimist "^0.6.1" source-map "^0.4.4" optionalDependencies: uglify-js "^2.6" har-validator@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" dependencies: chalk "^1.1.1" commander "^2.9.0" is-my-json-valid "^2.12.4" pinkie-promise "^2.0.0" has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" dependencies: boom "2.x.x" cryptiles "2.x.x" hoek "2.x.x" sntp "1.x.x" hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" dependencies: assert-plus "^0.2.0" jsprim "^1.2.2" sshpk "^1.7.0" inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" dependencies: once "^1.3.0" wrappy "1" inherits@2: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" is-buffer@^1.0.2: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" is-my-json-valid@^2.12.4: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" jsonpointer "^4.0.0" xtend "^4.0.0" is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" isarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" isexe@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" istanbul@0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" dependencies: abbrev "1.0.x" async "1.x" escodegen "1.8.x" esprima "2.7.x" glob "^5.0.15" handlebars "^4.0.1" js-yaml "3.x" mkdirp "0.5.x" nopt "3.x" once "1.x" resolve "1.1.x" supports-color "^3.1.0" which "^1.1.1" wordwrap "^1.0.0" jodid25519@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" dependencies: jsbn "~0.1.0" js-yaml@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" dependencies: argparse "^1.0.7" esprima "^2.6.0" js-yaml@3.x: version "3.8.2" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" dependencies: argparse "^1.0.7" esprima "^3.1.1" jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" jsonpointer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" jsprim@^1.2.2: version "1.4.0" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" dependencies: assert-plus "1.0.0" extsprintf "1.0.2" json-schema "0.2.3" verror "1.3.6" kind-of@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" dependencies: is-buffer "^1.0.2" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" lcov-parse@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" lodash@^4.17.2, lodash@^4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" mime-db@~1.26.0: version "1.26.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff" mime-types@^2.1.12, mime-types@~2.1.7: version "2.1.14" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee" dependencies: mime-db "~1.26.0" "minimatch@2 || 3": version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: brace-expansion "^1.0.0" minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" minimist@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" mkdirp@0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: abbrev "1" oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" once@1.x, once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: minimist "~0.0.1" wordwrap "~0.0.2" optionator@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" levn "~0.3.0" prelude-ls "~1.1.2" type-check "~0.3.2" wordwrap "~1.0.0" path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" platform@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.3.tgz#646c77011899870b6a0903e75e997e8e51da7461" prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" qunit-extras@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/qunit-extras/-/qunit-extras-3.0.0.tgz#aae0e2e0e22e980b58a25cfcff494af9959846db" qunitjs@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/qunitjs/-/qunitjs-2.2.1.tgz#76c0c08c9ebc2324267a590eecd2dfc32982d8f8" repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" request@2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: aws-sign2 "~0.6.0" aws4 "^1.2.1" caseless "~0.11.0" combined-stream "~1.0.5" extend "~3.0.0" forever-agent "~0.6.1" form-data "~2.1.1" har-validator "~2.0.6" hawk "~3.1.3" http-signature "~1.1.0" is-typedarray "~1.0.0" isstream "~0.1.2" json-stringify-safe "~5.0.1" mime-types "~2.1.7" oauth-sign "~0.8.1" qs "~6.3.0" stringstream "~0.0.4" tough-cookie "~2.3.0" tunnel-agent "~0.4.1" uuid "^3.0.0" requirejs@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.3.tgz#aa59fd3a0287eaf407959a138228044b5dd6a6a3" resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" dependencies: align-text "^0.1.1" sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" dependencies: hoek "2.x.x" source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: amdefine ">=0.0.4" source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" dependencies: amdefine ">=0.0.4" source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: version "1.11.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.11.0.tgz#2d8d5ebb4a6fab28ffba37fa62a90f4a3ea59d77" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" dashdash "^1.12.0" getpass "^0.1.1" optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" jodid25519 "^1.0.0" jsbn "~0.1.0" tweetnacl "~0.14.0" stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" dependencies: punycode "^1.4.1" tunnel-agent@~0.4.1: version "0.4.3" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" uglify-js@^2.6: version "2.8.14" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.14.tgz#25b15d1af39b21752ee33703adbf432e8bc8f77d" dependencies: source-map "~0.5.1" uglify-to-browserify "~1.0.0" yargs "~3.10.0" uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" uuid@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" verror@1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" dependencies: extsprintf "1.0.2" which@^1.1.1: version "1.2.12" resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" dependencies: isexe "^1.1.1" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" dependencies: camelcase "^1.0.2" cliui "^2.1.0" decamelize "^1.0.0" window-size "0.1.0"