[Pkg-javascript-commits] [node-lolex] 01/12: New upstream version 2.3.2

Praveen Arimbrathodiyil praveen at moszumanska.debian.org
Sat Feb 10 19:02:54 UTC 2018


This is an automated email from the git hooks/post-receive script.

praveen pushed a commit to branch master
in repository node-lolex.

commit 0e280800a46a7ef482a84c11b2416e7b9e5119fa
Author: Pirate Praveen <praveen at debian.org>
Date:   Fri Feb 2 18:53:14 2018 +0530

    New upstream version 2.3.2
---
 .eslintrc          |  172 --
 .github/stale.yml  |   17 +
 .gitignore         |    2 +
 .npmrc             |    1 +
 .travis.yml        |   13 +-
 AUTHORS            |   19 +-
 History.md         |   66 +
 RELEASE.md         |   15 +-
 Readme.md          |  117 +-
 lolex.js           | 1163 ++++++------
 package-lock.json  | 4994 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 package.json       |   56 +-
 src/lolex-src.js   | 1163 ++++++------
 test/.eslintrc     |   12 +
 test/lolex-test.js |  712 +++++++-
 15 files changed, 7245 insertions(+), 1277 deletions(-)

diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index e3240a7..0000000
--- a/.eslintrc
+++ /dev/null
@@ -1,172 +0,0 @@
-{
-    "ecmaFeatures": {},
-    "env": {
-        "browser": true,
-        "node": true
-    },
-    "rules": {
-        "no-alert": 2,
-        "no-array-constructor": 2,
-        "no-bitwise": 2,
-        "no-caller": 2,
-        "no-catch-shadow": 2,
-        "no-cond-assign": 2,
-        "no-console": 2,
-        "no-constant-condition": 2,
-        "no-continue": 2,
-        "no-control-regex": 2,
-        "no-debugger": 2,
-        "no-delete-var": 2,
-        "no-div-regex": 0,
-        "no-dupe-keys": 2,
-        "no-dupe-args": 2,
-        "no-duplicate-case": 2,
-        "no-else-return": 2,
-        "no-empty": 2,
-        "no-empty-character-class": 2,
-        "no-eq-null": 0,
-        "no-eval": 2,
-        "no-ex-assign": 2,
-        "no-extend-native": 2,
-        "no-extra-bind": 2,
-        "no-extra-boolean-cast": 2,
-        "no-extra-parens": [2, "functions"],
-        "no-extra-semi": 2,
-        "no-fallthrough": 2,
-        "no-floating-decimal": 0,
-        "no-func-assign": 2,
-        "no-implied-eval": 2,
-        "no-inline-comments": 0,
-        "no-inner-declarations": [2, "functions"],
-        "no-invalid-regexp": 2,
-        "no-irregular-whitespace": 2,
-        "no-iterator": 2,
-        "no-label-var": 2,
-        "no-labels": 2,
-        "no-lone-blocks": 2,
-        "no-lonely-if": 0,
-        "no-loop-func": 2,
-        "no-mixed-requires": [0, false],
-        "no-mixed-spaces-and-tabs": [2, false],
-        "linebreak-style": [0, "unix"],
-        "no-multi-spaces": 2,
-        "no-multi-str": 2,
-        "no-multiple-empty-lines": [2, {"max": 2}],
-        "no-negated-in-lhs": 2,
-        "no-nested-ternary": 2,
-        "no-new": 2,
-        "no-new-func": 2,
-        "no-new-object": 2,
-        "no-new-require": 0,
-        "no-new-wrappers": 2,
-        "no-obj-calls": 2,
-        "no-octal": 2,
-        "no-octal-escape": 2,
-        "no-param-reassign": 0,
-        "no-path-concat": 0,
-        "no-plusplus": 1,
-        "no-process-env": 0,
-        "no-process-exit": 2,
-        "no-proto": 2,
-        "no-redeclare": 2,
-        "no-regex-spaces": 2,
-        "no-reserved-keys": 0,
-        "no-restricted-modules": 0,
-        "no-return-assign": 2,
-        "no-script-url": 2,
-        "no-self-compare": 0,
-        "no-sequences": 2,
-        "no-shadow-restricted-names": 2,
-        "no-space-before-semi": 0,
-        "no-spaced-func": 2,
-        "no-sparse-arrays": 2,
-        "no-sync": 0,
-        "no-ternary": 0,
-        "no-trailing-spaces": 2,
-        "no-this-before-super": 0,
-        "no-throw-literal": 0,
-        "no-undef": 2,
-        "no-undef-init": 2,
-        "no-undefined": 0,
-        "no-unexpected-multiline": 0,
-        "no-underscore-dangle": 2,
-        "no-unneeded-ternary": 0,
-        "no-unreachable": 2,
-        "no-unused-expressions": 2,
-        "no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
-        "no-use-before-define": 2,
-        "no-void": 0,
-        "no-var": 0,
-        "prefer-const": 0,
-        "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
-        "no-with": 2,
-
-        "array-bracket-spacing": [2, "never"],
-        "accessor-pairs": 2,
-        "block-scoped-var": 0,
-        "brace-style": [0, "1tbs"],
-        "callback-return": 0,
-        "camelcase": 2,
-        "comma-dangle": [2, "never"],
-        "comma-spacing": 2,
-        "comma-style": 2,
-        "complexity": [0, 11],
-        "computed-property-spacing": [0, "never"],
-        "consistent-return": 2,
-        "consistent-this": [0, "that"],
-        "constructor-super": 0,
-        "curly": [2, "all"],
-        "default-case": 1,
-        "dot-location": 0,
-        "dot-notation": [2, { "allowKeywords": true }],
-        "eol-last": 2,
-        "eqeqeq": [2, "allow-null"],
-        "func-names": 0,
-        "func-style": [0, "declaration"],
-        "generator-star": 0,
-        "generator-star-spacing": 0,
-        "guard-for-in": 2,
-        "handle-callback-err": 0,
-        "indent": [2, 4, {"SwitchCase": 1}],
-        "init-declarations": 0,
-        "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
-        "lines-around-comment": 0,
-        "max-depth": [0, 4],
-        "max-len": [2, 120, 4],
-        "max-nested-callbacks": [1, 3],
-        "max-params": [0, 3],
-        "max-statements": [0, 10],
-        "new-cap": 2,
-        "new-parens": 2,
-        "newline-after-var": 0,
-        "object-curly-spacing": [0, "never"],
-        "object-shorthand": 0,
-        "operator-assignment": [0, "always"],
-        "operator-linebreak": 0,
-        "padded-blocks": 0,
-        "quote-props": 0,
-        "quotes": [2, "double"],
-        "radix": 0,
-        "require-yield": 0,
-        "semi": 2,
-        "semi-spacing": [2, {"before": false, "after": true}],
-        "sort-vars": 0,
-        "keyword-spacing": [ "error", { "after": true} ],
-        "space-before-blocks": [2, "always"],
-        "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
-        "space-before-function-parentheses": [0, "always"],
-        "space-in-brackets": [0, "never"],
-        "space-in-parens": [0, "never"],
-        "space-infix-ops": 2,
-        "space-unary-ops": [2, { "words": true, "nonwords": false }],
-        "spaced-comment": 0,
-        "spaced-line-comment": [0, "always"],
-        "use-isnan": 2,
-        "valid-jsdoc": 0,
-        "valid-typeof": 2,
-        "vars-on-top": 0,
-        "wrap-iife": 0,
-        "wrap-regex": 0,
-        "yoda": [2, "never"]
-    }
-}
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 0000000..e556fa9
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,17 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 60
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 7
+# Issues with these labels will never be considered stale
+exemptLabels:
+  - pinned
+  - security
+# Label to use when marking an issue as stale
+staleLabel: stale
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+  This issue has been automatically marked as stale because it has not had
+  recent activity. It will be closed if no further activity occurs. Thank you
+  for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/.gitignore b/.gitignore
index 07e6e47..96e4deb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
 /node_modules
+.DS_Store
+.idea
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..cffe8cd
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+save-exact=true
diff --git a/.travis.yml b/.travis.yml
index c217705..a498f0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,10 +3,10 @@ language: node_js
 sudo: false
 
 node_js:
-  - "0.10"
-  - "0.12"
-  - "4.2"
-  - "5"
+  # https://github.com/nodejs/LTS
+  - "4" # ends April 2018
+  - "6" # ends April 2019
+  - "8" # ends December 2019
 
 env:
   global:
@@ -15,6 +15,5 @@ env:
 
 script:
   - "./script/ci-test.sh"
-  - 'if [ "x$TRAVIS_NODE_VERSION" = "x4.2" ]; then npm run lint; fi'
-  - 'if [ "x$TRAVIS_NODE_VERSION" = "x4.2" ] && [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then npm run test-cloud; fi'
-
+  - 'if [ "x$TRAVIS_NODE_VERSION" = "x8" ]; then npm run lint; fi'
+  - 'if [ "x$TRAVIS_NODE_VERSION" = "x8" ] && [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then npm run test-cloud; fi'
diff --git a/AUTHORS b/AUTHORS
index 5249785..f15f634 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,15 +1,26 @@
-Christian Johansen <christian at cjohansen.no>
 Carl-Erik Kopseng <carlerik at gmail.com>
+Christian Johansen <christian at cjohansen.no>
 Morgan Roderick <morgan at roderick.dk>
 Maximilian Antoni <mail at maxantoni.de>
 Mark Wubben <mark at novemberborn.net>
-Soutaro Matsumoto <matsumoto at soutaro.com>
+Benjamin Gruenbaum <benji at peer5.com>
 Duncan Beevers <duncan at dweebd.com>
+Soutaro Matsumoto <matsumoto at soutaro.com>
 Rogier Schouten <github at workingcode.ninja>
 Karl O'Keeffe <karl at geckoboard.com>
-Thibault Hild <gautaz at users.noreply.github.com>
+Elad Nachmias <theman at elad.im>
+Clark Tomlinson <fallen013 at gmail.com>
+Josh Goldberg <joshuakgoldberg at outlook.com>
+Andy Edwards <jedwards at fastmail.com>
 Curtis M. Humphrey, Ph.D <curtis at createdwithflair.com>
+Edward Betts <edward at 4angle.com>
+Kyle Fleming <kyle at kylefleming.net>
 Mark Banner <standard8 at mozilla.com>
+Nando <fdanko at ekumenlabs.com>
+Peter A. Bigot <pab at pabigot.com>
 Simen Bekkhus <sbekkhus91 at gmail.com>
 Sylvain Fraïssé <fraisse.sylvain at gmail.com>
-Andy Edwards <jedwards at fastmail.com>
+Thibault Hild <gautaz at users.noreply.github.com>
+griest024 <griest024 at gmail.com>
+mAAdhaTTah <jamesorodig at gmail.com>
+medanat <medanat at gmail.com>
diff --git a/History.md b/History.md
index e3464a8..60f76ac 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,69 @@
+
+v2.3.1 / 2017-11-22
+==================
+
+  * bugfix for a setTimeout() or setSystemTime() within a nextTick() call. (#145)
+
+v2.3.0 / 2017-11-08
+==================
+
+  * Stops leak of (request|cancel)AnimationFrame into global scope. (#143)
+  * return timers on uninstall
+
+v2.2.0 / 2017-11-07
+==================
+
+  * Add support for requestAnimationFrame
+  * fix negative timeout bug
+
+v2.1.3 / 2017-10-03
+==================
+
+  * add module entry point (#133)
+
+v2.1.2 / 2017-07-25
+==================
+
+  * - does not fake process.nextTick by default - added .idea folder to .gitignore - fixed documentation - added clock teardowns in tests
+  * overflowing the timer correctly (issue #67)
+
+v2.1.1 / 2017-07-19
+==================
+
+  * support passing parameters in nextTick (fixes #122)
+
+v2.1.0 / 2017-07-18
+==================
+
+  * Throw error on incorrect install use (#112)
+  * Add support for process.nextTick
+  * lolex can now attach itself to the system timers and automatically ad… (#102)
+  * update hrtime when an interval ticks
+
+v2.0.0 / 2017-07-13
+==================
+
+  * New install() signature
+  * Add support for performance.now (#106)
+  * Fix issue with tick(): setSystemClock then throw
+  * Update old dependencies
+  * Added support to automatically increment time (#85)
+  * Changed internal uninstall method signature
+
+v1.6.0 / 2017-02-25
+===================
+
+  * Use common Sinon.JS eslint config
+  * Allow install to be called with date object
+  * Remove wrapper function
+  * Fixed typo in clock.runAll error
+
+v1.5.2 / 2016-11-10
+===================
+
+  * Upgrade mocha to latest
+  * Only overwrite globals when running in IE
+
 1.5.1 / 2016-07-26
 ==================
 
diff --git a/RELEASE.md b/RELEASE.md
index acb28ad..3191ce2 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -18,10 +18,6 @@ Compile interesting highlights from [`git changelog`](https://github.com/tj/git-
     git add lolex.js AUTHORS History.md
     git commit -m "Prepare for new release"
 
-## Create a new PR
-    The `master` branch is protected.
-    You can merge it yourself.
-
 ## Create a new version
 
 ```
@@ -30,10 +26,14 @@ $ npm version x.y.z
 
 Updates package.json and creates a new tag.
 
+## Create a new PR
+The `master` branch is protected.
+You can merge it yourself.
 
 ## Push new commits and tags
+> Assuming that `origin` points to `github.com/sinonjs/lolex`
 ```
-git push && git push --tags
+git push --follow-tags origin
 ```
 
 ## Publish to NPM
@@ -42,3 +42,8 @@ git push && git push --tags
 $ npm publish
 ```
 
+## Create a GitHub release
+Create a GitHub release where you highlight
+interesting additions from the changelog.
+Just add a release notes to [the existing tag](https://github.com/sinonjs/lolex/tags).
+
diff --git a/Readme.md b/Readme.md
index 312a050..cd2679f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,31 +1,28 @@
-# Lolex [![Build Status](https://secure.travis-ci.org/sinonjs/lolex.png)](http://travis-ci.org/sinonjs/lolex) [![bitHound Overall Score](https://www.bithound.io/github/sinonjs/lolex/badges/score.svg)](https://www.bithound.io/github/sinonjs/lolex)
+# Lolex [![Build Status](https://travis-ci.org/sinonjs/lolex.svg?branch=master)](https://travis-ci.org/sinonjs/lolex) [![bitHound Overall Score](https://www.bithound.io/github/sinonjs/lolex/badges/score.svg)](https://www.bithound.io/github/sinonjs/lolex)
 
-JavaScript implementation of the timer APIs; `setTimeout`, `clearTimeout`,
-`setImmediate`, `clearImmediate`, `setInterval` and `clearInterval`, along with
-a clock instance that controls the flow of time. Lolex also provides a `Date`
-implementation that gets its time from the clock.
+JavaScript implementation of the timer APIs; `setTimeout`, `clearTimeout`, `setImmediate`, `clearImmediate`, `setInterval`, `clearInterval`, `requestAnimationFrame`, and `cancelAnimationFrame`, along with a clock instance that controls the flow of time. Lolex also provides a `Date` implementation that gets its time from the clock.
+
+In addition in browser environment lolex provides a `performance` implementation that gets its time from the clock. In Node environments lolex provides a `nextTick` implementation that is synchronized with the clock - and a `process.hrtime` shim that works with the clock.
 
 Lolex can be used to simulate passing time in automated tests and other
 situations where you want the scheduling semantics, but don't want to actually
-wait. Lolex is extracted from [Sinon.JS](https://github.com/sinonjs/sinon.js).
+wait (however, from version 2.0 lolex supports those of you who would like to wait too).
+
+Lolex is extracted from [Sinon.JS](https://github.com/sinonjs/sinon.js).
 
 ## Installation
 
-Lolex can be installed using `npm`:
+Lolex can be used in both Node and browser environments. Installation is as easy as
 
 ```sh
 npm install lolex
 ```
 
-If you want to use Lolex in a browser, you have a few options. Releases are
-hosted on the [sinonjs.org](http://sinonjs.org/download/) website. You can also
-get the node module and build a file for the browser using browserify:
+If you want to use Lolex in a browser you can use [the pre-built
+version](https://github.com/sinonjs/lolex/blob/master/lolex.js) available in the repo
+and the npm package. Using npm you only need to reference `./node_modules/lolex/lolex.js` in your `<script>` tags.
 
-```sh
-npm install lolex
-npm install browserify # If you don't already have it globally installed
-browserify node_modules/lolex/lolex.js
-```
+You are always free to [build it yourself](https://github.com/sinonjs/lolex/blob/53ea4d9b9e5bcff53cc7c9755dc9aa340368cf1c/package.json#L22), of course.
 
 ## Usage
 
@@ -51,7 +48,7 @@ Upon executing the last line, an interesting fact about the
 the screen. If you want to simulate asynchronous behavior, you have to use your
 imagination when calling the various functions.
 
-The `next`, `runAll`, and `runToLast` methods are available to advance the clock. See the
+The `next`, `runAll`, `runToFrame`, and `runToLast` methods are available to advance the clock. See the
 API Reference for more details.
 
 ### Faking the native timers
@@ -84,7 +81,7 @@ var lolex = require("lolex");
 var context = {
     setTimeout: setTimeout // By default context.setTimeout uses the global setTimeout
 }
-var clock = lolex.install(context);
+var clock = lolex.install({target: context});
 
 context.setTimeout(fn, 15); // Schedules with clock.setTimeout
 
@@ -95,6 +92,35 @@ clock.uninstall();
 Usually you want to install the timers onto the global object, so call `install`
 without arguments.
 
+#### Automatically incrementing mocked time
+Since version 2.0 Lolex supports the possibility to attach the faked timers
+to any change in the real system time. This basically means you no longer need
+to `tick()` the clock in a situation where you won't know **when** to call `tick()`.
+
+Please note that this is achieved using the original setImmediate() API at a certain
+configurable interval `config.advanceTimeDelta` (default: 20ms). Meaning time would
+be incremented every 20ms, not in real time.
+
+An example would be:
+
+```js
+var lolex = require("lolex");
+var clock = lolex.install({shouldAdvanceTime: true, advanceTimeDelta: 40});
+
+setTimeout(() => {
+    console.log('this just timed out'); //executed after 40ms
+}, 30);
+
+setImmediate(() => {
+    console.log('not so immediate'); //executed after 40ms
+});
+
+setTimeout(() => {
+    console.log('this timed out after'); //executed after 80ms
+    clock.uninstall();
+}, 50);
+```
+
 ## API Reference
 
 ### `var clock = lolex.createClock([now[, loopLimit]])`
@@ -106,19 +132,17 @@ The `now` argument may be a number (in milliseconds) or a Date object.
 
 The `loopLimit` argument sets the maximum number of timers that will be run when calling `runAll()` before assuming that we have an infinite loop and throwing an error. The default is `1000`.
 
-### `var clock = lolex.install([context[, now[, toFake[, loopLimit]]]])`
+### `var clock = lolex.install([config])`
+Installs lolex using the specified config (otherwise with epoch `0` on the global scope). The following configuration options are available
 
-### `var clock = lolex.install([now[, toFake[, loopLimit]]])`
-
-Creates a clock and installs it onto the `context` object, or globally. The
-`now` argument is the same as in `lolex.createClock()`.
-
-`toFake` is an array of the names of the methods that should be faked. You can
-pick from `setTimeout`, `clearTimeout`, `setImmediate`, `clearImmediate`,
-`setInterval`, `clearInterval`, and `Date`. E.g. `lolex.install(["setTimeout",
-"clearTimeout"])`.
-
-The `loopLimit` argument is the same as in `lolex.createClock()`.
+Parameter | Type | Default | Description
+--------- | ---- | ------- | ------------
+`config.target`| Object | global | installs lolex onto the specified target context
+`config.now` | Number/Date | 0 | installs lolex with the specified unix epoch
+`config.toFake` | String[] | ["setTimeout", "clearTimeout", "setImmediate", "clearImmediate","setInterval", "clearInterval", "Date", "requestAnimationFrame", "cancelAnimationFrame", "hrtime"] | an array with explicit function names to hijack. *When not set, lolex will automatically fake all methods **except** `nextTick`* e.g., `lolex.install({ toFake: ["setTimeout","nextTick"]})` will fake only `setTimeout` and `nextTick`
+`config.loopLimit` | Number | 1000 | the maximum number of timers that will be run when calling runAll()
+`config.shouldAdvanceTime` | Boolean | false | tells lolex to increment mocked time automatically based on the real system time shift (e.g. the mocked time will be incremented by 20ms for every 20ms change in the real system time)
+`config.advanceTimeDelta` | Number | 20 | relevant only when using with `shouldAdvanceTime: true`. increment mocked time by `advanceTimeDelta` ms every `advanceTimeDelta` ms change in the real system time.
 
 ### `var id = clock.setTimeout(callback, timeout)`
 
@@ -151,7 +175,7 @@ Clears the timer given the ID or timer object, as long as it was created using
 
 ### `var id = clock.setImmediate(callback)`
 
-Schedules the callback, to be fired once `0` milliseconds have ticked by. Note
+Schedules the callback to be fired once `0` milliseconds have ticked by. Note
 that you'll still have to call `clock.tick()` for the callback to fire. If
 called during a tick the callback won't fire until `1` millisecond has ticked
 by.
@@ -166,8 +190,26 @@ In browsers a timer ID is returned.
 Clears the timer given the ID or timer object, as long as it was created using
 `setImmediate`.
 
+### `clock.requestAnimationFrame(callback)`
+
+Schedules the callback to be fired on the next animation frame, which runs every
+16 ticks. Returns an `id` which can be used to cancel the callback. This is
+available in both browser & node environments.
+
+### `clock.cancelAnimationFrame(id)`
+
+Cancels the callback scheduled by the provided id.
+
 ### `clock.hrtime(prevTime?)`
-Only available in Node.JS, mimicks process.hrtime().
+Only available in Node.js, mimicks process.hrtime().
+
+### `clock.nextTick(callback)`
+
+Only available in Node.js, mimics `process.nextTick` to enable completely synchronous testing flows.
+
+### `clock.performance.now()`
+Only available in browser environments, mimicks performance.now().
+
 
 ### `clock.tick(time)`
 
@@ -191,6 +233,11 @@ This makes it easier to run asynchronous tests to completion without worrying ab
 
 It runs a maximum of `loopLimit` times after which it assumes there is an infinite loop of timers and throws an error.
 
+### `clock.runToFrame()`
+
+Advances the clock to the next frame, firing all scheduled animation frame callbacks,
+if any, for that frame as well as any other timers scheduled along the way.
+
 ### `clock.runToLast()`
 
 This takes note of the last scheduled timer when it is run, and advances the
@@ -211,13 +258,17 @@ setSystemTime().
 
 ### `clock.uninstall()`
 
-Restores the original methods on the `context` that was passed to
-`lolex.install`, or the native timers if no `context` was given.
+Restores the original methods on the `target` that was passed to
+`lolex.install`, or the native timers if no `target` was given.
 
 ### `Date`
 
 Implements the `Date` object but using the clock to provide the correct time.
 
+### `Performance`
+
+Implements the `now` method of the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) object but using the clock to provide the correct time. Only available in environments that support the Performance object (browsers mostly).
+
 ## Running tests
 
 Lolex has a comprehensive test suite. If you're thinking of contributing bug
diff --git a/lolex.js b/lolex.js
index b49929a..a96fcde 100644
--- a/lolex.js
+++ b/lolex.js
@@ -1,660 +1,801 @@
 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lolex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)r [...]
 (function (global){
-/*global global, window*/
-/**
- * @author Christian Johansen (christian at cjohansen.no) and contributors
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
+"use strict";
 
-(function (global) {
-    "use strict";
+var userAgent = global.navigator && global.navigator.userAgent;
+var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
+var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
 
-    // Make properties writable in IE, as per
-    // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+// Make properties writable in IE, as per
+// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+if (isRunningInIE) {
     global.setTimeout = global.setTimeout;
     global.clearTimeout = global.clearTimeout;
     global.setInterval = global.setInterval;
     global.clearInterval = global.clearInterval;
     global.Date = global.Date;
+}
 
-    // setImmediate is not a standard function
-    // avoid adding the prop to the window object if not present
-    if (global.setImmediate !== undefined) {
-        global.setImmediate = global.setImmediate;
-        global.clearImmediate = global.clearImmediate;
-    }
-
-    // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
-    // browsers, a number.
-    // see https://github.com/cjohansen/Sinon.JS/pull/436
-
-    var NOOP = function () { return undefined; };
-    var timeoutResult = setTimeout(NOOP, 0);
-    var addTimerReturnsObject = typeof timeoutResult === "object";
-    var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
-    clearTimeout(timeoutResult);
-
-    var NativeDate = Date;
-    var uniqueTimerId = 1;
-
-    /**
-     * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
-     * number of milliseconds. This is used to support human-readable strings passed
-     * to clock.tick()
-     */
-    function parseTime(str) {
-        if (!str) {
-            return 0;
-        }
+// setImmediate is not a standard function
+// avoid adding the prop to the window object if not present
+if (global.setImmediate !== undefined) {
+    global.setImmediate = global.setImmediate;
+    global.clearImmediate = global.clearImmediate;
+}
 
-        var strings = str.split(":");
-        var l = strings.length, i = l;
-        var ms = 0, parsed;
+// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
+// browsers, a number.
+// see https://github.com/cjohansen/Sinon.JS/pull/436
 
-        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-            throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
-        }
+var NOOP = function () { return undefined; };
+var timeoutResult = setTimeout(NOOP, 0);
+var addTimerReturnsObject = typeof timeoutResult === "object";
+var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
+var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
+var performancePresent = (global.performance && typeof global.performance.now === "function");
+var requestAnimationFramePresent = (global.requestAnimationFrame && typeof global.requestAnimationFrame === "function");
+var cancelAnimationFramePresent = (global.cancelAnimationFrame && typeof global.cancelAnimationFrame === "function");
 
-        while (i--) {
-            parsed = parseInt(strings[i], 10);
+clearTimeout(timeoutResult);
 
-            if (parsed >= 60) {
-                throw new Error("Invalid time " + str);
-            }
-
-            ms += parsed * Math.pow(60, (l - i - 1));
-        }
+var NativeDate = Date;
+var uniqueTimerId = 1;
 
-        return ms * 1000;
+/**
+ * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
+ * number of milliseconds. This is used to support human-readable strings passed
+ * to clock.tick()
+ */
+function parseTime(str) {
+    if (!str) {
+        return 0;
     }
 
-    /**
-     * Floor function that also works for negative numbers
-     */
-    function fixedFloor(n) {
-        return (n >= 0 ? Math.floor(n) : Math.ceil(n));
-    }
+    var strings = str.split(":");
+    var l = strings.length;
+    var i = l;
+    var ms = 0;
+    var parsed;
 
-    /**
-     * % operator that also works for negative numbers
-     */
-    function fixedModulo(n, m) {
-        return ((n % m) + m) % m;
+    if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+        throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
     }
 
-    /**
-     * Used to grok the `now` parameter to createClock.
-     */
-    function getEpoch(epoch) {
-        if (!epoch) { return 0; }
-        if (typeof epoch.getTime === "function") { return epoch.getTime(); }
-        if (typeof epoch === "number") { return epoch; }
-        throw new TypeError("now should be milliseconds since UNIX epoch");
-    }
+    while (i--) {
+        parsed = parseInt(strings[i], 10);
+
+        if (parsed >= 60) {
+            throw new Error("Invalid time " + str);
+        }
 
-    function inRange(from, to, timer) {
-        return timer && timer.callAt >= from && timer.callAt <= to;
+        ms += parsed * Math.pow(60, (l - i - 1));
     }
 
-    function mirrorDateProperties(target, source) {
-        var prop;
-        for (prop in source) {
-            if (source.hasOwnProperty(prop)) {
-                target[prop] = source[prop];
-            }
-        }
+    return ms * 1000;
+}
 
-        // set special now implementation
-        if (source.now) {
-            target.now = function now() {
-                return target.clock.now;
-            };
-        } else {
-            delete target.now;
-        }
+/**
+ * Floor function that also works for negative numbers
+ */
+function fixedFloor(n) {
+    return (n >= 0 ? Math.floor(n) : Math.ceil(n));
+}
 
-        // set special toSource implementation
-        if (source.toSource) {
-            target.toSource = function toSource() {
-                return source.toSource();
-            };
-        } else {
-            delete target.toSource;
+/**
+ * % operator that also works for negative numbers
+ */
+function fixedModulo(n, m) {
+    return ((n % m) + m) % m;
+}
+
+/**
+ * Used to grok the `now` parameter to createClock.
+ * @param epoch {Date|number} the system time
+ */
+function getEpoch(epoch) {
+    if (!epoch) { return 0; }
+    if (typeof epoch.getTime === "function") { return epoch.getTime(); }
+    if (typeof epoch === "number") { return epoch; }
+    throw new TypeError("now should be milliseconds since UNIX epoch");
+}
+
+function inRange(from, to, timer) {
+    return timer && timer.callAt >= from && timer.callAt <= to;
+}
+
+function mirrorDateProperties(target, source) {
+    var prop;
+    for (prop in source) {
+        if (source.hasOwnProperty(prop)) {
+            target[prop] = source[prop];
         }
+    }
 
-        // set special toString implementation
-        target.toString = function toString() {
-            return source.toString();
+    // set special now implementation
+    if (source.now) {
+        target.now = function now() {
+            return target.clock.now;
         };
+    } else {
+        delete target.now;
+    }
 
-        target.prototype = source.prototype;
-        target.parse = source.parse;
-        target.UTC = source.UTC;
-        target.prototype.toUTCString = source.prototype.toUTCString;
-
-        return target;
-    }
-
-    function createDate() {
-        function ClockDate(year, month, date, hour, minute, second, ms) {
-            // Defensive and verbose to avoid potential harm in passing
-            // explicit undefined when user does not pass argument
-            switch (arguments.length) {
-                case 0:
-                    return new NativeDate(ClockDate.clock.now);
-                case 1:
-                    return new NativeDate(year);
-                case 2:
-                    return new NativeDate(year, month);
-                case 3:
-                    return new NativeDate(year, month, date);
-                case 4:
-                    return new NativeDate(year, month, date, hour);
-                case 5:
-                    return new NativeDate(year, month, date, hour, minute);
-                case 6:
-                    return new NativeDate(year, month, date, hour, minute, second);
-                default:
-                    return new NativeDate(year, month, date, hour, minute, second, ms);
-            }
-        }
-
-        return mirrorDateProperties(ClockDate, NativeDate);
+    // set special toSource implementation
+    if (source.toSource) {
+        target.toSource = function toSource() {
+            return source.toSource();
+        };
+    } else {
+        delete target.toSource;
     }
 
-    function addTimer(clock, timer) {
-        if (timer.func === undefined) {
-            throw new Error("Callback must be provided to timer calls");
-        }
+    // set special toString implementation
+    target.toString = function toString() {
+        return source.toString();
+    };
 
-        if (!clock.timers) {
-            clock.timers = {};
+    target.prototype = source.prototype;
+    target.parse = source.parse;
+    target.UTC = source.UTC;
+    target.prototype.toUTCString = source.prototype.toUTCString;
+
+    return target;
+}
+
+function createDate() {
+    function ClockDate(year, month, date, hour, minute, second, ms) {
+        // Defensive and verbose to avoid potential harm in passing
+        // explicit undefined when user does not pass argument
+        switch (arguments.length) {
+            case 0:
+                return new NativeDate(ClockDate.clock.now);
+            case 1:
+                return new NativeDate(year);
+            case 2:
+                return new NativeDate(year, month);
+            case 3:
+                return new NativeDate(year, month, date);
+            case 4:
+                return new NativeDate(year, month, date, hour);
+            case 5:
+                return new NativeDate(year, month, date, hour, minute);
+            case 6:
+                return new NativeDate(year, month, date, hour, minute, second);
+            default:
+                return new NativeDate(year, month, date, hour, minute, second, ms);
         }
+    }
 
-        timer.id = uniqueTimerId++;
-        timer.createdAt = clock.now;
-        timer.callAt = clock.now + (timer.delay || (clock.duringTick ? 1 : 0));
+    return mirrorDateProperties(ClockDate, NativeDate);
+}
 
-        clock.timers[timer.id] = timer;
 
-        if (addTimerReturnsObject) {
-            return {
-                id: timer.id,
-                ref: NOOP,
-                unref: NOOP
-            };
-        }
+function enqueueJob(clock, job) {
+    // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
+    if (!clock.jobs) {
+        clock.jobs = [];
+    }
+    clock.jobs.push(job);
+}
 
-        return timer.id;
+function runJobs(clock) {
+    // runs all microtick-deferred tasks - ecma262/#sec-runjobs
+    if (!clock.jobs) {
+        return;
     }
+    for (var i = 0; i < clock.jobs.length; i++) {
+        var job = clock.jobs[i];
+        job.func.apply(null, job.args);
+    }
+    clock.jobs = [];
+}
 
+function addTimer(clock, timer) {
+    if (timer.func === undefined) {
+        throw new Error("Callback must be provided to timer calls");
+    }
 
-    /* eslint consistent-return: "off" */
-    function compareTimers(a, b) {
-        // Sort first by absolute timing
-        if (a.callAt < b.callAt) {
-            return -1;
-        }
-        if (a.callAt > b.callAt) {
-            return 1;
-        }
+    timer.type = timer.immediate ? "Immediate" : "Timeout";
 
-        // Sort next by immediate, immediate timers take precedence
-        if (a.immediate && !b.immediate) {
-            return -1;
-        }
-        if (!a.immediate && b.immediate) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("delay")) {
+        timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
+        timer.delay = Math.max(0, timer.delay);
+    }
 
-        // Sort next by creation time, earlier-created timers take precedence
-        if (a.createdAt < b.createdAt) {
-            return -1;
-        }
-        if (a.createdAt > b.createdAt) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("interval")) {
+        timer.type = "Interval";
+        timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
+    }
 
-        // Sort next by id, lower-id timers take precedence
-        if (a.id < b.id) {
-            return -1;
-        }
-        if (a.id > b.id) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("animation")) {
+        timer.type = "AnimationFrame";
+        timer.animation = true;
+    }
 
-        // As timer ids are unique, no fallback `0` is necessary
+    if (!clock.timers) {
+        clock.timers = {};
     }
 
-    function firstTimerInRange(clock, from, to) {
-        var timers = clock.timers,
-            timer = null,
-            id,
-            isInRange;
+    timer.id = uniqueTimerId++;
+    timer.createdAt = clock.now;
+    timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                isInRange = inRange(from, to, timers[id]);
+    clock.timers[timer.id] = timer;
 
-                if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
-                    timer = timers[id];
-                }
-            }
-        }
+    if (addTimerReturnsObject) {
+        return {
+            id: timer.id,
+            ref: NOOP,
+            unref: NOOP
+        };
+    }
+
+    return timer.id;
+}
 
-        return timer;
+
+/* eslint consistent-return: "off" */
+function compareTimers(a, b) {
+    // Sort first by absolute timing
+    if (a.callAt < b.callAt) {
+        return -1;
+    }
+    if (a.callAt > b.callAt) {
+        return 1;
     }
 
-    function firstTimer(clock) {
-        var timers = clock.timers,
-            timer = null,
-            id;
+    // Sort next by immediate, immediate timers take precedence
+    if (a.immediate && !b.immediate) {
+        return -1;
+    }
+    if (!a.immediate && b.immediate) {
+        return 1;
+    }
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                if (!timer || compareTimers(timer, timers[id]) === 1) {
-                    timer = timers[id];
-                }
-            }
-        }
+    // Sort next by creation time, earlier-created timers take precedence
+    if (a.createdAt < b.createdAt) {
+        return -1;
+    }
+    if (a.createdAt > b.createdAt) {
+        return 1;
+    }
 
-        return timer;
+    // Sort next by id, lower-id timers take precedence
+    if (a.id < b.id) {
+        return -1;
+    }
+    if (a.id > b.id) {
+        return 1;
     }
 
-    function lastTimer(clock) {
-        var timers = clock.timers,
-            timer = null,
-            id;
+    // As timer ids are unique, no fallback `0` is necessary
+}
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                if (!timer || compareTimers(timer, timers[id]) === -1) {
-                    timer = timers[id];
-                }
+function firstTimerInRange(clock, from, to) {
+    var timers = clock.timers;
+    var timer = null;
+    var id, isInRange;
+
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            isInRange = inRange(from, to, timers[id]);
+
+            if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
+                timer = timers[id];
             }
         }
-
-        return timer;
     }
 
-    function callTimer(clock, timer) {
-        var exception;
+    return timer;
+}
 
-        if (typeof timer.interval === "number") {
-            clock.timers[timer.id].callAt += timer.interval;
-        } else {
-            delete clock.timers[timer.id];
-        }
+function firstTimer(clock) {
+    var timers = clock.timers;
+    var timer = null;
+    var id;
 
-        try {
-            if (typeof timer.func === "function") {
-                timer.func.apply(null, timer.args);
-            } else {
-                /* eslint no-eval: "off" */
-                eval(timer.func);
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            if (!timer || compareTimers(timer, timers[id]) === 1) {
+                timer = timers[id];
             }
-        } catch (e) {
-            exception = e;
         }
+    }
+
+    return timer;
+}
+
+function lastTimer(clock) {
+    var timers = clock.timers;
+    var timer = null;
+    var id;
 
-        if (!clock.timers[timer.id]) {
-            if (exception) {
-                throw exception;
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            if (!timer || compareTimers(timer, timers[id]) === -1) {
+                timer = timers[id];
             }
-            return;
         }
+    }
 
-        if (exception) {
-            throw exception;
-        }
+    return timer;
+}
+
+function callTimer(clock, timer) {
+    if (typeof timer.interval === "number") {
+        clock.timers[timer.id].callAt += timer.interval;
+    } else {
+        delete clock.timers[timer.id];
     }
 
-    function timerType(timer) {
-        if (timer.immediate) {
-            return "Immediate";
-        }
-        if (timer.interval !== undefined) {
-            return "Interval";
-        }
-        return "Timeout";
+    if (typeof timer.func === "function") {
+        timer.func.apply(null, timer.args);
+    } else {
+        /* eslint no-eval: "off" */
+        eval(timer.func);
     }
+}
 
-    function clearTimer(clock, timerId, ttype) {
-        if (!timerId) {
-            // null appears to be allowed in most browsers, and appears to be
-            // relied upon by some libraries, like Bootstrap carousel
-            return;
-        }
+function clearTimer(clock, timerId, ttype) {
+    if (!timerId) {
+        // null appears to be allowed in most browsers, and appears to be
+        // relied upon by some libraries, like Bootstrap carousel
+        return;
+    }
 
-        if (!clock.timers) {
-            clock.timers = [];
-        }
+    if (!clock.timers) {
+        clock.timers = [];
+    }
 
-        // in Node, timerId is an object with .ref()/.unref(), and
-        // its .id field is the actual timer id.
-        if (typeof timerId === "object") {
-            timerId = timerId.id;
-        }
+    // in Node, timerId is an object with .ref()/.unref(), and
+    // its .id field is the actual timer id.
+    if (typeof timerId === "object") {
+        timerId = timerId.id;
+    }
 
-        if (clock.timers.hasOwnProperty(timerId)) {
-            // check that the ID matches a timer of the correct type
-            var timer = clock.timers[timerId];
-            if (timerType(timer) === ttype) {
-                delete clock.timers[timerId];
+    if (clock.timers.hasOwnProperty(timerId)) {
+        // check that the ID matches a timer of the correct type
+        var timer = clock.timers[timerId];
+        if (timer.type === ttype) {
+            delete clock.timers[timerId];
+        } else {
+            var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
+            var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
+            throw new Error("Cannot clear timer: timer created with " + schedule
+                            + "() but cleared with " + clear + "()");
+        }
+    }
+}
+
+function uninstall(clock, target, config) {
+    var method,
+        i,
+        l;
+    var installedHrTime = "_hrtime";
+    var installedNextTick = "_nextTick";
+
+    for (i = 0, l = clock.methods.length; i < l; i++) {
+        method = clock.methods[i];
+        if (method === "hrtime" && target.process) {
+            target.process.hrtime = clock[installedHrTime];
+        } else if (method === "nextTick" && target.process) {
+            target.process.nextTick = clock[installedNextTick];
+        } else {
+            if (target[method] && target[method].hadOwnProperty) {
+                target[method] = clock["_" + method];
+                if (method === "clearInterval" && config.shouldAdvanceTime === true) {
+                    target[method](clock.attachedInterval);
+                }
             } else {
-                throw new Error("Cannot clear timer: timer created with set" + timerType(timer)
-                                + "() but cleared with clear" + ttype + "()");
+                try {
+                    delete target[method];
+                } catch (ignore) { /* eslint empty-block: "off" */ }
             }
         }
     }
 
-    function uninstall(clock, target) {
-        var method,
-            i,
-            l;
-        var installedHrTime = "_hrtime";
+    // Prevent multiple executions which will completely remove these props
+    clock.methods = [];
 
-        for (i = 0, l = clock.methods.length; i < l; i++) {
-            method = clock.methods[i];
-            if (method === "hrtime" && target.process) {
-                target.process.hrtime = clock[installedHrTime];
-            } else {
-                if (target[method] && target[method].hadOwnProperty) {
-                    target[method] = clock["_" + method];
-                } else {
-                    try {
-                        delete target[method];
-                    } catch (ignore) { /* eslint empty-block: "off" */ }
-                }
+    // return pending timers, to enable checking what timers remained on uninstall
+    if (!clock.timers) {
+        return [];
+    }
+    return Object.keys(clock.timers).map(function mapper(key) {
+        return clock.timers[key];
+    });
+}
+
+function hijackMethod(target, method, clock) {
+    var prop;
+    clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
+    clock["_" + method] = target[method];
+
+    if (method === "Date") {
+        var date = mirrorDateProperties(clock[method], target[method]);
+        target[method] = date;
+    } else {
+        target[method] = function () {
+            return clock[method].apply(clock, arguments);
+        };
+
+        for (prop in clock[method]) {
+            if (clock[method].hasOwnProperty(prop)) {
+                target[method][prop] = clock[method][prop];
             }
         }
-
-        // Prevent multiple executions which will completely remove these props
-        clock.methods = [];
     }
 
-    function hijackMethod(target, method, clock) {
-        var prop;
+    target[method].clock = clock;
+}
 
-        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
-        clock["_" + method] = target[method];
+function doIntervalTick(clock, advanceTimeDelta) {
+    clock.tick(advanceTimeDelta);
+}
 
-        if (method === "Date") {
-            var date = mirrorDateProperties(clock[method], target[method]);
-            target[method] = date;
-        } else {
-            target[method] = function () {
-                return clock[method].apply(clock, arguments);
-            };
+var timers = {
+    setTimeout: setTimeout,
+    clearTimeout: clearTimeout,
+    setImmediate: global.setImmediate,
+    clearImmediate: global.clearImmediate,
+    setInterval: setInterval,
+    clearInterval: clearInterval,
+    Date: Date
+};
 
-            for (prop in clock[method]) {
-                if (clock[method].hasOwnProperty(prop)) {
-                    target[method][prop] = clock[method][prop];
-                }
-            }
-        }
+if (hrtimePresent) {
+    timers.hrtime = global.process.hrtime;
+}
 
-        target[method].clock = clock;
-    }
+if (nextTickPresent) {
+    timers.nextTick = global.process.nextTick;
+}
 
-    var timers = {
-        setTimeout: setTimeout,
-        clearTimeout: clearTimeout,
-        setImmediate: global.setImmediate,
-        clearImmediate: global.clearImmediate,
-        setInterval: setInterval,
-        clearInterval: clearInterval,
-        Date: Date
-    };
+if (performancePresent) {
+    timers.performance = global.performance;
+}
 
-    if (hrtimePresent) {
-        timers.hrtime = global.process.hrtime;
-    }
+if (requestAnimationFramePresent) {
+    timers.requestAnimationFrame = global.requestAnimationFrame;
+}
 
-    var keys = Object.keys || function (obj) {
-        var ks = [],
-            key;
+if (cancelAnimationFramePresent) {
+    timers.cancelAnimationFrame = global.cancelAnimationFrame;
+}
 
-        for (key in obj) {
-            if (obj.hasOwnProperty(key)) {
-                ks.push(key);
-            }
+var keys = Object.keys || function (obj) {
+    var ks = [];
+    var key;
+
+    for (key in obj) {
+        if (obj.hasOwnProperty(key)) {
+            ks.push(key);
         }
+    }
 
-        return ks;
-    };
+    return ks;
+};
 
-    exports.timers = timers;
+exports.timers = timers;
 
-    function createClock(now, loopLimit) {
-        loopLimit = loopLimit || 1000;
+/**
+ * @param start {Date|number} the system time
+ * @param loopLimit {number}  maximum number of timers that will be run when calling runAll()
+ */
+function createClock(start, loopLimit) {
+    start = start || 0;
+    loopLimit = loopLimit || 1000;
+
+    var clock = {
+        now: getEpoch(start),
+        hrNow: 0,
+        timeouts: {},
+        Date: createDate(),
+        loopLimit: loopLimit
+    };
 
-        var clock = {
-            now: getEpoch(now),
-            hrNow: 0,
-            timeouts: {},
-            Date: createDate(),
-            loopLimit: loopLimit
-        };
+    clock.Date.clock = clock;
 
-        clock.Date.clock = clock;
+    function getTimeToNextFrame() {
+        return 16 - ((clock.now - start) % 16);
+    }
 
-        clock.setTimeout = function setTimeout(func, timeout) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 2),
-                delay: timeout
-            });
-        };
+    clock.setTimeout = function setTimeout(func, timeout) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 2),
+            delay: timeout
+        });
+    };
 
-        clock.clearTimeout = function clearTimeout(timerId) {
-            return clearTimer(clock, timerId, "Timeout");
-        };
+    clock.clearTimeout = function clearTimeout(timerId) {
+        return clearTimer(clock, timerId, "Timeout");
+    };
+    clock.nextTick = function nextTick(func) {
+        return enqueueJob(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 1)
+        });
+    };
+    clock.setInterval = function setInterval(func, timeout) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 2),
+            delay: timeout,
+            interval: timeout
+        });
+    };
 
-        clock.setInterval = function setInterval(func, timeout) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 2),
-                delay: timeout,
-                interval: timeout
-            });
-        };
+    clock.clearInterval = function clearInterval(timerId) {
+        return clearTimer(clock, timerId, "Interval");
+    };
 
-        clock.clearInterval = function clearInterval(timerId) {
-            return clearTimer(clock, timerId, "Interval");
-        };
+    clock.setImmediate = function setImmediate(func) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 1),
+            immediate: true
+        });
+    };
 
-        clock.setImmediate = function setImmediate(func) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 1),
-                immediate: true
-            });
-        };
+    clock.clearImmediate = function clearImmediate(timerId) {
+        return clearTimer(clock, timerId, "Immediate");
+    };
 
-        clock.clearImmediate = function clearImmediate(timerId) {
-            return clearTimer(clock, timerId, "Immediate");
-        };
+    clock.requestAnimationFrame = function requestAnimationFrame(func) {
+        var result = addTimer(clock, {
+            func: func,
+            delay: getTimeToNextFrame(),
+            args: [clock.now + getTimeToNextFrame()],
+            animation: true
+        });
 
-        clock.tick = function tick(ms) {
-            ms = typeof ms === "number" ? ms : parseTime(ms);
-            var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
-            var timer = firstTimerInRange(clock, tickFrom, tickTo);
-            var oldNow;
+        return result.id || result;
+    };
 
-            clock.duringTick = true;
+    clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
+        return clearTimer(clock, timerId, "AnimationFrame");
+    };
 
-            function updateHrTime(newNow) {
-                clock.hrNow += (newNow - clock.now);
-            }
+    function updateHrTime(newNow) {
+        clock.hrNow += (newNow - clock.now);
+    }
 
-            var firstException;
-            while (timer && tickFrom <= tickTo) {
-                if (clock.timers[timer.id]) {
-                    updateHrTime(timer.callAt);
-                    tickFrom = timer.callAt;
-                    clock.now = timer.callAt;
-                    try {
-                        oldNow = clock.now;
-                        callTimer(clock, timer);
-                        // compensate for any setSystemTime() call during timer callback
-                        if (oldNow !== clock.now) {
-                            tickFrom += clock.now - oldNow;
-                            tickTo += clock.now - oldNow;
-                            previous += clock.now - oldNow;
-                        }
-                    } catch (e) {
-                        firstException = firstException || e;
-                    }
+    clock.tick = function tick(ms) {
+        ms = typeof ms === "number" ? ms : parseTime(ms);
+        var tickFrom = clock.now;
+        var tickTo = clock.now + ms;
+        var previous = clock.now;
+        var timer, firstException, oldNow;
+
+        clock.duringTick = true;
+
+        // perform process.nextTick()s
+        oldNow = clock.now;
+        runJobs(clock);
+        if (oldNow !== clock.now) {
+            // compensate for any setSystemTime() call during process.nextTick() callback
+            tickFrom += clock.now - oldNow;
+            tickTo += clock.now - oldNow;
+        }
+
+        // perform each timer in the requested range
+        timer = firstTimerInRange(clock, tickFrom, tickTo);
+        while (timer && tickFrom <= tickTo) {
+            if (clock.timers[timer.id]) {
+                updateHrTime(timer.callAt);
+                tickFrom = timer.callAt;
+                clock.now = timer.callAt;
+                oldNow = clock.now;
+                try {
+                    runJobs(clock);
+                    callTimer(clock, timer);
+                } catch (e) {
+                    firstException = firstException || e;
                 }
 
-                timer = firstTimerInRange(clock, previous, tickTo);
-                previous = tickFrom;
+                // compensate for any setSystemTime() call during timer callback
+                if (oldNow !== clock.now) {
+                    tickFrom += clock.now - oldNow;
+                    tickTo += clock.now - oldNow;
+                    previous += clock.now - oldNow;
+                }
             }
 
-            clock.duringTick = false;
+            timer = firstTimerInRange(clock, previous, tickTo);
+            previous = tickFrom;
+        }
+
+        // perform process.nextTick()s again
+        oldNow = clock.now;
+        runJobs(clock);
+        if (oldNow !== clock.now) {
+            // compensate for any setSystemTime() call during process.nextTick() callback
+            tickFrom += clock.now - oldNow;
+            tickTo += clock.now - oldNow;
+        }
+        clock.duringTick = false;
+
+        // corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
+        timer = firstTimerInRange(clock, tickFrom, tickTo);
+        if (timer) {
+            try {
+                clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
+            } catch (e) {
+                firstException = firstException || e;
+            }
+        } else {
+            // no timers remaining in the requested range: move the clock all the way to the end
             updateHrTime(tickTo);
             clock.now = tickTo;
+        }
+        if (firstException) {
+            throw firstException;
+        }
+        return clock.now;
+    };
 
-            if (firstException) {
-                throw firstException;
-            }
+    clock.next = function next() {
+        runJobs(clock);
+        var timer = firstTimer(clock);
+        if (!timer) {
+            return clock.now;
+        }
 
+        clock.duringTick = true;
+        try {
+            updateHrTime(timer.callAt);
+            clock.now = timer.callAt;
+            callTimer(clock, timer);
+            runJobs(clock);
             return clock.now;
-        };
+        } finally {
+            clock.duringTick = false;
+        }
+    };
 
-        clock.next = function next() {
-            var timer = firstTimer(clock);
-            if (!timer) {
+    clock.runAll = function runAll() {
+        var numTimers, i;
+        runJobs(clock);
+        for (i = 0; i < clock.loopLimit; i++) {
+            if (!clock.timers) {
                 return clock.now;
             }
 
-            clock.duringTick = true;
-            try {
-                clock.now = timer.callAt;
-                callTimer(clock, timer);
+            numTimers = keys(clock.timers).length;
+            if (numTimers === 0) {
                 return clock.now;
-            } finally {
-                clock.duringTick = false;
             }
-        };
 
-        clock.runAll = function runAll() {
-            var numTimers, i;
-            for (i = 0; i < clock.loopLimit; i++) {
-                if (!clock.timers) {
-                    return clock.now;
-                }
-
-                numTimers = Object.keys(clock.timers).length;
-                if (numTimers === 0) {
-                    return clock.now;
-                }
+            clock.next();
+        }
 
-                clock.next();
-            }
+        throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
+    };
 
-            throw new Error("Aborting after running " + clock.loopLimit + "timers, assuming an infinite loop!");
-        };
+    clock.runToFrame = function runToFrame() {
+        return clock.tick(getTimeToNextFrame());
+    };
 
-        clock.runToLast = function runToLast() {
-            var timer = lastTimer(clock);
-            if (!timer) {
-                return clock.now;
-            }
+    clock.runToLast = function runToLast() {
+        var timer = lastTimer(clock);
+        if (!timer) {
+            runJobs(clock);
+            return clock.now;
+        }
 
-            return clock.tick(timer.callAt);
-        };
+        return clock.tick(timer.callAt);
+    };
 
-        clock.reset = function reset() {
-            clock.timers = {};
-        };
+    clock.reset = function reset() {
+        clock.timers = {};
+    };
 
-        clock.setSystemTime = function setSystemTime(now) {
-            // determine time difference
-            var newNow = getEpoch(now);
-            var difference = newNow - clock.now;
-            var id, timer;
-
-            // update 'system clock'
-            clock.now = newNow;
-
-            // update timers and intervals to keep them stable
-            for (id in clock.timers) {
-                if (clock.timers.hasOwnProperty(id)) {
-                    timer = clock.timers[id];
-                    timer.createdAt += difference;
-                    timer.callAt += difference;
-                }
+    clock.setSystemTime = function setSystemTime(systemTime) {
+        // determine time difference
+        var newNow = getEpoch(systemTime);
+        var difference = newNow - clock.now;
+        var id, timer;
+
+        // update 'system clock'
+        clock.now = newNow;
+
+        // update timers and intervals to keep them stable
+        for (id in clock.timers) {
+            if (clock.timers.hasOwnProperty(id)) {
+                timer = clock.timers[id];
+                timer.createdAt += difference;
+                timer.callAt += difference;
             }
-        };
+        }
+    };
 
-        if (hrtimePresent) {
-            clock.hrtime = function (prev) {
-                if (Array.isArray(prev)) {
-                    var oldSecs = (prev[0] + prev[1] / 1e9);
-                    var newSecs = (clock.hrNow / 1000);
-                    var difference = (newSecs - oldSecs);
-                    var secs = fixedFloor(difference);
-                    var nanosecs = fixedModulo(difference * 1e9, 1e9);
-                    return [
-                        secs,
-                        nanosecs
-                    ];
-                }
+    if (performancePresent) {
+        clock.performance = Object.create(global.performance);
+        clock.performance.now = function lolexNow() {
+            return clock.hrNow;
+        };
+    }
+    if (hrtimePresent) {
+        clock.hrtime = function (prev) {
+            if (Array.isArray(prev)) {
+                var oldSecs = (prev[0] + prev[1] / 1e9);
+                var newSecs = (clock.hrNow / 1000);
+                var difference = (newSecs - oldSecs);
+                var secs = fixedFloor(difference);
+                var nanosecs = fixedModulo(difference * 1e9, 1e9);
                 return [
-                    fixedFloor(clock.hrNow / 1000),
-                    fixedModulo(clock.hrNow * 1e6, 1e9)
+                    secs,
+                    nanosecs
                 ];
-            };
-        }
-
-        return clock;
+            }
+            return [
+                fixedFloor(clock.hrNow / 1000),
+                fixedModulo(clock.hrNow * 1e6, 1e9)
+            ];
+        };
     }
-    exports.createClock = createClock;
 
-    exports.install = function install(target, now, toFake, loopLimit) {
-        var i,
-            l;
+    return clock;
+}
+exports.createClock = createClock;
 
-        if (typeof target === "number") {
-            toFake = now;
-            now = target;
-            target = null;
-        }
-
-        if (!target) {
-            target = global;
-        }
+/**
+ * @param config {Object} optional config
+ * @param config.target {Object} the target to install timers in (default `window`)
+ * @param config.now {number|Date}  a number (in milliseconds) or a Date object (default epoch)
+ * @param config.toFake {string[]} names of the methods that should be faked.
+ * @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
+ * @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
+ * @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
+ */
+exports.install = function install(config) {
+    if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
+        throw new TypeError("lolex.install called with " + String(config) +
+            " lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
+    }
+    config = typeof config !== "undefined" ? config : {};
+    config.shouldAdvanceTime = config.shouldAdvanceTime || false;
+    config.advanceTimeDelta = config.advanceTimeDelta || 20;
 
-        var clock = createClock(now, loopLimit);
+    var i, l;
+    var target = config.target || global;
+    var clock = createClock(config.now, config.loopLimit);
 
-        clock.uninstall = function () {
-            uninstall(clock, target);
-        };
+    clock.uninstall = function () {
+        return uninstall(clock, target, config);
+    };
 
-        clock.methods = toFake || [];
+    clock.methods = config.toFake || [];
 
-        if (clock.methods.length === 0) {
-            clock.methods = keys(timers);
-        }
+    if (clock.methods.length === 0) {
+        // do not fake nextTick by default - GitHub#126
+        clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
+    }
 
-        for (i = 0, l = clock.methods.length; i < l; i++) {
-            if (clock.methods[i] === "hrtime") {
-                if (target.process && typeof target.process.hrtime === "function") {
-                    hijackMethod(target.process, clock.methods[i], clock);
-                }
-            } else {
-                hijackMethod(target, clock.methods[i], clock);
+    for (i = 0, l = clock.methods.length; i < l; i++) {
+        if (clock.methods[i] === "hrtime") {
+            if (target.process && typeof target.process.hrtime === "function") {
+                hijackMethod(target.process, clock.methods[i], clock);
             }
+        } else if (clock.methods[i] === "nextTick") {
+            if (target.process && typeof target.process.nextTick === "function") {
+                hijackMethod(target.process, clock.methods[i], clock);
+            }
+        } else {
+            if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
+                var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
+                var intervalId = target[clock.methods[i]](
+                    intervalTick,
+                    config.advanceTimeDelta);
+                clock.attachedInterval = intervalId;
+            }
+            hijackMethod(target, clock.methods[i], clock);
         }
+    }
 
-        return clock;
-    };
-
-}(global || this));
+    return clock;
+};
 
 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
 },{}]},{},[1])(1)
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..6f5e003
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,4994 @@
+{
+  "name": "lolex",
+  "version": "2.3.2",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "JSONStream": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz",
+      "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=",
+      "dev": true,
+      "requires": {
+        "jsonparse": "1.3.1",
+        "through": "2.3.8"
+      }
+    },
+    "acorn": {
+      "version": "4.0.13",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+      "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
+      "dev": true
+    },
+    "acorn-jsx": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+      "dev": true,
+      "requires": {
+        "acorn": "3.3.0"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+          "dev": true
+        }
+      }
+    },
+    "agent-base": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz",
+      "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=",
+      "dev": true,
+      "requires": {
+        "extend": "3.0.1",
+        "semver": "5.0.3"
+      }
+    },
+    "ajv": {
+      "version": "5.5.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+      "dev": true,
+      "requires": {
+        "co": "4.6.0",
+        "fast-deep-equal": "1.0.0",
+        "fast-json-stable-stringify": "2.0.0",
+        "json-schema-traverse": "0.3.1"
+      }
+    },
+    "ajv-keywords": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+      "dev": true
+    },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true
+    },
+    "ansi-escapes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+      "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+      "dev": true
+    },
+    "ansi_up": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-1.3.0.tgz",
+      "integrity": "sha1-yclGv8C5u16qBgaEvyq6r+aLvUQ=",
+      "dev": true
+    },
+    "anymatch": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+      "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+      "dev": true,
+      "requires": {
+        "micromatch": "2.3.11",
+        "normalize-path": "2.1.1"
+      },
+      "dependencies": {
+        "normalize-path": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+          "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+          "dev": true,
+          "requires": {
+            "remove-trailing-separator": "1.1.0"
+          }
+        }
+      }
+    },
+    "app-root-path": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz",
+      "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=",
+      "dev": true
+    },
+    "argparse": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+      "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "1.0.3"
+      }
+    },
+    "arr-diff": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+      "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+      "dev": true,
+      "requires": {
+        "arr-flatten": "1.1.0"
+      }
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "array-filter": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz",
+      "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=",
+      "dev": true
+    },
+    "array-map": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz",
+      "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
+      "dev": true
+    },
+    "array-reduce": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz",
+      "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=",
+      "dev": true
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "dev": true,
+      "requires": {
+        "array-uniq": "1.0.3"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+      "dev": true
+    },
+    "array-unique": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+      "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+      "dev": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "dev": true
+    },
+    "asn1.js": {
+      "version": "4.9.2",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz",
+      "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "inherits": "2.0.3",
+        "minimalistic-assert": "1.0.0"
+      }
+    },
+    "assert": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+      "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+      "dev": true,
+      "requires": {
+        "util": "0.10.3"
+      }
+    },
+    "astw": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz",
+      "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=",
+      "dev": true,
+      "requires": {
+        "acorn": "4.0.13"
+      }
+    },
+    "async-each": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+      "dev": true
+    },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "esutils": "2.0.2",
+        "js-tokens": "3.0.2"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "bane": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/bane/-/bane-1.1.2.tgz",
+      "integrity": "sha1-vGQkjMgjFgx98/I4uH/mLEThB7k=",
+      "dev": true
+    },
+    "base64-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+      "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
+      "dev": true
+    },
+    "binary-extensions": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+      "dev": true
+    },
+    "bn.js": {
+      "version": "4.11.8",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.8",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+      "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+      "dev": true,
+      "requires": {
+        "balanced-match": "1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+      "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+      "dev": true,
+      "requires": {
+        "expand-range": "1.8.2",
+        "preserve": "0.2.0",
+        "repeat-element": "1.1.2"
+      }
+    },
+    "brorand": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "dev": true
+    },
+    "brout": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/brout/-/brout-1.2.0.tgz",
+      "integrity": "sha1-B3Hav3ltMS8KfB8SgeAPdmDPcC8=",
+      "dev": true,
+      "requires": {
+        "through2": "2.0.3"
+      }
+    },
+    "browser-pack": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.3.tgz",
+      "integrity": "sha512-Jo+RYsn8X8OhyP9tMXXg0ueR2fW696HUu1Hf3/DeiwNean1oGiPtdgGRNuUHBpPHzBH3x4n1kzAlgOgHSIq88g==",
+      "dev": true,
+      "requires": {
+        "JSONStream": "1.3.2",
+        "combine-source-map": "0.8.0",
+        "defined": "1.0.0",
+        "safe-buffer": "5.1.1",
+        "through2": "2.0.3",
+        "umd": "3.0.1"
+      }
+    },
+    "browser-reload": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/browser-reload/-/browser-reload-1.1.0.tgz",
+      "integrity": "sha1-UTwetc6RP+NqC6GOE5CcsHtCWpI=",
+      "dev": true
+    },
+    "browser-resolve": {
+      "version": "1.11.2",
+      "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
+      "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=",
+      "dev": true,
+      "requires": {
+        "resolve": "1.1.7"
+      },
+      "dependencies": {
+        "resolve": {
+          "version": "1.1.7",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+          "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+          "dev": true
+        }
+      }
+    },
+    "browser-stdout": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+      "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+      "dev": true
+    },
+    "browserify": {
+      "version": "14.4.0",
+      "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.4.0.tgz",
+      "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=",
+      "dev": true,
+      "requires": {
+        "JSONStream": "1.3.2",
+        "assert": "1.4.1",
+        "browser-pack": "6.0.3",
+        "browser-resolve": "1.11.2",
+        "browserify-zlib": "0.1.4",
+        "buffer": "5.0.8",
+        "cached-path-relative": "1.0.1",
+        "concat-stream": "1.5.2",
+        "console-browserify": "1.1.0",
+        "constants-browserify": "1.0.0",
+        "crypto-browserify": "3.12.0",
+        "defined": "1.0.0",
+        "deps-sort": "2.0.0",
+        "domain-browser": "1.1.7",
+        "duplexer2": "0.1.4",
+        "events": "1.1.1",
+        "glob": "7.1.2",
+        "has": "1.0.1",
+        "htmlescape": "1.1.1",
+        "https-browserify": "1.0.0",
+        "inherits": "2.0.3",
+        "insert-module-globals": "7.0.1",
+        "labeled-stream-splicer": "2.0.0",
+        "module-deps": "4.1.1",
+        "os-browserify": "0.1.2",
+        "parents": "1.0.1",
+        "path-browserify": "0.0.0",
+        "process": "0.11.10",
+        "punycode": "1.4.1",
+        "querystring-es3": "0.2.1",
+        "read-only-stream": "2.0.0",
+        "readable-stream": "2.3.3",
+        "resolve": "1.5.0",
+        "shasum": "1.0.2",
+        "shell-quote": "1.6.1",
+        "stream-browserify": "2.0.1",
+        "stream-http": "2.8.0",
+        "string_decoder": "1.0.3",
+        "subarg": "1.0.0",
+        "syntax-error": "1.3.0",
+        "through2": "2.0.3",
+        "timers-browserify": "1.4.2",
+        "tty-browserify": "0.0.0",
+        "url": "0.11.0",
+        "util": "0.10.3",
+        "vm-browserify": "0.0.4",
+        "xtend": "4.0.1"
+      }
+    },
+    "browserify-aes": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz",
+      "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==",
+      "dev": true,
+      "requires": {
+        "buffer-xor": "1.0.3",
+        "cipher-base": "1.0.4",
+        "create-hash": "1.1.3",
+        "evp_bytestokey": "1.0.3",
+        "inherits": "2.0.3",
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "browserify-cipher": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+      "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+      "dev": true,
+      "requires": {
+        "browserify-aes": "1.1.1",
+        "browserify-des": "1.0.0",
+        "evp_bytestokey": "1.0.3"
+      }
+    },
+    "browserify-des": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+      "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+      "dev": true,
+      "requires": {
+        "cipher-base": "1.0.4",
+        "des.js": "1.0.0",
+        "inherits": "2.0.3"
+      }
+    },
+    "browserify-rsa": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "randombytes": "2.0.6"
+      }
+    },
+    "browserify-sign": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+      "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "browserify-rsa": "4.0.1",
+        "create-hash": "1.1.3",
+        "create-hmac": "1.1.6",
+        "elliptic": "6.4.0",
+        "inherits": "2.0.3",
+        "parse-asn1": "5.1.0"
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+      "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+      "dev": true,
+      "requires": {
+        "pako": "0.2.9"
+      }
+    },
+    "buffer": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz",
+      "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==",
+      "dev": true,
+      "requires": {
+        "base64-js": "1.2.1",
+        "ieee754": "1.1.8"
+      }
+    },
+    "buffer-xor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "dev": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "builtin-status-codes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+      "dev": true
+    },
+    "cached-path-relative": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz",
+      "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=",
+      "dev": true
+    },
+    "caller-path": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+      "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+      "dev": true,
+      "requires": {
+        "callsites": "0.2.0"
+      }
+    },
+    "callsites": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+      "dev": true
+    },
+    "chalk": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+      "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "2.2.1",
+        "escape-string-regexp": "1.0.5",
+        "has-ansi": "2.0.0",
+        "strip-ansi": "3.0.1",
+        "supports-color": "2.0.0"
+      }
+    },
+    "chardet": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
+      "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
+      "dev": true
+    },
+    "chokidar": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+      "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+      "dev": true,
+      "requires": {
+        "anymatch": "1.3.2",
+        "async-each": "1.0.1",
+        "fsevents": "1.1.3",
+        "glob-parent": "2.0.0",
+        "inherits": "2.0.3",
+        "is-binary-path": "1.0.1",
+        "is-glob": "2.0.1",
+        "path-is-absolute": "1.0.1",
+        "readdirp": "2.1.0"
+      }
+    },
+    "ci-info": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz",
+      "integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==",
+      "dev": true
+    },
+    "cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "circular-json": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+      "dev": true
+    },
+    "cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "2.0.0"
+      }
+    },
+    "cli-spinners": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
+      "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
+      "dev": true
+    },
+    "cli-truncate": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
+      "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
+      "dev": true,
+      "requires": {
+        "slice-ansi": "0.0.4",
+        "string-width": "1.0.2"
+      },
+      "dependencies": {
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "1.0.1"
+          }
+        },
+        "slice-ansi": {
+          "version": "0.0.4",
+          "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+          "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
+          }
+        }
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+      "dev": true
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "dev": true
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "color-convert": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+      "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "combine-source-map": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+      "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=",
+      "dev": true,
+      "requires": {
+        "convert-source-map": "1.1.3",
+        "inline-source-map": "0.6.2",
+        "lodash.memoize": "3.0.4",
+        "source-map": "0.5.7"
+      }
+    },
+    "commander": {
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+      "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "concat-stream": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz",
+      "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.0.6",
+        "typedarray": "0.0.6"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "1.0.7",
+            "string_decoder": "0.10.31",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+          "dev": true
+        }
+      }
+    },
+    "console-browserify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+      "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+      "dev": true,
+      "requires": {
+        "date-now": "0.1.4"
+      }
+    },
+    "consolify": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/consolify/-/consolify-2.2.0.tgz",
+      "integrity": "sha1-YiHbEHSgjYQP8wpcDLvzxgmnT4w=",
+      "dev": true,
+      "requires": {
+        "ansi_up": "1.3.0",
+        "brout": "1.2.0",
+        "browser-reload": "1.1.0",
+        "source-mapper": "2.0.0",
+        "through2": "2.0.3"
+      }
+    },
+    "constants-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+      "dev": true
+    },
+    "convert-source-map": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+      "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cosmiconfig": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-1.1.0.tgz",
+      "integrity": "sha1-DeoPmATv37kp+7GxiOJVU+oFPTc=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "js-yaml": "3.10.0",
+        "minimist": "1.2.0",
+        "object-assign": "4.1.1",
+        "os-homedir": "1.0.2",
+        "parse-json": "2.2.0",
+        "pinkie-promise": "2.0.1",
+        "require-from-string": "1.2.1"
+      }
+    },
+    "coverify": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/coverify/-/coverify-1.5.0.tgz",
+      "integrity": "sha512-5MJtBUIfjeg3y7JZo8NCpHnWqODzNPKg1SC4gDDj20L8+7345U30NdAOeb4Gq3ILvnem9g64B9qYAMRVb6TBOg==",
+      "dev": true,
+      "requires": {
+        "convert-source-map": "1.1.3",
+        "falafel": "2.1.0",
+        "minimist": "1.2.0",
+        "slash": "1.0.0",
+        "source-map": "0.4.4",
+        "split2": "0.2.1",
+        "stream-combiner2": "1.1.1",
+        "through2": "0.6.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "1.0.34",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "0.0.1",
+            "string_decoder": "0.10.31"
+          }
+        },
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "requires": {
+            "amdefine": "1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+          "dev": true
+        },
+        "through2": {
+          "version": "0.6.5",
+          "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+          "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+          "dev": true,
+          "requires": {
+            "readable-stream": "1.0.34",
+            "xtend": "4.0.1"
+          }
+        }
+      }
+    },
+    "create-ecdh": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+      "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "elliptic": "6.4.0"
+      }
+    },
+    "create-hash": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+      "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+      "dev": true,
+      "requires": {
+        "cipher-base": "1.0.4",
+        "inherits": "2.0.3",
+        "ripemd160": "2.0.1",
+        "sha.js": "2.4.9"
+      }
+    },
+    "create-hmac": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+      "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+      "dev": true,
+      "requires": {
+        "cipher-base": "1.0.4",
+        "create-hash": "1.1.3",
+        "inherits": "2.0.3",
+        "ripemd160": "2.0.1",
+        "safe-buffer": "5.1.1",
+        "sha.js": "2.4.9"
+      }
+    },
+    "cross-spawn": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+      "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "4.1.1",
+        "shebang-command": "1.2.0",
+        "which": "1.3.0"
+      }
+    },
+    "cross-spawn-async": {
+      "version": "2.2.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+      "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "4.1.1",
+        "which": "1.3.0"
+      }
+    },
+    "crypto-browserify": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dev": true,
+      "requires": {
+        "browserify-cipher": "1.0.0",
+        "browserify-sign": "4.0.4",
+        "create-ecdh": "4.0.0",
+        "create-hash": "1.1.3",
+        "create-hmac": "1.1.6",
+        "diffie-hellman": "5.0.2",
+        "inherits": "2.0.3",
+        "pbkdf2": "3.0.14",
+        "public-encrypt": "4.0.0",
+        "randombytes": "2.0.6",
+        "randomfill": "1.0.3"
+      }
+    },
+    "date-fns": {
+      "version": "1.29.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
+      "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
+      "dev": true
+    },
+    "date-now": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+      "dev": true
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "dev": true
+    },
+    "define-properties": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+      "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+      "dev": true,
+      "requires": {
+        "foreach": "2.0.5",
+        "object-keys": "1.0.11"
+      }
+    },
+    "defined": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+      "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+      "dev": true
+    },
+    "del": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+      "dev": true,
+      "requires": {
+        "globby": "5.0.0",
+        "is-path-cwd": "1.0.0",
+        "is-path-in-cwd": "1.0.0",
+        "object-assign": "4.1.1",
+        "pify": "2.3.0",
+        "pinkie-promise": "2.0.1",
+        "rimraf": "2.6.2"
+      }
+    },
+    "deps-sort": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz",
+      "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=",
+      "dev": true,
+      "requires": {
+        "JSONStream": "1.3.2",
+        "shasum": "1.0.2",
+        "subarg": "1.0.0",
+        "through2": "2.0.3"
+      }
+    },
+    "des.js": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+      "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "minimalistic-assert": "1.0.0"
+      }
+    },
+    "detective": {
+      "version": "4.7.1",
+      "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz",
+      "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==",
+      "dev": true,
+      "requires": {
+        "acorn": "5.3.0",
+        "defined": "1.0.0"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
+          "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==",
+          "dev": true
+        }
+      }
+    },
+    "diff": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
+      "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
+      "dev": true
+    },
+    "diffie-hellman": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+      "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "miller-rabin": "4.0.1",
+        "randombytes": "2.0.6"
+      }
+    },
+    "doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "requires": {
+        "esutils": "2.0.2"
+      }
+    },
+    "domain-browser": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+      "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=",
+      "dev": true
+    },
+    "duplexer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+      "dev": true
+    },
+    "duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "2.3.3"
+      }
+    },
+    "elegant-spinner": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
+      "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
+      "dev": true
+    },
+    "elliptic": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+      "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "brorand": "1.1.0",
+        "hash.js": "1.1.3",
+        "hmac-drbg": "1.0.1",
+        "inherits": "2.0.3",
+        "minimalistic-assert": "1.0.0",
+        "minimalistic-crypto-utils": "1.0.1"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+      "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "0.2.1"
+      }
+    },
+    "es-abstract": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz",
+      "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "1.1.1",
+        "function-bind": "1.1.1",
+        "has": "1.0.1",
+        "is-callable": "1.1.3",
+        "is-regex": "1.0.4"
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
+      "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+      "dev": true,
+      "requires": {
+        "is-callable": "1.1.3",
+        "is-date-object": "1.0.1",
+        "is-symbol": "1.0.1"
+      }
+    },
+    "es5-shim": {
+      "version": "4.5.10",
+      "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz",
+      "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "eslint": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.2.0.tgz",
+      "integrity": "sha1-orMYQRGxmOAunH88ymJaXgHFaz0=",
+      "dev": true,
+      "requires": {
+        "ajv": "5.5.2",
+        "babel-code-frame": "6.26.0",
+        "chalk": "1.1.3",
+        "concat-stream": "1.6.0",
+        "debug": "2.6.9",
+        "doctrine": "2.1.0",
+        "eslint-scope": "3.7.1",
+        "espree": "3.5.2",
+        "esquery": "1.0.0",
+        "estraverse": "4.2.0",
+        "esutils": "2.0.2",
+        "file-entry-cache": "2.0.0",
+        "glob": "7.1.2",
+        "globals": "9.18.0",
+        "ignore": "3.3.7",
+        "imurmurhash": "0.1.4",
+        "inquirer": "3.3.0",
+        "is-resolvable": "1.0.1",
+        "js-yaml": "3.10.0",
+        "json-stable-stringify": "1.0.1",
+        "levn": "0.3.0",
+        "lodash": "4.17.4",
+        "minimatch": "3.0.4",
+        "mkdirp": "0.5.1",
+        "natural-compare": "1.4.0",
+        "optionator": "0.8.2",
+        "path-is-inside": "1.0.2",
+        "pluralize": "4.0.0",
+        "progress": "2.0.0",
+        "require-uncached": "1.0.3",
+        "strip-json-comments": "2.0.1",
+        "table": "4.0.2",
+        "text-table": "0.2.0"
+      },
+      "dependencies": {
+        "concat-stream": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+          "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.3",
+            "readable-stream": "2.3.3",
+            "typedarray": "0.0.6"
+          }
+        },
+        "json-stable-stringify": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+          "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+          "dev": true,
+          "requires": {
+            "jsonify": "0.0.0"
+          }
+        }
+      }
+    },
+    "eslint-config-sinon": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-config-sinon/-/eslint-config-sinon-1.0.3.tgz",
+      "integrity": "sha1-6vcFIqGL8yUKuQMcfEPw2LD0Daw=",
+      "dev": true
+    },
+    "eslint-plugin-ie11": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-ie11/-/eslint-plugin-ie11-1.0.0.tgz",
+      "integrity": "sha512-PPv2Cbq5roUmoIZJfPWbEEILHvi2Yfp/cRVzaVKL/YJiYGGLJ0/Qrq1HKd2OZKb3RQQOXweCd/hh261bljEe8A==",
+      "dev": true,
+      "requires": {
+        "requireindex": "1.1.0"
+      }
+    },
+    "eslint-plugin-mocha": {
+      "version": "4.11.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-4.11.0.tgz",
+      "integrity": "sha1-kRk6L1XiCl41l0BUoAidMBmO5Xg=",
+      "dev": true,
+      "requires": {
+        "ramda": "0.24.1"
+      }
+    },
+    "eslint-scope": {
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+      "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+      "dev": true,
+      "requires": {
+        "esrecurse": "4.2.0",
+        "estraverse": "4.2.0"
+      }
+    },
+    "espree": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
+      "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
+      "dev": true,
+      "requires": {
+        "acorn": "5.3.0",
+        "acorn-jsx": "3.0.1"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
+          "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==",
+          "dev": true
+        }
+      }
+    },
+    "esprima": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+      "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+      "dev": true
+    },
+    "esquery": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
+      "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
+      "dev": true,
+      "requires": {
+        "estraverse": "4.2.0"
+      }
+    },
+    "esrecurse": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
+      "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+      "dev": true,
+      "requires": {
+        "estraverse": "4.2.0",
+        "object-assign": "4.1.1"
+      }
+    },
+    "estraverse": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "dev": true
+    },
+    "event-stream": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+      "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+      "dev": true,
+      "requires": {
+        "duplexer": "0.1.1",
+        "from": "0.1.7",
+        "map-stream": "0.1.0",
+        "pause-stream": "0.0.11",
+        "split": "0.3.3",
+        "stream-combiner": "0.0.4",
+        "through": "2.3.8"
+      }
+    },
+    "events": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+      "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+      "dev": true
+    },
+    "evp_bytestokey": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "dev": true,
+      "requires": {
+        "md5.js": "1.3.4",
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "execa": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+      "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "5.1.0",
+        "get-stream": "3.0.0",
+        "is-stream": "1.1.0",
+        "npm-run-path": "2.0.2",
+        "p-finally": "1.0.0",
+        "signal-exit": "3.0.2",
+        "strip-eof": "1.0.0"
+      }
+    },
+    "exit-hook": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+      "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
+      "dev": true
+    },
+    "expand-brackets": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+      "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+      "dev": true,
+      "requires": {
+        "is-posix-bracket": "0.1.1"
+      }
+    },
+    "expand-range": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "dev": true,
+      "requires": {
+        "fill-range": "2.2.3"
+      }
+    },
+    "extend": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+      "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
+      "dev": true
+    },
+    "external-editor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+      "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
+      "dev": true,
+      "requires": {
+        "chardet": "0.4.2",
+        "iconv-lite": "0.4.19",
+        "tmp": "0.0.33"
+      }
+    },
+    "extglob": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+      "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+      "dev": true,
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
+    },
+    "falafel": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz",
+      "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=",
+      "dev": true,
+      "requires": {
+        "acorn": "5.3.0",
+        "foreach": "2.0.5",
+        "isarray": "0.0.1",
+        "object-keys": "1.0.11"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
+          "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==",
+          "dev": true
+        },
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        }
+      }
+    },
+    "fast-deep-equal": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
+      "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
+      "dev": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+      "dev": true
+    },
+    "figures": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "1.0.5"
+      }
+    },
+    "file-entry-cache": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+      "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+      "dev": true,
+      "requires": {
+        "flat-cache": "1.3.0",
+        "object-assign": "4.1.1"
+      }
+    },
+    "filename-regex": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+      "dev": true
+    },
+    "fill-range": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+      "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+      "dev": true,
+      "requires": {
+        "is-number": "2.1.0",
+        "isobject": "2.1.0",
+        "randomatic": "1.1.7",
+        "repeat-element": "1.1.2",
+        "repeat-string": "1.6.1"
+      }
+    },
+    "flat-cache": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "dev": true,
+      "requires": {
+        "circular-json": "0.3.3",
+        "del": "2.2.2",
+        "graceful-fs": "4.1.11",
+        "write": "0.2.1"
+      }
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
+    "for-own": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+      "dev": true,
+      "requires": {
+        "for-in": "1.0.2"
+      }
+    },
+    "foreach": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+      "dev": true
+    },
+    "formatio": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz",
+      "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=",
+      "dev": true,
+      "requires": {
+        "samsam": "1.3.0"
+      }
+    },
+    "from": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+      "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
+      "dev": true
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+      "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "nan": "2.8.0",
+        "node-pre-gyp": "0.6.39"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ajv": {
+          "version": "4.11.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "co": "4.6.0",
+            "json-stable-stringify": "1.0.1"
+          }
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "aproba": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "delegates": "1.0.0",
+            "readable-stream": "2.2.9"
+          }
+        },
+        "asn1": {
+          "version": "0.2.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "assert-plus": {
+          "version": "0.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "asynckit": {
+          "version": "0.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "aws-sign2": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "aws4": {
+          "version": "1.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "balanced-match": {
+          "version": "0.4.2",
+          "bundled": true,
+          "dev": true
+        },
+        "bcrypt-pbkdf": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "tweetnacl": "0.14.5"
+          }
+        },
+        "block-stream": {
+          "version": "0.0.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.3"
+          }
+        },
+        "boom": {
+          "version": "2.10.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hoek": "2.16.3"
+          }
+        },
+        "brace-expansion": {
+          "version": "1.1.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "balanced-match": "0.4.2",
+            "concat-map": "0.0.1"
+          }
+        },
+        "buffer-shims": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "caseless": {
+          "version": "0.12.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "co": {
+          "version": "4.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "combined-stream": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "delayed-stream": "1.0.0"
+          }
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "cryptiles": {
+          "version": "2.0.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "boom": "2.10.1"
+          }
+        },
+        "dashdash": {
+          "version": "1.14.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "1.0.0"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "debug": {
+          "version": "2.6.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "deep-extend": {
+          "version": "0.4.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "delayed-stream": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ecc-jsbn": {
+          "version": "0.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsbn": "0.1.1"
+          }
+        },
+        "extend": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "extsprintf": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "forever-agent": {
+          "version": "0.6.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "form-data": {
+          "version": "2.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "asynckit": "0.4.0",
+            "combined-stream": "1.0.5",
+            "mime-types": "2.1.15"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "fstream": {
+          "version": "1.0.11",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "graceful-fs": "4.1.11",
+            "inherits": "2.0.3",
+            "mkdirp": "0.5.1",
+            "rimraf": "2.6.1"
+          }
+        },
+        "fstream-ignore": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "fstream": "1.0.11",
+            "inherits": "2.0.3",
+            "minimatch": "3.0.4"
+          }
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aproba": "1.1.1",
+            "console-control-strings": "1.1.0",
+            "has-unicode": "2.0.1",
+            "object-assign": "4.1.1",
+            "signal-exit": "3.0.2",
+            "string-width": "1.0.2",
+            "strip-ansi": "3.0.1",
+            "wide-align": "1.1.2"
+          }
+        },
+        "getpass": {
+          "version": "0.1.7",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "1.0.0"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "glob": {
+          "version": "7.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "fs.realpath": "1.0.0",
+            "inflight": "1.0.6",
+            "inherits": "2.0.3",
+            "minimatch": "3.0.4",
+            "once": "1.4.0",
+            "path-is-absolute": "1.0.1"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.1.11",
+          "bundled": true,
+          "dev": true
+        },
+        "har-schema": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "har-validator": {
+          "version": "4.2.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ajv": "4.11.8",
+            "har-schema": "1.0.5"
+          }
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "hawk": {
+          "version": "3.1.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "boom": "2.10.1",
+            "cryptiles": "2.0.5",
+            "hoek": "2.16.3",
+            "sntp": "1.0.9"
+          }
+        },
+        "hoek": {
+          "version": "2.16.3",
+          "bundled": true,
+          "dev": true
+        },
+        "http-signature": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "0.2.0",
+            "jsprim": "1.4.0",
+            "sshpk": "1.13.0"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "once": "1.4.0",
+            "wrappy": "1.0.2"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "ini": {
+          "version": "1.3.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "number-is-nan": "1.0.1"
+          }
+        },
+        "is-typedarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "isstream": {
+          "version": "0.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jodid25519": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsbn": "0.1.1"
+          }
+        },
+        "jsbn": {
+          "version": "0.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "json-schema": {
+          "version": "0.2.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "json-stable-stringify": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "jsonify": "0.0.0"
+          }
+        },
+        "json-stringify-safe": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jsonify": {
+          "version": "0.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "jsprim": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "assert-plus": "1.0.0",
+            "extsprintf": "1.0.2",
+            "json-schema": "0.2.3",
+            "verror": "1.3.6"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "mime-db": {
+          "version": "1.27.0",
+          "bundled": true,
+          "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.15",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mime-db": "1.27.0"
+          }
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "brace-expansion": "1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true,
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "node-pre-gyp": {
+          "version": "0.6.39",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "1.0.2",
+            "hawk": "3.1.3",
+            "mkdirp": "0.5.1",
+            "nopt": "4.0.1",
+            "npmlog": "4.1.0",
+            "rc": "1.2.1",
+            "request": "2.81.0",
+            "rimraf": "2.6.1",
+            "semver": "5.3.0",
+            "tar": "2.2.1",
+            "tar-pack": "3.4.0"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1.1.0",
+            "osenv": "0.1.4"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "are-we-there-yet": "1.1.4",
+            "console-control-strings": "1.1.0",
+            "gauge": "2.7.4",
+            "set-blocking": "2.0.0"
+          }
+        },
+        "number-is-nan": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "oauth-sign": {
+          "version": "0.8.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "wrappy": "1.0.2"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "1.0.2",
+            "os-tmpdir": "1.0.2"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "performance-now": {
+          "version": "0.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "bundled": true,
+          "dev": true
+        },
+        "punycode": {
+          "version": "1.4.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "qs": {
+          "version": "6.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "0.4.2",
+            "ini": "1.3.4",
+            "minimist": "1.2.0",
+            "strip-json-comments": "2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.2.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "buffer-shims": "1.0.0",
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "1.0.7",
+            "string_decoder": "1.0.1",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "request": {
+          "version": "2.81.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aws-sign2": "0.6.0",
+            "aws4": "1.6.0",
+            "caseless": "0.12.0",
+            "combined-stream": "1.0.5",
+            "extend": "3.0.1",
+            "forever-agent": "0.6.1",
+            "form-data": "2.1.4",
+            "har-validator": "4.2.1",
+            "hawk": "3.1.3",
+            "http-signature": "1.1.1",
+            "is-typedarray": "1.0.0",
+            "isstream": "0.1.2",
+            "json-stringify-safe": "5.0.1",
+            "mime-types": "2.1.15",
+            "oauth-sign": "0.8.2",
+            "performance-now": "0.2.0",
+            "qs": "6.4.0",
+            "safe-buffer": "5.0.1",
+            "stringstream": "0.0.5",
+            "tough-cookie": "2.3.2",
+            "tunnel-agent": "0.6.0",
+            "uuid": "3.0.1"
+          }
+        },
+        "rimraf": {
+          "version": "2.6.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "glob": "7.1.2"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "semver": {
+          "version": "5.3.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "sntp": {
+          "version": "1.0.9",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hoek": "2.16.3"
+          }
+        },
+        "sshpk": {
+          "version": "1.13.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "asn1": "0.2.3",
+            "assert-plus": "1.0.0",
+            "bcrypt-pbkdf": "1.0.1",
+            "dashdash": "1.14.1",
+            "ecc-jsbn": "0.1.1",
+            "getpass": "0.1.7",
+            "jodid25519": "1.0.2",
+            "jsbn": "0.1.1",
+            "tweetnacl": "0.14.5"
+          },
+          "dependencies": {
+            "assert-plus": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.0.1"
+          }
+        },
+        "stringstream": {
+          "version": "0.0.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "2.2.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "block-stream": "0.0.9",
+            "fstream": "1.0.11",
+            "inherits": "2.0.3"
+          }
+        },
+        "tar-pack": {
+          "version": "3.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "debug": "2.6.8",
+            "fstream": "1.0.11",
+            "fstream-ignore": "1.0.5",
+            "once": "1.4.0",
+            "readable-stream": "2.2.9",
+            "rimraf": "2.6.1",
+            "tar": "2.2.1",
+            "uid-number": "0.0.6"
+          }
+        },
+        "tough-cookie": {
+          "version": "2.3.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "punycode": "1.4.1"
+          }
+        },
+        "tunnel-agent": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "5.0.1"
+          }
+        },
+        "tweetnacl": {
+          "version": "0.14.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "uid-number": {
+          "version": "0.0.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "uuid": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "verror": {
+          "version": "1.3.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "extsprintf": "1.0.2"
+          }
+        },
+        "wide-align": {
+          "version": "1.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "string-width": "1.0.2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        }
+      }
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "get-stream": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+      "dev": true
+    },
+    "glob": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "1.0.0",
+        "inflight": "1.0.6",
+        "inherits": "2.0.3",
+        "minimatch": "3.0.4",
+        "once": "1.4.0",
+        "path-is-absolute": "1.0.1"
+      }
+    },
+    "glob-base": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "dev": true,
+      "requires": {
+        "glob-parent": "2.0.0",
+        "is-glob": "2.0.1"
+      }
+    },
+    "glob-parent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+      "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+      "dev": true,
+      "requires": {
+        "is-glob": "2.0.1"
+      }
+    },
+    "globals": {
+      "version": "9.18.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+      "dev": true
+    },
+    "globby": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+      "dev": true,
+      "requires": {
+        "array-union": "1.0.2",
+        "arrify": "1.0.1",
+        "glob": "7.1.2",
+        "object-assign": "4.1.1",
+        "pify": "2.3.0",
+        "pinkie-promise": "2.0.1"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "dev": true
+    },
+    "growl": {
+      "version": "1.10.3",
+      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
+      "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
+      "dev": true
+    },
+    "has": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
+      "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+      "dev": true,
+      "requires": {
+        "function-bind": "1.1.1"
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "2.1.1"
+      }
+    },
+    "has-flag": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+      "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+      "dev": true
+    },
+    "hash-base": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+      "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3"
+      }
+    },
+    "hash.js": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+      "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "minimalistic-assert": "1.0.0"
+      }
+    },
+    "he": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+      "dev": true
+    },
+    "hmac-drbg": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "dev": true,
+      "requires": {
+        "hash.js": "1.1.3",
+        "minimalistic-assert": "1.0.0",
+        "minimalistic-crypto-utils": "1.0.1"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
+      "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
+      "dev": true
+    },
+    "htmlescape": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+      "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=",
+      "dev": true
+    },
+    "https-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+      "dev": true
+    },
+    "https-proxy-agent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
+      "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=",
+      "dev": true,
+      "requires": {
+        "agent-base": "2.1.1",
+        "debug": "2.6.9",
+        "extend": "3.0.1"
+      }
+    },
+    "husky": {
+      "version": "0.14.3",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
+      "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==",
+      "dev": true,
+      "requires": {
+        "is-ci": "1.1.0",
+        "normalize-path": "1.0.0",
+        "strip-indent": "2.0.0"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.19",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+      "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+      "dev": true
+    },
+    "ieee754": {
+      "version": "1.1.8",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+      "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
+      "dev": true
+    },
+    "ignore": {
+      "version": "3.3.7",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
+      "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
+      "dev": true
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "requires": {
+        "repeating": "2.0.1"
+      }
+    },
+    "indexof": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "1.4.0",
+        "wrappy": "1.0.2"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
+    },
+    "inline-source-map": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+      "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=",
+      "dev": true,
+      "requires": {
+        "source-map": "0.5.7"
+      }
+    },
+    "inquirer": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+      "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "3.0.0",
+        "chalk": "2.3.0",
+        "cli-cursor": "2.1.0",
+        "cli-width": "2.2.0",
+        "external-editor": "2.1.0",
+        "figures": "2.0.0",
+        "lodash": "4.17.4",
+        "mute-stream": "0.0.7",
+        "run-async": "2.3.0",
+        "rx-lite": "4.0.8",
+        "rx-lite-aggregates": "4.0.8",
+        "string-width": "2.1.1",
+        "strip-ansi": "4.0.0",
+        "through": "2.3.8"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+          "dev": true,
+          "requires": {
+            "color-convert": "1.9.1"
+          }
+        },
+        "chalk": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+          "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "3.2.0",
+            "escape-string-regexp": "1.0.5",
+            "supports-color": "4.5.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "3.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
+        }
+      }
+    },
+    "insert-module-globals": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz",
+      "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=",
+      "dev": true,
+      "requires": {
+        "JSONStream": "1.3.2",
+        "combine-source-map": "0.7.2",
+        "concat-stream": "1.5.2",
+        "is-buffer": "1.1.6",
+        "lexical-scope": "1.2.0",
+        "process": "0.11.10",
+        "through2": "2.0.3",
+        "xtend": "4.0.1"
+      },
+      "dependencies": {
+        "combine-source-map": {
+          "version": "0.7.2",
+          "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz",
+          "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=",
+          "dev": true,
+          "requires": {
+            "convert-source-map": "1.1.3",
+            "inline-source-map": "0.6.2",
+            "lodash.memoize": "3.0.4",
+            "source-map": "0.5.7"
+          }
+        }
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "1.11.0"
+      }
+    },
+    "is-buffer": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+      "dev": true
+    },
+    "is-builtin-module": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+      "dev": true,
+      "requires": {
+        "builtin-modules": "1.1.1"
+      }
+    },
+    "is-callable": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
+      "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
+      "dev": true
+    },
+    "is-ci": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
+      "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==",
+      "dev": true,
+      "requires": {
+        "ci-info": "1.1.2"
+      }
+    },
+    "is-date-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "dev": true
+    },
+    "is-dotfile": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+      "dev": true
+    },
+    "is-equal-shallow": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "dev": true,
+      "requires": {
+        "is-primitive": "2.0.0"
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
+    "is-extglob": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+      "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+      "dev": true
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "1.0.1"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "dev": true
+    },
+    "is-glob": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+      "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+      "dev": true,
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
+    },
+    "is-number": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+      "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+      "dev": true,
+      "requires": {
+        "kind-of": "3.2.2"
+      }
+    },
+    "is-path-cwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+      "dev": true
+    },
+    "is-path-in-cwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+      "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+      "dev": true,
+      "requires": {
+        "is-path-inside": "1.0.1"
+      }
+    },
+    "is-path-inside": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+      "dev": true,
+      "requires": {
+        "path-is-inside": "1.0.2"
+      }
+    },
+    "is-posix-bracket": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "dev": true
+    },
+    "is-primitive": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+      "dev": true
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-regex": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+      "dev": true,
+      "requires": {
+        "has": "1.0.1"
+      }
+    },
+    "is-resolvable": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz",
+      "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "dev": true
+    },
+    "is-symbol": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
+      "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+      "dev": true
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "isobject": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+      "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+      "dev": true,
+      "requires": {
+        "isarray": "1.0.0"
+      }
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.10.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+      "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+      "dev": true,
+      "requires": {
+        "argparse": "1.0.9",
+        "esprima": "4.0.0"
+      }
+    },
+    "json-schema-traverse": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+      "dev": true
+    },
+    "json-stable-stringify": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz",
+      "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=",
+      "dev": true,
+      "requires": {
+        "jsonify": "0.0.0"
+      }
+    },
+    "jsonify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+      "dev": true
+    },
+    "jsonparse": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+      "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+      "dev": true
+    },
+    "just-extend": {
+      "version": "1.1.27",
+      "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz",
+      "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==",
+      "dev": true
+    },
+    "kind-of": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+      "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+      "dev": true,
+      "requires": {
+        "is-buffer": "1.1.6"
+      }
+    },
+    "labeled-stream-splicer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz",
+      "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "isarray": "0.0.1",
+        "stream-splicer": "2.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        }
+      }
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "1.1.2",
+        "type-check": "0.3.2"
+      }
+    },
+    "lexical-scope": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz",
+      "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=",
+      "dev": true,
+      "requires": {
+        "astw": "2.2.0"
+      }
+    },
+    "lint-staged": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-4.0.2.tgz",
+      "integrity": "sha1-joPhHp4WVsCbYRf22w1V/UlgocA=",
+      "dev": true,
+      "requires": {
+        "app-root-path": "2.0.1",
+        "cosmiconfig": "1.1.0",
+        "execa": "0.7.0",
+        "listr": "0.12.0",
+        "lodash.chunk": "4.2.0",
+        "minimatch": "3.0.4",
+        "npm-which": "3.0.1",
+        "p-map": "1.2.0",
+        "staged-git-files": "0.0.4"
+      }
+    },
+    "listen": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/listen/-/listen-1.0.1.tgz",
+      "integrity": "sha1-/u3j1ah0xTwihNPDWXpfxa/HTkM=",
+      "dev": true
+    },
+    "listr": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",
+      "integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "figures": "1.7.0",
+        "indent-string": "2.1.0",
+        "is-promise": "2.1.0",
+        "is-stream": "1.1.0",
+        "listr-silent-renderer": "1.1.1",
+        "listr-update-renderer": "0.2.0",
+        "listr-verbose-renderer": "0.4.1",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "ora": "0.2.3",
+        "p-map": "1.2.0",
+        "rxjs": "5.5.6",
+        "stream-to-observable": "0.1.0",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        }
+      }
+    },
+    "listr-silent-renderer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
+      "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
+      "dev": true
+    },
+    "listr-update-renderer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz",
+      "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "elegant-spinner": "1.0.1",
+        "figures": "1.7.0",
+        "indent-string": "3.2.0",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "indent-string": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+          "dev": true
+        }
+      }
+    },
+    "listr-verbose-renderer": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
+      "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-cursor": "1.0.2",
+        "date-fns": "1.29.0",
+        "figures": "1.7.0"
+      },
+      "dependencies": {
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
+    "load-json-file": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+      "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "parse-json": "2.2.0",
+        "pify": "2.3.0",
+        "strip-bom": "3.0.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.4",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+      "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+      "dev": true
+    },
+    "lodash.chunk": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
+      "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=",
+      "dev": true
+    },
+    "lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+      "dev": true
+    },
+    "lodash.memoize": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+      "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=",
+      "dev": true
+    },
+    "log-symbols": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+      "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3"
+      }
+    },
+    "log-update": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
+      "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "1.4.0",
+        "cli-cursor": "1.0.2"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+          "dev": true
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
+    "lolex": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz",
+      "integrity": "sha512-mQuW55GhduF3ppo+ZRUTz1PRjEh1hS5BbqU7d8D0ez2OKxHDod7StPPeAVKisZR5aLkHZjdGWSL42LSONUJsZw==",
+      "dev": true
+    },
+    "lru-cache": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+      "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+      "dev": true,
+      "requires": {
+        "pseudomap": "1.0.2",
+        "yallist": "2.1.2"
+      }
+    },
+    "map-stream": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+      "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+      "dev": true
+    },
+    "md5.js": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+      "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+      "dev": true,
+      "requires": {
+        "hash-base": "3.0.4",
+        "inherits": "2.0.3"
+      },
+      "dependencies": {
+        "hash-base": {
+          "version": "3.0.4",
+          "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+          "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.3",
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
+    "micromatch": {
+      "version": "2.3.11",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+      "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+      "dev": true,
+      "requires": {
+        "arr-diff": "2.0.0",
+        "array-unique": "0.2.1",
+        "braces": "1.8.5",
+        "expand-brackets": "0.1.5",
+        "extglob": "0.3.2",
+        "filename-regex": "2.0.1",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1",
+        "kind-of": "3.2.2",
+        "normalize-path": "2.1.1",
+        "object.omit": "2.0.1",
+        "parse-glob": "3.0.4",
+        "regex-cache": "0.4.4"
+      },
+      "dependencies": {
+        "normalize-path": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+          "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+          "dev": true,
+          "requires": {
+            "remove-trailing-separator": "1.1.0"
+          }
+        }
+      }
+    },
+    "miller-rabin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "brorand": "1.1.0"
+      }
+    },
+    "mimic-fn": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
+      "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
+      "dev": true
+    },
+    "min-wd": {
+      "version": "2.9.3",
+      "resolved": "https://registry.npmjs.org/min-wd/-/min-wd-2.9.3.tgz",
+      "integrity": "sha1-Nda8fTL2bmAZK6vf1sFnTpkvE70=",
+      "dev": true,
+      "requires": {
+        "brout": "1.2.0",
+        "listen": "1.0.1",
+        "resolve": "1.5.0",
+        "saucelabs": "1.4.0",
+        "source-mapper": "2.0.0",
+        "through2": "2.0.3"
+      }
+    },
+    "minimalistic-assert": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+      "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=",
+      "dev": true
+    },
+    "minimalistic-crypto-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "1.1.8"
+      }
+    },
+    "minimist": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+          "dev": true
+        }
+      }
+    },
+    "mocaccino": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/mocaccino/-/mocaccino-3.0.0.tgz",
+      "integrity": "sha512-mc0xkHFGxnW4B49la2LG8qaHBIiLArqG9zkgP+byp/kmWby1/Bi8CIpwBKANu91SkZ/c4Qk+0JnYM5u1PXEQYw==",
+      "dev": true,
+      "requires": {
+        "brout": "1.2.0",
+        "listen": "1.0.1",
+        "mocha": "4.0.1",
+        "resolve": "1.5.0",
+        "supports-color": "3.2.3",
+        "through2": "2.0.3"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "3.2.3",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+          "dev": true,
+          "requires": {
+            "has-flag": "1.0.0"
+          }
+        }
+      }
+    },
+    "mocha": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz",
+      "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==",
+      "dev": true,
+      "requires": {
+        "browser-stdout": "1.3.0",
+        "commander": "2.11.0",
+        "debug": "3.1.0",
+        "diff": "3.3.1",
+        "escape-string-regexp": "1.0.5",
+        "glob": "7.1.2",
+        "growl": "1.10.3",
+        "he": "1.1.1",
+        "mkdirp": "0.5.1",
+        "supports-color": "4.4.0"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.11.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+          "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
+        }
+      }
+    },
+    "mochify": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mochify/-/mochify-4.0.0.tgz",
+      "integrity": "sha512-VcjuFSgEP7QqTL1DB2q+wB9veQe7PghyD9KMQ1a8ulvN/1sXXssWPAQW4tK0o0KvMwMsojkKe71Vo/bkAvFOow==",
+      "dev": true,
+      "requires": {
+        "brout": "1.2.0",
+        "browserify": "14.4.0",
+        "consolify": "2.2.0",
+        "coverify": "1.5.0",
+        "glob": "7.1.2",
+        "min-wd": "2.9.3",
+        "mocaccino": "3.0.0",
+        "mocha": "4.0.1",
+        "phantomic": "1.5.2",
+        "resolve": "1.5.0",
+        "source-mapper": "2.0.0",
+        "subarg": "1.0.0",
+        "through2": "2.0.3",
+        "watchify": "3.9.0",
+        "which": "1.3.0"
+      }
+    },
+    "module-deps": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz",
+      "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=",
+      "dev": true,
+      "requires": {
+        "JSONStream": "1.3.2",
+        "browser-resolve": "1.11.2",
+        "cached-path-relative": "1.0.1",
+        "concat-stream": "1.5.2",
+        "defined": "1.0.0",
+        "detective": "4.7.1",
+        "duplexer2": "0.1.4",
+        "inherits": "2.0.3",
+        "parents": "1.0.1",
+        "readable-stream": "2.3.3",
+        "resolve": "1.5.0",
+        "stream-combiner2": "1.1.1",
+        "subarg": "1.0.0",
+        "through2": "2.0.3",
+        "xtend": "4.0.1"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "mute-stream": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+      "dev": true
+    },
+    "nan": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
+      "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
+      "dev": true,
+      "optional": true
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+      "dev": true
+    },
+    "nise": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz",
+      "integrity": "sha512-q9jXh3UNsMV28KeqI43ILz5+c3l+RiNW8mhurEwCKckuHQbL+hTJIKKTiUlCPKlgQ/OukFvSnKB/Jk3+sFbkGA==",
+      "dev": true,
+      "requires": {
+        "formatio": "1.2.0",
+        "just-extend": "1.1.27",
+        "lolex": "1.6.0",
+        "path-to-regexp": "1.7.0",
+        "text-encoding": "0.6.4"
+      },
+      "dependencies": {
+        "lolex": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
+          "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=",
+          "dev": true
+        }
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+      "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "2.5.0",
+        "is-builtin-module": "1.0.0",
+        "semver": "5.0.3",
+        "validate-npm-package-license": "3.0.1"
+      }
+    },
+    "normalize-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
+      "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+      "dev": true
+    },
+    "npm-path": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz",
+      "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==",
+      "dev": true,
+      "requires": {
+        "which": "1.3.0"
+      }
+    },
+    "npm-run-all": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.0.2.tgz",
+      "integrity": "sha1-qEZpNI5ttsy+BSIAtM22v+A0pP4=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cross-spawn": "5.1.0",
+        "minimatch": "3.0.4",
+        "ps-tree": "1.1.0",
+        "read-pkg": "2.0.0",
+        "shell-quote": "1.6.1",
+        "string.prototype.padend": "3.0.0"
+      }
+    },
+    "npm-run-path": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+      "dev": true,
+      "requires": {
+        "path-key": "2.0.1"
+      }
+    },
+    "npm-which": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz",
+      "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=",
+      "dev": true,
+      "requires": {
+        "commander": "2.13.0",
+        "npm-path": "2.0.4",
+        "which": "1.3.0"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-keys": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+      "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+      "dev": true
+    },
+    "object.omit": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+      "dev": true,
+      "requires": {
+        "for-own": "0.1.5",
+        "is-extendable": "0.1.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1.0.2"
+      }
+    },
+    "onetime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "1.1.0"
+      }
+    },
+    "optionator": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "dev": true,
+      "requires": {
+        "deep-is": "0.1.3",
+        "fast-levenshtein": "2.0.6",
+        "levn": "0.3.0",
+        "prelude-ls": "1.1.2",
+        "type-check": "0.3.2",
+        "wordwrap": "1.0.0"
+      }
+    },
+    "ora": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
+      "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-cursor": "1.0.2",
+        "cli-spinners": "0.1.2",
+        "object-assign": "4.1.1"
+      },
+      "dependencies": {
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
+    "os-browserify": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz",
+      "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=",
+      "dev": true
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-shim": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
+      "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=",
+      "dev": true
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "outpipe": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz",
+      "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=",
+      "dev": true,
+      "requires": {
+        "shell-quote": "1.6.1"
+      }
+    },
+    "p-finally": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+      "dev": true
+    },
+    "p-map": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+      "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+      "dev": true
+    },
+    "pako": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+      "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+      "dev": true
+    },
+    "parents": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+      "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=",
+      "dev": true,
+      "requires": {
+        "path-platform": "0.11.15"
+      }
+    },
+    "parse-asn1": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+      "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+      "dev": true,
+      "requires": {
+        "asn1.js": "4.9.2",
+        "browserify-aes": "1.1.1",
+        "create-hash": "1.1.3",
+        "evp_bytestokey": "1.0.3",
+        "pbkdf2": "3.0.14"
+      }
+    },
+    "parse-glob": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "dev": true,
+      "requires": {
+        "glob-base": "0.3.0",
+        "is-dotfile": "1.0.3",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1"
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
+      "requires": {
+        "error-ex": "1.3.1"
+      }
+    },
+    "path-browserify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+      "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+      "dev": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+      "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+      "dev": true
+    },
+    "path-platform": {
+      "version": "0.11.15",
+      "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+      "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=",
+      "dev": true
+    },
+    "path-to-regexp": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+      "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+      "dev": true,
+      "requires": {
+        "isarray": "0.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        }
+      }
+    },
+    "path-type": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+      "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+      "dev": true,
+      "requires": {
+        "pify": "2.3.0"
+      }
+    },
+    "pause-stream": {
+      "version": "0.0.11",
+      "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+      "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+      "dev": true,
+      "requires": {
+        "through": "2.3.8"
+      }
+    },
+    "pbkdf2": {
+      "version": "3.0.14",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+      "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+      "dev": true,
+      "requires": {
+        "create-hash": "1.1.3",
+        "create-hmac": "1.1.6",
+        "ripemd160": "2.0.1",
+        "safe-buffer": "5.1.1",
+        "sha.js": "2.4.9"
+      }
+    },
+    "phantomic": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/phantomic/-/phantomic-1.5.2.tgz",
+      "integrity": "sha1-U+GMW79vpSrE+oNdYVV/cgtK4l4=",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "2.2.3",
+        "es5-shim": "4.5.10",
+        "source-mapper": "2.0.0"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "2.2.3",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-2.2.3.tgz",
+          "integrity": "sha1-+sViAt/T0N2GF3jy2iA79DS7ghw=",
+          "dev": true,
+          "requires": {
+            "cross-spawn-async": "2.2.5",
+            "spawn-sync": "1.0.15"
+          }
+        }
+      }
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "2.0.4"
+      }
+    },
+    "pluralize": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz",
+      "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=",
+      "dev": true
+    },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+      "dev": true
+    },
+    "preserve": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "dev": true
+    },
+    "process": {
+      "version": "0.11.10",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+      "dev": true
+    },
+    "process-nextick-args": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+      "dev": true
+    },
+    "progress": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+      "dev": true
+    },
+    "ps-tree": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz",
+      "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=",
+      "dev": true,
+      "requires": {
+        "event-stream": "3.3.4"
+      }
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
+    "public-encrypt": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+      "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+      "dev": true,
+      "requires": {
+        "bn.js": "4.11.8",
+        "browserify-rsa": "4.0.1",
+        "create-hash": "1.1.3",
+        "parse-asn1": "5.1.0",
+        "randombytes": "2.0.6"
+      }
+    },
+    "punycode": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+      "dev": true
+    },
+    "querystring": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+      "dev": true
+    },
+    "querystring-es3": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+      "dev": true
+    },
+    "ramda": {
+      "version": "0.24.1",
+      "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",
+      "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc=",
+      "dev": true
+    },
+    "randomatic": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+      "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+      "dev": true,
+      "requires": {
+        "is-number": "3.0.0",
+        "kind-of": "4.0.0"
+      },
+      "dependencies": {
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "3.2.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "1.1.6"
+              }
+            }
+          }
+        },
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "1.1.6"
+          }
+        }
+      }
+    },
+    "randombytes": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
+      "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "randomfill": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
+      "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
+      "dev": true,
+      "requires": {
+        "randombytes": "2.0.6",
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "read-only-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+      "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "2.3.3"
+      }
+    },
+    "read-pkg": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+      "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "2.0.0",
+        "normalize-package-data": "2.4.0",
+        "path-type": "2.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "1.0.2",
+        "inherits": "2.0.3",
+        "isarray": "1.0.0",
+        "process-nextick-args": "1.0.7",
+        "safe-buffer": "5.1.1",
+        "string_decoder": "1.0.3",
+        "util-deprecate": "1.0.2"
+      }
+    },
+    "readdirp": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "minimatch": "3.0.4",
+        "readable-stream": "2.3.3",
+        "set-immediate-shim": "1.0.1"
+      }
+    },
+    "referee": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/referee/-/referee-1.2.0.tgz",
+      "integrity": "sha1-eneb7llVx4r/fYjAFhxaH0VFjJA=",
+      "dev": true,
+      "requires": {
+        "bane": "1.1.2",
+        "lodash": "3.10.1",
+        "samsam": "1.3.0"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+          "dev": true
+        }
+      }
+    },
+    "regex-cache": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "dev": true,
+      "requires": {
+        "is-equal-shallow": "0.1.3"
+      }
+    },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true
+    },
+    "repeat-element": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+      "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "1.0.2"
+      }
+    },
+    "require-from-string": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
+      "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=",
+      "dev": true
+    },
+    "require-uncached": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+      "dev": true,
+      "requires": {
+        "caller-path": "0.1.0",
+        "resolve-from": "1.0.1"
+      }
+    },
+    "requireindex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz",
+      "integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=",
+      "dev": true
+    },
+    "resolve": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
+      "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
+      "dev": true,
+      "requires": {
+        "path-parse": "1.0.5"
+      }
+    },
+    "resolve-from": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+      "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+      "dev": true,
+      "requires": {
+        "onetime": "2.0.1",
+        "signal-exit": "3.0.2"
+      }
+    },
+    "rimraf": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "dev": true,
+      "requires": {
+        "glob": "7.1.2"
+      }
+    },
+    "ripemd160": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+      "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+      "dev": true,
+      "requires": {
+        "hash-base": "2.0.2",
+        "inherits": "2.0.3"
+      }
+    },
+    "run-async": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "dev": true,
+      "requires": {
+        "is-promise": "2.1.0"
+      }
+    },
+    "rx-lite": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+      "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
+      "dev": true
+    },
+    "rx-lite-aggregates": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+      "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+      "dev": true,
+      "requires": {
+        "rx-lite": "4.0.8"
+      }
+    },
+    "rxjs": {
+      "version": "5.5.6",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
+      "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
+      "dev": true,
+      "requires": {
+        "symbol-observable": "1.0.1"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+      "dev": true
+    },
+    "samsam": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz",
+      "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==",
+      "dev": true
+    },
+    "saucelabs": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.4.0.tgz",
+      "integrity": "sha1-uTSpr52ih0s/QKrh/N5QpEZvXzg=",
+      "dev": true,
+      "requires": {
+        "https-proxy-agent": "1.0.0"
+      }
+    },
+    "semver": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
+      "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=",
+      "dev": true
+    },
+    "set-immediate-shim": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+      "dev": true
+    },
+    "sha.js": {
+      "version": "2.4.9",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
+      "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "shasum": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
+      "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=",
+      "dev": true,
+      "requires": {
+        "json-stable-stringify": "0.0.1",
+        "sha.js": "2.4.9"
+      }
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "shell-quote": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz",
+      "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=",
+      "dev": true,
+      "requires": {
+        "array-filter": "0.0.1",
+        "array-map": "0.0.0",
+        "array-reduce": "0.0.0",
+        "jsonify": "0.0.0"
+      }
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "sinon": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.1.2.tgz",
+      "integrity": "sha512-5uLBZPdCWl59Lpbf45ygKj7Z0LVol+ftBe7RDIXOQV/sF58pcFmbK8raA7bt6eljNuGnvBP+/ZxlicVn0emDjA==",
+      "dev": true,
+      "requires": {
+        "diff": "3.3.1",
+        "formatio": "1.2.0",
+        "lodash.get": "4.4.2",
+        "lolex": "2.3.1",
+        "nise": "1.2.0",
+        "supports-color": "4.5.0",
+        "type-detect": "4.0.6"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
+        }
+      }
+    },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+      "dev": true
+    },
+    "slice-ansi": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "dev": true,
+      "requires": {
+        "is-fullwidth-code-point": "2.0.0"
+      }
+    },
+    "source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+      "dev": true
+    },
+    "source-mapper": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/source-mapper/-/source-mapper-2.0.0.tgz",
+      "integrity": "sha1-Z8pIx5R1gS2HRiqnqqey9e0NNOo=",
+      "dev": true,
+      "requires": {
+        "convert-source-map": "1.1.3",
+        "source-map": "0.5.7",
+        "through2": "2.0.3"
+      }
+    },
+    "spawn-sync": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
+      "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
+      "dev": true,
+      "requires": {
+        "concat-stream": "1.5.2",
+        "os-shim": "0.1.3"
+      }
+    },
+    "spdx-correct": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+      "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+      "dev": true,
+      "requires": {
+        "spdx-license-ids": "1.2.2"
+      }
+    },
+    "spdx-expression-parse": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+      "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+      "dev": true
+    },
+    "spdx-license-ids": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+      "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+      "dev": true
+    },
+    "split": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+      "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+      "dev": true,
+      "requires": {
+        "through": "2.3.8"
+      }
+    },
+    "split2": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz",
+      "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=",
+      "dev": true,
+      "requires": {
+        "through2": "0.6.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "1.0.34",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "0.0.1",
+            "string_decoder": "0.10.31"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+          "dev": true
+        },
+        "through2": {
+          "version": "0.6.5",
+          "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+          "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+          "dev": true,
+          "requires": {
+            "readable-stream": "1.0.34",
+            "xtend": "4.0.1"
+          }
+        }
+      }
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "staged-git-files": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz",
+      "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=",
+      "dev": true
+    },
+    "stream-browserify": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+      "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.3"
+      }
+    },
+    "stream-combiner": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+      "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+      "dev": true,
+      "requires": {
+        "duplexer": "0.1.1"
+      }
+    },
+    "stream-combiner2": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+      "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=",
+      "dev": true,
+      "requires": {
+        "duplexer2": "0.1.4",
+        "readable-stream": "2.3.3"
+      }
+    },
+    "stream-http": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz",
+      "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==",
+      "dev": true,
+      "requires": {
+        "builtin-status-codes": "3.0.0",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.3",
+        "to-arraybuffer": "1.0.1",
+        "xtend": "4.0.1"
+      }
+    },
+    "stream-splicer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz",
+      "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.3"
+      }
+    },
+    "stream-to-observable": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz",
+      "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=",
+      "dev": true
+    },
+    "string-width": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "dev": true,
+      "requires": {
+        "is-fullwidth-code-point": "2.0.0",
+        "strip-ansi": "4.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "3.0.0"
+          }
+        }
+      }
+    },
+    "string.prototype.padend": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz",
+      "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=",
+      "dev": true,
+      "requires": {
+        "define-properties": "1.1.2",
+        "es-abstract": "1.10.0",
+        "function-bind": "1.1.1"
+      }
+    },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "2.1.1"
+      }
+    },
+    "strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-eof": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+      "dev": true
+    },
+    "strip-indent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+      "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+      "dev": true
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "dev": true
+    },
+    "subarg": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+      "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=",
+      "dev": true,
+      "requires": {
+        "minimist": "1.2.0"
+      }
+    },
+    "supports-color": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+      "dev": true
+    },
+    "symbol-observable": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+      "dev": true
+    },
+    "syntax-error": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz",
+      "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=",
+      "dev": true,
+      "requires": {
+        "acorn": "4.0.13"
+      }
+    },
+    "table": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+      "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+      "dev": true,
+      "requires": {
+        "ajv": "5.5.2",
+        "ajv-keywords": "2.1.1",
+        "chalk": "2.3.0",
+        "lodash": "4.17.4",
+        "slice-ansi": "1.0.0",
+        "string-width": "2.1.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+          "dev": true,
+          "requires": {
+            "color-convert": "1.9.1"
+          }
+        },
+        "chalk": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+          "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "3.2.0",
+            "escape-string-regexp": "1.0.5",
+            "supports-color": "4.5.0"
+          }
+        },
+        "supports-color": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
+        }
+      }
+    },
+    "text-encoding": {
+      "version": "0.6.4",
+      "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+      "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=",
+      "dev": true
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+      "dev": true
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+      "dev": true
+    },
+    "through2": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "2.3.3",
+        "xtend": "4.0.1"
+      }
+    },
+    "timers-browserify": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+      "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+      "dev": true,
+      "requires": {
+        "process": "0.11.10"
+      }
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "dev": true,
+      "requires": {
+        "os-tmpdir": "1.0.2"
+      }
+    },
+    "to-arraybuffer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+      "dev": true
+    },
+    "tty-browserify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+      "dev": true
+    },
+    "type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "1.1.2"
+      }
+    },
+    "type-detect": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.6.tgz",
+      "integrity": "sha512-qZ3bAurt2IXGPR3c57PyaSYEnQiLRwPeS60G9TahElBZsdOABo+iKYch/PhRjSTZJ5/DF08x43XMt9qec2g3ig==",
+      "dev": true
+    },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
+    "umd": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz",
+      "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=",
+      "dev": true
+    },
+    "url": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+      "dev": true,
+      "requires": {
+        "punycode": "1.3.2",
+        "querystring": "0.2.0"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+          "dev": true
+        }
+      }
+    },
+    "util": {
+      "version": "0.10.3",
+      "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+      "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.1"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+          "dev": true
+        }
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+      "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "1.0.2",
+        "spdx-expression-parse": "1.0.4"
+      }
+    },
+    "vm-browserify": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+      "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+      "dev": true,
+      "requires": {
+        "indexof": "0.0.1"
+      }
+    },
+    "watchify": {
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/watchify/-/watchify-3.9.0.tgz",
+      "integrity": "sha1-8HX9LoqGrN6Eztum5cKgvt1SPZ4=",
+      "dev": true,
+      "requires": {
+        "anymatch": "1.3.2",
+        "browserify": "14.4.0",
+        "chokidar": "1.7.0",
+        "defined": "1.0.0",
+        "outpipe": "1.1.1",
+        "through2": "2.0.3",
+        "xtend": "4.0.1"
+      }
+    },
+    "which": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+      "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+      "dev": true,
+      "requires": {
+        "isexe": "2.0.0"
+      }
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+      "dev": true
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "write": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+      "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+      "dev": true,
+      "requires": {
+        "mkdirp": "0.5.1"
+      }
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+      "dev": true
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "dev": true
+    }
+  }
+}
diff --git a/package.json b/package.json
index 20c7d54..d8d3c8f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "lolex",
   "description": "Fake JavaScript timers",
-  "version": "1.5.1",
+  "version": "2.3.2",
   "homepage": "http://github.com/sinonjs/lolex",
   "author": "Christian Johansen",
   "repository": {
@@ -15,20 +15,56 @@
   "license": "BSD-3-Clause",
   "scripts": {
     "lint": "eslint .",
-    "test-node": "mocha -R dot",
+    "test-node": "mocha -R dot --check-leaks",
     "test-headless": "mochify",
     "test-cloud": "mochify --wd",
     "test": "npm run lint && npm run test-node && npm run test-headless",
     "bundle": "browserify -s lolex -o lolex.js src/lolex-src.js",
-    "prepublish": "npm run bundle"
+    "prepublish": "npm run bundle",
+    "precommit": "run-p lint test-node"
   },
+  "lint-staged": {
+    "*.js": "eslint"
+  },
+  "files": [
+    "src/",
+    "lolex.js"
+  ],
   "devDependencies": {
-    "eslint": "^3.0.1",
-    "browserify": "^13.0.1",
-    "mocha": "^2.5.3",
-    "mochify": "^2.18.0",
-    "referee": "^1.2.0",
-    "sinon": "^1.17.4"
+    "browserify": "14.4.0",
+    "eslint": "4.2.0",
+    "eslint-config-sinon": "1.0.3",
+    "eslint-plugin-ie11": "1.0.0",
+    "eslint-plugin-mocha": "4.11.0",
+    "husky": "0.14.3",
+    "lint-staged": "4.0.2",
+    "mocha": "4.0.1",
+    "mochify": "4.0.0",
+    "npm-run-all": "4.0.2",
+    "referee": "1.2.0",
+    "sinon": "4.1.2"
+  },
+  "eslintConfig": {
+    "extends": "eslint-config-sinon",
+    "plugins": [
+      "ie11"
+    ],
+    "rules": {
+      "ie11/no-collection-args": [
+        "error"
+      ],
+      "ie11/no-for-in-const": [
+        "error"
+      ],
+      "ie11/no-loop-func": [
+        "warn"
+      ],
+      "ie11/no-weak-collections": [
+        "error"
+      ]
+    }
   },
-  "main": "./src/lolex-src.js"
+  "module": "./lolex.js",
+  "main": "./src/lolex-src.js",
+  "dependencies": {}
 }
diff --git a/src/lolex-src.js b/src/lolex-src.js
index 8ee5b34..dc6a8ab 100644
--- a/src/lolex-src.js
+++ b/src/lolex-src.js
@@ -1,655 +1,796 @@
-/*global global, window*/
-/**
- * @author Christian Johansen (christian at cjohansen.no) and contributors
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
+"use strict";
 
-(function (global) {
-    "use strict";
+var userAgent = global.navigator && global.navigator.userAgent;
+var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
+var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
 
-    // Make properties writable in IE, as per
-    // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+// Make properties writable in IE, as per
+// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+if (isRunningInIE) {
     global.setTimeout = global.setTimeout;
     global.clearTimeout = global.clearTimeout;
     global.setInterval = global.setInterval;
     global.clearInterval = global.clearInterval;
     global.Date = global.Date;
+}
 
-    // setImmediate is not a standard function
-    // avoid adding the prop to the window object if not present
-    if (global.setImmediate !== undefined) {
-        global.setImmediate = global.setImmediate;
-        global.clearImmediate = global.clearImmediate;
-    }
-
-    // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
-    // browsers, a number.
-    // see https://github.com/cjohansen/Sinon.JS/pull/436
-
-    var NOOP = function () { return undefined; };
-    var timeoutResult = setTimeout(NOOP, 0);
-    var addTimerReturnsObject = typeof timeoutResult === "object";
-    var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
-    clearTimeout(timeoutResult);
-
-    var NativeDate = Date;
-    var uniqueTimerId = 1;
-
-    /**
-     * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
-     * number of milliseconds. This is used to support human-readable strings passed
-     * to clock.tick()
-     */
-    function parseTime(str) {
-        if (!str) {
-            return 0;
-        }
+// setImmediate is not a standard function
+// avoid adding the prop to the window object if not present
+if (global.setImmediate !== undefined) {
+    global.setImmediate = global.setImmediate;
+    global.clearImmediate = global.clearImmediate;
+}
 
-        var strings = str.split(":");
-        var l = strings.length, i = l;
-        var ms = 0, parsed;
+// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
+// browsers, a number.
+// see https://github.com/cjohansen/Sinon.JS/pull/436
 
-        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-            throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
-        }
+var NOOP = function () { return undefined; };
+var timeoutResult = setTimeout(NOOP, 0);
+var addTimerReturnsObject = typeof timeoutResult === "object";
+var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
+var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
+var performancePresent = (global.performance && typeof global.performance.now === "function");
+var requestAnimationFramePresent = (global.requestAnimationFrame && typeof global.requestAnimationFrame === "function");
+var cancelAnimationFramePresent = (global.cancelAnimationFrame && typeof global.cancelAnimationFrame === "function");
 
-        while (i--) {
-            parsed = parseInt(strings[i], 10);
+clearTimeout(timeoutResult);
 
-            if (parsed >= 60) {
-                throw new Error("Invalid time " + str);
-            }
-
-            ms += parsed * Math.pow(60, (l - i - 1));
-        }
+var NativeDate = Date;
+var uniqueTimerId = 1;
 
-        return ms * 1000;
+/**
+ * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
+ * number of milliseconds. This is used to support human-readable strings passed
+ * to clock.tick()
+ */
+function parseTime(str) {
+    if (!str) {
+        return 0;
     }
 
-    /**
-     * Floor function that also works for negative numbers
-     */
-    function fixedFloor(n) {
-        return (n >= 0 ? Math.floor(n) : Math.ceil(n));
-    }
+    var strings = str.split(":");
+    var l = strings.length;
+    var i = l;
+    var ms = 0;
+    var parsed;
 
-    /**
-     * % operator that also works for negative numbers
-     */
-    function fixedModulo(n, m) {
-        return ((n % m) + m) % m;
+    if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+        throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
     }
 
-    /**
-     * Used to grok the `now` parameter to createClock.
-     */
-    function getEpoch(epoch) {
-        if (!epoch) { return 0; }
-        if (typeof epoch.getTime === "function") { return epoch.getTime(); }
-        if (typeof epoch === "number") { return epoch; }
-        throw new TypeError("now should be milliseconds since UNIX epoch");
-    }
+    while (i--) {
+        parsed = parseInt(strings[i], 10);
+
+        if (parsed >= 60) {
+            throw new Error("Invalid time " + str);
+        }
 
-    function inRange(from, to, timer) {
-        return timer && timer.callAt >= from && timer.callAt <= to;
+        ms += parsed * Math.pow(60, (l - i - 1));
     }
 
-    function mirrorDateProperties(target, source) {
-        var prop;
-        for (prop in source) {
-            if (source.hasOwnProperty(prop)) {
-                target[prop] = source[prop];
-            }
-        }
+    return ms * 1000;
+}
 
-        // set special now implementation
-        if (source.now) {
-            target.now = function now() {
-                return target.clock.now;
-            };
-        } else {
-            delete target.now;
-        }
+/**
+ * Floor function that also works for negative numbers
+ */
+function fixedFloor(n) {
+    return (n >= 0 ? Math.floor(n) : Math.ceil(n));
+}
 
-        // set special toSource implementation
-        if (source.toSource) {
-            target.toSource = function toSource() {
-                return source.toSource();
-            };
-        } else {
-            delete target.toSource;
+/**
+ * % operator that also works for negative numbers
+ */
+function fixedModulo(n, m) {
+    return ((n % m) + m) % m;
+}
+
+/**
+ * Used to grok the `now` parameter to createClock.
+ * @param epoch {Date|number} the system time
+ */
+function getEpoch(epoch) {
+    if (!epoch) { return 0; }
+    if (typeof epoch.getTime === "function") { return epoch.getTime(); }
+    if (typeof epoch === "number") { return epoch; }
+    throw new TypeError("now should be milliseconds since UNIX epoch");
+}
+
+function inRange(from, to, timer) {
+    return timer && timer.callAt >= from && timer.callAt <= to;
+}
+
+function mirrorDateProperties(target, source) {
+    var prop;
+    for (prop in source) {
+        if (source.hasOwnProperty(prop)) {
+            target[prop] = source[prop];
         }
+    }
 
-        // set special toString implementation
-        target.toString = function toString() {
-            return source.toString();
+    // set special now implementation
+    if (source.now) {
+        target.now = function now() {
+            return target.clock.now;
         };
+    } else {
+        delete target.now;
+    }
 
-        target.prototype = source.prototype;
-        target.parse = source.parse;
-        target.UTC = source.UTC;
-        target.prototype.toUTCString = source.prototype.toUTCString;
-
-        return target;
-    }
-
-    function createDate() {
-        function ClockDate(year, month, date, hour, minute, second, ms) {
-            // Defensive and verbose to avoid potential harm in passing
-            // explicit undefined when user does not pass argument
-            switch (arguments.length) {
-                case 0:
-                    return new NativeDate(ClockDate.clock.now);
-                case 1:
-                    return new NativeDate(year);
-                case 2:
-                    return new NativeDate(year, month);
-                case 3:
-                    return new NativeDate(year, month, date);
-                case 4:
-                    return new NativeDate(year, month, date, hour);
-                case 5:
-                    return new NativeDate(year, month, date, hour, minute);
-                case 6:
-                    return new NativeDate(year, month, date, hour, minute, second);
-                default:
-                    return new NativeDate(year, month, date, hour, minute, second, ms);
-            }
-        }
-
-        return mirrorDateProperties(ClockDate, NativeDate);
+    // set special toSource implementation
+    if (source.toSource) {
+        target.toSource = function toSource() {
+            return source.toSource();
+        };
+    } else {
+        delete target.toSource;
     }
 
-    function addTimer(clock, timer) {
-        if (timer.func === undefined) {
-            throw new Error("Callback must be provided to timer calls");
-        }
+    // set special toString implementation
+    target.toString = function toString() {
+        return source.toString();
+    };
 
-        if (!clock.timers) {
-            clock.timers = {};
+    target.prototype = source.prototype;
+    target.parse = source.parse;
+    target.UTC = source.UTC;
+    target.prototype.toUTCString = source.prototype.toUTCString;
+
+    return target;
+}
+
+function createDate() {
+    function ClockDate(year, month, date, hour, minute, second, ms) {
+        // Defensive and verbose to avoid potential harm in passing
+        // explicit undefined when user does not pass argument
+        switch (arguments.length) {
+            case 0:
+                return new NativeDate(ClockDate.clock.now);
+            case 1:
+                return new NativeDate(year);
+            case 2:
+                return new NativeDate(year, month);
+            case 3:
+                return new NativeDate(year, month, date);
+            case 4:
+                return new NativeDate(year, month, date, hour);
+            case 5:
+                return new NativeDate(year, month, date, hour, minute);
+            case 6:
+                return new NativeDate(year, month, date, hour, minute, second);
+            default:
+                return new NativeDate(year, month, date, hour, minute, second, ms);
         }
+    }
 
-        timer.id = uniqueTimerId++;
-        timer.createdAt = clock.now;
-        timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
+    return mirrorDateProperties(ClockDate, NativeDate);
+}
 
-        clock.timers[timer.id] = timer;
 
-        if (addTimerReturnsObject) {
-            return {
-                id: timer.id,
-                ref: NOOP,
-                unref: NOOP
-            };
-        }
+function enqueueJob(clock, job) {
+    // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
+    if (!clock.jobs) {
+        clock.jobs = [];
+    }
+    clock.jobs.push(job);
+}
 
-        return timer.id;
+function runJobs(clock) {
+    // runs all microtick-deferred tasks - ecma262/#sec-runjobs
+    if (!clock.jobs) {
+        return;
     }
+    for (var i = 0; i < clock.jobs.length; i++) {
+        var job = clock.jobs[i];
+        job.func.apply(null, job.args);
+    }
+    clock.jobs = [];
+}
 
+function addTimer(clock, timer) {
+    if (timer.func === undefined) {
+        throw new Error("Callback must be provided to timer calls");
+    }
 
-    /* eslint consistent-return: "off" */
-    function compareTimers(a, b) {
-        // Sort first by absolute timing
-        if (a.callAt < b.callAt) {
-            return -1;
-        }
-        if (a.callAt > b.callAt) {
-            return 1;
-        }
+    timer.type = timer.immediate ? "Immediate" : "Timeout";
 
-        // Sort next by immediate, immediate timers take precedence
-        if (a.immediate && !b.immediate) {
-            return -1;
-        }
-        if (!a.immediate && b.immediate) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("delay")) {
+        timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
+        timer.delay = Math.max(0, timer.delay);
+    }
 
-        // Sort next by creation time, earlier-created timers take precedence
-        if (a.createdAt < b.createdAt) {
-            return -1;
-        }
-        if (a.createdAt > b.createdAt) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("interval")) {
+        timer.type = "Interval";
+        timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
+    }
 
-        // Sort next by id, lower-id timers take precedence
-        if (a.id < b.id) {
-            return -1;
-        }
-        if (a.id > b.id) {
-            return 1;
-        }
+    if (timer.hasOwnProperty("animation")) {
+        timer.type = "AnimationFrame";
+        timer.animation = true;
+    }
 
-        // As timer ids are unique, no fallback `0` is necessary
+    if (!clock.timers) {
+        clock.timers = {};
     }
 
-    function firstTimerInRange(clock, from, to) {
-        var timers = clock.timers,
-            timer = null,
-            id,
-            isInRange;
+    timer.id = uniqueTimerId++;
+    timer.createdAt = clock.now;
+    timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                isInRange = inRange(from, to, timers[id]);
+    clock.timers[timer.id] = timer;
 
-                if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
-                    timer = timers[id];
-                }
-            }
-        }
+    if (addTimerReturnsObject) {
+        return {
+            id: timer.id,
+            ref: NOOP,
+            unref: NOOP
+        };
+    }
+
+    return timer.id;
+}
 
-        return timer;
+
+/* eslint consistent-return: "off" */
+function compareTimers(a, b) {
+    // Sort first by absolute timing
+    if (a.callAt < b.callAt) {
+        return -1;
+    }
+    if (a.callAt > b.callAt) {
+        return 1;
     }
 
-    function firstTimer(clock) {
-        var timers = clock.timers,
-            timer = null,
-            id;
+    // Sort next by immediate, immediate timers take precedence
+    if (a.immediate && !b.immediate) {
+        return -1;
+    }
+    if (!a.immediate && b.immediate) {
+        return 1;
+    }
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                if (!timer || compareTimers(timer, timers[id]) === 1) {
-                    timer = timers[id];
-                }
-            }
-        }
+    // Sort next by creation time, earlier-created timers take precedence
+    if (a.createdAt < b.createdAt) {
+        return -1;
+    }
+    if (a.createdAt > b.createdAt) {
+        return 1;
+    }
 
-        return timer;
+    // Sort next by id, lower-id timers take precedence
+    if (a.id < b.id) {
+        return -1;
+    }
+    if (a.id > b.id) {
+        return 1;
     }
 
-    function lastTimer(clock) {
-        var timers = clock.timers,
-            timer = null,
-            id;
+    // As timer ids are unique, no fallback `0` is necessary
+}
 
-        for (id in timers) {
-            if (timers.hasOwnProperty(id)) {
-                if (!timer || compareTimers(timer, timers[id]) === -1) {
-                    timer = timers[id];
-                }
+function firstTimerInRange(clock, from, to) {
+    var timers = clock.timers;
+    var timer = null;
+    var id, isInRange;
+
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            isInRange = inRange(from, to, timers[id]);
+
+            if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
+                timer = timers[id];
             }
         }
-
-        return timer;
     }
 
-    function callTimer(clock, timer) {
-        var exception;
+    return timer;
+}
 
-        if (typeof timer.interval === "number") {
-            clock.timers[timer.id].callAt += timer.interval;
-        } else {
-            delete clock.timers[timer.id];
-        }
+function firstTimer(clock) {
+    var timers = clock.timers;
+    var timer = null;
+    var id;
 
-        try {
-            if (typeof timer.func === "function") {
-                timer.func.apply(null, timer.args);
-            } else {
-                /* eslint no-eval: "off" */
-                eval(timer.func);
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            if (!timer || compareTimers(timer, timers[id]) === 1) {
+                timer = timers[id];
             }
-        } catch (e) {
-            exception = e;
         }
+    }
+
+    return timer;
+}
+
+function lastTimer(clock) {
+    var timers = clock.timers;
+    var timer = null;
+    var id;
 
-        if (!clock.timers[timer.id]) {
-            if (exception) {
-                throw exception;
+    for (id in timers) {
+        if (timers.hasOwnProperty(id)) {
+            if (!timer || compareTimers(timer, timers[id]) === -1) {
+                timer = timers[id];
             }
-            return;
         }
+    }
 
-        if (exception) {
-            throw exception;
-        }
+    return timer;
+}
+
+function callTimer(clock, timer) {
+    if (typeof timer.interval === "number") {
+        clock.timers[timer.id].callAt += timer.interval;
+    } else {
+        delete clock.timers[timer.id];
     }
 
-    function timerType(timer) {
-        if (timer.immediate) {
-            return "Immediate";
-        }
-        if (timer.interval !== undefined) {
-            return "Interval";
-        }
-        return "Timeout";
+    if (typeof timer.func === "function") {
+        timer.func.apply(null, timer.args);
+    } else {
+        /* eslint no-eval: "off" */
+        eval(timer.func);
     }
+}
 
-    function clearTimer(clock, timerId, ttype) {
-        if (!timerId) {
-            // null appears to be allowed in most browsers, and appears to be
-            // relied upon by some libraries, like Bootstrap carousel
-            return;
-        }
+function clearTimer(clock, timerId, ttype) {
+    if (!timerId) {
+        // null appears to be allowed in most browsers, and appears to be
+        // relied upon by some libraries, like Bootstrap carousel
+        return;
+    }
 
-        if (!clock.timers) {
-            clock.timers = [];
-        }
+    if (!clock.timers) {
+        clock.timers = [];
+    }
 
-        // in Node, timerId is an object with .ref()/.unref(), and
-        // its .id field is the actual timer id.
-        if (typeof timerId === "object") {
-            timerId = timerId.id;
-        }
+    // in Node, timerId is an object with .ref()/.unref(), and
+    // its .id field is the actual timer id.
+    if (typeof timerId === "object") {
+        timerId = timerId.id;
+    }
 
-        if (clock.timers.hasOwnProperty(timerId)) {
-            // check that the ID matches a timer of the correct type
-            var timer = clock.timers[timerId];
-            if (timerType(timer) === ttype) {
-                delete clock.timers[timerId];
+    if (clock.timers.hasOwnProperty(timerId)) {
+        // check that the ID matches a timer of the correct type
+        var timer = clock.timers[timerId];
+        if (timer.type === ttype) {
+            delete clock.timers[timerId];
+        } else {
+            var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
+            var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
+            throw new Error("Cannot clear timer: timer created with " + schedule
+                            + "() but cleared with " + clear + "()");
+        }
+    }
+}
+
+function uninstall(clock, target, config) {
+    var method,
+        i,
+        l;
+    var installedHrTime = "_hrtime";
+    var installedNextTick = "_nextTick";
+
+    for (i = 0, l = clock.methods.length; i < l; i++) {
+        method = clock.methods[i];
+        if (method === "hrtime" && target.process) {
+            target.process.hrtime = clock[installedHrTime];
+        } else if (method === "nextTick" && target.process) {
+            target.process.nextTick = clock[installedNextTick];
+        } else {
+            if (target[method] && target[method].hadOwnProperty) {
+                target[method] = clock["_" + method];
+                if (method === "clearInterval" && config.shouldAdvanceTime === true) {
+                    target[method](clock.attachedInterval);
+                }
             } else {
-                throw new Error("Cannot clear timer: timer created with set" + timerType(timer)
-                                + "() but cleared with clear" + ttype + "()");
+                try {
+                    delete target[method];
+                } catch (ignore) { /* eslint empty-block: "off" */ }
             }
         }
     }
 
-    function uninstall(clock, target) {
-        var method,
-            i,
-            l;
-        var installedHrTime = "_hrtime";
+    // Prevent multiple executions which will completely remove these props
+    clock.methods = [];
 
-        for (i = 0, l = clock.methods.length; i < l; i++) {
-            method = clock.methods[i];
-            if (method === "hrtime" && target.process) {
-                target.process.hrtime = clock[installedHrTime];
-            } else {
-                if (target[method] && target[method].hadOwnProperty) {
-                    target[method] = clock["_" + method];
-                } else {
-                    try {
-                        delete target[method];
-                    } catch (ignore) { /* eslint empty-block: "off" */ }
-                }
+    // return pending timers, to enable checking what timers remained on uninstall
+    if (!clock.timers) {
+        return [];
+    }
+    return Object.keys(clock.timers).map(function mapper(key) {
+        return clock.timers[key];
+    });
+}
+
+function hijackMethod(target, method, clock) {
+    var prop;
+    clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
+    clock["_" + method] = target[method];
+
+    if (method === "Date") {
+        var date = mirrorDateProperties(clock[method], target[method]);
+        target[method] = date;
+    } else {
+        target[method] = function () {
+            return clock[method].apply(clock, arguments);
+        };
+
+        for (prop in clock[method]) {
+            if (clock[method].hasOwnProperty(prop)) {
+                target[method][prop] = clock[method][prop];
             }
         }
-
-        // Prevent multiple executions which will completely remove these props
-        clock.methods = [];
     }
 
-    function hijackMethod(target, method, clock) {
-        var prop;
+    target[method].clock = clock;
+}
 
-        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
-        clock["_" + method] = target[method];
+function doIntervalTick(clock, advanceTimeDelta) {
+    clock.tick(advanceTimeDelta);
+}
 
-        if (method === "Date") {
-            var date = mirrorDateProperties(clock[method], target[method]);
-            target[method] = date;
-        } else {
-            target[method] = function () {
-                return clock[method].apply(clock, arguments);
-            };
+var timers = {
+    setTimeout: setTimeout,
+    clearTimeout: clearTimeout,
+    setImmediate: global.setImmediate,
+    clearImmediate: global.clearImmediate,
+    setInterval: setInterval,
+    clearInterval: clearInterval,
+    Date: Date
+};
 
-            for (prop in clock[method]) {
-                if (clock[method].hasOwnProperty(prop)) {
-                    target[method][prop] = clock[method][prop];
-                }
-            }
-        }
+if (hrtimePresent) {
+    timers.hrtime = global.process.hrtime;
+}
 
-        target[method].clock = clock;
-    }
+if (nextTickPresent) {
+    timers.nextTick = global.process.nextTick;
+}
 
-    var timers = {
-        setTimeout: setTimeout,
-        clearTimeout: clearTimeout,
-        setImmediate: global.setImmediate,
-        clearImmediate: global.clearImmediate,
-        setInterval: setInterval,
-        clearInterval: clearInterval,
-        Date: Date
-    };
+if (performancePresent) {
+    timers.performance = global.performance;
+}
 
-    if (hrtimePresent) {
-        timers.hrtime = global.process.hrtime;
-    }
+if (requestAnimationFramePresent) {
+    timers.requestAnimationFrame = global.requestAnimationFrame;
+}
 
-    var keys = Object.keys || function (obj) {
-        var ks = [],
-            key;
+if (cancelAnimationFramePresent) {
+    timers.cancelAnimationFrame = global.cancelAnimationFrame;
+}
 
-        for (key in obj) {
-            if (obj.hasOwnProperty(key)) {
-                ks.push(key);
-            }
+var keys = Object.keys || function (obj) {
+    var ks = [];
+    var key;
+
+    for (key in obj) {
+        if (obj.hasOwnProperty(key)) {
+            ks.push(key);
         }
+    }
 
-        return ks;
-    };
+    return ks;
+};
 
-    exports.timers = timers;
+exports.timers = timers;
 
-    function createClock(now, loopLimit) {
-        loopLimit = loopLimit || 1000;
+/**
+ * @param start {Date|number} the system time
+ * @param loopLimit {number}  maximum number of timers that will be run when calling runAll()
+ */
+function createClock(start, loopLimit) {
+    start = start || 0;
+    loopLimit = loopLimit || 1000;
+
+    var clock = {
+        now: getEpoch(start),
+        hrNow: 0,
+        timeouts: {},
+        Date: createDate(),
+        loopLimit: loopLimit
+    };
 
-        var clock = {
-            now: getEpoch(now),
-            hrNow: 0,
-            timeouts: {},
-            Date: createDate(),
-            loopLimit: loopLimit
-        };
+    clock.Date.clock = clock;
 
-        clock.Date.clock = clock;
+    function getTimeToNextFrame() {
+        return 16 - ((clock.now - start) % 16);
+    }
 
-        clock.setTimeout = function setTimeout(func, timeout) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 2),
-                delay: timeout
-            });
-        };
+    clock.setTimeout = function setTimeout(func, timeout) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 2),
+            delay: timeout
+        });
+    };
 
-        clock.clearTimeout = function clearTimeout(timerId) {
-            return clearTimer(clock, timerId, "Timeout");
-        };
+    clock.clearTimeout = function clearTimeout(timerId) {
+        return clearTimer(clock, timerId, "Timeout");
+    };
+    clock.nextTick = function nextTick(func) {
+        return enqueueJob(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 1)
+        });
+    };
+    clock.setInterval = function setInterval(func, timeout) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 2),
+            delay: timeout,
+            interval: timeout
+        });
+    };
 
-        clock.setInterval = function setInterval(func, timeout) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 2),
-                delay: timeout,
-                interval: timeout
-            });
-        };
+    clock.clearInterval = function clearInterval(timerId) {
+        return clearTimer(clock, timerId, "Interval");
+    };
 
-        clock.clearInterval = function clearInterval(timerId) {
-            return clearTimer(clock, timerId, "Interval");
-        };
+    clock.setImmediate = function setImmediate(func) {
+        return addTimer(clock, {
+            func: func,
+            args: Array.prototype.slice.call(arguments, 1),
+            immediate: true
+        });
+    };
 
-        clock.setImmediate = function setImmediate(func) {
-            return addTimer(clock, {
-                func: func,
-                args: Array.prototype.slice.call(arguments, 1),
-                immediate: true
-            });
-        };
+    clock.clearImmediate = function clearImmediate(timerId) {
+        return clearTimer(clock, timerId, "Immediate");
+    };
 
-        clock.clearImmediate = function clearImmediate(timerId) {
-            return clearTimer(clock, timerId, "Immediate");
-        };
+    clock.requestAnimationFrame = function requestAnimationFrame(func) {
+        var result = addTimer(clock, {
+            func: func,
+            delay: getTimeToNextFrame(),
+            args: [clock.now + getTimeToNextFrame()],
+            animation: true
+        });
 
-        clock.tick = function tick(ms) {
-            ms = typeof ms === "number" ? ms : parseTime(ms);
-            var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
-            var timer = firstTimerInRange(clock, tickFrom, tickTo);
-            var oldNow;
+        return result.id || result;
+    };
 
-            clock.duringTick = true;
+    clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
+        return clearTimer(clock, timerId, "AnimationFrame");
+    };
 
-            function updateHrTime(newNow) {
-                clock.hrNow += (newNow - clock.now);
-            }
+    function updateHrTime(newNow) {
+        clock.hrNow += (newNow - clock.now);
+    }
 
-            var firstException;
-            while (timer && tickFrom <= tickTo) {
-                if (clock.timers[timer.id]) {
-                    updateHrTime(timer.callAt);
-                    tickFrom = timer.callAt;
-                    clock.now = timer.callAt;
-                    try {
-                        oldNow = clock.now;
-                        callTimer(clock, timer);
-                        // compensate for any setSystemTime() call during timer callback
-                        if (oldNow !== clock.now) {
-                            tickFrom += clock.now - oldNow;
-                            tickTo += clock.now - oldNow;
-                            previous += clock.now - oldNow;
-                        }
-                    } catch (e) {
-                        firstException = firstException || e;
-                    }
+    clock.tick = function tick(ms) {
+        ms = typeof ms === "number" ? ms : parseTime(ms);
+        var tickFrom = clock.now;
+        var tickTo = clock.now + ms;
+        var previous = clock.now;
+        var timer, firstException, oldNow;
+
+        clock.duringTick = true;
+
+        // perform process.nextTick()s
+        oldNow = clock.now;
+        runJobs(clock);
+        if (oldNow !== clock.now) {
+            // compensate for any setSystemTime() call during process.nextTick() callback
+            tickFrom += clock.now - oldNow;
+            tickTo += clock.now - oldNow;
+        }
+
+        // perform each timer in the requested range
+        timer = firstTimerInRange(clock, tickFrom, tickTo);
+        while (timer && tickFrom <= tickTo) {
+            if (clock.timers[timer.id]) {
+                updateHrTime(timer.callAt);
+                tickFrom = timer.callAt;
+                clock.now = timer.callAt;
+                oldNow = clock.now;
+                try {
+                    runJobs(clock);
+                    callTimer(clock, timer);
+                } catch (e) {
+                    firstException = firstException || e;
                 }
 
-                timer = firstTimerInRange(clock, previous, tickTo);
-                previous = tickFrom;
+                // compensate for any setSystemTime() call during timer callback
+                if (oldNow !== clock.now) {
+                    tickFrom += clock.now - oldNow;
+                    tickTo += clock.now - oldNow;
+                    previous += clock.now - oldNow;
+                }
             }
 
-            clock.duringTick = false;
+            timer = firstTimerInRange(clock, previous, tickTo);
+            previous = tickFrom;
+        }
+
+        // perform process.nextTick()s again
+        oldNow = clock.now;
+        runJobs(clock);
+        if (oldNow !== clock.now) {
+            // compensate for any setSystemTime() call during process.nextTick() callback
+            tickFrom += clock.now - oldNow;
+            tickTo += clock.now - oldNow;
+        }
+        clock.duringTick = false;
+
+        // corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
+        timer = firstTimerInRange(clock, tickFrom, tickTo);
+        if (timer) {
+            try {
+                clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
+            } catch (e) {
+                firstException = firstException || e;
+            }
+        } else {
+            // no timers remaining in the requested range: move the clock all the way to the end
             updateHrTime(tickTo);
             clock.now = tickTo;
+        }
+        if (firstException) {
+            throw firstException;
+        }
+        return clock.now;
+    };
 
-            if (firstException) {
-                throw firstException;
-            }
+    clock.next = function next() {
+        runJobs(clock);
+        var timer = firstTimer(clock);
+        if (!timer) {
+            return clock.now;
+        }
 
+        clock.duringTick = true;
+        try {
+            updateHrTime(timer.callAt);
+            clock.now = timer.callAt;
+            callTimer(clock, timer);
+            runJobs(clock);
             return clock.now;
-        };
+        } finally {
+            clock.duringTick = false;
+        }
+    };
 
-        clock.next = function next() {
-            var timer = firstTimer(clock);
-            if (!timer) {
+    clock.runAll = function runAll() {
+        var numTimers, i;
+        runJobs(clock);
+        for (i = 0; i < clock.loopLimit; i++) {
+            if (!clock.timers) {
                 return clock.now;
             }
 
-            clock.duringTick = true;
-            try {
-                clock.now = timer.callAt;
-                callTimer(clock, timer);
+            numTimers = keys(clock.timers).length;
+            if (numTimers === 0) {
                 return clock.now;
-            } finally {
-                clock.duringTick = false;
             }
-        };
 
-        clock.runAll = function runAll() {
-            var numTimers, i;
-            for (i = 0; i < clock.loopLimit; i++) {
-                if (!clock.timers) {
-                    return clock.now;
-                }
-
-                numTimers = Object.keys(clock.timers).length;
-                if (numTimers === 0) {
-                    return clock.now;
-                }
+            clock.next();
+        }
 
-                clock.next();
-            }
+        throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
+    };
 
-            throw new Error("Aborting after running " + clock.loopLimit + "timers, assuming an infinite loop!");
-        };
+    clock.runToFrame = function runToFrame() {
+        return clock.tick(getTimeToNextFrame());
+    };
 
-        clock.runToLast = function runToLast() {
-            var timer = lastTimer(clock);
-            if (!timer) {
-                return clock.now;
-            }
+    clock.runToLast = function runToLast() {
+        var timer = lastTimer(clock);
+        if (!timer) {
+            runJobs(clock);
+            return clock.now;
+        }
 
-            return clock.tick(timer.callAt);
-        };
+        return clock.tick(timer.callAt);
+    };
 
-        clock.reset = function reset() {
-            clock.timers = {};
-        };
+    clock.reset = function reset() {
+        clock.timers = {};
+    };
 
-        clock.setSystemTime = function setSystemTime(now) {
-            // determine time difference
-            var newNow = getEpoch(now);
-            var difference = newNow - clock.now;
-            var id, timer;
-
-            // update 'system clock'
-            clock.now = newNow;
-
-            // update timers and intervals to keep them stable
-            for (id in clock.timers) {
-                if (clock.timers.hasOwnProperty(id)) {
-                    timer = clock.timers[id];
-                    timer.createdAt += difference;
-                    timer.callAt += difference;
-                }
+    clock.setSystemTime = function setSystemTime(systemTime) {
+        // determine time difference
+        var newNow = getEpoch(systemTime);
+        var difference = newNow - clock.now;
+        var id, timer;
+
+        // update 'system clock'
+        clock.now = newNow;
+
+        // update timers and intervals to keep them stable
+        for (id in clock.timers) {
+            if (clock.timers.hasOwnProperty(id)) {
+                timer = clock.timers[id];
+                timer.createdAt += difference;
+                timer.callAt += difference;
             }
-        };
+        }
+    };
 
-        if (hrtimePresent) {
-            clock.hrtime = function (prev) {
-                if (Array.isArray(prev)) {
-                    var oldSecs = (prev[0] + prev[1] / 1e9);
-                    var newSecs = (clock.hrNow / 1000);
-                    var difference = (newSecs - oldSecs);
-                    var secs = fixedFloor(difference);
-                    var nanosecs = fixedModulo(difference * 1e9, 1e9);
-                    return [
-                        secs,
-                        nanosecs
-                    ];
-                }
+    if (performancePresent) {
+        clock.performance = Object.create(global.performance);
+        clock.performance.now = function lolexNow() {
+            return clock.hrNow;
+        };
+    }
+    if (hrtimePresent) {
+        clock.hrtime = function (prev) {
+            if (Array.isArray(prev)) {
+                var oldSecs = (prev[0] + prev[1] / 1e9);
+                var newSecs = (clock.hrNow / 1000);
+                var difference = (newSecs - oldSecs);
+                var secs = fixedFloor(difference);
+                var nanosecs = fixedModulo(difference * 1e9, 1e9);
                 return [
-                    fixedFloor(clock.hrNow / 1000),
-                    fixedModulo(clock.hrNow * 1e6, 1e9)
+                    secs,
+                    nanosecs
                 ];
-            };
-        }
-
-        return clock;
+            }
+            return [
+                fixedFloor(clock.hrNow / 1000),
+                fixedModulo(clock.hrNow * 1e6, 1e9)
+            ];
+        };
     }
-    exports.createClock = createClock;
 
-    exports.install = function install(target, now, toFake, loopLimit) {
-        var i,
-            l;
+    return clock;
+}
+exports.createClock = createClock;
 
-        if (typeof target === "number") {
-            toFake = now;
-            now = target;
-            target = null;
-        }
-
-        if (!target) {
-            target = global;
-        }
+/**
+ * @param config {Object} optional config
+ * @param config.target {Object} the target to install timers in (default `window`)
+ * @param config.now {number|Date}  a number (in milliseconds) or a Date object (default epoch)
+ * @param config.toFake {string[]} names of the methods that should be faked.
+ * @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
+ * @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
+ * @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
+ */
+exports.install = function install(config) {
+    if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
+        throw new TypeError("lolex.install called with " + String(config) +
+            " lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
+    }
+    config = typeof config !== "undefined" ? config : {};
+    config.shouldAdvanceTime = config.shouldAdvanceTime || false;
+    config.advanceTimeDelta = config.advanceTimeDelta || 20;
 
-        var clock = createClock(now, loopLimit);
+    var i, l;
+    var target = config.target || global;
+    var clock = createClock(config.now, config.loopLimit);
 
-        clock.uninstall = function () {
-            uninstall(clock, target);
-        };
+    clock.uninstall = function () {
+        return uninstall(clock, target, config);
+    };
 
-        clock.methods = toFake || [];
+    clock.methods = config.toFake || [];
 
-        if (clock.methods.length === 0) {
-            clock.methods = keys(timers);
-        }
+    if (clock.methods.length === 0) {
+        // do not fake nextTick by default - GitHub#126
+        clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
+    }
 
-        for (i = 0, l = clock.methods.length; i < l; i++) {
-            if (clock.methods[i] === "hrtime") {
-                if (target.process && typeof target.process.hrtime === "function") {
-                    hijackMethod(target.process, clock.methods[i], clock);
-                }
-            } else {
-                hijackMethod(target, clock.methods[i], clock);
+    for (i = 0, l = clock.methods.length; i < l; i++) {
+        if (clock.methods[i] === "hrtime") {
+            if (target.process && typeof target.process.hrtime === "function") {
+                hijackMethod(target.process, clock.methods[i], clock);
             }
+        } else if (clock.methods[i] === "nextTick") {
+            if (target.process && typeof target.process.nextTick === "function") {
+                hijackMethod(target.process, clock.methods[i], clock);
+            }
+        } else {
+            if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
+                var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
+                var intervalId = target[clock.methods[i]](
+                    intervalTick,
+                    config.advanceTimeDelta);
+                clock.attachedInterval = intervalId;
+            }
+            hijackMethod(target, clock.methods[i], clock);
         }
+    }
 
-        return clock;
-    };
-
-}(global || this));
+    return clock;
+};
diff --git a/test/.eslintrc b/test/.eslintrc
new file mode 100644
index 0000000..fdd71bb
--- /dev/null
+++ b/test/.eslintrc
@@ -0,0 +1,12 @@
+{
+    "env": {
+        "mocha": true
+    },
+    "plugins": [
+        "mocha"
+    ],
+    "rules": {
+        "mocha/no-exclusive-tests": 2,
+        "max-nested-callbacks": 0
+    }
+}
diff --git a/test/lolex-test.js b/test/lolex-test.js
index 2fe03d5..0b9fa37 100644
--- a/test/lolex-test.js
+++ b/test/lolex-test.js
@@ -1,9 +1,3 @@
-/*global
-    describe,
-    beforeEach,
-    afterEach,
-    it
-*/
 /**
  * @author Christian Johansen (christian at cjohansen.no)
  * @license BSD
@@ -23,8 +17,11 @@ if (typeof require === "function" && typeof module === "object") {
 var assert = referee.assert;
 var refute = referee.refute;
 var GlobalDate = Date;
+
 var NOOP = function NOOP() { return undefined; };
+var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
 var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
+var performancePresent = (global.performance && typeof global.performance.now === "function");
 
 describe("issue #59", function () {
     var context = {
@@ -41,6 +38,71 @@ describe("issue #59", function () {
     });
 });
 
+describe("issue #73", function () {
+    it("should install with date object", function () {
+        var date = new Date("2015-09-25");
+        var clock = lolex.install( { now: date });
+        assert.same(clock.now, 1443139200000);
+        clock.uninstall();
+    });
+});
+
+describe("issue #67", function () {
+    // see https://nodejs.org/api/timers.html
+    it("should overflow to 1 on very big timeouts", function () {
+        var clock = lolex.install();
+        var stub1 = sinon.stub();
+        var stub2 = sinon.stub();
+
+        clock.setTimeout(stub1, 100);
+        clock.setTimeout(stub2, 214748334700); //should be called after 1 tick
+
+        clock.tick(1);
+        assert(stub2.called);
+        assert.isFalse(stub1.called);
+
+        clock.tick(99);
+        assert(stub1.called);
+        assert(stub2.called);
+
+        clock.uninstall();
+    });
+
+    it("should overflow to interval 1 on very big timeouts", function () {
+        var clock = lolex.install();
+        var stub = sinon.stub();
+
+        clock.setInterval(stub, 214748334700);
+        clock.tick(3);
+        assert(stub.calledThrice);
+
+        clock.uninstall();
+    });
+
+    it("should execute setTimeout smaller than 1", function () {
+        var clock = lolex.install();
+        var stub1 = sinon.stub();
+
+        clock.setTimeout(stub1, 0.5);
+        clock.tick(1);
+        assert(stub1.calledOnce);
+
+        clock.uninstall();
+    });
+
+
+    it("executes setTimeout with negative duration as if it has zero delay", function () {
+        var clock = lolex.install();
+        var stub1 = sinon.stub();
+
+        clock.setTimeout(stub1, -10);
+        clock.tick(1);
+        assert(stub1.calledOnce);
+
+        clock.uninstall();
+    });
+});
+
 describe("lolex", function () {
 
     describe("setTimeout", function () {
@@ -156,6 +218,20 @@ describe("lolex", function () {
             assert.equals(stub.callCount, 1);
         });
 
+        it("is not influenced by forward system clock changes during process.nextTick()", function () {
+            var me = this;
+            var stub = sinon.stub();
+            this.clock.setTimeout(stub, 5000);
+            this.clock.tick(1000);
+            this.clock.nextTick(function () {
+                me.clock.setSystemTime(me.clock.now + 1000);
+            });
+            this.clock.tick(3990);
+            assert.equals(stub.callCount, 0);
+            this.clock.tick(20);
+            assert.equals(stub.callCount, 1);
+        });
+
         it("is not influenced by backward system clock changes", function () {
             var stub = sinon.stub();
             this.clock.setTimeout(stub, 5000);
@@ -166,6 +242,44 @@ describe("lolex", function () {
             this.clock.tick(20);
             assert.equals(stub.callCount, 1);
         });
+
+        it("should work when called from a process.nextTick()", function () {
+            var me = this;
+            var callbackCalled = false;
+            this.clock.nextTick(function () {
+                me.clock.setTimeout(function () {
+                    callbackCalled = true;
+                }, 50);
+            });
+            this.clock.tick(60);
+            assert.equals(callbackCalled, true);
+        });
+        it("should work when called from a process.nextTick() (across the tick())", function () {
+            var me = this;
+            var callbackCalled = false;
+            this.clock.nextTick(function () {
+                me.clock.setTimeout(function () {
+                    callbackCalled = true;
+                }, 100);
+            });
+            this.clock.tick(60);
+            assert.equals(callbackCalled, false);
+            this.clock.tick(41);
+            assert.equals(callbackCalled, true);
+        });
+        it("should work when called from setTimeout(() => process.nextTick())", function () {
+            var me = this;
+            var callbackCalled = false;
+            this.clock.setTimeout(function () {
+                me.clock.nextTick(function () {
+                    me.clock.setTimeout(function () {
+                        callbackCalled = true;
+                    }, 50);
+                });
+            }, 10);
+            this.clock.tick(61);
+            assert.equals(callbackCalled, true);
+        });
     });
 
     describe("setImmediate", function () {
@@ -296,7 +410,7 @@ describe("lolex", function () {
     describe("tick", function () {
 
         beforeEach(function () {
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0 });
         });
 
         afterEach(function () {
@@ -628,12 +742,75 @@ describe("lolex", function () {
             var value = clock.tick(200);
             assert.equals(clock.now, value);
         });
+
+        it("is not influenced by forward system clock changes", function () {
+            var clock = this.clock;
+            var callback = function () {
+                clock.setSystemTime((new clock.Date()).getTime() + 1000);
+            };
+            var stub = sinon.stub();
+            clock.setTimeout(callback, 1000);
+            clock.setTimeout(stub, 2000);
+            clock.tick(1990);
+            assert.equals(stub.callCount, 0);
+            clock.tick(20);
+            assert.equals(stub.callCount, 1);
+        });
+
+        it("is not influenced by forward system clock changes", function () {
+            var clock = this.clock;
+            var callback = function () {
+                clock.setSystemTime((new clock.Date()).getTime() - 1000);
+            };
+            var stub = sinon.stub();
+            clock.setTimeout(callback, 1000);
+            clock.setTimeout(stub, 2000);
+            clock.tick(1990);
+            assert.equals(stub.callCount, 0);
+            clock.tick(20);
+            assert.equals(stub.callCount, 1);
+        });
+
+        it("is not influenced by forward system clock changes when an error is thrown", function () {
+            var clock = this.clock;
+            var callback = function () {
+                clock.setSystemTime((new clock.Date()).getTime() + 1000);
+                throw new Error();
+            };
+            var stub = sinon.stub();
+            clock.setTimeout(callback, 1000);
+            clock.setTimeout(stub, 2000);
+            assert.exception(function () {
+                clock.tick(1990);
+            });
+            assert.equals(stub.callCount, 0);
+            clock.tick(20);
+            assert.equals(stub.callCount, 1);
+        });
+
+        it("is not influenced by forward system clock changes when an error is thrown", function () {
+            var clock = this.clock;
+            var callback = function () {
+                clock.setSystemTime((new clock.Date()).getTime() - 1000);
+                throw new Error();
+            };
+            var stub = sinon.stub();
+            clock.setTimeout(callback, 1000);
+            clock.setTimeout(stub, 2000);
+            assert.exception(function () {
+                clock.tick(1990);
+            });
+            assert.equals(stub.callCount, 0);
+            clock.tick(20);
+            assert.equals(stub.callCount, 1);
+        });
+
     });
 
     describe("next", function () {
 
         beforeEach(function () {
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0 });
         });
 
         afterEach(function () {
@@ -893,7 +1070,7 @@ describe("lolex", function () {
         });
 
         it("the loop limit can be set when installing a clock", function () {
-            this.clock = lolex.install(0, null, null, 1);
+            this.clock = lolex.install({ loopLimit: 1 });
             var test = this;
 
             var spies = [sinon.spy(), sinon.spy()];
@@ -973,7 +1150,7 @@ describe("lolex", function () {
             assert.isFalse(spies[1].called);
         });
 
-        it("new timers added with a call time ealier than the last existing timer are run", function () {
+        it("new timers added with a call time earlier than the last existing timer are run", function () {
             this.clock = lolex.createClock();
             var test = this;
             var spies = [
@@ -1041,6 +1218,19 @@ describe("lolex", function () {
             assert.isTrue(stub.called);
         });
 
+        it("does not remove interval with undefined interval", function () {
+            var stub = sinon.stub();
+            var id = this.clock.setInterval(stub);
+            assert.exception(function () {
+                this.clock.clearTimeout(id);
+            }.bind(this), {
+                message: "Cannot clear timer: timer created with setInterval() but cleared with clearTimeout()"
+            });
+            this.clock.tick(50);
+
+            assert.isTrue(stub.called);
+        });
+
         it("does not remove immediate", function () {
             var stub = sinon.stub();
             var id = this.clock.setImmediate(stub);
@@ -1180,6 +1370,15 @@ describe("lolex", function () {
             assert.isFalse(stub.called);
         });
 
+        it("removes interval with undefined interval", function () {
+            var stub = sinon.stub();
+            var id = this.clock.setInterval(stub);
+            this.clock.clearInterval(id);
+            this.clock.tick(50);
+
+            assert.isFalse(stub.called);
+        });
+
         it("does not remove timeout", function () {
             var stub = sinon.stub();
             var id = this.clock.setTimeout(stub, 50);
@@ -1241,7 +1440,7 @@ describe("lolex", function () {
 
         it("creates real Date objects when Date constructor is gone", function () {
             var realDate = new Date();
-            Date = NOOP;
+            Date = NOOP; // eslint-disable-line no-native-reassign
             global.Date = NOOP;
 
             var date = new this.clock.Date();
@@ -1486,8 +1685,18 @@ describe("lolex", function () {
             assert.same(Date.clock, this.clock);
         });
 
+        it("takes an object parameter", function () {
+            this.clock = lolex.install({});
+        });
+
+        it("throws a TypeError on a number parameter", function () {
+            assert.exception(function () {
+                this.clock = lolex.install(0);
+            });
+        });
+
         it("sets initial timestamp", function () {
-            this.clock = lolex.install(1400);
+            this.clock = lolex.install({ now: 1400 });
 
             assert.equals(this.clock.now, 1400);
         });
@@ -1607,6 +1816,24 @@ describe("lolex", function () {
                 assert.same(result[0], 0);
             });
         }
+        if (performancePresent) {
+            it("replaces global performance.now", function () {
+                this.clock = lolex.install();
+                var prev = performance.now();
+                this.clock.tick(1000);
+                var next = performance.now();
+                assert.same(next, 1000);
+                assert.same(prev, 0);
+            });
+
+            it("uninstalls global performance.now", function () {
+                var oldNow = performance.now;
+                this.clock = lolex.install();
+                assert.same(performance.now, this.clock.performance.now);
+                this.clock.uninstall();
+                assert.same(performance.now, oldNow);
+            });
+        }
 
         if (Object.getPrototypeOf(global)) {
             delete global.hasOwnPropertyTest;
@@ -1618,7 +1845,7 @@ describe("lolex", function () {
                     delete global.tick;
                     Object.getPrototypeOf(global).tick = function () { };
 
-                    this.clock = lolex.install(0, ["tick"]);
+                    this.clock = lolex.install({ now: 0, toFake: ["tick"] });
                     assert.isTrue(global.hasOwnProperty("tick"));
                     this.clock.uninstall();
 
@@ -1634,7 +1861,7 @@ describe("lolex", function () {
             // Directly give the global object a tick method
             global.tick = NOOP;
 
-            this.clock = lolex.install(0, ["tick"]);
+            this.clock = lolex.install({ now: 0, toFake: ["tick"] });
             assert.isTrue(global.hasOwnProperty("tick"));
             this.clock.uninstall();
 
@@ -1643,7 +1870,7 @@ describe("lolex", function () {
         });
 
         it("fakes Date constructor", function () {
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0 });
             var now = new Date();
 
             refute.same(Date, lolex.timers.Date);
@@ -1651,7 +1878,7 @@ describe("lolex", function () {
         });
 
         it("fake Date constructor should mirror Date's properties", function () {
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0});
 
             assert(!!Date.parse);
             assert(!!Date.UTC);
@@ -1659,14 +1886,14 @@ describe("lolex", function () {
 
         it("decide on Date.now support at call-time when supported", function () {
             global.Date.now = NOOP;
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0});
 
             assert.equals(typeof Date.now, "function");
         });
 
         it("decide on Date.now support at call-time when unsupported", function () {
             global.Date.now = undefined;
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0});
 
             refute.defined(Date.now);
         });
@@ -1680,21 +1907,21 @@ describe("lolex", function () {
         });
 
         it("uninstalls Date constructor", function () {
-            this.clock = lolex.install(0);
+            this.clock = lolex.install({ now: 0});
             this.clock.uninstall();
 
             assert.same(GlobalDate, lolex.timers.Date);
         });
 
         it("fakes provided methods", function () {
-            this.clock = lolex.install(0, ["setTimeout", "Date", "setImmediate"]);
+            this.clock = lolex.install({ now: 0, toFake: ["setTimeout", "Date", "setImmediate"] });
 
             refute.same(setTimeout, lolex.timers.setTimeout);
             refute.same(Date, lolex.timers.Date);
         });
 
         it("resets faked methods", function () {
-            this.clock = lolex.install(0, ["setTimeout", "Date", "setImmediate"]);
+            this.clock = lolex.install({ now: 0, toFake: ["setTimeout", "Date", "setImmediate"] });
             this.clock.uninstall();
 
             assert.same(setTimeout, lolex.timers.setTimeout);
@@ -1702,22 +1929,278 @@ describe("lolex", function () {
         });
 
         it("does not fake methods not provided", function () {
-            this.clock = lolex.install(0, ["setTimeout", "Date", "setImmediate"]);
+            this.clock = lolex.install({ now: 0, toFake: ["setTimeout", "Date", "setImmediate"] });
 
             assert.same(clearTimeout, lolex.timers.clearTimeout);
             assert.same(setInterval, lolex.timers.setInterval);
             assert.same(clearInterval, lolex.timers.clearInterval);
         });
+    });
+
+    describe("shouldAdvanceTime", function () {
+        it("should create an auto advancing timer", function (done) {
+            var testDelay = 29;
+            var date = new Date("2015-09-25");
+            var clock = lolex.install({now: date, shouldAdvanceTime: true});
+            assert.same(Date.now(), 1443139200000);
+            var timeoutStarted = Date.now();
+
+            setTimeout(function () {
+                var timeDifference = Date.now() - timeoutStarted;
+                assert.same(timeDifference, testDelay);
+                clock.uninstall();
+                done();
+            }, testDelay);
+        });
+
+        it("should test setImmediate", function (done) {
+            var date = new Date("2015-09-25");
+            var clock = lolex.install({now: date, shouldAdvanceTime: true});
+            assert.same(Date.now(), 1443139200000);
+            var timeoutStarted = Date.now();
+
+            setImmediate(function () {
+                var timeDifference = Date.now() - timeoutStarted;
+                assert.same(timeDifference, 0);
+                clock.uninstall();
+                done();
+            });
+        });
+
+        it("should test setInterval", function (done) {
+            var interval = 20;
+            var intervalsTriggered = 0;
+            var cyclesToTrigger = 3;
+            var date = new Date("2015-09-25");
+            var clock = lolex.install({now: date, shouldAdvanceTime: true});
+            assert.same(Date.now(), 1443139200000);
+            var timeoutStarted = Date.now();
+
+            var intervalId = setInterval(function () {
+                if (++intervalsTriggered === cyclesToTrigger) {
+                    clearInterval(intervalId);
+                    var timeDifference = Date.now() - timeoutStarted;
+                    assert.same(timeDifference, interval * cyclesToTrigger);
+                    clock.uninstall();
+                    done();
+                }
+            }, interval);
+        });
+    });
+
+    describe("requestAnimationFrame", function () {
+        beforeEach(function () {
+            this.clock = lolex.createClock();
+        });
+
+        it("throws if no arguments", function () {
+            var clock = this.clock;
+
+            assert.exception(function () { clock.requestAnimationFrame(); });
+        });
+
+        it("returns numeric id or object with numeric id", function () {
+            var result = this.clock.requestAnimationFrame(NOOP);
+
+            assert.isNumber(result);
+        });
+
+        it("returns unique id", function () {
+            var id1 = this.clock.requestAnimationFrame(NOOP);
+            var id2 = this.clock.requestAnimationFrame(NOOP);
+
+            refute.equals(id2, id1);
+        });
+
+        it("should run every 16ms", function () {
+            var stub = sinon.stub();
+            this.clock.requestAnimationFrame(stub);
+            this.clock.tick(15);
+
+            assert.equals(0, stub.callCount);
+
+            this.clock.tick(1);
+
+            assert.equals(1, stub.callCount);
+        });
+
+        it("should be called with current time", function () {
+            var stub = sinon.stub();
+            this.clock.requestAnimationFrame(stub);
+            this.clock.tick(16);
+
+            assert(stub.calledWith(16));
+        });
+
+        it("should call callback once", function () {
+            var stub = sinon.stub();
+            this.clock.requestAnimationFrame(stub);
+            this.clock.tick(32);
+
+            assert.equals(stub.callCount, 1);
+        });
+
+        it("should schedule two callbacks before the next frame at the same time", function () {
+            var stub1 = sinon.stub();
+            var stub2 = sinon.stub();
+
+            this.clock.requestAnimationFrame(stub1);
+
+            this.clock.tick(5);
+
+            this.clock.requestAnimationFrame(stub2);
+
+            this.clock.tick(11);
+
+            assert(stub1.calledWith(16));
+            assert(stub2.calledWith(16));
+        });
+
+        it("should properly schedule callback for 3rd frame", function () {
+            var stub1 = sinon.stub();
+            var stub2 = sinon.stub();
+
+            this.clock.requestAnimationFrame(stub1);
+
+            this.clock.tick(57);
+
+            this.clock.requestAnimationFrame(stub2);
+
+            this.clock.tick(10);
+
+            assert(stub1.calledWith(16));
+            assert(stub2.calledWith(64));
+        });
+
+        it("should schedule for next frame if on current frame", function () {
+            var stub = sinon.stub();
+            this.clock.tick(16);
+            this.clock.requestAnimationFrame(stub);
+            this.clock.tick(16);
+
+            assert(stub.calledWith(32));
+        });
+    });
+
+    describe("cancelAnimationFrame", function () {
+
+        beforeEach(function () {
+            this.clock = lolex.createClock();
+        });
+
+        it("removes animation frame", function () {
+            var stub = sinon.stub();
+            var id = this.clock.requestAnimationFrame(stub);
+            this.clock.cancelAnimationFrame(id);
+            this.clock.tick(16);
+
+            assert.isFalse(stub.called);
+        });
+
+        it("does not remove timeout", function () {
+            var stub = sinon.stub();
+            var id = this.clock.setTimeout(stub, 50);
+            assert.exception(function () {
+                this.clock.cancelAnimationFrame(id);
+            }.bind(this), {
+                message: "Cannot clear timer: timer created with setTimeout() but cleared with cancelAnimationFrame()"
+            });
+            this.clock.tick(50);
+
+            assert.isTrue(stub.called);
+        });
 
-        it("does not be able to use date object for now", function () {
+        it("does not remove interval", function () {
+            var stub = sinon.stub();
+            var id = this.clock.setInterval(stub, 50);
             assert.exception(function () {
-                lolex.install(new Date(2011, 9, 1));
+                this.clock.cancelAnimationFrame(id);
+            }.bind(this), {
+                message: "Cannot clear timer: timer created with setInterval() but cleared with cancelAnimationFrame()"
             });
+            this.clock.tick(50);
+
+            assert.isTrue(stub.called);
+        });
+
+        it("does not remove immediate", function () {
+            var stub = sinon.stub();
+            var id = this.clock.setImmediate(stub);
+            assert.exception(function () {
+                this.clock.cancelAnimationFrame(id);
+            }.bind(this), {
+                message: "Cannot clear timer: timer created with setImmediate() but cleared with cancelAnimationFrame()"
+            });
+            this.clock.tick(50);
+
+            assert.isTrue(stub.called);
+        });
+
+        it("ignores null argument", function () {
+            this.clock.cancelAnimationFrame(null);
+            assert(true); // doesn't fail
+        });
+    });
+
+    describe("runToFrame", function () {
+        beforeEach(function () {
+            this.clock = lolex.createClock();
+        });
+
+        it("should tick next frame", function () {
+            this.clock.runToFrame();
+
+            assert.equals(this.clock.now, 16);
+
+            this.clock.tick(3);
+            this.clock.runToFrame();
+
+            assert.equals(this.clock.now, 32);
         });
     });
 
+    if (performancePresent) {
+        describe("performance.now()", function () {
+            it("should start at 0", function () {
+                var clock = lolex.createClock(1001);
+                var result = clock.performance.now();
+                assert.same(result, 0);
+            });
+
+            it("should run along with clock.tick", function () {
+                var clock = lolex.createClock(0);
+                clock.tick(5001);
+                var result = clock.performance.now();
+                assert.same(result, 5001);
+            });
+
+            it("should listen to multiple ticks in performance.now", function () {
+                var clock = lolex.createClock(0);
+                for (var i = 0; i < 10; i++) {
+                    var next = clock.performance.now();
+                    assert.same(next, 1000 * i);
+                    clock.tick(1000);
+                }
+            });
+
+            it("should run with ticks with timers set", function () {
+                var clock = lolex.createClock(0);
+                clock.setTimeout(function () {
+                    var result = clock.performance.now();
+                    assert.same(result, 2500);
+                }, 2500);
+                clock.tick(5000);
+            });
+
+        });
+    }
     if (hrtimePresent) {
         describe("process.hrtime()", function () {
+            afterEach(function () {
+                if (this.clock) {
+                    this.clock.uninstall();
+                }
+            });
 
             it("should start at 0", function () {
                 var clock = lolex.createClock(1001);
@@ -1755,6 +2238,187 @@ describe("lolex", function () {
                 assert.same(result[0], 0);
                 assert.same(result[1], 0);
             });
+
+            it("should move with timeouts", function () {
+                var clock = lolex.createClock();
+                var result = clock.hrtime();
+                assert.same(result[0], 0);
+                assert.same(result[1], 0);
+                clock.setTimeout(function () {}, 1000);
+                clock.runAll();
+                result = clock.hrtime();
+                assert.same(result[0], 1);
+                assert.same(result[1], 0);
+            });
+        });
+    }
+    if (nextTickPresent) {
+        describe("microtask semantics", function () {
+            it("runs without timers", function () {
+                var clock = lolex.createClock();
+                var called = false;
+                clock.nextTick(function () {
+                    called = true;
+                });
+                clock.runAll();
+                assert(called);
+            });
+
+            it("runs with timers - and before them", function () {
+                var clock = lolex.createClock();
+                var last = "";
+                var called = false;
+                clock.nextTick(function () {
+                    called = true;
+                    last = "tick";
+                });
+                clock.setTimeout(function () {
+                    last = "timeout";
+                });
+                clock.runAll();
+                assert(called);
+                assert.equals(last, "timeout");
+            });
+
+            it("runs when time is progressed", function () {
+                var clock = lolex.createClock();
+                var called = false;
+                clock.nextTick(function () {
+                    called = true;
+                });
+                assert(!called);
+                clock.tick(0);
+                assert(called);
+            });
+
+            it("runs between timers", function () {
+                var clock = lolex.createClock();
+                var order = [];
+                clock.setTimeout(function () {
+                    order.push("timer-1");
+                    clock.nextTick(function () {
+                        order.push("tick");
+                    });
+                });
+
+                clock.setTimeout(function () {
+                    order.push("timer-2");
+                });
+                clock.runAll();
+                assert.same(order[0], "timer-1");
+                assert.same(order[1], "tick");
+                assert.same(order[2], "timer-2");
+            });
+
+            it("installs with microticks", function () {
+                var clock = lolex.install({toFake: ["nextTick"]});
+                var called = false;
+                process.nextTick(function () {
+                    called = true;
+                });
+                clock.runAll();
+                assert(called);
+                clock.uninstall();
+            });
+
+            it("installs with microticks and timers in order", function () {
+                var clock = lolex.install({toFake: ["nextTick", "setTimeout"]});
+                var order = [];
+                setTimeout(function () {
+                    order.push("timer-1");
+                    process.nextTick(function () {
+                        order.push("tick");
+                    });
+                });
+                setTimeout(function () {
+                    order.push("timer-2");
+                });
+                clock.runAll();
+                assert.same(order[0], "timer-1");
+                assert.same(order[1], "tick");
+                assert.same(order[2], "timer-2");
+                clock.uninstall();
+            });
+
+            it("uninstalls", function () {
+                var clock = lolex.install({toFake: ["nextTick"]});
+                clock.uninstall();
+                var called = false;
+                process.nextTick(function () {
+                    called = true;
+                });
+                clock.runAll();
+                assert(!called);
+            });
+
+            it("returns an empty list of timers on immediate uninstall", function () {
+                var clock = lolex.install();
+                var timers = clock.uninstall();
+                assert.equals(timers, []);
+            });
+
+
+            it("returns a timer if uninstalling before it's called", function () {
+                var clock = lolex.install();
+                clock.setTimeout(function () {}, 100);
+                var timers = clock.uninstall();
+                assert.equals(timers.length, 1);
+                assert.equals(timers[0].createdAt, clock.now);
+                assert.equals(timers[0].callAt, clock.now + 100);
+                assert(typeof timers[0].id !== "undefined");
+            });
+
+            it("does not return already executed timers on uninstall", function () {
+                var clock = lolex.install();
+                clock.setTimeout(function () {}, 100);
+                clock.setTimeout(function () {}, 200);
+                clock.tick(100);
+                var timers = clock.uninstall();
+                assert.equals(timers.length, 1);
+                assert.equals(timers[0].createdAt, clock.now - 100);
+                assert.equals(timers[0].callAt, clock.now + 100);
+                assert(typeof timers[0].id !== "undefined");
+            });
+
+            it("returns multiple timers on uninstall if created", function () {
+                var clock = lolex.install();
+                for (var i = 0; i < 5; i++) {
+                    // yes, it's silly to create a function in a loop. This is a test, we can live with it
+                    // eslint-disable-next-line ie11/no-loop-func
+                    clock.setTimeout(function () {}, 100 * i);
+                }
+                var timers = clock.uninstall();
+                assert.equals(timers.length, 5);
+                for (i = 0; i < 5; i++) {
+                    assert.equals(timers[i].createdAt, clock.now);
+                    assert.equals(timers[i].callAt, clock.now + 100 * i);
+                }
+                assert(typeof timers[0].id !== "undefined");
+            });
+
+            it("passes arguments when installed - GitHub#122", function () {
+                var clock = lolex.install({toFake: ["nextTick"]});
+                var called = false;
+                process.nextTick(function (value) {
+                    called = value;
+                }, true);
+                clock.runAll();
+                assert(called);
+                clock.uninstall();
+            });
+
+            it("does not install by default - GitHub#126", function (done) {
+                var clock = lolex.install();
+                var spy = sinon.spy(clock, "nextTick");
+                var called = false;
+                process.nextTick(function (value) {
+                    called = value;
+                    assert(called);
+                    assert(!spy.called);
+                    clock.uninstall();
+                    done();
+                }, true);
+            });
         });
     }
 });

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-lolex.git



More information about the Pkg-javascript-commits mailing list