diff --git a/node_modules/.bin/cdl b/node_modules/.bin/cdl
new file mode 100644
index 0000000000000000000000000000000000000000..7c99649175b7a3953d922a3dcdd65a1bb05f2d45
--- /dev/null
+++ b/node_modules/.bin/cdl
@@ -0,0 +1,16 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*)
+        if command -v cygpath > /dev/null 2>&1; then
+            basedir=`cygpath -w "$basedir"`
+        fi
+    ;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../cardinal/bin/cdl.js" "$@"
+else 
+  exec node  "$basedir/../cardinal/bin/cdl.js" "$@"
+fi
diff --git a/node_modules/.bin/cdl.cmd b/node_modules/.bin/cdl.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..b44765681f04ea8aa94d4cedd0590faff107b246
--- /dev/null
+++ b/node_modules/.bin/cdl.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\cardinal\bin\cdl.js" %*
diff --git a/node_modules/.bin/cdl.ps1 b/node_modules/.bin/cdl.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..caaa97727590bc379446fffc2d327d8464417e96
--- /dev/null
+++ b/node_modules/.bin/cdl.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../cardinal/bin/cdl.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../cardinal/bin/cdl.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../cardinal/bin/cdl.js" $args
+  } else {
+    & "node$exe"  "$basedir/../cardinal/bin/cdl.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/.bin/esparse b/node_modules/.bin/esparse
new file mode 100644
index 0000000000000000000000000000000000000000..601762cefbe13be5c1436be07066efc0331332da
--- /dev/null
+++ b/node_modules/.bin/esparse
@@ -0,0 +1,16 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*)
+        if command -v cygpath > /dev/null 2>&1; then
+            basedir=`cygpath -w "$basedir"`
+        fi
+    ;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../esprima/bin/esparse.js" "$@"
+else 
+  exec node  "$basedir/../esprima/bin/esparse.js" "$@"
+fi
diff --git a/node_modules/.bin/esparse.cmd b/node_modules/.bin/esparse.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..2ca6d502e8f05830f7ecce61e81fa466c72eda88
--- /dev/null
+++ b/node_modules/.bin/esparse.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\esprima\bin\esparse.js" %*
diff --git a/node_modules/.bin/esparse.ps1 b/node_modules/.bin/esparse.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..f19ed7301976b8e3b40bc7eb818b04a1958b50a1
--- /dev/null
+++ b/node_modules/.bin/esparse.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  } else {
+    & "node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/.bin/esvalidate b/node_modules/.bin/esvalidate
new file mode 100644
index 0000000000000000000000000000000000000000..e2fee1f12c07b80a8652b2fc3fd205d022082be7
--- /dev/null
+++ b/node_modules/.bin/esvalidate
@@ -0,0 +1,16 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*)
+        if command -v cygpath > /dev/null 2>&1; then
+            basedir=`cygpath -w "$basedir"`
+        fi
+    ;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../esprima/bin/esvalidate.js" "$@"
+else 
+  exec node  "$basedir/../esprima/bin/esvalidate.js" "$@"
+fi
diff --git a/node_modules/.bin/esvalidate.cmd b/node_modules/.bin/esvalidate.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..4c41643ef5b75495b8a6a70864d84ed5b24e5576
--- /dev/null
+++ b/node_modules/.bin/esvalidate.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\esprima\bin\esvalidate.js" %*
diff --git a/node_modules/.bin/esvalidate.ps1 b/node_modules/.bin/esvalidate.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..23699d11e09c2a5795ebb26a2f59f7c0beee3277
--- /dev/null
+++ b/node_modules/.bin/esvalidate.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  } else {
+    & "node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index 13e8ba72c7581f4e61010e4240a18fb6d7a121a3..848b80bf312c227566e69b9dc93a71f8e5beaa5e 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -30,6 +30,11 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/ansicolors": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz",
+      "integrity": "sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w=="
+    },
     "node_modules/array-flatten": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -53,6 +58,11 @@
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
+    "node_modules/bn.js": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.0.tgz",
+      "integrity": "sha512-NmOLApC80+n+P28y06yHgwGlOCkq/X4jRh5s590959FZXSrM+I/61h0xxuIaYsg0mD44mEAZYG/rnclWuRoz+A=="
+    },
     "node_modules/body-parser": {
       "version": "1.20.3",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
@@ -120,6 +130,18 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/cardinal": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.4.tgz",
+      "integrity": "sha512-3MxV0o9wOpQcobrcSrRpaSxlYkohCcZu0ytOjJUww/Yo/223q4Ecloo7odT+M0SI5kPgb1JhvSaF4EEuVXOLAQ==",
+      "dependencies": {
+        "ansicolors": "~0.2.1",
+        "redeyed": "~0.4.0"
+      },
+      "bin": {
+        "cdl": "bin/cdl.js"
+      }
+    },
     "node_modules/chalk": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -188,6 +210,11 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+    },
     "node_modules/debug": {
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -232,6 +259,11 @@
         "url": "https://dotenvx.com"
       }
     },
+    "node_modules/double-ended-queue": {
+      "version": "2.0.0-0",
+      "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.0.0-0.tgz",
+      "integrity": "sha512-t5ouWOpItmHrm0J0+bX/cFrIjBFWnJkk5LbIJq6bbU/M4aLX2c3LrM4QYsBptwvlPe3WzdpQefQ0v1pe/A5wjg=="
+    },
     "node_modules/dunder-proto": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -304,6 +336,18 @@
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
+    "node_modules/esprima": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
+      "integrity": "sha512-rp5dMKN8zEs9dfi9g0X1ClLmV//WRyk/R15mppFNICIFRG5P92VP7Z04p8pk++gABo9W2tY+kHyu6P1mEHgmTA==",
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -553,6 +597,11 @@
       "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
       "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
     },
+    "node_modules/isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+    },
     "node_modules/jake": {
       "version": "10.9.2",
       "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
@@ -694,6 +743,46 @@
         "node": ">= 8.0"
       }
     },
+    "node_modules/mysql2-promise": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/mysql2-promise/-/mysql2-promise-0.1.4.tgz",
+      "integrity": "sha512-/h8ubU/36aIPpbfB6CENw9ZdbzIhZMZOIbstJUHVKp4J9JBRSLScrYImVx+3yZilgag732UhpQMMK5+ktdhLCw==",
+      "dependencies": {
+        "mysql2": "^0.15.7",
+        "q": "^1.3.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/mysql2-promise/node_modules/lru-cache": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
+      "integrity": "sha512-dVmQmXPBlTgFw77hm60ud//l2bCuDKkqC2on1EBoM7s9Urm9IQDrnujwZ93NFnAq0dVZ0HBXTS7PwEG+YE7+EQ=="
+    },
+    "node_modules/mysql2-promise/node_modules/mysql2": {
+      "version": "0.15.8",
+      "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-0.15.8.tgz",
+      "integrity": "sha512-3x5o6C20bfwJYPSoT74MOoad7/chJoq4qXHDL5VAuRBBrIyErovLoj04Dz/5EY9X2kTxWSGNiTegtxpROTd2YQ==",
+      "dependencies": {
+        "bn.js": "2.0.0",
+        "cardinal": "0.4.4",
+        "double-ended-queue": "2.0.0-0",
+        "named-placeholders": "0.1.3",
+        "readable-stream": "1.0.33"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/mysql2-promise/node_modules/named-placeholders": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-0.1.3.tgz",
+      "integrity": "sha512-Mt79RtxZ6MYTIEemPGv/YDKpbuavcAyGHb0r37xB2mnE5jej3uBzc4+nzOeoZ4nZiii1M32URKt9IjkSTZAmTA==",
+      "dependencies": {
+        "lru-cache": "2.5.0"
+      }
+    },
     "node_modules/mysql2/node_modules/iconv-lite": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -771,6 +860,16 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/q": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+      "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+      "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
+      "engines": {
+        "node": ">=0.6.0",
+        "teleport": ">=0.2.0"
+      }
+    },
     "node_modules/qs": {
       "version": "6.13.0",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
@@ -807,6 +906,25 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/readable-stream": {
+      "version": "1.0.33",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz",
+      "integrity": "sha512-72KxhcKi8bAvHP/cyyWSP+ODS5ef0DIRs0OzrhGXw31q41f19aoELCbvd42FjhpyEDxQMRiiC5rq9rfE5PzTqg==",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.1",
+        "isarray": "0.0.1",
+        "string_decoder": "~0.10.x"
+      }
+    },
+    "node_modules/redeyed": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz",
+      "integrity": "sha512-pnk1vsaNLu1UAAClKsImKz9HjBvg9i8cbRqTRzJbiCjGF0fZSMqpdcA5W3juO3c4etFvTrabECkq9wjC45ZyxA==",
+      "dependencies": {
+        "esprima": "~1.0.4"
+      }
+    },
     "node_modules/safe-buffer": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -975,6 +1093,11 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+    },
     "node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
diff --git a/node_modules/ansicolors/.npmignore b/node_modules/ansicolors/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..a72b52ebe897796e4a289cf95ff6270e04637aad
--- /dev/null
+++ b/node_modules/ansicolors/.npmignore
@@ -0,0 +1,15 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+npm-debug.log
+node_modules
diff --git a/node_modules/ansicolors/.travis.yml b/node_modules/ansicolors/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..895dbd36234210374d68a0f020b2d6e7abf736fa
--- /dev/null
+++ b/node_modules/ansicolors/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.8
diff --git a/node_modules/ansicolors/LICENSE b/node_modules/ansicolors/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..41702c5043478f994b93a4eb5edf5ec3db9ec1fd
--- /dev/null
+++ b/node_modules/ansicolors/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2013 Thorsten Lorenz. 
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/ansicolors/README.md b/node_modules/ansicolors/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..30b6a52e6b38a489e481b8eb620462e0aca31edb
--- /dev/null
+++ b/node_modules/ansicolors/README.md
@@ -0,0 +1,42 @@
+# ansicolors [![build status](https://secure.travis-ci.org/thlorenz/ansicolors.png)](http://next.travis-ci.org/thlorenz/ansicolors)
+
+Functions that surround a string with ansicolor codes so it prints in color.
+
+## Installation
+
+    npm install ansicolors
+
+## Usage
+
+```js
+var colors = require('ansicolors');
+
+// foreground colors
+var redHerring = colors.red('herring');
+var blueMoon = colors.blue('moon');
+var brighBlueMoon = colors.brightBlue('moon');
+
+console.log(redHerring);      // this will print 'herring' in red
+console.log(blueMoon);        // this 'moon' in blue
+console.log(brightBlueMoon);  // I think you got the idea
+
+// background colors
+console.log(colors.bgYellow('printed on yellow background'));
+console.log(colors.bgBrightBlue('printed on bright blue background'));
+
+// mixing background and foreground colors
+// below two lines have same result (order in which bg and fg are combined doesn't matter)
+console.log(colors.bgYellow(colors.blue('printed on yellow background in blue')));
+console.log(colors.blue(colors.bgYellow('printed on yellow background in blue')));
+```
+
+## Tests
+
+Look at the [tests](https://github.com/thlorenz/ansicolors/blob/master/test/ansicolors.js) to see more examples and/or run them via: 
+
+    npm explore ansicolors && npm test
+
+## Alternatives
+
+**ansicolors** tries to meet simple use cases with a very simple API. However, if you need a more powerful ansi formatting tool, 
+I'd suggest to look at the [features](https://github.com/TooTallNate/ansi.js#features) of the [ansi module](https://github.com/TooTallNate/ansi.js).
diff --git a/node_modules/ansicolors/ansicolors.js b/node_modules/ansicolors/ansicolors.js
new file mode 100644
index 0000000000000000000000000000000000000000..b0e18f621a678ec0d0c0a5761aa1435228c9a9de
--- /dev/null
+++ b/node_modules/ansicolors/ansicolors.js
@@ -0,0 +1,55 @@
+// ColorCodes explained: http://www.termsys.demon.co.uk/vtansi.htm
+'use strict';
+
+var colorNums = {
+      white         :  37
+    , black         :  30
+    , blue          :  34
+    , cyan          :  36
+    , green         :  32
+    , magenta       :  35
+    , red           :  31
+    , yellow        :  33
+    , brightBlack   :  90
+    , brightRed     :  91
+    , brightGreen   :  92
+    , brightYellow  :  93
+    , brightBlue    :  94
+    , brightMagenta :  95
+    , brightCyan    :  96
+    , brightWhite   :  97
+    }
+  , backgroundColorNums = {
+      bgBlack         :  40
+    , bgRed           :  41
+    , bgGreen         :  42
+    , bgYellow        :  43
+    , bgBlue          :  44
+    , bgMagenta       :  45
+    , bgCyan          :  46
+    , bgWhite         :  47
+    , bgBrightBlack   :  100
+    , bgBrightRed     :  101
+    , bgBrightGreen   :  102
+    , bgBrightYellow  :  103
+    , bgBrightBlue    :  104
+    , bgBrightMagenta :  105
+    , bgBrightCyan    :  106
+    , bgBrightWhite   :  107
+    } 
+  , colors = {};
+
+
+Object.keys(colorNums).forEach(function (k) {
+  colors[k] = function (s) { 
+    return '\u001b[' + colorNums[k] + 'm' + s + '\u001b[39m';
+  };
+});
+
+Object.keys(backgroundColorNums).forEach(function (k) {
+  colors[k] = function (s) { 
+    return '\u001b[' + backgroundColorNums[k] + 'm' + s + '\u001b[49m';
+  };
+});
+
+module.exports = colors;
diff --git a/node_modules/ansicolors/package.json b/node_modules/ansicolors/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..b8bf12e5b41d08a1191746239211a543479b6269
--- /dev/null
+++ b/node_modules/ansicolors/package.json
@@ -0,0 +1,23 @@
+{
+  "name": "ansicolors",
+  "version": "0.2.1",
+  "description": "Functions that surround a string with ansicolor codes so it prints in color.",
+  "main": "ansicolors.js",
+  "scripts": {
+    "test": "node test/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/thlorenz/ansicolors.git"
+  },
+  "keywords": [
+    "ansi",
+    "colors",
+    "highlight",
+    "string"
+  ],
+  "author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
+  "license": "MIT",
+  "readmeFilename": "README.md",
+  "gitHead": "858847ca28e8b360d9b70eee0592700fa2ab087d"
+}
diff --git a/node_modules/ansicolors/test/ansicolors.js b/node_modules/ansicolors/test/ansicolors.js
new file mode 100644
index 0000000000000000000000000000000000000000..46aec3e28065507bea09859d24129e8d2139d59d
--- /dev/null
+++ b/node_modules/ansicolors/test/ansicolors.js
@@ -0,0 +1,55 @@
+'use strict';
+
+var assert = require('assert')
+  , colors = require('..');
+
+console.log('Foreground colors ..');
+
+assert.equal(colors.white('printed in white'), '\u001b[37mprinted in white\u001b[39m');
+
+assert.equal(colors.black('printed in black'), '\u001b[30mprinted in black\u001b[39m');
+assert.equal(colors.brightBlack('printed in bright black'), '\u001b[90mprinted in bright black\u001b[39m');
+
+assert.equal(colors.green('printed in green'), '\u001b[32mprinted in green\u001b[39m');
+assert.equal(colors.brightGreen('printed in bright green'), '\u001b[92mprinted in bright green\u001b[39m');
+
+assert.equal(colors.red('printed in red'), '\u001b[31mprinted in red\u001b[39m');
+assert.equal(colors.brightRed('printed in bright red'), '\u001b[91mprinted in bright red\u001b[39m');
+
+console.log('OK');
+
+console.log('Background colors ..');
+
+assert.equal(
+    colors.bgBlack('printed with black background')
+  , '\u001b[40mprinted with black background\u001b[49m'
+);
+
+assert.equal(
+    colors.bgYellow('printed with yellow background')
+  , '\u001b[43mprinted with yellow background\u001b[49m'
+);
+assert.equal(
+    colors.bgBrightYellow('printed with bright yellow background')
+  , '\u001b[103mprinted with bright yellow background\u001b[49m'
+);
+
+assert.equal(
+    colors.bgWhite('printed with white background')
+  , '\u001b[47mprinted with white background\u001b[49m'
+);
+
+console.log('OK');
+
+console.log('Mixing background and foreground colors ..');
+
+assert.equal(
+    colors.blue(colors.bgYellow('printed in blue with yellow background'))
+  , '\u001b[34m\u001b[43mprinted in blue with yellow background\u001b[49m\u001b[39m'
+);
+assert.equal(
+    colors.bgYellow(colors.blue('printed in blue with yellow background again'))
+  , '\u001b[43m\u001b[34mprinted in blue with yellow background again\u001b[39m\u001b[49m'
+);
+
+console.log('OK');
diff --git a/node_modules/bn.js/.jscsrc b/node_modules/bn.js/.jscsrc
new file mode 100644
index 0000000000000000000000000000000000000000..dbaae20574debf185058ae1ba189ee3d5adb4d93
--- /dev/null
+++ b/node_modules/bn.js/.jscsrc
@@ -0,0 +1,46 @@
+{
+  "disallowKeywordsOnNewLine": [ "else" ],
+  "disallowMixedSpacesAndTabs": true,
+  "disallowMultipleLineStrings": true,
+  "disallowMultipleVarDecl": true,
+  "disallowNewlineBeforeBlockStatements": true,
+  "disallowQuotedKeysInObjects": true,
+  "disallowSpaceAfterObjectKeys": true,
+  "disallowSpaceAfterPrefixUnaryOperators": true,
+  "disallowSpaceBeforePostfixUnaryOperators": true,
+  "disallowSpacesInCallExpression": true,
+  "disallowTrailingComma": true,
+  "disallowTrailingWhitespace": true,
+  "disallowYodaConditions": true,
+
+  "requireCommaBeforeLineBreak": true,
+  "requireOperatorBeforeLineBreak": true,
+  "requireSpaceAfterBinaryOperators": true,
+  "requireSpaceAfterKeywords": [ "if", "for", "while", "else", "try", "catch" ],
+  "requireSpaceAfterLineComment": true,
+  "requireSpaceBeforeBinaryOperators": true,
+  "requireSpaceBeforeBlockStatements": true,
+  "requireSpaceBeforeKeywords": [ "else", "catch" ],
+  "requireSpaceBeforeObjectValues": true,
+  "requireSpaceBetweenArguments": true,
+  "requireSpacesInAnonymousFunctionExpression": {
+    "beforeOpeningCurlyBrace": true
+  },
+  "requireSpacesInFunctionDeclaration": {
+    "beforeOpeningCurlyBrace": true
+  },
+  "requireSpacesInFunctionExpression": {
+    "beforeOpeningCurlyBrace": true
+  },
+  "requireSpacesInConditionalExpression": true,
+  "requireSpacesInForStatement": true,
+  "requireSpacesInsideArrayBrackets": "all",
+  "requireSpacesInsideObjectBrackets": "all",
+  "requireDotNotation": true,
+
+  "maximumLineLength": 80,
+  "validateIndentation": 2,
+  "validateLineBreaks": "LF",
+  "validateParameterSeparator": ", ",
+  "validateQuoteMarks": "'"
+}
diff --git a/node_modules/bn.js/.jshintrc b/node_modules/bn.js/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..87f72f9aad011568e0b8d15e3e6350e4570691ad
--- /dev/null
+++ b/node_modules/bn.js/.jshintrc
@@ -0,0 +1,89 @@
+{
+    // JSHint Default Configuration File (as on JSHint website)
+    // See http://jshint.com/docs/ for more details
+
+    "maxerr"        : 50,       // {int} Maximum error before stopping
+
+    // Enforcing
+    "bitwise"       : false,     // true: Prohibit bitwise operators (&, |, ^, etc.)
+    "camelcase"     : true,      // true: Identifiers must be in camelCase
+    "curly"         : false,     // true: Require {} for every new block or scope
+    "eqeqeq"        : true,     // true: Require triple equals (===) for comparison
+    "forin"         : true,     // true: Require filtering for..in loops with obj.hasOwnProperty()
+    "freeze"        : true,     // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
+    "immed"         : false,    // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
+    "indent"        : 2,        // {int} Number of spaces to use for indentation
+    "latedef"       : true,     // true: Require variables/functions to be defined before being used
+    "newcap"        : true,     // true: Require capitalization of all constructor functions e.g. `new F()`
+    "noarg"         : true,     // true: Prohibit use of `arguments.caller` and `arguments.callee`
+    "noempty"       : false,    // true: Prohibit use of empty blocks
+    "nonbsp"        : true,     // true: Prohibit "non-breaking whitespace" characters.
+    "nonew"         : false,    // true: Prohibit use of constructors for side-effects (without assignment)
+    "plusplus"      : false,    // true: Prohibit use of `++` & `--`
+    "quotmark"      : "single", // Quotation mark consistency:
+                                //   false    : do nothing (default)
+                                //   true     : ensure whatever is used is consistent
+                                //   "single" : require single quotes
+                                //   "double" : require double quotes
+    "undef"         : true,     // true: Require all non-global variables to be declared (prevents global leaks)
+    "unused"        : true,     // true: Require all defined variables be used
+    "strict"        : true,     // true: Requires all functions run in ES5 Strict Mode
+    "maxparams"     : false,    // {int} Max number of formal params allowed per function
+    "maxdepth"      : 3,        // {int} Max depth of nested blocks (within functions)
+    "maxstatements" : false,    // {int} Max number statements per function
+    "maxcomplexity" : false,    // {int} Max cyclomatic complexity per function
+    "maxlen"        : false,    // {int} Max number of characters per line
+
+    // Relaxing
+    "asi"           : false,     // true: Tolerate Automatic Semicolon Insertion (no semicolons)
+    "boss"          : false,     // true: Tolerate assignments where comparisons would be expected
+    "debug"         : false,     // true: Allow debugger statements e.g. browser breakpoints.
+    "eqnull"        : false,     // true: Tolerate use of `== null`
+    "es5"           : false,     // true: Allow ES5 syntax (ex: getters and setters)
+    "esnext"        : false,     // true: Allow ES.next (ES6) syntax (ex: `const`)
+    "moz"           : false,     // true: Allow Mozilla specific syntax (extends and overrides esnext features)
+                                 // (ex: `for each`, multiple try/catch, function expression…)
+    "evil"          : false,     // true: Tolerate use of `eval` and `new Function()`
+    "expr"          : false,     // true: Tolerate `ExpressionStatement` as Programs
+    "funcscope"     : false,     // true: Tolerate defining variables inside control statements
+    "globalstrict"  : false,     // true: Allow global "use strict" (also enables 'strict')
+    "iterator"      : false,     // true: Tolerate using the `__iterator__` property
+    "lastsemic"     : false,     // true: Tolerate omitting a semicolon for the last statement of a 1-line block
+    "laxbreak"      : false,     // true: Tolerate possibly unsafe line breakings
+    "laxcomma"      : false,     // true: Tolerate comma-first style coding
+    "loopfunc"      : false,     // true: Tolerate functions being defined in loops
+    "multistr"      : false,     // true: Tolerate multi-line strings
+    "noyield"       : false,     // true: Tolerate generator functions with no yield statement in them.
+    "notypeof"      : false,     // true: Tolerate invalid typeof operator values
+    "proto"         : false,     // true: Tolerate using the `__proto__` property
+    "scripturl"     : false,     // true: Tolerate script-targeted URLs
+    "shadow"        : true,      // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
+    "sub"           : false,     // true: Tolerate using `[]` notation when it can still be expressed in dot notation
+    "supernew"      : false,     // true: Tolerate `new function () { ... };` and `new Object;`
+    "validthis"     : false,     // true: Tolerate using this in a non-constructor function
+
+    // Environments
+    "browser"       : true,     // Web Browser (window, document, etc)
+    "browserify"    : true,     // Browserify (node.js code in the browser)
+    "couch"         : false,    // CouchDB
+    "devel"         : true,     // Development/debugging (alert, confirm, etc)
+    "dojo"          : false,    // Dojo Toolkit
+    "jasmine"       : false,    // Jasmine
+    "jquery"        : false,    // jQuery
+    "mocha"         : true,     // Mocha
+    "mootools"      : false,    // MooTools
+    "node"          : true,     // Node.js
+    "nonstandard"   : false,    // Widely adopted globals (escape, unescape, etc)
+    "prototypejs"   : false,    // Prototype and Scriptaculous
+    "qunit"         : false,    // QUnit
+    "rhino"         : false,    // Rhino
+    "shelljs"       : false,    // ShellJS
+    "worker"        : false,    // Web Workers
+    "wsh"           : false,    // Windows Scripting Host
+    "yui"           : false,    // Yahoo User Interface
+
+    // Custom Globals
+    "globals"       : {
+        "module": true
+    }        // additional predefined global variables
+}
diff --git a/node_modules/bn.js/.npmignore b/node_modules/bn.js/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..de5c5a18e947be30ba57c3de920a1fc349d41e51
--- /dev/null
+++ b/node_modules/bn.js/.npmignore
@@ -0,0 +1,5 @@
+benchmarks/
+coverage/
+node_modules/
+npm-debug.log
+1.js
diff --git a/node_modules/bn.js/.travis.yml b/node_modules/bn.js/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..92a990f6797578b242b1b787a264d8ad07e2e75a
--- /dev/null
+++ b/node_modules/bn.js/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+node_js:
+  - "0.10"
+  - "0.11"
+branches:
+  only:
+    - master
diff --git a/node_modules/bn.js/README.md b/node_modules/bn.js/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0f3078e28d5233ef2bb6617e1980904bc6fa4051
--- /dev/null
+++ b/node_modules/bn.js/README.md
@@ -0,0 +1,124 @@
+# bn.js [![Build Status](https://secure.travis-ci.org/indutny/bn.js.png)](http://travis-ci.org/indutny/bn.js)
+> BigNum in pure javascript
+
+## Install
+`npm install --save bn.js`
+
+## API
+
+```js
+const BN = require('bn.js');
+
+// Numbers
+new BN(12345);     // <BN: 3039>
+new BN(0x4123456); // <BN: 4123456>
+
+// Strings
+new BN('FF', 16); // <BN: 255>
+new BN('1A6B765D8CDF', 16); // <BN: 29048849665247>
+
+// Big endian
+new BN([1,2,3,4]); // <BN: 1020304>
+new BN([1,2,3,4]).toArray().join(','); // <BN: 1,2,3,4>
+
+// Little endian
+new BN([1,2,3], 10, 'le'); // <BN: 30201>
+new BN([1,2,3,4], 10, 'le'); // <BN: 4030201>
+
+// bitLength
+new BN(0x123456).bitLength(); // <BN: 21>
+new BN('123456789', 16).bitLength(); // <BN: 33>
+
+// zeroBits
+new BN('11000', 2).zeroBits(); // 3
+
+// iaddn
+new BN(-100).sign;  // true
+new BN(100).sign;   // false
+
+// isubn
+new BN(-100).isubn(200) // <BN: -300>
+
+// add
+new BN(14).add(new BN(26)); // <BN: 28>
+
+// mul
+new BN(0x1001).mul(new BN(0x1234)); // <BN: 1235234>
+
+// div
+new BN('-69527932928').div(new BN('16974594')); // <BN: -fff>
+
+// mod
+new BN('10').mod(new BN(256)); // <BN: a>
+
+// divRound
+new BN(9).divRound(new BN(20)).toString(10); // <BN: 0>
+
+// abs
+new BN(0x1001).abs(); // <BN: 4097>
+
+// modn
+new BN('10', 16).modn(256); // <BN: 10>
+
+// idivn
+new BN('10', 16).idivn(3); // <BN: 5>
+
+// shl
+new BN('69527932928').shln(13); // <BN: 2060602000000>
+
+// shrn
+new BN('69527932928').shrn(13); // <BN: 818180>
+
+// bincn
+new BN(0xffffff).bincn(1);  // <BN: 1000001>
+
+// imaskn
+new BN('123456789', 16).imaskn(4); // <BN: 9>
+
+// gcd
+new BN(-18).gcd(new BN(12)); // <BN: 6>
+
+// iand
+(new BN('1', 2)
+.iand(new BN('1000000000000000000000000000000000000001', 2))
+.toString(2); // '1'
+
+// ior
+new BN('1', 2)
+.ior(new BN('1000000000000000000000000000000000000000', 2));
+// <BN: 1000000000000000000000000000000000000001>
+
+// ixor
+new BN('1', 2)
+.ixor(new BN('11001100110011001100110011001100', 2));
+// <BN: '11001100110011001100110011001101'>
+
+// setn
+new BN(0).setn(2, true); // <BN: 100>
+
+```
+
+## LICENSE
+
+This software is licensed under the MIT License.
+
+Copyright Fedor Indutny, 2015.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/bn.js/lib/bn.js b/node_modules/bn.js/lib/bn.js
new file mode 100644
index 0000000000000000000000000000000000000000..caa8c5caba5546a8be24041e45ed130f7028415a
--- /dev/null
+++ b/node_modules/bn.js/lib/bn.js
@@ -0,0 +1,2266 @@
+(function (module, exports) {
+
+'use strict';
+
+// Utils
+
+function assert(val, msg) {
+  if (!val)
+    throw new Error(msg || 'Assertion failed');
+}
+
+// Could use `inherits` module, but don't want to move from single file
+// architecture yet.
+function inherits(ctor, superCtor) {
+  ctor.super_ = superCtor;
+  var TempCtor = function () {};
+  TempCtor.prototype = superCtor.prototype;
+  ctor.prototype = new TempCtor();
+  ctor.prototype.constructor = ctor;
+}
+
+// BN
+
+function BN(number, base, endian) {
+  // May be `new BN(bn)` ?
+  if (number !== null &&
+      typeof number === 'object' &&
+      Array.isArray(number.words)) {
+    return number;
+  }
+
+  this.sign = false;
+  this.words = null;
+  this.length = 0;
+
+  // Reduction context
+  this.red = null;
+
+  if (base === 'le' || base === 'be') {
+    endian = base;
+    base = 10;
+  }
+
+  if (number !== null)
+    this._init(number || 0, base || 10, endian || 'be');
+}
+if (typeof module === 'object')
+  module.exports = BN;
+else
+  exports.BN = BN;
+
+BN.BN = BN;
+BN.wordSize = 26;
+
+BN.prototype._init = function init(number, base, endian) {
+  if (typeof number === 'number') {
+    if (number < 0) {
+      this.sign = true;
+      number = -number;
+    }
+    if (number < 0x4000000) {
+      this.words = [ number & 0x3ffffff ];
+      this.length = 1;
+    } else {
+      this.words = [
+        number & 0x3ffffff,
+        (number / 0x4000000) & 0x3ffffff
+      ];
+      this.length = 2;
+    }
+    return;
+  } else if (typeof number === 'object') {
+    return this._initArray(number, base, endian);
+  }
+  if (base === 'hex')
+    base = 16;
+  assert(base === (base | 0) && base >= 2 && base <= 36);
+
+  number = number.toString().replace(/\s+/g, '');
+  var start = 0;
+  if (number[0] === '-')
+    start++;
+
+  if (base === 16)
+    this._parseHex(number, start);
+  else
+    this._parseBase(number, base, start);
+
+  if (number[0] === '-')
+    this.sign = true;
+
+  this.strip();
+};
+
+BN.prototype._initArray = function _initArray(number, base, endian) {
+  // Perhaps a Uint8Array
+  assert(typeof number.length === 'number');
+  this.length = Math.ceil(number.length / 3);
+  this.words = new Array(this.length);
+  for (var i = 0; i < this.length; i++)
+    this.words[i] = 0;
+
+  var off = 0;
+  if (endian === 'be') {
+    for (var i = number.length - 1, j = 0; i >= 0; i -= 3) {
+      var w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
+      this.words[j] |= (w << off) & 0x3ffffff;
+      this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
+      off += 24;
+      if (off >= 26) {
+        off -= 26;
+        j++;
+      }
+    }
+  } else if (endian === 'le') {
+    for (var i = 0, j = 0; i < number.length; i += 3) {
+      var w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
+      this.words[j] |= (w << off) & 0x3ffffff;
+      this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
+      off += 24;
+      if (off >= 26) {
+        off -= 26;
+        j++;
+      }
+    }
+  }
+  return this.strip();
+};
+
+function parseHex(str, start, end) {
+  var r = 0;
+  var len = Math.min(str.length, end);
+  for (var i = start; i < len; i++) {
+    var c = str.charCodeAt(i) - 48;
+
+    r <<= 4;
+
+    // 'a' - 'f'
+    if (c >= 49 && c <= 54)
+      r |= c - 49 + 0xa;
+
+    // 'A' - 'F'
+    else if (c >= 17 && c <= 22)
+      r |= c - 17 + 0xa;
+
+    // '0' - '9'
+    else
+      r |= c & 0xf;
+  }
+  return r;
+}
+
+BN.prototype._parseHex = function _parseHex(number, start) {
+  // Create possibly bigger array to ensure that it fits the number
+  this.length = Math.ceil((number.length - start) / 6);
+  this.words = new Array(this.length);
+  for (var i = 0; i < this.length; i++)
+    this.words[i] = 0;
+
+  // Scan 24-bit chunks and add them to the number
+  var off = 0;
+  for (var i = number.length - 6, j = 0; i >= start; i -= 6) {
+    var w = parseHex(number, i, i + 6);
+    this.words[j] |= (w << off) & 0x3ffffff;
+    this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
+    off += 24;
+    if (off >= 26) {
+      off -= 26;
+      j++;
+    }
+  }
+  if (i + 6 !== start) {
+    var w = parseHex(number, start, i + 6);
+    this.words[j] |= (w << off) & 0x3ffffff;
+    this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
+  }
+  this.strip();
+};
+
+function parseBase(str, start, end, mul) {
+  var r = 0;
+  var len = Math.min(str.length, end);
+  for (var i = start; i < len; i++) {
+    var c = str.charCodeAt(i) - 48;
+
+    r *= mul;
+
+    // 'a'
+    if (c >= 49)
+      r += c - 49 + 0xa;
+
+    // 'A'
+    else if (c >= 17)
+      r += c - 17 + 0xa;
+
+    // '0' - '9'
+    else
+      r += c;
+  }
+  return r;
+}
+
+BN.prototype._parseBase = function _parseBase(number, base, start) {
+  // Initialize as zero
+  this.words = [ 0 ];
+  this.length = 1;
+
+  // Find length of limb in base
+  for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base)
+    limbLen++;
+  limbLen--;
+  limbPow = (limbPow / base) | 0;
+
+  var total = number.length - start;
+  var mod = total % limbLen;
+  var end = Math.min(total, total - mod) + start;
+
+  var word = 0;
+  for (var i = start; i < end; i += limbLen) {
+    word = parseBase(number, i, i + limbLen, base);
+
+    this.imuln(limbPow);
+    if (this.words[0] + word < 0x4000000)
+      this.words[0] += word;
+    else
+      this._iaddn(word);
+  }
+
+  if (mod !== 0) {
+    var pow = 1;
+    var word = parseBase(number, i, number.length, base);
+
+    for (var i = 0; i < mod; i++)
+      pow *= base;
+    this.imuln(pow);
+    if (this.words[0] + word < 0x4000000)
+      this.words[0] += word;
+    else
+      this._iaddn(word);
+  }
+};
+
+BN.prototype.copy = function copy(dest) {
+  dest.words = new Array(this.length);
+  for (var i = 0; i < this.length; i++)
+    dest.words[i] = this.words[i];
+  dest.length = this.length;
+  dest.sign = this.sign;
+  dest.red = this.red;
+};
+
+BN.prototype.clone = function clone() {
+  var r = new BN(null);
+  this.copy(r);
+  return r;
+};
+
+// Remove leading `0` from `this`
+BN.prototype.strip = function strip() {
+  while (this.length > 1 && this.words[this.length - 1] === 0)
+    this.length--;
+  return this._normSign();
+};
+
+BN.prototype._normSign = function _normSign() {
+  // -0 = 0
+  if (this.length === 1 && this.words[0] === 0)
+    this.sign = false;
+  return this;
+};
+
+BN.prototype.inspect = function inspect() {
+  return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
+};
+
+/*
+
+var zeros = [];
+var groupSizes = [];
+var groupBases = [];
+
+var s = '';
+var i = -1;
+while (++i < BN.wordSize) {
+  zeros[i] = s;
+  s += '0';
+}
+groupSizes[0] = 0;
+groupSizes[1] = 0;
+groupBases[0] = 0;
+groupBases[1] = 0;
+var base = 2 - 1;
+while (++base < 36 + 1) {
+  var groupSize = 0;
+  var groupBase = 1;
+  while (groupBase < (1 << BN.wordSize) / base) {
+    groupBase *= base;
+    groupSize += 1;
+  }
+  groupSizes[base] = groupSize;
+  groupBases[base] = groupBase;
+}
+
+*/
+
+var zeros = [
+  '',
+  '0',
+  '00',
+  '000',
+  '0000',
+  '00000',
+  '000000',
+  '0000000',
+  '00000000',
+  '000000000',
+  '0000000000',
+  '00000000000',
+  '000000000000',
+  '0000000000000',
+  '00000000000000',
+  '000000000000000',
+  '0000000000000000',
+  '00000000000000000',
+  '000000000000000000',
+  '0000000000000000000',
+  '00000000000000000000',
+  '000000000000000000000',
+  '0000000000000000000000',
+  '00000000000000000000000',
+  '000000000000000000000000',
+  '0000000000000000000000000'
+];
+
+var groupSizes = [
+  0, 0,
+  25, 16, 12, 11, 10, 9, 8,
+  8, 7, 7, 7, 7, 6, 6,
+  6, 6, 6, 6, 6, 5, 5,
+  5, 5, 5, 5, 5, 5, 5,
+  5, 5, 5, 5, 5, 5, 5
+];
+
+var groupBases = [
+  0, 0,
+  33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
+  43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
+  16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
+  6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
+  24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
+];
+
+BN.prototype.toString = function toString(base, padding) {
+  base = base || 10;
+  if (base === 16 || base === 'hex') {
+    var out = '';
+    var off = 0;
+    var padding = padding | 0 || 1;
+    var carry = 0;
+    for (var i = 0; i < this.length; i++) {
+      var w = this.words[i];
+      var word = (((w << off) | carry) & 0xffffff).toString(16);
+      carry = (w >>> (24 - off)) & 0xffffff;
+      if (carry !== 0 || i !== this.length - 1)
+        out = zeros[6 - word.length] + word + out;
+      else
+        out = word + out;
+      off += 2;
+      if (off >= 26) {
+        off -= 26;
+        i--;
+      }
+    }
+    if (carry !== 0)
+      out = carry.toString(16) + out;
+    while (out.length % padding !== 0)
+      out = '0' + out;
+    if (this.sign)
+      out = '-' + out;
+    return out;
+  } else if (base === (base | 0) && base >= 2 && base <= 36) {
+    // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
+    var groupSize = groupSizes[base];
+    // var groupBase = Math.pow(base, groupSize);
+    var groupBase = groupBases[base];
+    var out = '';
+    var c = this.clone();
+    c.sign = false;
+    while (c.cmpn(0) !== 0) {
+      var r = c.modn(groupBase).toString(base);
+      c = c.idivn(groupBase);
+
+      if (c.cmpn(0) !== 0)
+        out = zeros[groupSize - r.length] + r + out;
+      else
+        out = r + out;
+    }
+    if (this.cmpn(0) === 0)
+      out = '0' + out;
+    if (this.sign)
+      out = '-' + out;
+    return out;
+  } else {
+    assert(false, 'Base should be between 2 and 36');
+  }
+};
+
+BN.prototype.toJSON = function toJSON() {
+  return this.toString(16);
+};
+
+BN.prototype.toArray = function toArray() {
+  this.strip();
+  var res = new Array(this.byteLength());
+  res[0] = 0;
+
+  var q = this.clone();
+  for (var i = 0; q.cmpn(0) !== 0; i++) {
+    var b = q.andln(0xff);
+    q.ishrn(8);
+
+    // Assume big-endian
+    res[res.length - i - 1] = b;
+  }
+
+  return res;
+};
+
+if (Math.clz32) {
+  BN.prototype._countBits = function _countBits(w) {
+    return 32 - Math.clz32(w);
+  };
+} else {
+  BN.prototype._countBits = function _countBits(w) {
+    var t = w;
+    var r = 0;
+    if (t >= 0x1000) {
+      r += 13;
+      t >>>= 13;
+    }
+    if (t >= 0x40) {
+      r += 7;
+      t >>>= 7;
+    }
+    if (t >= 0x8) {
+      r += 4;
+      t >>>= 4;
+    }
+    if (t >= 0x02) {
+      r += 2;
+      t >>>= 2;
+    }
+    return r + t;
+  };
+}
+
+BN.prototype._zeroBits = function _zeroBits(w) {
+  // Short-cut
+  if (w === 0)
+    return 26;
+
+  var t = w;
+  var r = 0;
+  if ((t & 0x1fff) === 0) {
+    r += 13;
+    t >>>= 13;
+  }
+  if ((t & 0x7f) === 0) {
+    r += 7;
+    t >>>= 7;
+  }
+  if ((t & 0xf) === 0) {
+    r += 4;
+    t >>>= 4;
+  }
+  if ((t & 0x3) === 0) {
+    r += 2;
+    t >>>= 2;
+  }
+  if ((t & 0x1) === 0)
+    r++;
+  return r;
+};
+
+// Return number of used bits in a BN
+BN.prototype.bitLength = function bitLength() {
+  var hi = 0;
+  var w = this.words[this.length - 1];
+  var hi = this._countBits(w);
+  return (this.length - 1) * 26 + hi;
+};
+
+// Number of trailing zero bits
+BN.prototype.zeroBits = function zeroBits() {
+  if (this.cmpn(0) === 0)
+    return 0;
+
+  var r = 0;
+  for (var i = 0; i < this.length; i++) {
+    var b = this._zeroBits(this.words[i]);
+    r += b;
+    if (b !== 26)
+      break;
+  }
+  return r;
+};
+
+BN.prototype.byteLength = function byteLength() {
+  return Math.ceil(this.bitLength() / 8);
+};
+
+// Return negative clone of `this`
+BN.prototype.neg = function neg() {
+  if (this.cmpn(0) === 0)
+    return this.clone();
+
+  var r = this.clone();
+  r.sign = !this.sign;
+  return r;
+};
+
+
+// Or `num` with `this` in-place
+BN.prototype.ior = function ior(num) {
+  this.sign = this.sign || num.sign;
+
+  while (this.length < num.length)
+    this.words[this.length++] = 0;
+
+  for (var i = 0; i < num.length; i++)
+    this.words[i] = this.words[i] | num.words[i];
+
+  return this.strip();
+};
+
+
+// Or `num` with `this`
+BN.prototype.or = function or(num) {
+  if (this.length > num.length)
+    return this.clone().ior(num);
+  else
+    return num.clone().ior(this);
+};
+
+
+// And `num` with `this` in-place
+BN.prototype.iand = function iand(num) {
+  this.sign = this.sign && num.sign;
+
+  // b = min-length(num, this)
+  var b;
+  if (this.length > num.length)
+    b = num;
+  else
+    b = this;
+
+  for (var i = 0; i < b.length; i++)
+    this.words[i] = this.words[i] & num.words[i];
+
+  this.length = b.length;
+
+  return this.strip();
+};
+
+
+// And `num` with `this`
+BN.prototype.and = function and(num) {
+  if (this.length > num.length)
+    return this.clone().iand(num);
+  else
+    return num.clone().iand(this);
+};
+
+
+// Xor `num` with `this` in-place
+BN.prototype.ixor = function ixor(num) {
+  this.sign = this.sign || num.sign;
+
+  // a.length > b.length
+  var a;
+  var b;
+  if (this.length > num.length) {
+    a = this;
+    b = num;
+  } else {
+    a = num;
+    b = this;
+  }
+
+  for (var i = 0; i < b.length; i++)
+    this.words[i] = a.words[i] ^ b.words[i];
+
+  if (this !== a)
+    for (; i < a.length; i++)
+      this.words[i] = a.words[i];
+
+  this.length = a.length;
+
+  return this.strip();
+};
+
+
+// Xor `num` with `this`
+BN.prototype.xor = function xor(num) {
+  if (this.length > num.length)
+    return this.clone().ixor(num);
+  else
+    return num.clone().ixor(this);
+};
+
+
+// Set `bit` of `this`
+BN.prototype.setn = function setn(bit, val) {
+  assert(typeof bit === 'number' && bit >= 0);
+
+  var off = (bit / 26) | 0;
+  var wbit = bit % 26;
+
+  while (this.length <= off)
+    this.words[this.length++] = 0;
+
+  if (val)
+    this.words[off] = this.words[off] | (1 << wbit);
+  else
+    this.words[off] = this.words[off] & ~(1 << wbit);
+
+  return this.strip();
+};
+
+
+// Add `num` to `this` in-place
+BN.prototype.iadd = function iadd(num) {
+  // negative + positive
+  if (this.sign && !num.sign) {
+    this.sign = false;
+    var r = this.isub(num);
+    this.sign = !this.sign;
+    return this._normSign();
+
+  // positive + negative
+  } else if (!this.sign && num.sign) {
+    num.sign = false;
+    var r = this.isub(num);
+    num.sign = true;
+    return r._normSign();
+  }
+
+  // a.length > b.length
+  var a;
+  var b;
+  if (this.length > num.length) {
+    a = this;
+    b = num;
+  } else {
+    a = num;
+    b = this;
+  }
+
+  var carry = 0;
+  for (var i = 0; i < b.length; i++) {
+    var r = a.words[i] + b.words[i] + carry;
+    this.words[i] = r & 0x3ffffff;
+    carry = r >>> 26;
+  }
+  for (; carry !== 0 && i < a.length; i++) {
+    var r = a.words[i] + carry;
+    this.words[i] = r & 0x3ffffff;
+    carry = r >>> 26;
+  }
+
+  this.length = a.length;
+  if (carry !== 0) {
+    this.words[this.length] = carry;
+    this.length++;
+  // Copy the rest of the words
+  } else if (a !== this) {
+    for (; i < a.length; i++)
+      this.words[i] = a.words[i];
+  }
+
+  return this;
+};
+
+// Add `num` to `this`
+BN.prototype.add = function add(num) {
+  if (num.sign && !this.sign) {
+    num.sign = false;
+    var res = this.sub(num);
+    num.sign = true;
+    return res;
+  } else if (!num.sign && this.sign) {
+    this.sign = false;
+    var res = num.sub(this);
+    this.sign = true;
+    return res;
+  }
+
+  if (this.length > num.length)
+    return this.clone().iadd(num);
+  else
+    return num.clone().iadd(this);
+};
+
+// Subtract `num` from `this` in-place
+BN.prototype.isub = function isub(num) {
+  // this - (-num) = this + num
+  if (num.sign) {
+    num.sign = false;
+    var r = this.iadd(num);
+    num.sign = true;
+    return r._normSign();
+
+  // -this - num = -(this + num)
+  } else if (this.sign) {
+    this.sign = false;
+    this.iadd(num);
+    this.sign = true;
+    return this._normSign();
+  }
+
+  // At this point both numbers are positive
+  var cmp = this.cmp(num);
+
+  // Optimization - zeroify
+  if (cmp === 0) {
+    this.sign = false;
+    this.length = 1;
+    this.words[0] = 0;
+    return this;
+  }
+
+  // a > b
+  var a;
+  var b;
+  if (cmp > 0) {
+    a = this;
+    b = num;
+  } else {
+    a = num;
+    b = this;
+  }
+
+  var carry = 0;
+  for (var i = 0; i < b.length; i++) {
+    var r = a.words[i] - b.words[i] + carry;
+    carry = r >> 26;
+    this.words[i] = r & 0x3ffffff;
+  }
+  for (; carry !== 0 && i < a.length; i++) {
+    var r = a.words[i] + carry;
+    carry = r >> 26;
+    this.words[i] = r & 0x3ffffff;
+  }
+
+  // Copy rest of the words
+  if (carry === 0 && i < a.length && a !== this)
+    for (; i < a.length; i++)
+      this.words[i] = a.words[i];
+  this.length = Math.max(this.length, i);
+
+  if (a !== this)
+    this.sign = true;
+
+  return this.strip();
+};
+
+// Subtract `num` from `this`
+BN.prototype.sub = function sub(num) {
+  return this.clone().isub(num);
+};
+
+/*
+// NOTE: This could be potentionally used to generate loop-less multiplications
+function _genCombMulTo(alen, blen) {
+  var len = alen + blen - 1;
+  var src = [
+    'var a = this.words, b = num.words, o = out.words, c = 0, w, ' +
+        'mask = 0x3ffffff, shift = 0x4000000;',
+    'out.length = ' + len + ';'
+  ];
+  for (var k = 0; k < len; k++) {
+    var minJ = Math.max(0, k - alen + 1);
+    var maxJ = Math.min(k, blen - 1);
+
+    for (var j = minJ; j <= maxJ; j++) {
+      var i = k - j;
+      var mul = 'a[' + i + '] * b[' + j + ']';
+
+      if (j === minJ) {
+        src.push('w = ' + mul + ' + c;');
+        src.push('c = (w / shift) | 0;');
+      } else {
+        src.push('w += ' + mul + ';');
+        src.push('c += (w / shift) | 0;');
+      }
+      src.push('w &= mask;');
+    }
+    src.push('o[' + k + '] = w;');
+  }
+  src.push('if (c !== 0) {',
+           '  o[' + k + '] = c;',
+           '  out.length++;',
+           '}',
+           'return out;');
+
+  return src.join('\n');
+}
+*/
+
+BN.prototype._smallMulTo = function _smallMulTo(num, out) {
+  out.sign = num.sign !== this.sign;
+  out.length = this.length + num.length;
+
+  var carry = 0;
+  for (var k = 0; k < out.length - 1; k++) {
+    // Sum all words with the same `i + j = k` and accumulate `ncarry`,
+    // note that ncarry could be >= 0x3ffffff
+    var ncarry = carry >>> 26;
+    var rword = carry & 0x3ffffff;
+    var maxJ = Math.min(k, num.length - 1);
+    for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
+      var i = k - j;
+      var a = this.words[i] | 0;
+      var b = num.words[j] | 0;
+      var r = a * b;
+
+      var lo = r & 0x3ffffff;
+      ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
+      lo = (lo + rword) | 0;
+      rword = lo & 0x3ffffff;
+      ncarry = (ncarry + (lo >>> 26)) | 0;
+    }
+    out.words[k] = rword;
+    carry = ncarry;
+  }
+  if (carry !== 0) {
+    out.words[k] = carry;
+  } else {
+    out.length--;
+  }
+
+  return out.strip();
+};
+
+BN.prototype._bigMulTo = function _bigMulTo(num, out) {
+  out.sign = num.sign !== this.sign;
+  out.length = this.length + num.length;
+
+  var carry = 0;
+  var hncarry = 0;
+  for (var k = 0; k < out.length - 1; k++) {
+    // Sum all words with the same `i + j = k` and accumulate `ncarry`,
+    // note that ncarry could be >= 0x3ffffff
+    var ncarry = hncarry;
+    hncarry = 0;
+    var rword = carry & 0x3ffffff;
+    var maxJ = Math.min(k, num.length - 1);
+    for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) {
+      var i = k - j;
+      var a = this.words[i] | 0;
+      var b = num.words[j] | 0;
+      var r = a * b;
+
+      var lo = r & 0x3ffffff;
+      ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
+      lo = (lo + rword) | 0;
+      rword = lo & 0x3ffffff;
+      ncarry = (ncarry + (lo >>> 26)) | 0;
+
+      hncarry += ncarry >>> 26;
+      ncarry &= 0x3ffffff;
+    }
+    out.words[k] = rword;
+    carry = ncarry;
+    ncarry = hncarry;
+  }
+  if (carry !== 0) {
+    out.words[k] = carry;
+  } else {
+    out.length--;
+  }
+
+  return out.strip();
+};
+
+BN.prototype.mulTo = function mulTo(num, out) {
+  var res;
+  if (this.length + num.length < 63)
+    res = this._smallMulTo(num, out);
+  else
+    res = this._bigMulTo(num, out);
+  return res;
+};
+
+// Multiply `this` by `num`
+BN.prototype.mul = function mul(num) {
+  var out = new BN(null);
+  out.words = new Array(this.length + num.length);
+  return this.mulTo(num, out);
+};
+
+// In-place Multiplication
+BN.prototype.imul = function imul(num) {
+  if (this.cmpn(0) === 0 || num.cmpn(0) === 0) {
+    this.words[0] = 0;
+    this.length = 1;
+    return this;
+  }
+
+  var tlen = this.length;
+  var nlen = num.length;
+
+  this.sign = num.sign !== this.sign;
+  this.length = this.length + num.length;
+  this.words[this.length - 1] = 0;
+
+  for (var k = this.length - 2; k >= 0; k--) {
+    // Sum all words with the same `i + j = k` and accumulate `carry`,
+    // note that carry could be >= 0x3ffffff
+    var carry = 0;
+    var rword = 0;
+    var maxJ = Math.min(k, nlen - 1);
+    for (var j = Math.max(0, k - tlen + 1); j <= maxJ; j++) {
+      var i = k - j;
+      var a = this.words[i];
+      var b = num.words[j];
+      var r = a * b;
+
+      var lo = r & 0x3ffffff;
+      carry += (r / 0x4000000) | 0;
+      lo += rword;
+      rword = lo & 0x3ffffff;
+      carry += lo >>> 26;
+    }
+    this.words[k] = rword;
+    this.words[k + 1] += carry;
+    carry = 0;
+  }
+
+  // Propagate overflows
+  var carry = 0;
+  for (var i = 1; i < this.length; i++) {
+    var w = this.words[i] + carry;
+    this.words[i] = w & 0x3ffffff;
+    carry = w >>> 26;
+  }
+
+  return this.strip();
+};
+
+BN.prototype.imuln = function imuln(num) {
+  assert(typeof num === 'number');
+
+  // Carry
+  var carry = 0;
+  for (var i = 0; i < this.length; i++) {
+    var w = this.words[i] * num;
+    var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
+    carry >>= 26;
+    carry += (w / 0x4000000) | 0;
+    // NOTE: lo is 27bit maximum
+    carry += lo >>> 26;
+    this.words[i] = lo & 0x3ffffff;
+  }
+
+  if (carry !== 0) {
+    this.words[i] = carry;
+    this.length++;
+  }
+
+  return this;
+};
+
+// `this` * `this`
+BN.prototype.sqr = function sqr() {
+  return this.mul(this);
+};
+
+// `this` * `this` in-place
+BN.prototype.isqr = function isqr() {
+  return this.mul(this);
+};
+
+// Shift-left in-place
+BN.prototype.ishln = function ishln(bits) {
+  assert(typeof bits === 'number' && bits >= 0);
+  var r = bits % 26;
+  var s = (bits - r) / 26;
+  var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
+
+  if (r !== 0) {
+    var carry = 0;
+    for (var i = 0; i < this.length; i++) {
+      var newCarry = this.words[i] & carryMask;
+      var c = (this.words[i] - newCarry) << r;
+      this.words[i] = c | carry;
+      carry = newCarry >>> (26 - r);
+    }
+    if (carry) {
+      this.words[i] = carry;
+      this.length++;
+    }
+  }
+
+  if (s !== 0) {
+    for (var i = this.length - 1; i >= 0; i--)
+      this.words[i + s] = this.words[i];
+    for (var i = 0; i < s; i++)
+      this.words[i] = 0;
+    this.length += s;
+  }
+
+  return this.strip();
+};
+
+// Shift-right in-place
+// NOTE: `hint` is a lowest bit before trailing zeroes
+// NOTE: if `extended` is present - it will be filled with destroyed bits
+BN.prototype.ishrn = function ishrn(bits, hint, extended) {
+  assert(typeof bits === 'number' && bits >= 0);
+  var h;
+  if (hint)
+    h = (hint - (hint % 26)) / 26;
+  else
+    h = 0;
+
+  var r = bits % 26;
+  var s = Math.min((bits - r) / 26, this.length);
+  var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
+  var maskedWords = extended;
+
+  h -= s;
+  h = Math.max(0, h);
+
+  // Extended mode, copy masked part
+  if (maskedWords) {
+    for (var i = 0; i < s; i++)
+      maskedWords.words[i] = this.words[i];
+    maskedWords.length = s;
+  }
+
+  if (s === 0) {
+    // No-op, we should not move anything at all
+  } else if (this.length > s) {
+    this.length -= s;
+    for (var i = 0; i < this.length; i++)
+      this.words[i] = this.words[i + s];
+  } else {
+    this.words[0] = 0;
+    this.length = 1;
+  }
+
+  var carry = 0;
+  for (var i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
+    var word = this.words[i];
+    this.words[i] = (carry << (26 - r)) | (word >>> r);
+    carry = word & mask;
+  }
+
+  // Push carried bits as a mask
+  if (maskedWords && carry !== 0)
+    maskedWords.words[maskedWords.length++] = carry;
+
+  if (this.length === 0) {
+    this.words[0] = 0;
+    this.length = 1;
+  }
+
+  this.strip();
+
+  return this;
+};
+
+// Shift-left
+BN.prototype.shln = function shln(bits) {
+  return this.clone().ishln(bits);
+};
+
+// Shift-right
+BN.prototype.shrn = function shrn(bits) {
+  return this.clone().ishrn(bits);
+};
+
+// Test if n bit is set
+BN.prototype.testn = function testn(bit) {
+  assert(typeof bit === 'number' && bit >= 0);
+  var r = bit % 26;
+  var s = (bit - r) / 26;
+  var q = 1 << r;
+
+  // Fast case: bit is much higher than all existing words
+  if (this.length <= s) {
+    return false;
+  }
+
+  // Check bit and return
+  var w = this.words[s];
+
+  return !!(w & q);
+};
+
+// Return only lowers bits of number (in-place)
+BN.prototype.imaskn = function imaskn(bits) {
+  assert(typeof bits === 'number' && bits >= 0);
+  var r = bits % 26;
+  var s = (bits - r) / 26;
+
+  assert(!this.sign, 'imaskn works only with positive numbers');
+
+  if (r !== 0)
+    s++;
+  this.length = Math.min(s, this.length);
+
+  if (r !== 0) {
+    var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
+    this.words[this.length - 1] &= mask;
+  }
+
+  return this.strip();
+};
+
+// Return only lowers bits of number
+BN.prototype.maskn = function maskn(bits) {
+  return this.clone().imaskn(bits);
+};
+
+// Add plain number `num` to `this`
+BN.prototype.iaddn = function iaddn(num) {
+  assert(typeof num === 'number');
+  if (num < 0)
+    return this.isubn(-num);
+
+  // Possible sign change
+  if (this.sign) {
+    if (this.length === 1 && this.words[0] < num) {
+      this.words[0] = num - this.words[0];
+      this.sign = false;
+      return this;
+    }
+
+    this.sign = false;
+    this.isubn(num);
+    this.sign = true;
+    return this;
+  }
+
+  // Add without checks
+  return this._iaddn(num);
+};
+
+BN.prototype._iaddn = function _iaddn(num) {
+  this.words[0] += num;
+
+  // Carry
+  for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
+    this.words[i] -= 0x4000000;
+    if (i === this.length - 1)
+      this.words[i + 1] = 1;
+    else
+      this.words[i + 1]++;
+  }
+  this.length = Math.max(this.length, i + 1);
+
+  return this;
+};
+
+// Subtract plain number `num` from `this`
+BN.prototype.isubn = function isubn(num) {
+  assert(typeof num === 'number');
+  if (num < 0)
+    return this.iaddn(-num);
+
+  if (this.sign) {
+    this.sign = false;
+    this.iaddn(num);
+    this.sign = true;
+    return this;
+  }
+
+  this.words[0] -= num;
+
+  // Carry
+  for (var i = 0; i < this.length && this.words[i] < 0; i++) {
+    this.words[i] += 0x4000000;
+    this.words[i + 1] -= 1;
+  }
+
+  return this.strip();
+};
+
+BN.prototype.addn = function addn(num) {
+  return this.clone().iaddn(num);
+};
+
+BN.prototype.subn = function subn(num) {
+  return this.clone().isubn(num);
+};
+
+BN.prototype.iabs = function iabs() {
+  this.sign = false;
+
+  return this;
+};
+
+BN.prototype.abs = function abs() {
+  return this.clone().iabs();
+};
+
+BN.prototype._ishlnsubmul = function _ishlnsubmul(num, mul, shift) {
+  // Bigger storage is needed
+  var len = num.length + shift;
+  var i;
+  if (this.words.length < len) {
+    var t = new Array(len);
+    for (var i = 0; i < this.length; i++)
+      t[i] = this.words[i];
+    this.words = t;
+  } else {
+    i = this.length;
+  }
+
+  // Zeroify rest
+  this.length = Math.max(this.length, len);
+  for (; i < this.length; i++)
+    this.words[i] = 0;
+
+  var carry = 0;
+  for (var i = 0; i < num.length; i++) {
+    var w = this.words[i + shift] + carry;
+    var right = num.words[i] * mul;
+    w -= right & 0x3ffffff;
+    carry = (w >> 26) - ((right / 0x4000000) | 0);
+    this.words[i + shift] = w & 0x3ffffff;
+  }
+  for (; i < this.length - shift; i++) {
+    var w = this.words[i + shift] + carry;
+    carry = w >> 26;
+    this.words[i + shift] = w & 0x3ffffff;
+  }
+
+  if (carry === 0)
+    return this.strip();
+
+  // Subtraction overflow
+  assert(carry === -1);
+  carry = 0;
+  for (var i = 0; i < this.length; i++) {
+    var w = -this.words[i] + carry;
+    carry = w >> 26;
+    this.words[i] = w & 0x3ffffff;
+  }
+  this.sign = true;
+
+  return this.strip();
+};
+
+BN.prototype._wordDiv = function _wordDiv(num, mode) {
+  var shift = this.length - num.length;
+
+  var a = this.clone();
+  var b = num;
+
+  // Normalize
+  var bhi = b.words[b.length - 1];
+  var bhiBits = this._countBits(bhi);
+  shift = 26 - bhiBits;
+  if (shift !== 0) {
+    b = b.shln(shift);
+    a.ishln(shift);
+    bhi = b.words[b.length - 1];
+  }
+
+  // Initialize quotient
+  var m = a.length - b.length;
+  var q;
+
+  if (mode !== 'mod') {
+    q = new BN(null);
+    q.length = m + 1;
+    q.words = new Array(q.length);
+    for (var i = 0; i < q.length; i++)
+      q.words[i] = 0;
+  }
+
+  var diff = a.clone()._ishlnsubmul(b, 1, m);
+  if (!diff.sign) {
+    a = diff;
+    if (q)
+      q.words[m] = 1;
+  }
+
+  for (var j = m - 1; j >= 0; j--) {
+    var qj = a.words[b.length + j] * 0x4000000 + a.words[b.length + j - 1];
+
+    // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
+    // (0x7ffffff)
+    qj = Math.min((qj / bhi) | 0, 0x3ffffff);
+
+    a._ishlnsubmul(b, qj, j);
+    while (a.sign) {
+      qj--;
+      a.sign = false;
+      a._ishlnsubmul(b, 1, j);
+      a.sign = !a.sign;
+    }
+    if (q)
+      q.words[j] = qj;
+  }
+  if (q)
+    q.strip();
+  a.strip();
+
+  // Denormalize
+  if (mode !== 'div' && shift !== 0)
+    a.ishrn(shift);
+  return { div: q ? q : null, mod: a };
+};
+
+BN.prototype.divmod = function divmod(num, mode) {
+  assert(num.cmpn(0) !== 0);
+
+  if (this.sign && !num.sign) {
+    var res = this.neg().divmod(num, mode);
+    var div;
+    var mod;
+    if (mode !== 'mod')
+      div = res.div.neg();
+    if (mode !== 'div')
+      mod = res.mod.cmpn(0) === 0 ? res.mod : num.sub(res.mod);
+    return {
+      div: div,
+      mod: mod
+    };
+  } else if (!this.sign && num.sign) {
+    var res = this.divmod(num.neg(), mode);
+    var div;
+    if (mode !== 'mod')
+      div = res.div.neg();
+    return { div: div, mod: res.mod };
+  } else if (this.sign && num.sign) {
+    return this.neg().divmod(num.neg(), mode);
+  }
+
+  // Both numbers are positive at this point
+
+  // Strip both numbers to approximate shift value
+  if (num.length > this.length || this.cmp(num) < 0)
+    return { div: new BN(0), mod: this };
+
+  // Very short reduction
+  if (num.length === 1) {
+    if (mode === 'div')
+      return { div: this.divn(num.words[0]), mod: null };
+    else if (mode === 'mod')
+      return { div: null, mod: new BN(this.modn(num.words[0])) };
+    return {
+      div: this.divn(num.words[0]),
+      mod: new BN(this.modn(num.words[0]))
+    };
+  }
+
+  return this._wordDiv(num, mode);
+};
+
+// Find `this` / `num`
+BN.prototype.div = function div(num) {
+  return this.divmod(num, 'div').div;
+};
+
+// Find `this` % `num`
+BN.prototype.mod = function mod(num) {
+  return this.divmod(num, 'mod').mod;
+};
+
+// Find Round(`this` / `num`)
+BN.prototype.divRound = function divRound(num) {
+  var dm = this.divmod(num);
+
+  // Fast case - exact division
+  if (dm.mod.cmpn(0) === 0)
+    return dm.div;
+
+  var mod = dm.div.sign ? dm.mod.isub(num) : dm.mod;
+
+  var half = num.shrn(1);
+  var r2 = num.andln(1);
+  var cmp = mod.cmp(half);
+
+  // Round down
+  if (cmp < 0 || r2 === 1 && cmp === 0)
+    return dm.div;
+
+  // Round up
+  return dm.div.sign ? dm.div.isubn(1) : dm.div.iaddn(1);
+};
+
+BN.prototype.modn = function modn(num) {
+  assert(num <= 0x3ffffff);
+  var p = (1 << 26) % num;
+
+  var acc = 0;
+  for (var i = this.length - 1; i >= 0; i--)
+    acc = (p * acc + this.words[i]) % num;
+
+  return acc;
+};
+
+// In-place division by number
+BN.prototype.idivn = function idivn(num) {
+  assert(num <= 0x3ffffff);
+
+  var carry = 0;
+  for (var i = this.length - 1; i >= 0; i--) {
+    var w = this.words[i] + carry * 0x4000000;
+    this.words[i] = (w / num) | 0;
+    carry = w % num;
+  }
+
+  return this.strip();
+};
+
+BN.prototype.divn = function divn(num) {
+  return this.clone().idivn(num);
+};
+
+BN.prototype.egcd = function egcd(p) {
+  assert(!p.sign);
+  assert(p.cmpn(0) !== 0);
+
+  var x = this;
+  var y = p.clone();
+
+  if (x.sign)
+    x = x.mod(p);
+  else
+    x = x.clone();
+
+  // A * x + B * y = x
+  var A = new BN(1);
+  var B = new BN(0);
+
+  // C * x + D * y = y
+  var C = new BN(0);
+  var D = new BN(1);
+
+  var g = 0;
+
+  while (x.isEven() && y.isEven()) {
+    x.ishrn(1);
+    y.ishrn(1);
+    ++g;
+  }
+
+  var yp = y.clone();
+  var xp = x.clone();
+
+  while (x.cmpn(0) !== 0) {
+    while (x.isEven()) {
+      x.ishrn(1);
+      if (A.isEven() && B.isEven()) {
+        A.ishrn(1);
+        B.ishrn(1);
+      } else {
+        A.iadd(yp).ishrn(1);
+        B.isub(xp).ishrn(1);
+      }
+    }
+
+    while (y.isEven()) {
+      y.ishrn(1);
+      if (C.isEven() && D.isEven()) {
+        C.ishrn(1);
+        D.ishrn(1);
+      } else {
+        C.iadd(yp).ishrn(1);
+        D.isub(xp).ishrn(1);
+      }
+    }
+
+    if (x.cmp(y) >= 0) {
+      x.isub(y);
+      A.isub(C);
+      B.isub(D);
+    } else {
+      y.isub(x);
+      C.isub(A);
+      D.isub(B);
+    }
+  }
+
+  return {
+    a: C,
+    b: D,
+    gcd: y.ishln(g)
+  };
+};
+
+// This is reduced incarnation of the binary EEA
+// above, designated to invert members of the
+// _prime_ fields F(p) at a maximal speed
+BN.prototype._invmp = function _invmp(p) {
+  assert(!p.sign);
+  assert(p.cmpn(0) !== 0);
+
+  var a = this;
+  var b = p.clone();
+
+  if (a.sign)
+    a = a.mod(p);
+  else
+    a = a.clone();
+
+  var x1 = new BN(1);
+  var x2 = new BN(0);
+
+  var delta = b.clone();
+
+  while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
+    while (a.isEven()) {
+      a.ishrn(1);
+      if (x1.isEven())
+        x1.ishrn(1);
+      else
+        x1.iadd(delta).ishrn(1);
+    }
+    while (b.isEven()) {
+      b.ishrn(1);
+      if (x2.isEven())
+        x2.ishrn(1);
+      else
+        x2.iadd(delta).ishrn(1);
+    }
+    if (a.cmp(b) >= 0) {
+      a.isub(b);
+      x1.isub(x2);
+    } else {
+      b.isub(a);
+      x2.isub(x1);
+    }
+  }
+  if (a.cmpn(1) === 0)
+    return x1;
+  else
+    return x2;
+};
+
+BN.prototype.gcd = function gcd(num) {
+  if (this.cmpn(0) === 0)
+    return num.clone();
+  if (num.cmpn(0) === 0)
+    return this.clone();
+
+  var a = this.clone();
+  var b = num.clone();
+  a.sign = false;
+  b.sign = false;
+
+  // Remove common factor of two
+  for (var shift = 0; a.isEven() && b.isEven(); shift++) {
+    a.ishrn(1);
+    b.ishrn(1);
+  }
+
+  do {
+    while (a.isEven())
+      a.ishrn(1);
+    while (b.isEven())
+      b.ishrn(1);
+
+    var r = a.cmp(b);
+    if (r < 0) {
+      // Swap `a` and `b` to make `a` always bigger than `b`
+      var t = a;
+      a = b;
+      b = t;
+    } else if (r === 0 || b.cmpn(1) === 0) {
+      break;
+    }
+
+    a.isub(b);
+  } while (true);
+
+  return b.ishln(shift);
+};
+
+// Invert number in the field F(num)
+BN.prototype.invm = function invm(num) {
+  return this.egcd(num).a.mod(num);
+};
+
+BN.prototype.isEven = function isEven() {
+  return (this.words[0] & 1) === 0;
+};
+
+BN.prototype.isOdd = function isOdd() {
+  return (this.words[0] & 1) === 1;
+};
+
+// And first word and num
+BN.prototype.andln = function andln(num) {
+  return this.words[0] & num;
+};
+
+// Increment at the bit position in-line
+BN.prototype.bincn = function bincn(bit) {
+  assert(typeof bit === 'number');
+  var r = bit % 26;
+  var s = (bit - r) / 26;
+  var q = 1 << r;
+
+  // Fast case: bit is much higher than all existing words
+  if (this.length <= s) {
+    for (var i = this.length; i < s + 1; i++)
+      this.words[i] = 0;
+    this.words[s] |= q;
+    this.length = s + 1;
+    return this;
+  }
+
+  // Add bit and propagate, if needed
+  var carry = q;
+  for (var i = s; carry !== 0 && i < this.length; i++) {
+    var w = this.words[i];
+    w += carry;
+    carry = w >>> 26;
+    w &= 0x3ffffff;
+    this.words[i] = w;
+  }
+  if (carry !== 0) {
+    this.words[i] = carry;
+    this.length++;
+  }
+  return this;
+};
+
+BN.prototype.cmpn = function cmpn(num) {
+  var sign = num < 0;
+  if (sign)
+    num = -num;
+
+  if (this.sign && !sign)
+    return -1;
+  else if (!this.sign && sign)
+    return 1;
+
+  num &= 0x3ffffff;
+  this.strip();
+
+  var res;
+  if (this.length > 1) {
+    res = 1;
+  } else {
+    var w = this.words[0];
+    res = w === num ? 0 : w < num ? -1 : 1;
+  }
+  if (this.sign)
+    res = -res;
+  return res;
+};
+
+// Compare two numbers and return:
+// 1 - if `this` > `num`
+// 0 - if `this` == `num`
+// -1 - if `this` < `num`
+BN.prototype.cmp = function cmp(num) {
+  if (this.sign && !num.sign)
+    return -1;
+  else if (!this.sign && num.sign)
+    return 1;
+
+  var res = this.ucmp(num);
+  if (this.sign)
+    return -res;
+  else
+    return res;
+};
+
+// Unsigned comparison
+BN.prototype.ucmp = function ucmp(num) {
+  // At this point both numbers have the same sign
+  if (this.length > num.length)
+    return 1;
+  else if (this.length < num.length)
+    return -1;
+
+  var res = 0;
+  for (var i = this.length - 1; i >= 0; i--) {
+    var a = this.words[i];
+    var b = num.words[i];
+
+    if (a === b)
+      continue;
+    if (a < b)
+      res = -1;
+    else if (a > b)
+      res = 1;
+    break;
+  }
+  return res;
+};
+
+//
+// A reduce context, could be using montgomery or something better, depending
+// on the `m` itself.
+//
+BN.red = function red(num) {
+  return new Red(num);
+};
+
+BN.prototype.toRed = function toRed(ctx) {
+  assert(!this.red, 'Already a number in reduction context');
+  assert(!this.sign, 'red works only with positives');
+  return ctx.convertTo(this)._forceRed(ctx);
+};
+
+BN.prototype.fromRed = function fromRed() {
+  assert(this.red, 'fromRed works only with numbers in reduction context');
+  return this.red.convertFrom(this);
+};
+
+BN.prototype._forceRed = function _forceRed(ctx) {
+  this.red = ctx;
+  return this;
+};
+
+BN.prototype.forceRed = function forceRed(ctx) {
+  assert(!this.red, 'Already a number in reduction context');
+  return this._forceRed(ctx);
+};
+
+BN.prototype.redAdd = function redAdd(num) {
+  assert(this.red, 'redAdd works only with red numbers');
+  return this.red.add(this, num);
+};
+
+BN.prototype.redIAdd = function redIAdd(num) {
+  assert(this.red, 'redIAdd works only with red numbers');
+  return this.red.iadd(this, num);
+};
+
+BN.prototype.redSub = function redSub(num) {
+  assert(this.red, 'redSub works only with red numbers');
+  return this.red.sub(this, num);
+};
+
+BN.prototype.redISub = function redISub(num) {
+  assert(this.red, 'redISub works only with red numbers');
+  return this.red.isub(this, num);
+};
+
+BN.prototype.redShl = function redShl(num) {
+  assert(this.red, 'redShl works only with red numbers');
+  return this.red.shl(this, num);
+};
+
+BN.prototype.redMul = function redMul(num) {
+  assert(this.red, 'redMul works only with red numbers');
+  this.red._verify2(this, num);
+  return this.red.mul(this, num);
+};
+
+BN.prototype.redIMul = function redIMul(num) {
+  assert(this.red, 'redMul works only with red numbers');
+  this.red._verify2(this, num);
+  return this.red.imul(this, num);
+};
+
+BN.prototype.redSqr = function redSqr() {
+  assert(this.red, 'redSqr works only with red numbers');
+  this.red._verify1(this);
+  return this.red.sqr(this);
+};
+
+BN.prototype.redISqr = function redISqr() {
+  assert(this.red, 'redISqr works only with red numbers');
+  this.red._verify1(this);
+  return this.red.isqr(this);
+};
+
+// Square root over p
+BN.prototype.redSqrt = function redSqrt() {
+  assert(this.red, 'redSqrt works only with red numbers');
+  this.red._verify1(this);
+  return this.red.sqrt(this);
+};
+
+BN.prototype.redInvm = function redInvm() {
+  assert(this.red, 'redInvm works only with red numbers');
+  this.red._verify1(this);
+  return this.red.invm(this);
+};
+
+// Return negative clone of `this` % `red modulo`
+BN.prototype.redNeg = function redNeg() {
+  assert(this.red, 'redNeg works only with red numbers');
+  this.red._verify1(this);
+  return this.red.neg(this);
+};
+
+BN.prototype.redPow = function redPow(num) {
+  assert(this.red && !num.red, 'redPow(normalNum)');
+  this.red._verify1(this);
+  return this.red.pow(this, num);
+};
+
+// Prime numbers with efficient reduction
+var primes = {
+  k256: null,
+  p224: null,
+  p192: null,
+  p25519: null
+};
+
+// Pseudo-Mersenne prime
+function MPrime(name, p) {
+  // P = 2 ^ N - K
+  this.name = name;
+  this.p = new BN(p, 16);
+  this.n = this.p.bitLength();
+  this.k = new BN(1).ishln(this.n).isub(this.p);
+
+  this.tmp = this._tmp();
+}
+
+MPrime.prototype._tmp = function _tmp() {
+  var tmp = new BN(null);
+  tmp.words = new Array(Math.ceil(this.n / 13));
+  return tmp;
+};
+
+MPrime.prototype.ireduce = function ireduce(num) {
+  // Assumes that `num` is less than `P^2`
+  // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
+  var r = num;
+  var rlen;
+
+  do {
+    this.split(r, this.tmp);
+    r = this.imulK(r);
+    r = r.iadd(this.tmp);
+    rlen = r.bitLength();
+  } while (rlen > this.n);
+
+  var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
+  if (cmp === 0) {
+    r.words[0] = 0;
+    r.length = 1;
+  } else if (cmp > 0) {
+    r.isub(this.p);
+  } else {
+    r.strip();
+  }
+
+  return r;
+};
+
+MPrime.prototype.split = function split(input, out) {
+  input.ishrn(this.n, 0, out);
+};
+
+MPrime.prototype.imulK = function imulK(num) {
+  return num.imul(this.k);
+};
+
+function K256() {
+  MPrime.call(
+    this,
+    'k256',
+    'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
+}
+inherits(K256, MPrime);
+
+K256.prototype.split = function split(input, output) {
+  // 256 = 9 * 26 + 22
+  var mask = 0x3fffff;
+
+  var outLen = Math.min(input.length, 9);
+  for (var i = 0; i < outLen; i++)
+    output.words[i] = input.words[i];
+  output.length = outLen;
+
+  if (input.length <= 9) {
+    input.words[0] = 0;
+    input.length = 1;
+    return;
+  }
+
+  // Shift by 9 limbs
+  var prev = input.words[9];
+  output.words[output.length++] = prev & mask;
+
+  for (var i = 10; i < input.length; i++) {
+    var next = input.words[i];
+    input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
+    prev = next;
+  }
+  input.words[i - 10] = prev >>> 22;
+  input.length -= 9;
+};
+
+K256.prototype.imulK = function imulK(num) {
+  // K = 0x1000003d1 = [ 0x40, 0x3d1 ]
+  num.words[num.length] = 0;
+  num.words[num.length + 1] = 0;
+  num.length += 2;
+
+  // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
+  var hi;
+  var lo = 0;
+  for (var i = 0; i < num.length; i++) {
+    var w = num.words[i];
+    hi = w * 0x40;
+    lo += w * 0x3d1;
+    hi += (lo / 0x4000000) | 0;
+    lo &= 0x3ffffff;
+
+    num.words[i] = lo;
+
+    lo = hi;
+  }
+
+  // Fast length reduction
+  if (num.words[num.length - 1] === 0) {
+    num.length--;
+    if (num.words[num.length - 1] === 0)
+      num.length--;
+  }
+  return num;
+};
+
+function P224() {
+  MPrime.call(
+    this,
+    'p224',
+    'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
+}
+inherits(P224, MPrime);
+
+function P192() {
+  MPrime.call(
+    this,
+    'p192',
+    'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
+}
+inherits(P192, MPrime);
+
+function P25519() {
+  // 2 ^ 255 - 19
+  MPrime.call(
+    this,
+    '25519',
+    '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
+}
+inherits(P25519, MPrime);
+
+P25519.prototype.imulK = function imulK(num) {
+  // K = 0x13
+  var carry = 0;
+  for (var i = 0; i < num.length; i++) {
+    var hi = num.words[i] * 0x13 + carry;
+    var lo = hi & 0x3ffffff;
+    hi >>>= 26;
+
+    num.words[i] = lo;
+    carry = hi;
+  }
+  if (carry !== 0)
+    num.words[num.length++] = carry;
+  return num;
+};
+
+// Exported mostly for testing purposes, use plain name instead
+BN._prime = function prime(name) {
+  // Cached version of prime
+  if (primes[name])
+    return primes[name];
+
+  var prime;
+  if (name === 'k256')
+    prime = new K256();
+  else if (name === 'p224')
+    prime = new P224();
+  else if (name === 'p192')
+    prime = new P192();
+  else if (name === 'p25519')
+    prime = new P25519();
+  else
+    throw new Error('Unknown prime ' + name);
+  primes[name] = prime;
+
+  return prime;
+};
+
+//
+// Base reduction engine
+//
+function Red(m) {
+  if (typeof m === 'string') {
+    var prime = BN._prime(m);
+    this.m = prime.p;
+    this.prime = prime;
+  } else {
+    this.m = m;
+    this.prime = null;
+  }
+}
+
+Red.prototype._verify1 = function _verify1(a) {
+  assert(!a.sign, 'red works only with positives');
+  assert(a.red, 'red works only with red numbers');
+};
+
+Red.prototype._verify2 = function _verify2(a, b) {
+  assert(!a.sign && !b.sign, 'red works only with positives');
+  assert(a.red && a.red === b.red,
+         'red works only with red numbers');
+};
+
+Red.prototype.imod = function imod(a) {
+  if (this.prime)
+    return this.prime.ireduce(a)._forceRed(this);
+  return a.mod(this.m)._forceRed(this);
+};
+
+Red.prototype.neg = function neg(a) {
+  var r = a.clone();
+  r.sign = !r.sign;
+  return r.iadd(this.m)._forceRed(this);
+};
+
+Red.prototype.add = function add(a, b) {
+  this._verify2(a, b);
+
+  var res = a.add(b);
+  if (res.cmp(this.m) >= 0)
+    res.isub(this.m);
+  return res._forceRed(this);
+};
+
+Red.prototype.iadd = function iadd(a, b) {
+  this._verify2(a, b);
+
+  var res = a.iadd(b);
+  if (res.cmp(this.m) >= 0)
+    res.isub(this.m);
+  return res;
+};
+
+Red.prototype.sub = function sub(a, b) {
+  this._verify2(a, b);
+
+  var res = a.sub(b);
+  if (res.cmpn(0) < 0)
+    res.iadd(this.m);
+  return res._forceRed(this);
+};
+
+Red.prototype.isub = function isub(a, b) {
+  this._verify2(a, b);
+
+  var res = a.isub(b);
+  if (res.cmpn(0) < 0)
+    res.iadd(this.m);
+  return res;
+};
+
+Red.prototype.shl = function shl(a, num) {
+  this._verify1(a);
+  return this.imod(a.shln(num));
+};
+
+Red.prototype.imul = function imul(a, b) {
+  this._verify2(a, b);
+  return this.imod(a.imul(b));
+};
+
+Red.prototype.mul = function mul(a, b) {
+  this._verify2(a, b);
+  return this.imod(a.mul(b));
+};
+
+Red.prototype.isqr = function isqr(a) {
+  return this.imul(a, a);
+};
+
+Red.prototype.sqr = function sqr(a) {
+  return this.mul(a, a);
+};
+
+Red.prototype.sqrt = function sqrt(a) {
+  if (a.cmpn(0) === 0)
+    return a.clone();
+
+  var mod3 = this.m.andln(3);
+  assert(mod3 % 2 === 1);
+
+  // Fast case
+  if (mod3 === 3) {
+    var pow = this.m.add(new BN(1)).ishrn(2);
+    var r = this.pow(a, pow);
+    return r;
+  }
+
+  // Tonelli-Shanks algorithm (Totally unoptimized and slow)
+  //
+  // Find Q and S, that Q * 2 ^ S = (P - 1)
+  var q = this.m.subn(1);
+  var s = 0;
+  while (q.cmpn(0) !== 0 && q.andln(1) === 0) {
+    s++;
+    q.ishrn(1);
+  }
+  assert(q.cmpn(0) !== 0);
+
+  var one = new BN(1).toRed(this);
+  var nOne = one.redNeg();
+
+  // Find quadratic non-residue
+  // NOTE: Max is such because of generalized Riemann hypothesis.
+  var lpow = this.m.subn(1).ishrn(1);
+  var z = this.m.bitLength();
+  z = new BN(2 * z * z).toRed(this);
+  while (this.pow(z, lpow).cmp(nOne) !== 0)
+    z.redIAdd(nOne);
+
+  var c = this.pow(z, q);
+  var r = this.pow(a, q.addn(1).ishrn(1));
+  var t = this.pow(a, q);
+  var m = s;
+  while (t.cmp(one) !== 0) {
+    var tmp = t;
+    for (var i = 0; tmp.cmp(one) !== 0; i++)
+      tmp = tmp.redSqr();
+    assert(i < m);
+    var b = this.pow(c, new BN(1).ishln(m - i - 1));
+
+    r = r.redMul(b);
+    c = b.redSqr();
+    t = t.redMul(c);
+    m = i;
+  }
+
+  return r;
+};
+
+Red.prototype.invm = function invm(a) {
+  var inv = a._invmp(this.m);
+  if (inv.sign) {
+    inv.sign = false;
+    return this.imod(inv).redNeg();
+  } else {
+    return this.imod(inv);
+  }
+};
+
+Red.prototype.pow = function pow(a, num) {
+  var w = [];
+  var q = num.clone();
+  while (q.cmpn(0) !== 0) {
+    w.push(q.andln(1));
+    q.ishrn(1);
+  }
+
+  // Skip leading zeroes
+  var res = a;
+  for (var i = 0; i < w.length; i++, res = this.sqr(res))
+    if (w[i] !== 0)
+      break;
+
+  if (++i < w.length) {
+    for (var q = this.sqr(res); i < w.length; i++, q = this.sqr(q)) {
+      if (w[i] === 0)
+        continue;
+      res = this.mul(res, q);
+    }
+  }
+
+  return res;
+};
+
+Red.prototype.convertTo = function convertTo(num) {
+  return num.clone();
+};
+
+Red.prototype.convertFrom = function convertFrom(num) {
+  var res = num.clone();
+  res.red = null;
+  return res;
+};
+
+//
+// Montgomery method engine
+//
+
+BN.mont = function mont(num) {
+  return new Mont(num);
+};
+
+function Mont(m) {
+  Red.call(this, m);
+
+  this.shift = this.m.bitLength();
+  if (this.shift % 26 !== 0)
+    this.shift += 26 - (this.shift % 26);
+  this.r = new BN(1).ishln(this.shift);
+  this.r2 = this.imod(this.r.sqr());
+  this.rinv = this.r._invmp(this.m);
+
+  this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
+  this.minv.sign = true;
+  this.minv = this.minv.mod(this.r);
+}
+inherits(Mont, Red);
+
+Mont.prototype.convertTo = function convertTo(num) {
+  return this.imod(num.shln(this.shift));
+};
+
+Mont.prototype.convertFrom = function convertFrom(num) {
+  var r = this.imod(num.mul(this.rinv));
+  r.red = null;
+  return r;
+};
+
+Mont.prototype.imul = function imul(a, b) {
+  if (a.cmpn(0) === 0 || b.cmpn(0) === 0) {
+    a.words[0] = 0;
+    a.length = 1;
+    return a;
+  }
+
+  var t = a.imul(b);
+  var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
+  var u = t.isub(c).ishrn(this.shift);
+  var res = u;
+  if (u.cmp(this.m) >= 0)
+    res = u.isub(this.m);
+  else if (u.cmpn(0) < 0)
+    res = u.iadd(this.m);
+
+  return res._forceRed(this);
+};
+
+Mont.prototype.mul = function mul(a, b) {
+  if (a.cmpn(0) === 0 || b.cmpn(0) === 0)
+    return new BN(0)._forceRed(this);
+
+  var t = a.mul(b);
+  var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
+  var u = t.isub(c).ishrn(this.shift);
+  var res = u;
+  if (u.cmp(this.m) >= 0)
+    res = u.isub(this.m);
+  else if (u.cmpn(0) < 0)
+    res = u.iadd(this.m);
+
+  return res._forceRed(this);
+};
+
+Mont.prototype.invm = function invm(a) {
+  // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
+  var res = this.imod(a._invmp(this.m).mul(this.r2));
+  return res._forceRed(this);
+};
+
+})(typeof module === 'undefined' || module, this);
diff --git a/node_modules/bn.js/package.json b/node_modules/bn.js/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..a71cfac069a28121d6696d27900b5f6ee63c838d
--- /dev/null
+++ b/node_modules/bn.js/package.json
@@ -0,0 +1,32 @@
+{
+  "name": "bn.js",
+  "version": "2.0.0",
+  "description": "Big number implementation in pure javascript",
+  "main": "lib/bn.js",
+  "scripts": {
+    "test": "jscs lib/*.js test/*.js && jshint lib/*.js && mocha --reporter=spec test/*-test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git@github.com:indutny/bn.js"
+  },
+  "keywords": [
+    "BN",
+    "BigNum",
+    "Big number",
+    "Modulo",
+    "Montgomery"
+  ],
+  "author": "Fedor Indutny <fedor@indutny.com>",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/indutny/bn.js/issues"
+  },
+  "homepage": "https://github.com/indutny/bn.js",
+  "devDependencies": {
+    "istanbul": "^0.3.5",
+    "jscs": "^1.11.1",
+    "jshint": "^2.6.0",
+    "mocha": "^2.1.0"
+  }
+}
diff --git a/node_modules/bn.js/test/arithmetic-test.js b/node_modules/bn.js/test/arithmetic-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad012301c9fbaa5c1af9cd1dbe8829a05ef1fd7d
--- /dev/null
+++ b/node_modules/bn.js/test/arithmetic-test.js
@@ -0,0 +1,386 @@
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Arithmetic', function() {
+  describe('.add()', function() {
+    it('should add numbers', function() {
+      assert.equal(new BN(14).add(new BN(26)).toString(16), '28');
+      var k = new BN(0x1234);
+      var r = k;
+      for (var i = 0; i < 257; i++)
+        r = r.add(k);
+      assert.equal(r.toString(16), '125868');
+    });
+
+    it('should handle carry properly (in-place)', function() {
+      var k = new BN('abcdefabcdefabcdef', 16);
+      var r = new BN('deadbeef', 16);
+      for (var i = 0; i < 257; i++)
+        r.iadd(k);
+      assert.equal(r.toString(16), 'ac79bd9b79be7a277bde');
+    });
+
+    it('should properly do positive + negative', function() {
+      var a = new BN('abcd', 16);
+      var b = new BN('-abce', 16);
+
+      assert.equal(a.iadd(b).toString(16), '-1');
+
+      var a = new BN('abcd', 16);
+      var b = new BN('-abce', 16);
+
+      assert.equal(a.add(b).toString(16), '-1');
+      assert.equal(b.add(a).toString(16), '-1');
+    });
+  });
+
+  describe('.iaddn()', function() {
+    it('should allow a sign change', function() {
+      var a = new BN(-100);
+      assert.equal(a.sign, true);
+
+      a.iaddn(200);
+
+      assert.equal(a.sign, false);
+      assert.equal(a.toString(), '100');
+    });
+
+    it('should add negative number', function() {
+      var a = new BN(-100);
+      assert.equal(a.sign, true);
+
+      a.iaddn(-200);
+
+      assert.equal(a.toString(), '-300');
+    });
+
+    it('should allow neg + pos with big number', function() {
+      var a = new BN('-1000000000', 10);
+      assert.equal(a.sign, true);
+
+      a.iaddn(200);
+
+      assert.equal(a.toString(), '-999999800');
+    });
+
+    it('should carry limb', function() {
+      var a = new BN('3ffffff', 16);
+
+      assert.equal(a.iaddn(1).toString(16), '4000000');
+    });
+  });
+
+  describe('.sub()', function() {
+    it('should subtract small numbers', function() {
+      assert.equal(new BN(26).sub(new BN(14)).toString(16), 'c');
+      assert.equal(new BN(14).sub(new BN(26)).toString(16), '-c');
+      assert.equal(new BN(26).sub(new BN(26)).toString(16), '0');
+      assert.equal(new BN(-26).sub(new BN(26)).toString(16), '-34');
+    });
+
+    var a = new BN(
+      '31ff3c61db2db84b9823d320907a573f6ad37c437abe458b1802cda041d6384' +
+          'a7d8daef41395491e2',
+      16);
+    var b = new BN(
+      '6f0e4d9f1d6071c183677f601af9305721c91d31b0bbbae8fb790000',
+      16);
+    var r = new BN(
+      '31ff3c61db2db84b9823d3208989726578fd75276287cd9516533a9acfb9a67' +
+          '76281f34583ddb91e2',
+      16);
+
+    it('should subtract big numbers', function() {
+      assert.equal(a.sub(b).cmp(r), 0);
+    });
+
+    it('should subtract numbers in place', function() {
+      assert.equal(b.clone().isub(a).neg().cmp(r), 0);
+    });
+
+    it('should subtract with carry', function() {
+      // Carry and copy
+      var a = new BN('12345', 16);
+      var b = new BN('1000000000000', 16);
+      assert.equal(a.isub(b).toString(16), '-fffffffedcbb');
+
+      var a = new BN('12345', 16);
+      var b = new BN('1000000000000', 16);
+      assert.equal(b.isub(a).toString(16), 'fffffffedcbb');
+    });
+  });
+
+  describe('.isubn()', function() {
+    it('should subtract negative number', function() {
+      var r = new BN(
+        '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b', 16);
+      assert.equal(r.isubn(-1).toString(16),
+        '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681c');
+    });
+
+    it('should work for positive numbers', function() {
+      var a = new BN(-100);
+      assert.equal(a.sign, true);
+
+      a.isubn(200);
+      assert.equal(a.sign, true);
+      assert.equal(a.toString(), '-300');
+    });
+
+    it('should not allow a sign change', function() {
+      var a = new BN(-100);
+      assert.equal(a.sign, true);
+
+      a.isubn(-200);
+      assert.equal(a.sign, false);
+      assert.equal(a.toString(), '100');
+    });
+  });
+
+  describe('.mul()', function() {
+    it('should multiply numbers of different signs', function() {
+      assert.equal(new BN(0x1001).mul(new BN(0x1234)).toString(16),
+                   '1235234');
+      assert.equal(new BN(-0x1001).mul(new BN(0x1234)).toString(16),
+                   '-1235234');
+      assert.equal(new BN(-0x1001).mul(new BN(-0x1234)).toString(16),
+                   '1235234');
+    });
+
+    it('should multiply with carry', function() {
+      var n = new BN(0x1001);
+      var r = n;
+      for (var i = 0; i < 4; i++)
+        r = r.mul(n);
+      assert.equal(r.toString(16),
+                   '100500a00a005001');
+    });
+
+    it('should correctly multiply big numbers', function() {
+      var n = new BN(
+        '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+        16
+      );
+      assert.equal(
+        n.mul(n).toString(16),
+        '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9' +
+            'b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9' +
+            '978a8bd8acaa40');
+      assert.equal(
+        n.mul(n).mul(n).toString(16),
+        '1b888e01a06e974017a28a5b4da436169761c9730b7aeedf75fc60f687b' +
+            '46e0cf2cb11667f795d5569482640fe5f628939467a01a612b02350' +
+            '0d0161e9730279a7561043af6197798e41b7432458463e64fa81158' +
+            '907322dc330562697d0d600');
+    });
+
+    it('should multiply neg number on 0', function() {
+      assert.equal(
+        new BN('-100000000000').mul(new BN('3').div(new BN('4'))).toString(16),
+        '0'
+      );
+    });
+
+    it('should regress mul big numbers', function() {
+      var q = fixtures.dhGroups.p17.q;
+      var qs = fixtures.dhGroups.p17.qs;
+
+      var q = new BN(q, 16);
+      assert.equal(q.sqr().toString(16), qs);
+      assert.equal(q.isqr().toString(16), qs);
+    });
+  });
+
+  describe('.imul()', function() {
+    it('should multiply numbers in-place', function() {
+      var a = new BN('abcdef01234567890abcd', 16);
+      var b = new BN('deadbeefa551edebabba8', 16);
+      var c = a.mul(b);
+
+      assert.equal(a.imul(b).toString(16), c.toString(16));
+
+      var a = new BN('abcdef01234567890abcd214a25123f512361e6d236', 16);
+      var b = new BN('deadbeefa551edebabba8121234fd21bac0341324dd', 16);
+      var c = a.mul(b);
+
+      assert.equal(a.imul(b).toString(16), c.toString(16));
+    });
+
+    it('should multiply by 0', function() {
+      var a = new BN('abcdef01234567890abcd', 16);
+      var b = new BN('0', 16);
+      var c = a.mul(b);
+
+      assert.equal(a.imul(b).toString(16), c.toString(16));
+    });
+  });
+
+  describe('.div()', function() {
+    it('should divide numbers', function() {
+      assert.equal(new BN('10').div(new BN(256)).toString(16),
+                   '0');
+      assert.equal(new BN('69527932928').div(new BN('16974594')).toString(16),
+                   'fff');
+      assert.equal(new BN('-69527932928').div(new BN('16974594')).toString(16),
+                   '-fff');
+
+      var b = new BN(
+        '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9' +
+            'b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9' +
+            '978a8bd8acaa40',
+        16);
+      var n = new BN(
+        '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+        16
+      );
+      assert.equal(b.div(n).toString(16), n.toString(16));
+
+      assert.equal(new BN('1').div(new BN('-5')).toString(10), '0');
+    });
+
+    it('should not fail on regression after moving to _wordDiv', function() {
+      // Regression after moving to word div
+      var p = new BN(
+        'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
+        16);
+      var a = new BN(
+        '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+        16);
+      var as = a.sqr();
+      assert.equal(
+          as.div(p).toString(16),
+          '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729e58090b9');
+
+      var p = new BN(
+        'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
+        16);
+      var a = new BN(
+        'fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffff' +
+        'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+        16);
+      assert.equal(
+        a.div(p).toString(16),
+        'ffffffff00000002000000000000000000000001000000000000000000000001');
+    });
+  });
+
+  describe('.idivn()', function() {
+    it('should divide numbers in-place', function() {
+      assert.equal(new BN('10', 16).idivn(3).toString(16), '5');
+      assert.equal(new BN('12', 16).idivn(3).toString(16), '6');
+      assert.equal(new BN('10000000000000000').idivn(3).toString(10),
+                   '3333333333333333');
+      assert.equal(
+          new BN('100000000000000000000000000000').idivn(3).toString(10),
+          '33333333333333333333333333333');
+
+      var t = new BN(3);
+      assert.equal(
+          new BN('12345678901234567890123456', 16).idivn(3).toString(16),
+          new BN('12345678901234567890123456', 16).div(t).toString(16));
+    });
+  });
+
+  describe('.divRound()', function() {
+    it('should divide numbers with rounding', function() {
+      assert.equal(new BN(9).divRound(new BN(20)).toString(10),
+                   '0');
+      assert.equal(new BN(10).divRound(new BN(20)).toString(10),
+                   '1');
+      assert.equal(new BN(150).divRound(new BN(20)).toString(10),
+                   '8');
+      assert.equal(new BN(149).divRound(new BN(20)).toString(10),
+                   '7');
+      assert.equal(new BN(149).divRound(new BN(17)).toString(10),
+                   '9');
+      assert.equal(new BN(144).divRound(new BN(17)).toString(10),
+                   '8');
+      assert.equal(new BN(-144).divRound(new BN(17)).toString(10),
+                   '-8');
+    });
+
+    it('should return 1 on exact division', function() {
+      assert.equal(new BN(144).divRound(new BN(144)).toString(10), '1');
+    });
+  });
+
+  describe('.mod()', function() {
+    it('should mod numbers', function() {
+      assert.equal(new BN('10').mod(new BN(256)).toString(16),
+                   'a');
+      assert.equal(new BN('69527932928').mod(new BN('16974594')).toString(16),
+                   '102f302');
+      assert.equal(new BN('-69527932928').mod(new BN('16974594')).toString(16),
+                   '1000');
+
+      var p = new BN(
+        'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
+        16);
+      var a = new BN(
+        'fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffff' +
+        'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+        16);
+      assert.equal(
+        a.mod(p).toString(16),
+        '0');
+    });
+  });
+
+  describe('.modn()', function() {
+    it('should act like .mod() on small numbers', function() {
+      assert.equal(new BN('10', 16).modn(256).toString(16), '10');
+      assert.equal(new BN('100', 16).modn(256).toString(16), '0');
+      assert.equal(new BN('1001', 16).modn(256).toString(16), '1');
+      assert.equal(new BN('100000000001', 16).modn(256).toString(16), '1');
+      assert.equal(new BN('100000000001', 16).modn(257).toString(16),
+                   new BN('100000000001', 16).mod(new BN(257)).toString(16));
+      assert.equal(new BN('123456789012', 16).modn(3).toString(16),
+                   new BN('123456789012', 16).mod(new BN(3)).toString(16));
+    });
+  });
+
+  describe('.abs()', function() {
+    it('should return absolute value', function() {
+      assert.equal(new BN(0x1001).abs().toString(), '4097');
+      assert.equal(new BN(-0x1001).abs().toString(), '4097');
+      assert.equal(new BN('ffffffff', 16).abs().toString(), '4294967295');
+    })
+  });
+
+  describe('.invm()', function() {
+    it('should invert relatively-prime numbers', function() {
+      var p = new BN(257);
+      var a = new BN(3);
+      var b = a.invm(p);
+      assert.equal(a.mul(b).mod(p).toString(16), '1');
+
+      var p192 = new BN(
+          'fffffffffffffffffffffffffffffffeffffffffffffffff',
+          16);
+      var a = new BN('deadbeef', 16);
+      var b = a.invm(p192);
+      assert.equal(a.mul(b).mod(p192).toString(16), '1');
+
+      // Even base
+      var phi = new BN('872d9b030ba368706b68932cf07a0e0c', 16);
+      var e = new BN(65537);
+      var d = e.invm(phi);
+      assert.equal(e.mul(d).mod(phi).toString(16), '1');
+
+      // Even base (take #2)
+      var a = new BN('5');
+      var b = new BN('6');
+      var r = a.invm(b);
+      assert.equal(r.mul(a).mod(b).toString(16), '1');
+    });
+  });
+
+  describe('.gcd()', function() {
+    it('should return GCD', function() {
+      assert.equal(new BN(3).gcd(new BN(2)).toString(16), '1');
+      assert.equal(new BN(18).gcd(new BN(12)).toString(16), '6');
+      assert.equal(new BN(-18).gcd(new BN(12)).toString(16), '6');
+    });
+  });
+});
diff --git a/node_modules/bn.js/test/binary-test.js b/node_modules/bn.js/test/binary-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..9a0673a293cf2b818637911ea2fdcb0e121fa694
--- /dev/null
+++ b/node_modules/bn.js/test/binary-test.js
@@ -0,0 +1,182 @@
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Binary', function() {
+  describe('.shl()', function() {
+    it('should shl numbers', function() {
+      assert.equal(new BN('69527932928').shln(13).toString(16),
+                   '2060602000000');
+      assert.equal(new BN('69527932928').shln(45).toString(16),
+                   '206060200000000000000');
+    });
+  });
+
+  describe('.shr()', function() {
+    it('should shr numbers', function() {
+      assert.equal(new BN('69527932928').shrn(13).toString(16),
+                   '818180');
+      assert.equal(new BN('69527932928').shrn(17).toString(16),
+                   '81818');
+      assert.equal(new BN('69527932928').shrn(256).toString(16),
+                   '0');
+    });
+  });
+
+  describe('.bincn()', function() {
+    it('should increment bit', function() {
+      assert.equal(new BN(0).bincn(1).toString(16), '2');
+      assert.equal(new BN(2).bincn(1).toString(16), '4');
+      assert.equal(new BN(2).bincn(1).bincn(1).toString(16),
+                   new BN(2).bincn(2).toString(16));
+      assert.equal(new BN(0xffffff).bincn(1).toString(16), '1000001');
+    });
+  });
+
+  describe('.imaskn()', function() {
+    it('should mask bits in-place', function() {
+      assert.equal(new BN(0).imaskn(1).toString(16), '0');
+      assert.equal(new BN(3).imaskn(1).toString(16), '1');
+      assert.equal(new BN('123456789', 16).imaskn(4).toString(16), '9');
+      assert.equal(new BN('123456789', 16).imaskn(16).toString(16), '6789');
+      assert.equal(new BN('123456789', 16).imaskn(28).toString(16), '3456789');
+    });
+  });
+
+  describe('.testn()', function() {
+    it('should support test specific bit', function() {
+      [
+        'ff',
+        'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+      ].forEach(function(hex) {
+        var bn = new BN(hex, 16)
+        var bl = bn.bitLength()
+
+        for (var i = 0; i < bl; ++i) {
+          assert.equal(bn.testn(i), true);
+        }
+
+        // test off the end
+        assert.equal(bn.testn(bl), false);
+      })
+
+      var xbits = '01111001010111001001000100011101' +
+                  '11010011101100011000111001011101' +
+                  '10010100111000000001011000111101' +
+                  '01011111001111100100011110000010' +
+                  '01011010100111010001010011000100' +
+                  '01101001011110100001001111100110' +
+                  '001110010111';
+
+      var x = new BN(
+        '23478905234580795234378912401239784125643978256123048348957342'
+      )
+      for (var i = 0; i < x.bitLength(); ++i) {
+        assert.equal(x.testn(i), (xbits.charAt(i) === '1'), 'Failed @ bit ' + i)
+      }
+    });
+
+    it('should have short-cuts', function() {
+      var x = new BN('abcd', 16);
+      assert(!x.testn(128));
+    });
+  });
+
+  describe('.and()', function() {
+    it('should and numbers', function() {
+      assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+                   .and(new BN('101010101010101010101010101010101010101', 2))
+                   .toString(2), '0');
+    });
+
+    it('should and numbers of different limb-length', function() {
+      assert.equal(
+          new BN('abcd0000ffff', 16)
+              .and(new BN('abcd', 16)).toString(16),
+          'abcd');
+    });
+  });
+
+  describe('.iand()', function() {
+    it('should iand numbers', function() {
+      assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+                   .iand(new BN('101010101010101010101010101010101010101', 2))
+                   .toString(2), '0');
+      assert.equal(new BN('1000000000000000000000000000000000000001', 2)
+                   .iand(new BN('1', 2))
+                   .toString(2), '1')
+      assert.equal(new BN('1', 2)
+                   .iand(new BN('1000000000000000000000000000000000000001', 2))
+                   .toString(2), '1')
+    });
+  });
+
+  describe('.or()', function() {
+    it('should or numbers', function () {
+      assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+                   .or(new BN('101010101010101010101010101010101010101', 2))
+                   .toString(2), '1111111111111111111111111111111111111111');
+    });
+
+    it('should or numbers of different limb-length', function() {
+      assert.equal(
+          new BN('abcd00000000', 16)
+              .or(new BN('abcd', 16)).toString(16),
+          'abcd0000abcd');
+    });
+  });
+
+  describe('.ior()', function() {
+    it('should ior numbers', function () {
+      assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+                   .ior(new BN('101010101010101010101010101010101010101', 2))
+                   .toString(2), '1111111111111111111111111111111111111111');
+      assert.equal(new BN('1000000000000000000000000000000000000000', 2)
+                   .ior(new BN('1', 2))
+                   .toString(2), '1000000000000000000000000000000000000001');
+      assert.equal(new BN('1', 2)
+                   .ior(new BN('1000000000000000000000000000000000000000', 2))
+                   .toString(2), '1000000000000000000000000000000000000001');
+    });
+  });
+
+  describe('.xor()', function() {
+    it('should xor numbers', function () {
+      assert.equal(new BN('11001100110011001100110011001100', 2)
+                   .xor(new BN('1100110011001100110011001100110', 2))
+                   .toString(2), '10101010101010101010101010101010');
+    });
+  });
+
+  describe('.ixor()', function() {
+    it('should ixor numbers', function () {
+      assert.equal(new BN('11001100110011001100110011001100', 2)
+                   .ixor(new BN('1100110011001100110011001100110', 2))
+                   .toString(2), '10101010101010101010101010101010');
+      assert.equal(new BN('11001100110011001100110011001100', 2)
+                   .ixor(new BN('1', 2))
+                   .toString(2), '11001100110011001100110011001101');
+      assert.equal(new BN('1', 2)
+                   .ixor(new BN('11001100110011001100110011001100', 2))
+                   .toString(2), '11001100110011001100110011001101');
+    });
+
+    it('should and numbers of different limb-length', function() {
+      assert.equal(
+          new BN('abcd0000ffff', 16)
+              .xor(new BN('abcd', 16)).toString(16),
+          'abcd00005432');
+    });
+  });
+
+  describe('.setn()', function() {
+    it('should allow single bits to be set', function () {
+      assert.equal(new BN(0).setn(2, true).toString(2), '100');
+      assert.equal(new BN(0).setn(27, true).toString(2),
+                   '1000000000000000000000000000');
+      assert.equal(new BN('1000000000000000000000000001', 2).setn(27, false)
+                   .toString(2), '1');
+      assert.equal(new BN('101', 2).setn(2, false).toString(2), '1');
+    });
+  });
+});
diff --git a/node_modules/bn.js/test/constructor-test.js b/node_modules/bn.js/test/constructor-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..3790c0d8f23d6860f12a8eab8d04bfb3c20bb495
--- /dev/null
+++ b/node_modules/bn.js/test/constructor-test.js
@@ -0,0 +1,99 @@
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Constructor', function() {
+  describe('with Smi input', function() {
+    it('should accept one limb number', function() {
+      assert.equal(new BN(12345).toString(16), '3039');
+    });
+
+    it('should accept two-limb number', function() {
+      assert.equal(new BN(0x4123456).toString(16), '4123456');
+    });
+  });
+
+  describe('with String input', function() {
+    it('should accept base-16', function() {
+      assert.equal(new BN('1A6B765D8CDF', 16).toString(16), '1a6b765d8cdf');
+      assert.equal(new BN('1A6B765D8CDF', 16).toString(), '29048849665247');
+    });
+
+    it('should accept base-hex', function() {
+      assert.equal(new BN('FF', 'hex').toString(), '255');
+    });
+
+    it('should accept base-16 with spaces', function() {
+      var num = 'a89c e5af8724 c0a23e0e 0ff77500';
+      assert.equal(new BN(num, 16).toString(16), num.replace(/ /g, ''));
+    });
+
+    it('should accept long base-16', function() {
+      var num = '123456789abcdef123456789abcdef123456789abcdef';
+      assert.equal(new BN(num, 16).toString(16), num);
+    });
+
+    it('should accept positive base-10', function() {
+      assert.equal(new BN('10654321').toString(), '10654321');
+      assert.equal(new BN('29048849665247').toString(16), '1a6b765d8cdf');
+    });
+
+    it('should accept negative base-10', function() {
+      assert.equal(new BN('-29048849665247').toString(16), '-1a6b765d8cdf');
+    });
+
+    it('should accept long base-10', function() {
+      var num = '10000000000000000';
+      assert.equal(new BN(num).toString(10), num);
+    });
+
+    it('should accept base-2', function() {
+      var base2 = '11111111111111111111111111111111111111111111111111111';
+      assert.equal(new BN(base2, 2).toString(2), base2);
+    });
+
+    it('should accept base-36', function() {
+      var base36 = 'zzZzzzZzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
+      assert.equal(new BN(base36, 36).toString(36), base36.toLowerCase());
+    });
+
+    it('should not overflow limbs during base-10', function() {
+      var num = '65820182292848241686198767302293' +
+                '20890292528855852623664389292032';
+      assert(new BN(num).words[0] < 0x4000000);
+    });
+  });
+
+  describe('with Array input', function() {
+    it('should import/export big endian', function() {
+      assert.equal(new BN([ 1, 2, 3 ]).toString(16), '10203');
+      assert.equal(new BN([ 1, 2, 3, 4 ]).toString(16), '1020304');
+      assert.equal(new BN([ 1, 2, 3, 4, 5 ]).toString(16), '102030405');
+      assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ]).toString(16),
+                   '102030405060708');
+      assert.equal(new BN([ 1, 2, 3, 4 ]).toArray().join(','), '1,2,3,4');
+      assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ]).toArray().join(','),
+                   '1,2,3,4,5,6,7,8');
+    });
+
+    it('should import little endian', function() {
+      assert.equal(new BN([ 1, 2, 3 ], 10, 'le').toString(16), '30201');
+      assert.equal(new BN([ 1, 2, 3, 4 ], 10, 'le').toString(16), '4030201');
+      assert.equal(new BN([ 1, 2, 3, 4, 5 ], 10, 'le').toString(16),
+                   '504030201');
+      assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ], 'le').toString(16),
+                   '807060504030201');
+    });
+
+    it('should import big endian with implicit base', function() {
+      assert.equal(new BN([ 1, 2, 3, 4, 5 ], 'le').toString(16), '504030201');
+    });
+  });
+
+  describe('with BN input', function() {
+    it('should clone BN', function() {
+      var num = new BN(12345);
+      assert.equal(new BN(num).toString(10), '12345');
+    });
+  });
+});
diff --git a/node_modules/bn.js/test/fixtures.js b/node_modules/bn.js/test/fixtures.js
new file mode 100644
index 0000000000000000000000000000000000000000..29442d929fe6be74dc2b2dbf5b3f5386ec6d4f32
--- /dev/null
+++ b/node_modules/bn.js/test/fixtures.js
@@ -0,0 +1,264 @@
+exports.dhGroups = {
+  p16: {
+    prime: 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' +
+      '29024e088a67cc74020bbea63b139b22514a08798e3404dd' +
+      'ef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245' +
+      'e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed' +
+      'ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3d' +
+      'c2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f' +
+      '83655d23dca3ad961c62f356208552bb9ed529077096966d' +
+      '670c354e4abc9804f1746c08ca18217c32905e462e36ce3b' +
+      'e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9' +
+      'de2bcbf6955817183995497cea956ae515d2261898fa0510' +
+      '15728e5a8aaac42dad33170d04507a33a85521abdf1cba64' +
+      'ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7' +
+      'abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6b' +
+      'f12ffa06d98a0864d87602733ec86a64521f2b18177b200c' +
+      'bbe117577a615d6c770988c0bad946e208e24fa074e5ab31' +
+      '43db5bfce0fd108e4b82d120a92108011a723c12a787e6d7' +
+      '88719a10bdba5b2699c327186af4e23c1a946834b6150bda' +
+      '2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6' +
+      '287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed' +
+      '1f612970cee2d7afb81bdd762170481cd0069127d5b05aa9' +
+      '93b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199' +
+      'ffffffffffffffff',
+    priv: '6d5923e6449122cbbcc1b96093e0b7e4fd3e469f58daddae' +
+      '53b49b20664f4132675df9ce98ae0cfdcac0f4181ccb643b' +
+      '625f98104dcf6f7d8e81961e2cab4b5014895260cb977c7d' +
+      '2f981f8532fb5da60b3676dfe57f293f05d525866053ac7e' +
+      '65abfd19241146e92e64f309a97ef3b529af4d6189fa416c' +
+      '9e1a816c3bdf88e5edf48fbd8233ef9038bb46faa95122c0' +
+      '5a426be72039639cd2d53d37254b3d258960dcb33c255ede' +
+      '20e9d7b4b123c8b4f4b986f53cdd510d042166f7dd7dca98' +
+      '7c39ab36381ba30a5fdd027eb6128d2ef8e5802a2194d422' +
+      'b05fe6e1cb4817789b923d8636c1ec4b7601c90da3ddc178' +
+      '52f59217ae070d87f2e75cbfb6ff92430ad26a71c8373452' +
+      'ae1cc5c93350e2d7b87e0acfeba401aaf518580937bf0b6c' +
+      '341f8c49165a47e49ce50853989d07171c00f43dcddddf72' +
+      '94fb9c3f4e1124e98ef656b797ef48974ddcd43a21fa06d0' +
+      '565ae8ce494747ce9e0ea0166e76eb45279e5c6471db7df8' +
+      'cc88764be29666de9c545e72da36da2f7a352fb17bdeb982' +
+      'a6dc0193ec4bf00b2e533efd6cd4d46e6fb237b775615576' +
+      'dd6c7c7bbc087a25e6909d1ebc6e5b38e5c8472c0fc429c6' +
+      'f17da1838cbcd9bbef57c5b5522fd6053e62ba21fe97c826' +
+      'd3889d0cc17e5fa00b54d8d9f0f46fb523698af965950f4b' +
+      '941369e180f0aece3870d9335f2301db251595d173902cad' +
+      '394eaa6ffef8be6c',
+    pub: 'd53703b7340bc89bfc47176d351e5cf86d5a18d9662eca3c' +
+      '9759c83b6ccda8859649a5866524d77f79e501db923416ca' +
+      '2636243836d3e6df752defc0fb19cc386e3ae48ad647753f' +
+      'bf415e2612f8a9fd01efe7aca249589590c7e6a0332630bb' +
+      '29c5b3501265d720213790556f0f1d114a9e2071be3620bd' +
+      '4ee1e8bb96689ac9e226f0a4203025f0267adc273a43582b' +
+      '00b70b490343529eaec4dcff140773cd6654658517f51193' +
+      '13f21f0a8e04fe7d7b21ffeca85ff8f87c42bb8d9cb13a72' +
+      'c00e9c6e9dfcedda0777af951cc8ccab90d35e915e707d8e' +
+      '4c2aca219547dd78e9a1a0730accdc9ad0b854e51edd1e91' +
+      '4756760bab156ca6e3cb9c625cf0870def34e9ac2e552800' +
+      'd6ce506d43dbbc75acfa0c8d8fb12daa3c783fb726f187d5' +
+      '58131779239c912d389d0511e0f3a81969d12aeee670e48f' +
+      'ba41f7ed9f10705543689c2506b976a8ffabed45e33795b0' +
+      '1df4f6b993a33d1deab1316a67419afa31fbb6fdd252ee8c' +
+      '7c7d1d016c44e3fcf6b41898d7f206aa33760b505e4eff2e' +
+      'c624bc7fe636b1d59e45d6f904fc391419f13d1f0cdb5b6c' +
+      '2378b09434159917dde709f8a6b5dc30994d056e3f964371' +
+      '11587ac7af0a442b8367a7bd940f752ddabf31cf01171e24' +
+      'd78df136e9681cd974ce4f858a5fb6efd3234a91857bb52d' +
+      '9e7b414a8bc66db4b5a73bbeccfb6eb764b4f0cbf0375136' +
+      'b024b04e698d54a5'
+  },
+  p17: {
+    prime: 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' +
+      '29024e088a67cc74020bbea63b139b22514a08798e3404dd' +
+      'ef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245' +
+      'e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed' +
+      'ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3d' +
+      'c2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f' +
+      '83655d23dca3ad961c62f356208552bb9ed529077096966d' +
+      '670c354e4abc9804f1746c08ca18217c32905e462e36ce3b' +
+      'e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9' +
+      'de2bcbf6955817183995497cea956ae515d2261898fa0510' +
+      '15728e5a8aaac42dad33170d04507a33a85521abdf1cba64' +
+      'ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7' +
+      'abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6b' +
+      'f12ffa06d98a0864d87602733ec86a64521f2b18177b200c' +
+      'bbe117577a615d6c770988c0bad946e208e24fa074e5ab31' +
+      '43db5bfce0fd108e4b82d120a92108011a723c12a787e6d7' +
+      '88719a10bdba5b2699c327186af4e23c1a946834b6150bda' +
+      '2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6' +
+      '287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed' +
+      '1f612970cee2d7afb81bdd762170481cd0069127d5b05aa9' +
+      '93b4ea988d8fddc186ffb7dc90a6c08f4df435c934028492' +
+      '36c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bd' +
+      'f8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831' +
+      '179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1b' +
+      'db7f1447e6cc254b332051512bd7af426fb8f401378cd2bf' +
+      '5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6' +
+      'd55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f3' +
+      '23a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aa' +
+      'cc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be328' +
+      '06a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55c' +
+      'da56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee' +
+      '12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff',
+    priv: '6017f2bc23e1caff5b0a8b4e1fc72422b5204415787801dc' +
+      '025762b8dbb98ab57603aaaa27c4e6bdf742b4a1726b9375' +
+      'a8ca3cf07771779589831d8bd18ddeb79c43e7e77d433950' +
+      'e652e49df35b11fa09644874d71d62fdaffb580816c2c88c' +
+      '2c4a2eefd4a660360316741b05a15a2e37f236692ad3c463' +
+      'fff559938fc6b77176e84e1bb47fb41af691c5eb7bb81bd8' +
+      'c918f52625a1128f754b08f5a1403b84667231c4dfe07ed4' +
+      '326234c113931ce606037e960f35a2dfdec38a5f057884d3' +
+      '0af8fab3be39c1eeb390205fd65982191fc21d5aa30ddf51' +
+      'a8e1c58c0c19fc4b4a7380ea9e836aaf671c90c29bc4bcc7' +
+      '813811aa436a7a9005de9b507957c56a9caa1351b6efc620' +
+      '7225a18f6e97f830fb6a8c4f03b82f4611e67ab9497b9271' +
+      'd6ac252793cc3e5538990dbd894d2dbc2d152801937d9f74' +
+      'da4b741b50b4d40e4c75e2ac163f7b397fd555648b249f97' +
+      'ffe58ffb6d096aa84534c4c5729cff137759bd34e80db4ab' +
+      '47e2b9c52064e7f0bf677f72ac9e5d0c6606943683f9d12f' +
+      '180cf065a5cb8ec3179a874f358847a907f8471d15f1e728' +
+      '7023249d6d13c82da52628654438f47b8b5cdf4761fbf6ad' +
+      '9219eceac657dbd06cf2ab776ad4c968f81c3d039367f0a4' +
+      'd77c7ec4435c27b6c147071665100063b5666e06eb2fb2cc' +
+      '3159ba34bc98ca346342195f6f1fb053ddc3bc1873564d40' +
+      '1c6738cdf764d6e1ff25ca5926f80102ea6593c17170966b' +
+      'b5d7352dd7fb821230237ea3ebed1f920feaadbd21be295a' +
+      '69f2083deae9c5cdf5f4830eb04b7c1f80cc61c17232d79f' +
+      '7ecc2cc462a7965f804001c89982734e5abba2d31df1b012' +
+      '152c6b226dff34510b54be8c2cd68d795def66c57a3abfb6' +
+      '896f1d139e633417f8c694764974d268f46ece3a8d6616ea' +
+      'a592144be48ee1e0a1595d3e5edfede5b27cec6c48ceb2ff' +
+      'b42cb44275851b0ebf87dfc9aa2d0cb0805e9454b051dfe8' +
+      'a29fadd82491a4b4c23f2d06ba45483ab59976da1433c9ce' +
+      '500164b957a04cf62dd67595319b512fc4b998424d1164dd' +
+      'bbe5d1a0f7257cbb04ec9b5ed92079a1502d98725023ecb2',
+    pub: '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +
+      '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +
+      'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +
+      'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +
+      'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +
+      'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +
+      'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +
+      '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +
+      'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +
+      '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +
+      '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +
+      '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +
+      'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +
+      '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +
+      'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +
+      '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +
+      '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +
+      'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +
+      'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +
+      '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +
+      'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +
+      '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +
+      'fbedccbc786951025597522eef283e3f56b44561a0765783' +
+      '420128638c257e54b972a76e4261892d81222b3e2039c61a' +
+      'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +
+      'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +
+      '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +
+      'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +
+      'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +
+      '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +
+      'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +
+      '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d',
+    q:  'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +
+      '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +
+      '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +
+      'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +
+      'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +
+      'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +
+      'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +
+      'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +
+      '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +
+      '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +
+      'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +
+      'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +
+      '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +
+      'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +
+      'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +
+      '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +
+      '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +
+      '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +
+      '100050a430b47bc592995606440272a4994677577a6aaa1b' +
+      'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +
+      'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +
+      '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +
+      'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +
+      '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +
+      '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +
+      '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +
+      '1c64145849b3da8c2d343410df892d958db232617f9896f1' +
+      'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +
+      'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +
+      'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +
+      'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +
+      '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0',
+    qs: '6f0a2fb763eaeb8eb324d564f03d4a55fdcd709e5f1b65e9' +
+      '5702b0141182f9f945d71bc3e64a7dfdae7482a7dd5a4e58' +
+      'bc38f78de2013f2c468a621f08536969d2c8d011bb3bc259' +
+      '2124692c91140a5472cad224acdacdeae5751dadfdf068b8' +
+      '77bfa7374694c6a7be159fc3d24ff9eeeecaf62580427ad8' +
+      '622d48c51a1c4b1701d768c79d8c819776e096d2694107a2' +
+      'f3ec0c32224795b59d32894834039dacb369280afb221bc0' +
+      '90570a93cf409889b818bb30cccee98b2aa26dbba0f28499' +
+      '08e1a3cd43fa1f1fb71049e5c77c3724d74dc351d9989057' +
+      '37bbda3805bd6b1293da8774410fb66e3194e18cdb304dd9' +
+      'a0b59b583dcbc9fc045ac9d56aea5cfc9f8a0b95da1e11b7' +
+      '574d1f976e45fe12294997fac66ca0b83fc056183549e850' +
+      'a11413cc4abbe39a211e8c8cbf82f2a23266b3c10ab9e286' +
+      '07a1b6088909cddff856e1eb6b2cde8bdac53fa939827736' +
+      'ca1b892f6c95899613442bd02dbdb747f02487718e2d3f22' +
+      'f73734d29767ed8d0e346d0c4098b6fdcb4df7d0c4d29603' +
+      '5bffe80d6c65ae0a1b814150d349096baaf950f2caf298d2' +
+      'b292a1d48cf82b10734fe8cedfa16914076dfe3e9b51337b' +
+      'ed28ea1e6824bb717b641ca0e526e175d3e5ed7892aebab0' +
+      'f207562cc938a821e2956107c09b6ce4049adddcd0b7505d' +
+      '49ae6c69a20122461102d465d93dc03db026be54c303613a' +
+      'b8e5ce3fd4f65d0b6162ff740a0bf5469ffd442d8c509cd2' +
+      '3b40dab90f6776ca17fc0678774bd6eee1fa85ababa52ec1' +
+      'a15031eb677c6c488661dddd8b83d6031fe294489ded5f08' +
+      '8ad1689a14baeae7e688afa3033899c81f58de39b392ca94' +
+      'af6f15a46f19fa95c06f9493c8b96a9be25e78b9ea35013b' +
+      'caa76de6303939299d07426a88a334278fc3d0d9fa71373e' +
+      'be51d3c1076ab93a11d3d0d703366ff8cde4c11261d488e5' +
+      '60a2bdf3bfe2476032294800d6a4a39d306e65c6d7d8d66e' +
+      '5ec63eee94531e83a9bddc458a2b508285c0ee10b7bd94da' +
+      '2815a0c5bd5b2e15cbe66355e42f5af8955cdfc0b3a4996d' +
+      '288db1f4b32b15643b18193e378cb7491f3c3951cdd044b1' +
+      'a519571bffac2da986f5f1d506c66530a55f70751e24fa8e' +
+      'd83ac2347f4069fb561a5565e78c6f0207da24e889a93a96' +
+      '65f717d9fe8a2938a09ab5f81be7ccecf466c0397fc15a57' +
+      '469939793f302739765773c256a3ca55d0548afd117a7cae' +
+      '98ca7e0d749a130c7b743d376848e255f8fdbe4cb4480b63' +
+      'cd2c015d1020cf095d175f3ca9dcdfbaf1b2a6e6468eee4c' +
+      'c750f2132a77f376bd9782b9d0ff4da98621b898e251a263' +
+      '4301ba2214a8c430b2f7a79dbbfd6d7ff6e9b0c137b025ff' +
+      '587c0bf912f0b19d4fff96b1ecd2ca990c89b386055c60f2' +
+      '3b94214bd55096f17a7b2c0fa12b333235101cd6f28a128c' +
+      '782e8a72671adadebbd073ded30bd7f09fb693565dcf0bf3' +
+      '090c21d13e5b0989dd8956f18f17f4f69449a13549c9d80a' +
+      '77e5e61b5aeeee9528634100e7bc390672f0ded1ca53555b' +
+      'abddbcf700b9da6192255bddf50a76b709fbed251dce4c7e' +
+      '1ca36b85d1e97c1bc9d38c887a5adf140f9eeef674c31422' +
+      'e65f63cae719f8c1324e42fa5fd8500899ef5aa3f9856aa7' +
+      'ce10c85600a040343204f36bfeab8cfa6e9deb8a2edd2a8e' +
+      '018d00c7c9fa3a251ad0f57183c37e6377797653f382ec7a' +
+      '2b0145e16d3c856bc3634b46d90d7198aff12aff88a30e34' +
+      'e2bfaf62705f3382576a9d3eeb0829fca2387b5b654af46e' +
+      '5cf6316fb57d59e5ea6c369061ac64d99671b0e516529dd5' +
+      'd9c48ea0503e55fee090d36c5ea8b5954f6fcc0060794e1c' +
+      'b7bc24aa1e5c0142fd4ce6e8fd5aa92a7bf84317ea9e1642' +
+      'b6995bac6705adf93cbce72433ed0871139970d640f67b78' +
+      'e63a7a6d849db2567df69ac7d79f8c62664ac221df228289' +
+      'd0a4f9ebd9acb4f87d49da64e51a619fd3f3baccbd9feb12' +
+      '5abe0cc2c8d17ed1d8546da2b6c641f4d3020a5f9b9f26ac' +
+      '16546c2d61385505612275ea344c2bbf1ce890023738f715' +
+      '5e9eba6a071678c8ebd009c328c3eb643679de86e69a9fa5' +
+      '67a9e146030ff03d546310a0a568c5ba0070e0da22f2cef8' +
+      '54714b04d399bbc8fd261f9e8efcd0e83bdbc3f5cfb2d024' +
+      '3e398478cc598e000124eb8858f9df8f52946c2a1ca5c400'
+  }
+};
diff --git a/node_modules/bn.js/test/pummel/dh-group-test.js b/node_modules/bn.js/test/pummel/dh-group-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..dd6481f02d05ff39c9cef1a7be4feefb1ed5fa67
--- /dev/null
+++ b/node_modules/bn.js/test/pummel/dh-group-test.js
@@ -0,0 +1,21 @@
+var assert = require('assert');
+var BN = require('../../').BN;
+var fixtures = require('../fixtures');
+
+describe('BN.js/Slow DH test', function() {
+  var groups = fixtures.dhGroups;
+  Object.keys(groups).forEach(function(name) {
+    it('should match public key for ' + name + ' group', function() {
+      var group = groups[name];
+
+      this.timeout(3600 * 1000);
+
+      var base = new BN(2);
+      var mont = BN.red(new BN(group.prime, 16));
+      var priv = new BN(group.priv, 16);
+      var multed = base.toRed(mont).redPow(priv).fromRed();
+      var actual = new Buffer(multed.toArray());
+      assert.equal(actual.toString('hex'), group.pub);
+    });
+  });
+});
diff --git a/node_modules/bn.js/test/red-test.js b/node_modules/bn.js/test/red-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..474679caa9da11283b0216664003aa50c3ef1a67
--- /dev/null
+++ b/node_modules/bn.js/test/red-test.js
@@ -0,0 +1,140 @@
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Reduction context', function() {
+  function testMethod(name, fn) {
+    describe(name + ' method', function() {
+      it('should support add, iadd, sub, isub operations', function() {
+        var p = new BN(257);
+        var m = fn(p);
+        var a = new BN(123).toRed(m);
+        var b = new BN(231).toRed(m);
+
+        assert.equal(a.redAdd(b).fromRed().toString(10), '97');
+        assert.equal(a.redSub(b).fromRed().toString(10), '149');
+        assert.equal(b.redSub(a).fromRed().toString(10), '108');
+
+        assert.equal(a.clone().redIAdd(b).fromRed().toString(10), '97');
+        assert.equal(a.clone().redISub(b).fromRed().toString(10), '149');
+        assert.equal(b.clone().redISub(a).fromRed().toString(10), '108');
+      });
+
+      it('should support pow and mul operations', function() {
+        var p192 = new BN(
+            'fffffffffffffffffffffffffffffffeffffffffffffffff',
+            16);
+        var m = fn(p192);
+        var a = new BN(123);
+        var b = new BN(231);
+        var c = a.toRed(m).redMul(b.toRed(m)).fromRed();
+        assert(c.cmp(a.mul(b).mod(p192)) === 0);
+
+        assert.equal(a.toRed(m).redPow(new BN(3)).fromRed()
+                                .cmp(a.sqr().mul(a)), 0);
+        assert.equal(a.toRed(m).redPow(new BN(4)).fromRed()
+                                .cmp(a.sqr().sqr()), 0);
+        assert.equal(a.toRed(m).redPow(new BN(8)).fromRed()
+                                .cmp(a.sqr().sqr().sqr()), 0);
+        assert.equal(a.toRed(m).redPow(new BN(9)).fromRed()
+                                .cmp(a.sqr().sqr().sqr().mul(a)), 0);
+        assert.equal(a.toRed(m).redPow(new BN(17)).fromRed()
+                                .cmp(a.sqr().sqr().sqr().sqr().mul(a)), 0);
+      });
+
+      it('should sqrtm numbers', function() {
+        var p = new BN(263);
+        var m = fn(p);
+        var q = new BN(11).toRed(m);
+        var qr = q.redSqrt(true, p);
+        assert.equal(qr.redSqr().cmp(q), 0);
+        var qr = q.redSqrt(false, p);
+        assert.equal(qr.redSqr().cmp(q), 0);
+
+        var p = new BN(
+            'fffffffffffffffffffffffffffffffeffffffffffffffff',
+            16);
+        var m = fn(p);
+        var q = new BN(13).toRed(m);
+        var qr = q.redSqrt(true, p);
+        assert.equal(qr.redSqr().cmp(q), 0);
+        var qr = q.redSqrt(false, p);
+        assert.equal(qr.redSqr().cmp(q), 0);
+
+        // Tonelli-shanks
+        var p = new BN(13);
+        var m = fn(p);
+        var q = new BN(10).toRed(m);
+        assert.equal(q.redSqrt().fromRed().toString(10), '7');
+      });
+
+      it('should invm numbers', function() {
+        var p = new BN(257);
+        var m = fn(p);
+        var a = new BN(3).toRed(m);
+        var b = a.redInvm(p);
+        assert.equal(a.redMul(b).fromRed().toString(16), '1');
+      });
+
+      it('should imul numbers', function() {
+        var p = new BN(
+            'fffffffffffffffffffffffffffffffeffffffffffffffff',
+            16);
+        var m = fn(p);
+
+        var a = new BN('deadbeefabbadead', 16);
+        var b = new BN('abbadeadbeefdead', 16);
+        var c = a.mul(b).mod(p);
+
+        assert.equal(a.toRed(m).redIMul(b.toRed(m)).fromRed().toString(16),
+                     c.toString(16));
+      });
+    });
+  }
+
+  testMethod('Plain', BN.red);
+  testMethod('Montgomery', BN.mont);
+
+  describe('Pseudo-Mersenne Primes', function() {
+    it('should reduce numbers mod k256', function() {
+      var p = BN._prime('k256');
+
+      assert.equal(p.ireduce(new BN(0xdead)).toString(16), 'dead');
+      assert.equal(p.ireduce(new BN('deadbeef', 16)).toString(16), 'deadbeef');
+
+      var num = new BN('fedcba9876543210fedcba9876543210dead' +
+                           'fedcba9876543210fedcba9876543210dead',
+                       16);
+      var exp = num.mod(p.p).toString(16);
+      assert.equal(p.ireduce(num).toString(16), exp);
+
+      var regr = new BN('f7e46df64c1815962bf7bc9c56128798' +
+                            '3f4fcef9cb1979573163b477eab93959' +
+                            '335dfb29ef07a4d835d22aa3b6797760' +
+                            '70a8b8f59ba73d56d01a79af9',
+                        16);
+      var exp = regr.mod(p.p).toString(16);
+      assert.equal(p.ireduce(regr).toString(16), exp);
+    });
+
+    it('should not fail to invm number mod k256', function() {
+      var regr2 = new BN(
+        '6c150c4aa9a8cf1934485d40674d4a7cd494675537bda36d49405c5d2c6f496f', 16);
+      regr2 = regr2.toRed(BN.red('k256'));
+      assert.equal(regr2.redInvm().redMul(regr2).fromRed().cmpn(1), 0);
+    });
+
+    it('should correctly square the number', function() {
+      var p = BN._prime('k256').p;
+      var red = BN.red('k256');
+
+      var n = new BN('9cd8cb48c3281596139f147c1364a3ed' +
+                         'e88d3f310fdb0eb98c924e599ca1b3c9',
+                     16);
+      var expected = n.sqr().mod(p);
+      var actual = n.toRed(red).redSqr().fromRed();
+
+      assert.equal(actual.toString(16), expected.toString(16));
+    });
+  });
+});
diff --git a/node_modules/bn.js/test/utils-test.js b/node_modules/bn.js/test/utils-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..c033aa7cd29e00f569e512728ed2e23e5775657c
--- /dev/null
+++ b/node_modules/bn.js/test/utils-test.js
@@ -0,0 +1,80 @@
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Utils', function() {
+  describe('.toString()', function() {
+    describe('hex padding', function() {
+      it('should have length of 8 from leading 15', function() {
+        var a = new BN('ffb9602', 16);
+        var b = new Buffer(a.toString('hex', 2), 'hex');
+        assert.equal(a.toString('hex', 2).length, 8);
+      });
+
+      it('should have length of 8 from leading zero', function() {
+        var a = new BN('fb9604', 16);
+        var b = new Buffer(a.toString('hex', 8), 'hex');
+        assert.equal(a.toString('hex', 8).length, 8);
+      });
+
+      it('should have length of 8 from leading zeros', function() {
+        var a = new BN(0);
+        var b = new Buffer(a.toString('hex', 8), 'hex');
+        assert.equal(a.toString('hex', 8).length, 8);
+      });
+
+      it('should have length of 64 from leading 15', function() {
+        var a = new BN(
+            'ffb96ff654e61130ba8422f0debca77a0ea74ae5ea8bca9b54ab64aabf01003',
+            16);
+        var b = new Buffer(a.toString('hex', 2), 'hex');
+        assert.equal(a.toString('hex', 2).length, 64);
+      });
+
+      it('should have length of 64 from leading zero', function() {
+        var a = new BN(
+            'fb96ff654e61130ba8422f0debca77a0ea74ae5ea8bca9b54ab64aabf01003',
+            16);
+        var b = new Buffer(a.toString('hex', 64), 'hex');
+        assert.equal(a.toString('hex', 64).length, 64);
+      });
+    });
+  });
+
+  describe('.bitLength()', function() {
+    it('should return proper bitLength', function() {
+      assert.equal(new BN(0).bitLength(), 0);
+      assert.equal(new BN(0x1).bitLength(), 1);
+      assert.equal(new BN(0x2).bitLength(), 2);
+      assert.equal(new BN(0x3).bitLength(), 2);
+      assert.equal(new BN(0x4).bitLength(), 3);
+      assert.equal(new BN(0x8).bitLength(), 4);
+      assert.equal(new BN(0x10).bitLength(), 5);
+      assert.equal(new BN(0x100).bitLength(), 9);
+      assert.equal(new BN(0x123456).bitLength(), 21);
+      assert.equal(new BN('123456789', 16).bitLength(), 33);
+      assert.equal(new BN('8023456789', 16).bitLength(), 40);
+    });
+  });
+
+  describe('.zeroBits()', function() {
+    it('should return proper zeroBits', function() {
+      assert.equal(new BN(0).zeroBits(), 0);
+      assert.equal(new BN(0x1).zeroBits(), 0);
+      assert.equal(new BN(0x2).zeroBits(), 1);
+      assert.equal(new BN(0x3).zeroBits(), 0);
+      assert.equal(new BN(0x4).zeroBits(), 2);
+      assert.equal(new BN(0x8).zeroBits(), 3);
+      assert.equal(new BN(0x10).zeroBits(), 4);
+      assert.equal(new BN(0x100).zeroBits(), 8);
+      assert.equal(new BN(0x1000000).zeroBits(), 24);
+      assert.equal(new BN(0x123456).zeroBits(), 1);
+    });
+  });
+
+  describe('.toJSON', function() {
+    it('should return hex string', function() {
+      assert.equal(new BN(0x123).toJSON(), '123');
+    });
+  });
+});
diff --git a/node_modules/cardinal/.npmignore b/node_modules/cardinal/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..7e2f179b52bfdb0e9106bcb5b92a123b3a347bd7
--- /dev/null
+++ b/node_modules/cardinal/.npmignore
@@ -0,0 +1 @@
+assets
diff --git a/node_modules/cardinal/.travis.yml b/node_modules/cardinal/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..65488b07a9d244f95aeef1200d48bd9ea917e85d
--- /dev/null
+++ b/node_modules/cardinal/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.8
+  - 0.10 
diff --git a/node_modules/cardinal/LICENSE b/node_modules/cardinal/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..19c037f3b9ccd64a734039fb973be4b72b944a55
--- /dev/null
+++ b/node_modules/cardinal/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2012 Thorsten Lorenz. 
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/cardinal/README.md b/node_modules/cardinal/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5c3d5ad9d86837e7bd5551a5040fb1b5c6df3340
--- /dev/null
+++ b/node_modules/cardinal/README.md
@@ -0,0 +1,132 @@
+# cardinal [![Build Status](https://secure.travis-ci.org/thlorenz/cardinal.png)](http://travis-ci.org/thlorenz/cardinal)
+
+[![NPM](https://nodei.co/npm/cardinal.png?downloads=true&stars=true)](https://nodei.co/npm/cardinal/)
+
+**car·di·nal** *(kärdn-l, kärdnl)* - crested thick-billed North American finch having bright red plumage in the male.
+
+![screenshot](https://github.com/thlorenz/cardinal/raw/master/assets/screen-shot.png)
+
+## Features
+
+- highlights JavaScript code with ANSI colors to improve terminal output
+- theming support, see [custom color themes](https://github.com/thlorenz/cardinal/tree/master/themes)
+- optionally print line numbers
+- API and command line interface (`cdl`)
+- `.cardinalrc` config to customize settings
+- supports UNIX pipes
+
+***
+
+**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*
+
+- [Installation](#installation)
+  - [As library](#as-library)
+  - [As Commandline Tool](#as-commandline-tool)
+- [Commandline](#commandline)
+  - [Highlight a file](#highlight-a-file)
+  - [As part of a UNIX pipe](#as-part-of-a-unix-pipe)
+  - [Theme](#theme)
+- [API](#api)
+  - [*highlight(code[, opts])*](#highlightcode-opts)
+  - [*highlightFileSync(fullPath[, opts])*](#highlightfilesyncfullpath-opts)
+  - [*highlightFile(fullPath[, opts], callback)*](#highlightfilefullpath-opts-callback)
+  - [opts](#opts)
+- [Examples ([*browse*](https://github.com/thlorenz/cardinal/tree/master/examples))](#examples-[browse]https://githubcom/thlorenz/cardinal/tree/master/examples)
+
+
+## Installation
+
+### As library
+
+    npm install cardinal
+
+### As Commandline Tool
+
+    [sudo] npm install -g cardinal
+
+**Note:** 
+
+When installed globally, cardinal exposes itself as the `cdl` command.
+
+## Commandline
+
+### Highlight a file
+
+    cdl <file.js> [options]
+
+**options**:
+  - `--nonum`: turns off line number printing (relevant if it is turned on inside `~/.cardinalrc`
+
+### As part of a UNIX pipe
+
+    cat file.js | grep console | cdl
+
+**Note:**
+
+Not all code lines may be parsable JavaScript. In these cases the line is printed to the terminal without
+highlighting it.
+
+### Theme
+
+The default theme will be used for highlighting.
+
+To use a different theme, include a `.cardinalrc` file in your `HOME` directory.
+
+This is a JSON file of the following form:
+
+```json
+{
+  "theme": "hide-semicolons",
+  "linenos": true|false
+}
+```
+
+- `theme` can be the name of any of the [built-in themes](https://github.com/thlorenz/cardinal/tree/master/themes) or the
+full path to a custom theme anywhere on your computer.
+- linenos toggles line number printing
+
+## API
+
+### *highlight(code[, opts])*
+
+- returns the highlighted version of the passed code ({String}) or throws an error if it was not able to parse it
+- opts (see below)
+
+### *highlightFileSync(fullPath[, opts])*
+
+- returns the highlighted version of the file whose fullPath ({String}) was passed or throws an error if it was not able
+  to parse it
+- opts (see below)
+
+### *highlightFile(fullPath[, opts], callback)*
+
+- calls back with the highlighted version of the file whose fullPath ({String}) was passed or with an error if it was not able
+  to parse it
+- opts (see below)
+- `callback` ({Function}) has the following signature: `function (err, highlighted) { .. }`
+
+### opts
+
+opts is an {Object} with the following properties:
+
+- `theme` {Object} is used to optionally override the theme used to highlight
+- `linenos` {Boolean} if `true` line numbers are included in the highlighted code
+- `firstline` {Integer} sets line number of the first line when line numbers are printed
+- `json` {Boolean} if `true` highlights JSON in addition to JavaScript (`true` by default if file extension is `.json`)
+
+## Examples ([*browse*](https://github.com/thlorenz/cardinal/tree/master/examples))
+
+- [sample .cardinalrc](https://github.com/thlorenz/cardinal/blob/master/examples/.cardinalrc)
+- [highlighting a code snippet](https://github.com/thlorenz/cardinal/blob/master/examples/highlight-string.js) via
+  ***highlight()***
+- [file that highlights itself](https://github.com/thlorenz/cardinal/blob/master/examples/highlight-self.js) via
+  ***highlightFile()*** including line numbers
+- [file that highlights itself hiding all
+  semicolons](https://github.com/thlorenz/cardinal/blob/master/examples/highlight-self-hide-semicolons.js) via
+  ***highlightFileSync()***
+
+
+
+
+[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/thlorenz/cardinal/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
+
diff --git a/node_modules/cardinal/bin/cdl.js b/node_modules/cardinal/bin/cdl.js
new file mode 100644
index 0000000000000000000000000000000000000000..c58eb08a6421881cc2f7f69ec8dcbd50ab418324
--- /dev/null
+++ b/node_modules/cardinal/bin/cdl.js
@@ -0,0 +1,74 @@
+#!/usr/bin/env node
+var cardinal = require('..')
+  , utl = require('../utl')
+  , settings = require('../settings')
+  , args = process.argv
+  , theme = settings.resolveTheme()
+  , opts = settings.getSettings()
+  , highlighted
+  ;
+
+opts = opts || {};
+opts.theme = theme;
+
+function usage() {
+  var msg = [ 
+      'Usage: cdl <filename.js> [options]'
+    , ''
+    , 'Options (~/.cardinalrc overrides):'
+    , '  --nonum: turn off line printing'
+    , ''
+    , 'Unix Pipe Example: cat filename.js | grep console | cdl'
+    , ''
+  ].join('\n');
+  console.log(msg);
+}
+
+function highlightFile () {
+  try {
+    highlighted = cardinal.highlightFileSync(args[2], opts);
+    console.log(highlighted);
+  } catch (e) {
+    console.trace();
+    console.error(e);
+  }
+}
+
+// E.g., "cardinal myfile.js"
+if (args.length === 3) return highlightFile();
+
+var opt = args[3];
+
+// E.g., "cardinal myfile.js --nonum"
+if (opt && opt.indexOf('--') === 0 ) {
+  if ((/^--(nonum|noline)/i).test(opt)) opts.linenos = false;
+  else { 
+    usage();
+    return console.error('Unknown option: ', opt);
+  }
+ 
+  return highlightFile();
+}
+
+
+// UNIX pipes e.g., "cat myfile.js | grep console | cardinal
+var stdin = process.stdin
+  , stdout = process.stdout;
+
+// line numbers don't make sense when we are printing line by line
+opts.linenos = false;
+
+stdin.setEncoding('utf-8');
+stdin.resume();
+stdin
+  .on('data', function (chunk) {
+    chunk.split('\n').forEach(function (line) {
+      try {
+        stdout.write(cardinal.highlight(line, opts) + '\n');
+      } catch (e) {
+        // line doesn't represent a valid js snippet and therefore cannot be parsed -> just print as is
+        stdout.write(line + '\n');
+      }
+    });
+  });
+
diff --git a/node_modules/cardinal/cardinal.js b/node_modules/cardinal/cardinal.js
new file mode 100644
index 0000000000000000000000000000000000000000..4df4bb4a1984d9de26655c0bd2c69f993368c901
--- /dev/null
+++ b/node_modules/cardinal/cardinal.js
@@ -0,0 +1,5 @@
+module.exports = {
+    highlight: require('./lib/highlight')
+  , highlightFile: require('./lib/highlightFile')
+  , highlightFileSync: require('./lib/highlightFileSync')
+};
diff --git a/node_modules/cardinal/examples/.cardinalrc b/node_modules/cardinal/examples/.cardinalrc
new file mode 100644
index 0000000000000000000000000000000000000000..34be5cc31ab01dff95ad068b800827361d40ea2c
--- /dev/null
+++ b/node_modules/cardinal/examples/.cardinalrc
@@ -0,0 +1,3 @@
+{
+  "theme": "hide-semicolons"
+}
diff --git a/node_modules/cardinal/examples/README.md b/node_modules/cardinal/examples/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a6c2cd98a5f2353bff2db1a697f14b8b7e81dfa3
--- /dev/null
+++ b/node_modules/cardinal/examples/README.md
@@ -0,0 +1,7 @@
+# Cardinal Examples
+
+You can run the examples individually or as a demo:
+
+- install cardinal: `npm install cardinal`
+- explore cardinal: `npm explore cardinal`
+- run the demo: `npm run demo`
diff --git a/node_modules/cardinal/examples/highlight-json.js b/node_modules/cardinal/examples/highlight-json.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c06e5d442128709ad229a837fec8bf8233b913a
--- /dev/null
+++ b/node_modules/cardinal/examples/highlight-json.js
@@ -0,0 +1,10 @@
+// This file will highlight the passed code using the custom theme when run via: "node highlight-json"
+
+var cardinal = require('..');
+
+var json = JSON.stringify({
+  foo: 'bar',
+  baz: 'quux'
+});
+
+console.log(cardinal.highlight(json, {json: true}));
diff --git a/node_modules/cardinal/examples/highlight-self-hide-semicolons.js b/node_modules/cardinal/examples/highlight-self-hide-semicolons.js
new file mode 100644
index 0000000000000000000000000000000000000000..bf2c7d6e6b6d896bdb82525874258bf2d7608215
--- /dev/null
+++ b/node_modules/cardinal/examples/highlight-self-hide-semicolons.js
@@ -0,0 +1,22 @@
+ /*
+  * This file will highlight itself using a custom theme when run via: "node highlight-self-hide-semicolons"
+  * The custom theme highlights semicolons as 'black', thus hiding them.
+  */
+
+var cardinal = require('..')
+  , hideSemicolonsTheme = require('../themes/hide-semicolons');
+
+function highlight () {
+  
+  // Using the synchronous highlightFileSync()
+  // For asynchronous highlighting use: highlightFile() - see highlight-self.js
+  
+  try {
+    var highlighted = cardinal.highlightFileSync(__filename, hideSemicolonsTheme);
+    console.log(highlighted);
+  } catch (err) {
+    console.error(err);
+  }
+}
+
+highlight();
diff --git a/node_modules/cardinal/examples/highlight-self.js b/node_modules/cardinal/examples/highlight-self.js
new file mode 100644
index 0000000000000000000000000000000000000000..ceeb599eba02473f00b14a9eeb82492a68d3a9e4
--- /dev/null
+++ b/node_modules/cardinal/examples/highlight-self.js
@@ -0,0 +1,16 @@
+// This file will highlight itself using the default theme when run via: "node highlight-self"
+
+var cardinal = require('..');
+
+function highlight () {
+  
+  // Using the asynchronous highlightFile()
+  // For synchronous highlighting use: highlightFileSync() - see highlight-self-hide-semicolons.js
+  
+  cardinal.highlightFile(__filename, { linenos: true }, function (err, res) {
+    if (err) return console.error(err);
+    console.log(res);
+  });
+}
+
+highlight();
diff --git a/node_modules/cardinal/examples/highlight-string.js b/node_modules/cardinal/examples/highlight-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..dcc7b4ea613ffdfc0292f77d716869e9da808e7f
--- /dev/null
+++ b/node_modules/cardinal/examples/highlight-string.js
@@ -0,0 +1,14 @@
+// This file will highlight the passed code using the custom theme when run via: "node highlight-string"
+
+var cardinal = require('..');
+
+var code = '' + 
+
+function add (a, b) {
+  var sum = a + b;
+  return sum;
+} + 
+  
+'';
+
+console.log(cardinal.highlight(code));
diff --git a/node_modules/cardinal/lib/highlight.js b/node_modules/cardinal/lib/highlight.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c55e2c275e852dd015007f0f45f502382059fb7
--- /dev/null
+++ b/node_modules/cardinal/lib/highlight.js
@@ -0,0 +1,83 @@
+var redeyed =  require('redeyed')
+  , theme   =  require('../themes/default')
+  , colors  =  require('ansicolors')
+
+  , colorSurround =  colors.brightBlack
+  , surroundClose =  '\u001b[39m'
+  ;
+
+function trimEmptyLines(lines) {
+
+  // remove lines from the end until we find a non-empy one
+  var line = lines.pop();
+  while(!line || !line.length)
+    line = lines.pop();
+
+  // put the non-empty line back
+  if (line) lines.push(line);
+}
+
+function addLinenos (highlightedCode, firstline) {
+  var highlightedLines = highlightedCode.split('\n');
+
+  trimEmptyLines(highlightedLines);
+
+  var linesLen = highlightedLines.length
+    , lines = []
+    , totalDigits
+    , lineno
+    ;
+
+  function getDigits (n) {
+    if (n < 10) return 1;
+    if (n < 100) return 2;
+    if (n < 1000) return 3;
+    if (n < 10000) return 4;
+    // this works for up to 99,999 lines - any questions?
+    return 5;
+  }
+
+  function pad (n, totalDigits) {
+    // not pretty, but simple and should perform quite well
+    var padDigits= totalDigits - getDigits(n);
+    switch(padDigits) {
+      case 0: return '' + n;
+      case 1: return ' ' + n;
+      case 2: return '  ' + n;
+      case 3: return '   ' + n;
+      case 4: return '    ' + n;
+      case 5: return '     ' + n;
+    }
+  }
+
+  totalDigits = getDigits(linesLen + firstline - 1);
+
+  for (var i = 0; i < linesLen; i++) {
+    // Don't close the escape sequence here in order to not break multi line code highlights like block comments
+    lineno = colorSurround(pad(i + firstline, totalDigits) + ': ').replace(surroundClose, '');
+    lines.push(lineno + highlightedLines[i]);
+  }
+
+  return lines.join('\n');
+}
+
+module.exports = function highlight (code, opts) {
+  opts = opts || { };
+  if (opts.json) {
+    code = '!\n' + code;
+  }
+  try {
+
+    var result = redeyed(code, opts.theme || theme)
+      , firstline = opts.firstline && !isNaN(opts.firstline) ? opts.firstline : 1;
+
+    if (opts.json) {
+      result.code = result.code.split('\n').slice(1).join('\n');
+    }
+
+    return opts.linenos ? addLinenos(result.code, firstline) : result.code;
+  } catch (e) {
+    e.message = 'Unable to perform highlight. The code contained syntax errors: ' + e.message;
+    throw e;
+  }
+};
diff --git a/node_modules/cardinal/lib/highlightFile.js b/node_modules/cardinal/lib/highlightFile.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb3271dc14f8b8b0e3aa90b51fac6697314e3afe
--- /dev/null
+++ b/node_modules/cardinal/lib/highlightFile.js
@@ -0,0 +1,26 @@
+var fs = require('fs')
+  , highlight = require('./highlight');
+
+function isFunction (obj) {
+  return toString.call(obj) == '[object Function]';
+}
+
+module.exports = function highlightFile (fullPath, opts, cb) {
+  if (isFunction(opts)) { 
+    cb = opts;
+    opts = { };
+  }
+  opts = opts || { };
+  if (opts.json !== false && fullPath.match(/\.json$/i)) {
+    opts.json = true;
+  }
+
+  fs.readFile(fullPath, 'utf-8', function (err, code) {
+    if (err) return cb(err);
+    try {
+      cb(null, highlight(code, opts));
+    } catch (e) {
+      cb(e);
+    }
+  });
+};
diff --git a/node_modules/cardinal/lib/highlightFileSync.js b/node_modules/cardinal/lib/highlightFileSync.js
new file mode 100644
index 0000000000000000000000000000000000000000..bc33dd4f09ddcde8975a7cd5b0e874aa688c897c
--- /dev/null
+++ b/node_modules/cardinal/lib/highlightFileSync.js
@@ -0,0 +1,11 @@
+var fs = require('fs')
+  , highlight = require('./highlight');
+
+module.exports = function highlightFileSync (fullPath, opts) {
+  var code = fs.readFileSync(fullPath, 'utf-8');
+  opts = opts || { };
+  if (opts.json !== false && fullPath.match(/\.json$/i)) {
+    opts.json = true;
+  }
+  return highlight(code, opts);
+};
diff --git a/node_modules/cardinal/package.json b/node_modules/cardinal/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..e69c9837085a3abce994c775bc5e7229ae58948f
--- /dev/null
+++ b/node_modules/cardinal/package.json
@@ -0,0 +1,38 @@
+{
+  "name": "cardinal",
+  "version": "0.4.4",
+  "description": "Syntax highlights JavaScript code with ANSI colors to be printed to the terminal.",
+  "main": "cardinal.js",
+  "scripts": {
+    "test": "tap ./test/*.js",
+    "demo": "node examples/highlight-string.js; node examples/highlight-self; node examples/highlight-self-hide-semicolons;"
+  },
+  "bin": {
+    "cdl": "./bin/cdl.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/thlorenz/cardinal.git"
+  },
+  "keywords": [
+    "syntax",
+    "highlight",
+    "theme",
+    "javascript",
+    "json",
+    "terminal",
+    "console",
+    "print",
+    "output"
+  ],
+  "author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
+  "license": "MIT",
+  "dependencies": {
+    "redeyed": "~0.4.0",
+    "ansicolors": "~0.2.1"
+  },
+  "devDependencies": {
+    "tap": "~0.3.1",
+    "readdirp": "~0.2.1"
+  }
+}
diff --git a/node_modules/cardinal/settings.js b/node_modules/cardinal/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..f31817ac072b5416a36ca2cf4a5dc755cc7168f0
--- /dev/null
+++ b/node_modules/cardinal/settings.js
@@ -0,0 +1,51 @@
+var path =  require('path')
+  , util =  require('util')
+  , fs   =  require('fs')
+  , utl  =  require('./utl')
+  , home =  process.env.HOME
+  , settings;
+
+function getSettings (home_) {
+  if (settings) return settings;
+  try {
+    settingsJson = fs.readFileSync(path.join(home_ || home, '.cardinalrc'), 'utf-8');
+  } catch (_) {
+    // no .cardinalrc found - not a problem
+    return undefined;
+  }
+  try {
+    return JSON.parse(settingsJson);
+  } catch (e) {
+    // Have a .cardinalrc, but something about it is wrong - warn the user
+    // Coudn't parse the contained JSON
+    console.error(e);
+    return undefined;
+  }
+}
+
+// home_ mainly to be used during tests
+// Resolves the preferred theme from the .cardinalrc found in the HOME directory
+// If it couldn't be resolved, undefined is returned
+function resolveTheme (home_) {
+  var themePath
+    , settings = getSettings(home_);
+
+  if (!settings || !settings.theme) return undefined;
+
+  try {
+    // allow specifying just the name of a built-in theme or a full path to a custom theme
+    themePath = utl.isPath(settings.theme) ? settings.theme : path.join(__dirname, 'themes', settings.theme);
+
+    return require(themePath);
+  } catch (e) {
+    // Specified theme path is invalid
+    console.error(e);
+    return undefined;
+  }
+}
+
+module.exports = {
+    resolveTheme: resolveTheme
+  , getSettings: getSettings
+};
+
diff --git a/node_modules/cardinal/test/cardinal-highlight-block-comment.js b/node_modules/cardinal/test/cardinal-highlight-block-comment.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b99a1ba7b278d312465db821098b8992fda43da
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-block-comment.js
@@ -0,0 +1,25 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , fs = require('fs')
+  , customTheme = require('./fixtures/custom') 
+  , cardinal = require('..')
+
+function inspect(obj, depth) {
+  console.log(require('util').inspect(obj, false, depth || 5, true));
+}
+
+test('\nhighlighting a block comment without line numbers', function (t) {
+  var code = fs.readFileSync(__dirname + '/fixtures/block-comment.js', 'utf8');
+  var highlighted = cardinal.highlight(code, { theme: customTheme });
+  t.equal(highlighted, '\n\u001b[90m/**\n * This is a meaningless block jsdoc for a meaningless function.\n * Joins two strings, separating them to appear on two lines.\n * \n * @name foo\n * @function\n * @param uno {String} first string\n * @param dos {String} second string\n * @return {String} result of the join\n */\u001b[39m\n\u001b[96mmodule\u001b[39m\u001b[32m.\u001b[39m\u001b[96mexports\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[96mfoo\u001b[39m \u001b[90m(\u001b[39m\u001b[96muno\u001b[39m\u001b[32m,\u001b[39m \u001b[96mdos\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m\n  \u001b[31mreturn\u001b[39m \u001b[96muno\u001b[39m \u001b[93m+\u001b[39m \u001b[92m\'\\n\'\u001b[39m \u001b[93m+\u001b[39m \u001b[96mdos\u001b[39m\u001b[90m;\u001b[39m\n\u001b[33m}\u001b[39m\n')
+  t.end()
+})
+
+test('\nhighlighting a block comment with line numbers', function (t) {
+  var code = fs.readFileSync(__dirname + '/fixtures/block-comment.js', 'utf8');
+  var highlighted = cardinal.highlight(code, { theme: customTheme, linenos: true });
+  t.equal(highlighted, '\u001b[90m 1: \n\u001b[90m 2: \u001b[90m/**\n\u001b[90m 3:  * This is a meaningless block jsdoc for a meaningless function.\n\u001b[90m 4:  * Joins two strings, separating them to appear on two lines.\n\u001b[90m 5:  * \n\u001b[90m 6:  * @name foo\n\u001b[90m 7:  * @function\n\u001b[90m 8:  * @param uno {String} first string\n\u001b[90m 9:  * @param dos {String} second string\n\u001b[90m10:  * @return {String} result of the join\n\u001b[90m11:  */\u001b[39m\n\u001b[90m12: \u001b[96mmodule\u001b[39m\u001b[32m.\u001b[39m\u001b[96mexports\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[96mfoo\u001b[39m \u001b[90m(\u001b[39m\u001b[96muno\u001b[39m\u001b[32m,\u001b[39m \u001b[96mdos\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m\n\u001b[90m13:   \u001b[31mreturn\u001b[39m \u001b[96muno\u001b[39m \u001b[93m+\u001b[39m \u001b[92m\'\\n\'\u001b[39m \u001b[93m+\u001b[39m \u001b[96mdos\u001b[39m\u001b[90m;\u001b[39m\n\u001b[90m14: \u001b[33m}\u001b[39m')
+  t.end()
+})
diff --git a/node_modules/cardinal/test/cardinal-highlight-diff-spike.js b/node_modules/cardinal/test/cardinal-highlight-diff-spike.js
new file mode 100644
index 0000000000000000000000000000000000000000..eec53171e0a49e5689bad3c6ffb5f099b0623867
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-diff-spike.js
@@ -0,0 +1,95 @@
+/*jshint asi:true */
+'use strict';
+
+var fs          =  require('fs')
+  , path        =  require('path')
+  , utl         =  require('../utl')
+  , highlighter =  require('..')
+  , colors      =  require('ansicolors')
+  , diffFile    =  path.join(__dirname, 'fixtures', 'git-diff.txt')
+  , diff        =  fs.readFileSync(diffFile, 'utf-8')
+
+
+// @@ is not a valid js token, so when we see it, we can be sure that we are dealing with a git or svn diff
+var diffRegex = /^@@[^@]+@@$/m;
+var diffIndRegex = /^(@@[^@]+@@)(.*)$/;
+var addRemRegex = /^[+\-]/;
+var lines = diff.split('\n');
+
+function isDiff(lines) {
+  return !!lines
+    .filter(function (line) { 
+      return diffRegex.test(line); 
+    })
+    .length;
+}
+
+var diff = isDiff(lines);
+
+function tryHighlight(code) {
+
+  // TODO: need to remove symbols added to get valid code
+  //       this should be done by getting the splits instead of the actual code from the highlighter
+  //       now we can remove first / last one after highlighting completed
+  function tryAppending(appended, tryNext) {
+    try {
+       return highlighter.highlight(code + appended);
+    } catch (e) {
+      return tryNext(code);
+    }
+  }
+
+  function tryRemoveLeadingComma(tryNext) {
+    var success;
+    try {
+       success = highlighter.highlight(code.replace(/^( +),(.+)$/, '$1 $2'));
+       return success;
+    } catch (e) {
+      return tryNext(code);
+    }
+  }
+
+  function tryPlain() { 
+    try {
+      return highlighter.highlight(code);
+    } catch (e) {
+      return tryCloseMustache();
+    }
+  }
+
+  function tryCloseMustache() { return tryAppending('}', tryCloseParen); }
+
+  function tryCloseParen() { return tryAppending('\\)', tryCloseMustacheParen); }
+
+  function tryCloseMustacheParen() { return tryAppending('})', tryRemovingCommas);}
+
+  function tryRemovingCommas() { return tryRemoveLeadingComma(giveUp); }
+
+  function giveUp() { return code; }
+
+  return tryPlain();
+}
+
+function highlightDiffInd(line, matches) {
+  var highlighted = colors.brightBlue(matches[1])
+    , code = matches[2];
+  return code ? highlighted + tryHighlight(code) : highlighted;
+}
+
+function colorsAddRemove(c) {
+  return addRemRegex.test(c) ? colors.yellow(c) : c;
+}
+
+function highlightDiff(line) {
+  var diffIndMatches = diffIndRegex.exec(line);
+
+  return diffIndMatches 
+    ? highlightDiffInd(line, diffIndMatches)
+    : colorsAddRemove(line[0]) + tryHighlight(line.slice(1));
+}
+
+var highlightFn = diff ? highlightDiff : tryHighlight;
+var highlightedLines = lines.map(highlightFn);
+
+console.log(highlightedLines.join('\n'));
+
diff --git a/node_modules/cardinal/test/cardinal-highlight-file-async.js b/node_modules/cardinal/test/cardinal-highlight-file-async.js
new file mode 100644
index 0000000000000000000000000000000000000000..02b8d961ee26a8bbb364176a33676b52d5e03a9d
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-file-async.js
@@ -0,0 +1,48 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , fs = require('fs')
+  , path = require('path')
+  , customTheme = require('./fixtures/custom') 
+  , cardinal = require('..')
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var file = path.join(__dirname, 'fixtures/foo.js')
+  , fileWithErrors = path.join(__dirname, 'fixtures/foo-with-errors.js')
+
+test('supplying custom theme', function (t) {
+  cardinal.highlightFile(file, { theme: customTheme }, function (err, highlighted) {
+
+    t.equals(null, err, 'no error')
+    t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[96mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \n  \u001b[32mvar\u001b[39m \u001b[96ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[96ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[31mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \n\u001b[33m}\u001b[39m\n')
+    t.end()
+  })
+})
+
+test('not supplying custom theme', function (t) {
+  cardinal.highlightFile(file, function (err, highlighted) {
+
+    t.equals(null, err, 'no error')
+    t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \n  \u001b[32mvar\u001b[39m \u001b[37ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[37ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[91mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \n\u001b[33m}\u001b[39m\n')
+    t.end()
+  })
+})
+
+test('errornous code', function (t) {
+  cardinal.highlightFile(fileWithErrors, function (err, highlighted) {
+    t.similar(err.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token [(]/)
+    t.end()
+  })
+})
+
+test('non existing file', function (t) {
+  cardinal.highlightFile('./not/existing', function (err, highlighted) {
+    t.similar(err.message, /ENOENT, .*not.existing/)
+    t.end()
+  })
+})
diff --git a/node_modules/cardinal/test/cardinal-highlight-file-sync.js b/node_modules/cardinal/test/cardinal-highlight-file-sync.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b16e4eac6edfb056adea38d19c2b055c9feafff
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-file-sync.js
@@ -0,0 +1,48 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , fs = require('fs')
+  , path = require('path')
+  , customTheme = require('./fixtures/custom') 
+  , cardinal = require('..')
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var file = path.join(__dirname, 'fixtures/foo.js')
+  , fileWithErrors = path.join(__dirname, 'fixtures/foo-with-errors.js')
+
+test('supplying custom theme', function (t) {
+  var highlighted = cardinal.highlightFileSync(file, { theme: customTheme });
+
+  t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[96mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \n  \u001b[32mvar\u001b[39m \u001b[96ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[96ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[31mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \n\u001b[33m}\u001b[39m\n')
+  t.end()
+})
+
+test('not supplying custom theme', function (t) {
+  var highlighted = cardinal.highlightFileSync(file);
+
+  t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \n  \u001b[32mvar\u001b[39m \u001b[37ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[37ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[91mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \n\u001b[33m}\u001b[39m\n')
+  t.end()
+})
+
+test('errornous code', function (t) {
+  try {
+    cardinal.highlightFileSync(fileWithErrors);
+  } catch (e) {
+    t.similar(e.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token [(]/)
+    t.end()
+  }
+})
+
+test('non existing file', function (t) {
+  try {
+    cardinal.highlightFileSync('./not/existing');
+  } catch (e) {
+    t.similar(e.message, /ENOENT, .*not.existing/)
+    t.end()
+  }
+})
diff --git a/node_modules/cardinal/test/cardinal-highlight-git-diff.js b/node_modules/cardinal/test/cardinal-highlight-git-diff.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f7482d66e901721939ec567c55b7617801e5711
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-git-diff.js
@@ -0,0 +1,3 @@
+
+// Test Cases
+//  highlightDiff('@@ -25,22 +31,47 @@ function resolveTheme (config) { }')
diff --git a/node_modules/cardinal/test/cardinal-highlight-json-file-async.js b/node_modules/cardinal/test/cardinal-highlight-json-file-async.js
new file mode 100644
index 0000000000000000000000000000000000000000..54fd16918acb5629ca9b8ed80022b1b75581325c
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-json-file-async.js
@@ -0,0 +1,31 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , path = require('path')
+  , cardinal = require('..')
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var file = path.join(__dirname, 'fixtures/json.json');
+
+test('json option set from extension', function (t) {
+  cardinal.highlightFile(file, function (err, highlighted) {
+
+    t.equals(null, err, 'no error');
+    t.equals(highlighted, '\u001b[33m{\u001b[39m\u001b[32m"foo"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"bar"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"baz"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"quux"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"bam"\u001b[39m\u001b[93m:\u001b[39m\u001b[90mnull\u001b[39m\u001b[33m}\u001b[39m');
+    t.end();
+  });
+});
+
+test('json option respected if false', function (t) {
+  cardinal.highlightFile(file, { json: false }, function (err, highlighted) {
+
+    t.similar(err.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token /);
+    t.end();
+
+  });
+});
diff --git a/node_modules/cardinal/test/cardinal-highlight-json-file-sync.js b/node_modules/cardinal/test/cardinal-highlight-json-file-sync.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f75077a31d885c8e1605d908c486a214b4bf16e
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-json-file-sync.js
@@ -0,0 +1,29 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , path = require('path')
+  , cardinal = require('..')
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var file = path.join(__dirname, 'fixtures/json.json');
+
+test('json option set from extension', function (t) {
+  var highlighted = cardinal.highlightFileSync(file);
+
+  t.equals(highlighted, '\u001b[33m{\u001b[39m\u001b[32m"foo"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"bar"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"baz"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"quux"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"bam"\u001b[39m\u001b[93m:\u001b[39m\u001b[90mnull\u001b[39m\u001b[33m}\u001b[39m');
+  t.end();
+});
+
+test('json option respected if false', function (t) {
+  try {
+    var highlighted = cardinal.highlightFileSync(file, { json: false });
+  } catch (e) {
+    t.similar(e.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token /);
+    t.end();
+  }
+});
diff --git a/node_modules/cardinal/test/cardinal-highlight-json.js b/node_modules/cardinal/test/cardinal-highlight-json.js
new file mode 100644
index 0000000000000000000000000000000000000000..bbbe27da6a3bbd79c571749a789b63f274cda687
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-json.js
@@ -0,0 +1,41 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , customTheme = require('./fixtures/custom') 
+  , cardinal = require('..')
+
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var json = JSON.stringify({
+  foo: 'bar',
+  baz: 'quux',
+  bam: null
+});
+
+test('supplying custom theme', function (t) {
+  var highlighted = cardinal.highlight(json, { json: true, theme: customTheme });
+
+  t.equals(highlighted, '\u001b[33m{\u001b[39m\u001b[92m"foo"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"bar"\u001b[39m\u001b[32m,\u001b[39m\u001b[92m"baz"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"quux"\u001b[39m\u001b[32m,\u001b[39m\u001b[92m"bam"\u001b[39m\u001b[93m:\u001b[39m\u001b[90mnull\u001b[39m\u001b[33m}\u001b[39m')
+  t.end();
+});
+
+test('not supplying custom theme', function (t) {
+  var highlighted = cardinal.highlight(json, { json: true });
+
+  t.equals(highlighted, '\u001b[33m{\u001b[39m\u001b[32m"foo"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"bar"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"baz"\u001b[39m\u001b[93m:\u001b[39m\u001b[92m"quux"\u001b[39m\u001b[32m,\u001b[39m\u001b[32m"bam"\u001b[39m\u001b[93m:\u001b[39m\u001b[90mnull\u001b[39m\u001b[33m}\u001b[39m')
+  t.end();
+});
+
+test('without json option', function (t) {
+  try {
+    cardinal.highlight(json);
+  } catch (e) {
+    t.similar(e.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token /)
+    t.end();
+  }
+});
diff --git a/node_modules/cardinal/test/cardinal-highlight-string.js b/node_modules/cardinal/test/cardinal-highlight-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..beefe0d6f8ef2fe51696bb28d97211171a6007b9
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-highlight-string.js
@@ -0,0 +1,70 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , fs = require('fs')
+  , customTheme = require('./fixtures/custom') 
+  , cardinal = require('..')
+
+function inspect (obj) {
+  return console.log(util.inspect(obj, false, 5, false))
+}
+
+var code = 'function foo() { var a = 3; return a > 2 ? true : false; }'
+  , codeWithErrors = 'function () { var a = 3; return a > 2 ? true : false; }';
+
+test('supplying custom theme', function (t) {
+  var highlighted = cardinal.highlight(code, { theme: customTheme });
+
+  t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[96mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \u001b[32mvar\u001b[39m \u001b[96ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[96ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[31mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \u001b[33m}\u001b[39m')
+  t.end()
+})
+
+test('not supplying custom theme', function (t) {
+  var highlighted = cardinal.highlight(code);
+
+  t.equals(highlighted, '\u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \u001b[32mvar\u001b[39m \u001b[37ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[37ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[91mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \u001b[33m}\u001b[39m')
+  t.end()
+})
+
+test('errornous code', function (t) {
+  try {
+    cardinal.highlight(codeWithErrors);
+  } catch (e) {
+    t.similar(e.message, /Unable to perform highlight. The code contained syntax errors.* Line 1: Unexpected token [(]/)
+    t.end()
+  }
+})
+
+test('line numbers no firstline given', function (t) {
+  var highlighted = cardinal.highlight(code, { linenos: true });
+  t.equals(highlighted, '\u001b[90m1: \u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \u001b[32mvar\u001b[39m \u001b[37ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[37ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[91mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \u001b[33m}\u001b[39m')
+  t.end()
+})
+
+test('line numbers firstline 99', function (t) {
+  var highlighted = cardinal.highlight(code, { linenos: true, firstline: 99 });
+  t.equals(highlighted, '\u001b[90m99: \u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m \u001b[32mvar\u001b[39m \u001b[37ma\u001b[39m \u001b[93m=\u001b[39m \u001b[34m3\u001b[39m\u001b[90m;\u001b[39m \u001b[31mreturn\u001b[39m \u001b[37ma\u001b[39m \u001b[93m>\u001b[39m \u001b[34m2\u001b[39m \u001b[93m?\u001b[39m \u001b[91mtrue\u001b[39m \u001b[93m:\u001b[39m \u001b[91mfalse\u001b[39m\u001b[90m;\u001b[39m \u001b[33m}\u001b[39m')
+  t.end()
+})
+
+test('line numbers multi line no first line given', function (t) {
+  var multilineCode = '' + 
+    function foo () {
+      return 1;
+    };
+  var highlighted = cardinal.highlight(multilineCode, { linenos: true });
+  t.equals(highlighted,'\u001b[90m1: \u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m\n\u001b[90m2:       \u001b[31mreturn\u001b[39m \u001b[34m1\u001b[39m\u001b[90m;\u001b[39m\n\u001b[90m3:     \u001b[33m}\u001b[39m')
+  t.end()
+})
+
+test('line numbers multi line first line 99', function (t) {
+  var multilineCode = '' + 
+    function foo () {
+      return 1;
+    };
+  var highlighted = cardinal.highlight(multilineCode, { linenos: true, firstline: 99 });
+  t.equals(highlighted,'\u001b[90m 99: \u001b[94mfunction\u001b[39m \u001b[37mfoo\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m\n\u001b[90m100:       \u001b[31mreturn\u001b[39m \u001b[34m1\u001b[39m\u001b[90m;\u001b[39m\n\u001b[90m101:     \u001b[33m}\u001b[39m')
+  t.end()
+})
diff --git a/node_modules/cardinal/test/cardinal-smoke.js b/node_modules/cardinal/test/cardinal-smoke.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2d0e18cbea070af1fba95e43472eb7f824fe8d5
--- /dev/null
+++ b/node_modules/cardinal/test/cardinal-smoke.js
@@ -0,0 +1,44 @@
+'use strict';
+/*jshint asi: true*/
+
+// applying esprima to a bunch of files of contained libraries as a smoke test
+var test     =  require('tap').test
+  , path     =  require('path')
+  , fs       =  require('fs')
+  , readdirp =  require('readdirp')
+  , cardinal  =  require('..')
+  , node_modules =  path.join(__dirname, '..', 'node_modules')
+  , tapdir       =  path.join(node_modules, 'tap')
+  , redeyeddir   =  path.join(node_modules, 'redeyed')
+
+
+test('tap', function (t) {
+  var invalidTapFiles = [
+      'async-map-ordered.js'
+    , 'prof.js'
+  ]
+
+  readdirp({ root: tapdir, fileFilter: '*.js' })
+    .on('data', function (entry) {
+      
+      if (~invalidTapFiles.indexOf(entry.name)) return
+
+      var code = fs.readFileSync(entry.fullPath, 'utf-8')
+        , result = cardinal.highlight(code);
+
+      t.assert(~result.indexOf('[32mvar\u001b[39m') || !(~result.indexOf('var ')), 'highlighted ' + entry.path)
+    })
+    .on('end', t.end.bind(t))
+})
+
+test('redeyed', function (t) {
+  readdirp({ root: redeyeddir, fileFilter: 'redeyed.js' })
+    .on('data', function (entry) {
+      
+      var code = fs.readFileSync(entry.fullPath, 'utf-8')
+        , result = cardinal.highlight(code);
+
+      t.assert(~result.indexOf('[32mvar\u001b[39m') || !(~result.indexOf('var ')), 'highlighted ' + entry.path)
+    })
+    .on('end', t.end.bind(t))
+})
diff --git a/node_modules/cardinal/test/fixtures/block-comment.js b/node_modules/cardinal/test/fixtures/block-comment.js
new file mode 100644
index 0000000000000000000000000000000000000000..597bc69d836aea481d59bcfe682a1fc93bee023a
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/block-comment.js
@@ -0,0 +1,14 @@
+
+/**
+ * This is a meaningless block jsdoc for a meaningless function.
+ * Joins two strings, separating them to appear on two lines.
+ * 
+ * @name foo
+ * @function
+ * @param uno {String} first string
+ * @param dos {String} second string
+ * @return {String} result of the join
+ */
+module.exports = function foo (uno, dos) {
+  return uno + '\n' + dos;
+}
diff --git a/node_modules/cardinal/test/fixtures/custom.js b/node_modules/cardinal/test/fixtures/custom.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc369fc2d3ff7a8925c4b2456385652609415f93
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/custom.js
@@ -0,0 +1,144 @@
+var colors = require('ansicolors');
+
+// Change the below definitions in order to tweak the color theme.
+module.exports = {
+
+    'Boolean': {
+      // changed from default
+      'true'   :  colors.red
+
+    , 'false'  :  undefined
+    , _default :  colors.brightRed
+    }
+
+  , 'Identifier': {
+      'undefined' :  colors.brightBlack
+    , 'self'      :  colors.brightRed
+    , 'console'   :  colors.blue
+    , 'log'       :  colors.blue
+    , 'warn'      :  colors.red
+    , 'error'     :  colors.brightRed
+    //
+      // changed from default
+    , _default    :  colors.brightCyan
+    }
+
+  , 'Null': {
+      _default: colors.brightBlack
+    }
+
+  , 'Numeric': {
+      _default: colors.blue
+    }
+
+  , 'String': {
+      _default: colors.brightGreen
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  colors.cyan
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  colors.red
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  colors.cyan
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  colors.red
+    , 'return'      :  colors.red
+    , 'switch'      :  undefined
+
+    , 'this'        :  colors.brightRed
+    , 'throw'       :  undefined
+    , 'try'         :  colors.cyan
+    , 'typeof'      :  undefined
+
+    , 'var'         :  colors.green
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  colors.brightBlue
+  }
+  , 'Punctuator': {
+      ';': colors.brightBlack
+    , '.': colors.green  
+    , ',': colors.green  
+
+    , '{': colors.yellow
+    , '}': colors.yellow
+    , '(': colors.brightBlack  
+    , ')': colors.brightBlack  
+    , '[': colors.yellow
+    , ']': colors.yellow
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: colors.brightYellow
+  }
+
+    // line comment
+  , Line: {
+     _default: colors.brightBlack
+    }
+
+    /* block comment */
+  , Block: {
+     _default: colors.brightBlack
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/cardinal/test/fixtures/foo-with-errors.js b/node_modules/cardinal/test/fixtures/foo-with-errors.js
new file mode 100644
index 0000000000000000000000000000000000000000..fefebe2bb29650cc055c53ec09bf7cff4942c4e0
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/foo-with-errors.js
@@ -0,0 +1,3 @@
+function () { 
+  var a = 3; return a > 2 ? true : false; 
+};
diff --git a/node_modules/cardinal/test/fixtures/foo.js b/node_modules/cardinal/test/fixtures/foo.js
new file mode 100644
index 0000000000000000000000000000000000000000..bd9a3e07d2a978473b65d7831b810794e7ec3c2b
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/foo.js
@@ -0,0 +1,3 @@
+function foo() { 
+  var a = 3; return a > 2 ? true : false; 
+}
diff --git a/node_modules/cardinal/test/fixtures/git-diff.txt b/node_modules/cardinal/test/fixtures/git-diff.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e324b670fdedcc0d4f762add290148fafd3e12e8
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/git-diff.txt
@@ -0,0 +1,78 @@
+diff --git a/test/settings.js b/test/settings.js
+index 7b28d66..642688f 100644
+--- a/test/settings.js
++++ b/test/settings.js
+@@ -1,14 +1,20 @@
+ 'use strict';
+ /*jshint asi: true*/
+ 
+-var test     =  require('tap').test
+-  , path     =  require('path')
+-  , fs       =  require('fs')
+-  , settings =  require('../settings')
+-  , existsSync = fs.existsSync || path.existsSync
++var test                =  require('tap').test
++  , path                =  require('path')
++  , fs                  =  require('fs')
+   , hideSemicolonsTheme =  require('../themes/hide-semicolons')
+   , home                =  path.join(__dirname, 'fixtures', 'home')
+   , rcpath              =  path.join(home, '.cardinalrc')
++  , existsSync          =  fs.existsSync || path.existsSync
++  , settingsResolve     =  require.resolve('../settings')
++  , settings
++
++function setup () {
++  delete require.cache[settingsResolve]
++  settings = require(settingsResolve)
++}
+ 
+ function writerc(config) {
+   fs.writeFileSync(rcpath, JSON.stringify(config), 'utf-8')
+@@ -25,22 +31,47 @@ function resolveTheme (config) {
+   return result;
+ }
+ 
++function getSettings (config) {
++  writerc(config)
++  var result = settings.getSettings(home)
++  removerc()
++  return result;
++}
++
+ if (!existsSync(home)) fs.mkdirSync(home);
+ 
+ test('no .cardinalrc in home', function (t) {
++  setup()
+   var theme = settings.resolveTheme(home)
+   t.equals(theme, undefined, 'resolves no theme') 
+   t.end()
+ })
+ 
+ test('.cardinalrc with theme "hide-semicolons" in home', function (t) {
++  setup()
+   var theme = resolveTheme({ theme: "hide-semicolons" })
+   t.deepEquals(theme, hideSemicolonsTheme, 'resolves hide-semicolons theme') 
+   t.end()
+ })
+ 
+ test('.cardinalrc with full path to "hide-semicolons.js" in home', function (t) {
++  setup()
+   var theme = resolveTheme({ theme: path.join(__dirname, '..', 'themes', 'hide-semicolons.js') })
+   t.deepEquals(theme, hideSemicolonsTheme, 'resolves hide-semicolons theme') 
+   t.end()
+ })
++
++test('.cardinalrc with linenos: true', function (t) {
++  setup()
++  var opts = { linenos: true }
++  t.deepEquals(getSettings(opts), opts)
++  t.end()
++})
++
++test('.cardinalrc with linenos: true and theme', function (t) {
++  setup()
++  var opts = { linenos: true, theme: 'some theme' }
++  t.deepEquals(getSettings(opts), opts)
++  t.end()
++})
++
diff --git a/node_modules/cardinal/test/fixtures/json.json b/node_modules/cardinal/test/fixtures/json.json
new file mode 100644
index 0000000000000000000000000000000000000000..0c39df44b5d2bcab2d6f260036a366f6eca18a91
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/json.json
@@ -0,0 +1 @@
+{"foo":"bar","baz":"quux","bam":null}
\ No newline at end of file
diff --git a/node_modules/cardinal/test/fixtures/svn-diff.txt b/node_modules/cardinal/test/fixtures/svn-diff.txt
new file mode 100644
index 0000000000000000000000000000000000000000..635b056da0fff3a2b18cec61b34ada5afd8f724f
--- /dev/null
+++ b/node_modules/cardinal/test/fixtures/svn-diff.txt
@@ -0,0 +1,23 @@
+Index: grunt.js
+===================================================================
+--- grunt.js	(revision 31200)
++++ grunt.js	(working copy)
+@@ -12,6 +12,7 @@
+ 
+ module.exports = function (grunt) {
+ 
++  console.log('hello world');
+   // Project configuration.
+   grunt.initConfig({
+     lint: {
+@@ -19,10 +20,6 @@
+         'packages/services.web/{!(test)/**/,}*.js',
+         'packages/error/**/*.js'
+       ],
+-      scripts: [
+-        'grunt.js',
+-        'db/**/*.js'
+-      ],
+       browser: [
+         'packages/web/server.js',
+         'packages/web/server/**/*.js',
diff --git a/node_modules/cardinal/test/settings.js b/node_modules/cardinal/test/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..642688f148b932d4892da460450417d455767b46
--- /dev/null
+++ b/node_modules/cardinal/test/settings.js
@@ -0,0 +1,77 @@
+'use strict';
+/*jshint asi: true*/
+
+var test                =  require('tap').test
+  , path                =  require('path')
+  , fs                  =  require('fs')
+  , hideSemicolonsTheme =  require('../themes/hide-semicolons')
+  , home                =  path.join(__dirname, 'fixtures', 'home')
+  , rcpath              =  path.join(home, '.cardinalrc')
+  , existsSync          =  fs.existsSync || path.existsSync
+  , settingsResolve     =  require.resolve('../settings')
+  , settings
+
+function setup () {
+  delete require.cache[settingsResolve]
+  settings = require(settingsResolve)
+}
+
+function writerc(config) {
+  fs.writeFileSync(rcpath, JSON.stringify(config), 'utf-8')
+}
+
+function removerc () {
+  fs.unlinkSync(rcpath)
+}
+
+function resolveTheme (config) {
+  writerc(config)
+  var result = settings.resolveTheme(home)
+  removerc()
+  return result;
+}
+
+function getSettings (config) {
+  writerc(config)
+  var result = settings.getSettings(home)
+  removerc()
+  return result;
+}
+
+if (!existsSync(home)) fs.mkdirSync(home);
+
+test('no .cardinalrc in home', function (t) {
+  setup()
+  var theme = settings.resolveTheme(home)
+  t.equals(theme, undefined, 'resolves no theme') 
+  t.end()
+})
+
+test('.cardinalrc with theme "hide-semicolons" in home', function (t) {
+  setup()
+  var theme = resolveTheme({ theme: "hide-semicolons" })
+  t.deepEquals(theme, hideSemicolonsTheme, 'resolves hide-semicolons theme') 
+  t.end()
+})
+
+test('.cardinalrc with full path to "hide-semicolons.js" in home', function (t) {
+  setup()
+  var theme = resolveTheme({ theme: path.join(__dirname, '..', 'themes', 'hide-semicolons.js') })
+  t.deepEquals(theme, hideSemicolonsTheme, 'resolves hide-semicolons theme') 
+  t.end()
+})
+
+test('.cardinalrc with linenos: true', function (t) {
+  setup()
+  var opts = { linenos: true }
+  t.deepEquals(getSettings(opts), opts)
+  t.end()
+})
+
+test('.cardinalrc with linenos: true and theme', function (t) {
+  setup()
+  var opts = { linenos: true, theme: 'some theme' }
+  t.deepEquals(getSettings(opts), opts)
+  t.end()
+})
+
diff --git a/node_modules/cardinal/test/themes.js b/node_modules/cardinal/test/themes.js
new file mode 100644
index 0000000000000000000000000000000000000000..590cdcaf60582a0244b64e9a1b89d8002e538c32
--- /dev/null
+++ b/node_modules/cardinal/test/themes.js
@@ -0,0 +1,22 @@
+'use strict';
+/*jshint asi: true*/
+
+var test     =  require('tap').test
+  , path     =  require('path')
+  , fs       =  require('fs')
+  , themesdir = path.join(__dirname, '..', 'themes')
+  , allFiles = fs.readdirSync(themesdir)
+
+test('validate themes by requiring all of them', function (t) {
+  allFiles
+    .filter(function (file) { return path.extname(file) === '.js'; })
+    .forEach(function (theme) {
+      try {
+        t.ok(require(path.join(themesdir, theme)), theme + ' is valid')   
+      } catch (e) {
+        t.fail('theme: ' + theme + ' is invalid! ' + e.message)
+      }
+    })
+  t.end()
+})
+  
diff --git a/node_modules/cardinal/themes/README.md b/node_modules/cardinal/themes/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..fe2a44342e700a7ea4d67ec2f5806f818aba8f05
--- /dev/null
+++ b/node_modules/cardinal/themes/README.md
@@ -0,0 +1,31 @@
+# cardinal themes
+
+These are the built in themes that come with cardinal.
+
+You can create more themes by copying and then editing the [empty
+theme](https://github.com/thlorenz/cardinal/blob/master/themes/empty.js) which is provided for that purpose.
+
+The [hide semicolons theme](https://github.com/thlorenz/cardinal/blob/master/themes/hide-semicolons.js) has the added
+benefit of making all semicolons invisible. This makes code more readable at times.
+
+Find out how to change the theme used by cardinal [here](https://github.com/thlorenz/cardinal#theme).
+
+# sharing themes
+
+To add your theme to the cardinal built-in themes, follow the below steps:
+
+1. fork the cardinal repository
+2. add your theme to the themes folder and commit your changes
+3. create a pull request
+
+If you believe that your theme is better than the current default theme, let me know by creating an issue. 
+
+This will allow others to cast their vote. If enough people agree, your theme will be promoted to be the default.
+
+## Contributed Themes
+
+### tomorrow night
+
+[![tomorrow-night](https://github.com/thlorenz/cardinal/raw/master/assets/theme-tomorrow-night.png)](https://github.com/thlorenz/cardinal/blob/master/themes/tomorrow-night.js)
+
+*by [firede](https://github.com/firede)*
diff --git a/node_modules/cardinal/themes/default.js b/node_modules/cardinal/themes/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..86ee59ad46e97fb362e4733396e2994b567eb2f6
--- /dev/null
+++ b/node_modules/cardinal/themes/default.js
@@ -0,0 +1,147 @@
+var colors = require('ansicolors');
+
+// Change the below definitions in order to tweak the color theme.
+module.exports = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  colors.brightRed
+    }
+
+  , 'Identifier': {
+      'undefined' :  colors.brightBlack
+    , 'self'      :  colors.brightRed
+    , 'console'   :  colors.blue
+    , 'log'       :  colors.blue
+    , 'warn'      :  colors.red
+    , 'error'     :  colors.brightRed
+    , _default    :  colors.white
+    }
+
+  , 'Null': {
+      _default: colors.brightBlack
+    }
+
+  , 'Numeric': {
+      _default: colors.blue
+    }
+
+  , 'String': {
+      _default: function (s, info) {
+        var nextToken = info.tokens[info.tokenIndex + 1];
+
+        // show keys of object literals and json in different color
+        return (nextToken && nextToken.type === 'Punctuator' && nextToken.value === ':') 
+          ? colors.green(s)
+          : colors.brightGreen(s);
+      }
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  colors.cyan
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  colors.red
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  colors.cyan
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  colors.red
+    , 'return'      :  colors.red
+    , 'switch'      :  undefined
+
+    , 'this'        :  colors.brightRed
+    , 'throw'       :  undefined
+    , 'try'         :  colors.cyan
+    , 'typeof'      :  undefined
+
+    , 'var'         :  colors.green
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  colors.brightBlue
+  }
+  , 'Punctuator': {
+      ';': colors.brightBlack
+    , '.': colors.green  
+    , ',': colors.green  
+
+    , '{': colors.yellow
+    , '}': colors.yellow
+    , '(': colors.brightBlack  
+    , ')': colors.brightBlack  
+    , '[': colors.yellow
+    , ']': colors.yellow
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: colors.brightYellow
+  }
+
+    // line comment
+  , Line: {
+     _default: colors.brightBlack
+    }
+
+    /* block comment */
+  , Block: {
+     _default: colors.brightBlack
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/cardinal/themes/empty.js b/node_modules/cardinal/themes/empty.js
new file mode 100644
index 0000000000000000000000000000000000000000..3203aacbd343bea894d1295146fcf7d2a3ce96a2
--- /dev/null
+++ b/node_modules/cardinal/themes/empty.js
@@ -0,0 +1,140 @@
+/* 
+ * Copy this file and use it as a starting point for your custom cardinal color theme.
+ * Just fill in or change the entries for the tokens you want to color
+ * Keep in mind that more specific configurations override less specific ones.
+ */
+
+var colors = require('ansicolors');
+
+// Change the below definitions in order to tweak the color theme.
+module.exports = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  undefined
+    }
+
+  , 'Identifier': {
+      _default: undefined
+    }
+
+  , 'Null': {
+      _default: undefined
+    }
+
+  , 'Numeric': {
+      _default: undefined
+    }
+
+  , 'String': {
+      _default: undefined
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  undefined
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  undefined
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  undefined
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  undefined
+    , 'return'      :  undefined
+    , 'switch'      :  undefined
+
+    , 'this'        :  undefined
+    , 'throw'       :  undefined
+    , 'try'         :  undefined
+    , 'typeof'      :  undefined
+
+    , 'var'         :  undefined
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  undefined
+  }
+  , 'Punctuator': {
+      ';': undefined  
+    , '.': undefined  
+    , ',': undefined  
+
+    , '{': undefined  
+    , '}': undefined  
+    , '(': undefined  
+    , ')': undefined  
+    , '[': undefined
+    , ']': undefined
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: undefined
+  }
+
+    // line comment
+  , Line: {
+     _default: undefined
+    }
+
+    /* block comment */
+  , Block: {
+     _default: undefined
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/cardinal/themes/hide-semicolons.js b/node_modules/cardinal/themes/hide-semicolons.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1871ee705ffef24ddd0446ae4e27906cee181e4
--- /dev/null
+++ b/node_modules/cardinal/themes/hide-semicolons.js
@@ -0,0 +1,149 @@
+var colors = require('ansicolors');
+
+// Change the below definitions in order to tweak the color theme.
+module.exports = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  colors.brightRed
+    }
+
+  , 'Identifier': {
+      'undefined' :  colors.brightBlack
+    , 'self'      :  colors.brightRed
+    , 'console'   :  colors.blue
+    , 'log'       :  colors.blue
+    , 'warn'      :  colors.red
+    , 'error'     :  colors.brightRed
+    , _default    :  colors.white
+    }
+
+  , 'Null': {
+      _default: colors.brightBlack
+    }
+
+  , 'Numeric': {
+      _default: colors.blue
+    }
+
+  , 'String': {
+      _default: function (s, info) {
+        var nextToken = info.tokens[info.tokenIndex + 1];
+
+        // show keys of object literals and json in different color
+        return (nextToken && nextToken.type === 'Punctuator' && nextToken.value === ':') 
+          ? colors.green(s)
+          : colors.brightGreen(s);
+      }
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  colors.cyan
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  colors.red
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  colors.cyan
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  colors.red
+    , 'return'      :  colors.red
+    , 'switch'      :  undefined
+
+    , 'this'        :  colors.brightRed
+    , 'throw'       :  undefined
+    , 'try'         :  colors.cyan
+    , 'typeof'      :  undefined
+
+    , 'var'         :  colors.green
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  colors.brightBlue
+  }
+  , 'Punctuator': {
+      // setting semicolon's color to the same as the terminal background makes it invisible
+      ';': colors.black
+
+    , '.': colors.green  
+    , ',': colors.green  
+
+    , '{': colors.yellow
+    , '}': colors.yellow
+    , '(': colors.brightBlack  
+    , ')': colors.brightBlack  
+    , '[': colors.yellow
+    , ']': colors.yellow
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: colors.brightYellow
+  }
+
+    // line comment
+  , Line: {
+     _default: colors.brightBlack
+    }
+
+    /* block comment */
+  , Block: {
+     _default: colors.brightBlack
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/cardinal/themes/tomorrow-night.js b/node_modules/cardinal/themes/tomorrow-night.js
new file mode 100644
index 0000000000000000000000000000000000000000..9e0fc58433dbf4b0be41a73ad6acb83a47607731
--- /dev/null
+++ b/node_modules/cardinal/themes/tomorrow-night.js
@@ -0,0 +1,161 @@
+var colors = require('ansicolors');
+
+// Change the below definitions in order to tweak the color theme.
+module.exports = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  colors.yellow
+    }
+
+  , 'Identifier': {
+      'undefined' :  colors.yellow
+    , 'self'      :  colors.yellow
+    , 'type'      :  colors.yellow
+    , 'value'     :  colors.yellow
+    , 'console'   :  undefined
+    , 'log'       :  colors.blue
+    , 'warn'      :  colors.blue
+    , 'error'     :  colors.blue
+    , 'join'      :  colors.blue
+    , _default    :  function (s, info) {
+        var prevToken = info.tokens[info.tokenIndex - 1];
+        var nextToken = info.tokens[info.tokenIndex + 1];
+
+        return (nextToken
+            && nextToken.type === 'Punctuator'
+            && nextToken.value === '('
+            && prevToken
+            && prevToken.type === 'Keyword'
+            && prevToken.value === 'function'
+          ) ? colors.blue(s) : colors.white(s);
+      }
+    }
+
+  , 'Null': {
+      _default: colors.yellow
+    }
+
+  , 'Numeric': {
+      _default: colors.yellow
+    }
+
+  , 'String': {
+      _default: function (s, info) {
+        var nextToken = info.tokens[info.tokenIndex + 1];
+
+        // show keys of object literals and json in different color
+        return (nextToken && nextToken.type === 'Punctuator' && nextToken.value === ':') 
+          ? colors.green(s)
+          : colors.brightGreen(s);
+      }
+    }
+
+  , 'Keyword': {
+      'break'       :  colors.magenta
+
+    , 'case'        :  colors.magenta
+    , 'catch'       :  colors.magenta
+    , 'continue'    :  colors.magenta
+
+    , 'debugger'    :  colors.magenta
+    , 'default'     :  colors.magenta
+    , 'delete'      :  colors.red
+    , 'do'          :  colors.magenta
+
+    , 'else'        :  colors.magenta
+
+    , 'finally'     :  colors.magenta
+    , 'for'         :  colors.magenta
+    , 'function'    :  colors.magenta
+
+    , 'if'          :  colors.magenta
+    , 'in'          :  colors.cyan
+    , 'instanceof'  :  colors.cyan
+
+    , 'new'         :  colors.cyan
+    , 'return'      :  colors.magenta
+    , 'switch'      :  colors.magenta
+
+    , 'this'        :  colors.red
+    , 'throw'       :  colors.magenta
+    , 'try'         :  colors.magenta
+    , 'typeof'      :  colors.cyan
+
+    , 'var'         :  colors.magenta
+    , 'void'        :  colors.magenta
+
+    , 'while'       :  colors.magenta
+    , 'with'        :  colors.cyan
+    , _default      :  colors.white
+  }
+  , 'Punctuator': {
+      ';': colors.white
+    , '.': colors.white
+    , ',': colors.white
+
+    , '{': colors.white
+    , '}': colors.white
+    , '(': colors.white
+    , ')': colors.white
+    , '[': colors.white
+    , ']': colors.white
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': colors.white
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': colors.white
+    , ':': colors.white
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: colors.cyan
+  }
+
+    // line comment
+  , Line: {
+     _default: colors.brightBlack
+    }
+
+    /* block comment */
+  , Block: {
+     _default: colors.brightBlack
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/cardinal/utl.js b/node_modules/cardinal/utl.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f36e40b3bfca3679f0a45da1c92726d3be4fa2f
--- /dev/null
+++ b/node_modules/cardinal/utl.js
@@ -0,0 +1,11 @@
+var util = require('util');
+
+module.exports.isPath = function (s) {
+  return (/[\/\\]/).test(s);
+};
+
+module.exports.inspect = function(obj, depth) {
+  console.log(util.inspect(obj, false, depth || 5, true));
+};
+
+
diff --git a/node_modules/core-util-is/LICENSE b/node_modules/core-util-is/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d8d7f9437dbf5ad54701a187f05988bcf0006fd8
--- /dev/null
+++ b/node_modules/core-util-is/LICENSE
@@ -0,0 +1,19 @@
+Copyright Node.js contributors. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/node_modules/core-util-is/README.md b/node_modules/core-util-is/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5a76b4149c5eb5077c09578e349820bccbbd266e
--- /dev/null
+++ b/node_modules/core-util-is/README.md
@@ -0,0 +1,3 @@
+# core-util-is
+
+The `util.is*` functions introduced in Node v0.12.
diff --git a/node_modules/core-util-is/lib/util.js b/node_modules/core-util-is/lib/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e5a20d7dc09e280bf06302f4f872b8eb168aac0
--- /dev/null
+++ b/node_modules/core-util-is/lib/util.js
@@ -0,0 +1,107 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+
+function isArray(arg) {
+  if (Array.isArray) {
+    return Array.isArray(arg);
+  }
+  return objectToString(arg) === '[object Array]';
+}
+exports.isArray = isArray;
+
+function isBoolean(arg) {
+  return typeof arg === 'boolean';
+}
+exports.isBoolean = isBoolean;
+
+function isNull(arg) {
+  return arg === null;
+}
+exports.isNull = isNull;
+
+function isNullOrUndefined(arg) {
+  return arg == null;
+}
+exports.isNullOrUndefined = isNullOrUndefined;
+
+function isNumber(arg) {
+  return typeof arg === 'number';
+}
+exports.isNumber = isNumber;
+
+function isString(arg) {
+  return typeof arg === 'string';
+}
+exports.isString = isString;
+
+function isSymbol(arg) {
+  return typeof arg === 'symbol';
+}
+exports.isSymbol = isSymbol;
+
+function isUndefined(arg) {
+  return arg === void 0;
+}
+exports.isUndefined = isUndefined;
+
+function isRegExp(re) {
+  return objectToString(re) === '[object RegExp]';
+}
+exports.isRegExp = isRegExp;
+
+function isObject(arg) {
+  return typeof arg === 'object' && arg !== null;
+}
+exports.isObject = isObject;
+
+function isDate(d) {
+  return objectToString(d) === '[object Date]';
+}
+exports.isDate = isDate;
+
+function isError(e) {
+  return (objectToString(e) === '[object Error]' || e instanceof Error);
+}
+exports.isError = isError;
+
+function isFunction(arg) {
+  return typeof arg === 'function';
+}
+exports.isFunction = isFunction;
+
+function isPrimitive(arg) {
+  return arg === null ||
+         typeof arg === 'boolean' ||
+         typeof arg === 'number' ||
+         typeof arg === 'string' ||
+         typeof arg === 'symbol' ||  // ES6 symbol
+         typeof arg === 'undefined';
+}
+exports.isPrimitive = isPrimitive;
+
+exports.isBuffer = require('buffer').Buffer.isBuffer;
+
+function objectToString(o) {
+  return Object.prototype.toString.call(o);
+}
diff --git a/node_modules/core-util-is/package.json b/node_modules/core-util-is/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..b0c51f580be4cff40105d5b52a8a513bc0330e94
--- /dev/null
+++ b/node_modules/core-util-is/package.json
@@ -0,0 +1,38 @@
+{
+  "name": "core-util-is",
+  "version": "1.0.3",
+  "description": "The `util.is*` functions introduced in Node v0.12.",
+  "main": "lib/util.js",
+  "files": [
+    "lib"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/core-util-is"
+  },
+  "keywords": [
+    "util",
+    "isBuffer",
+    "isArray",
+    "isNumber",
+    "isString",
+    "isRegExp",
+    "isThis",
+    "isThat",
+    "polyfill"
+  ],
+  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/isaacs/core-util-is/issues"
+  },
+  "scripts": {
+    "test": "tap test.js",
+    "preversion": "npm test",
+    "postversion": "npm publish",
+    "prepublishOnly": "git push origin --follow-tags"
+  },
+  "devDependencies": {
+    "tap": "^15.0.9"
+  }
+}
diff --git a/node_modules/double-ended-queue/.npmignore b/node_modules/double-ended-queue/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..bd236a0e87572a78aca7b84c078f5b3554022281
--- /dev/null
+++ b/node_modules/double-ended-queue/.npmignore
@@ -0,0 +1,31 @@
+node_modules/*
+todo.txt
+npm-debug.log
+test/*
+benchmark/*
+browser/*
+src/*
+async
+sync
+mixed
+bench.json
+js/browser
+js/browser/*
+js/debug
+js/debug/*
+reader.js
+read.txt
+bench
+.editorconfig
+.jshintrc
+ast_passes.js
+mocharun.js
+throwaway.js
+throwaway.html
+deque.sublime-workspace
+deque.sublime-project
+changelog.js
+.travis.yml
+sauce_connect.log
+nodex64.exe
+bump.js
diff --git a/node_modules/double-ended-queue/Gruntfile.js b/node_modules/double-ended-queue/Gruntfile.js
new file mode 100644
index 0000000000000000000000000000000000000000..7aed70d6a04a2369840aa9f07d1a2fb117366c24
--- /dev/null
+++ b/node_modules/double-ended-queue/Gruntfile.js
@@ -0,0 +1,188 @@
+"use strict";
+Error.stackTraceLimit = 100;
+var astPasses = require("./ast_passes.js");
+
+module.exports = function( grunt ) {
+    var isCI = !!grunt.option("ci");
+
+    var license;
+    function getLicense() {
+        if( !license ) {
+            var fs = require("fs");
+            var text = fs.readFileSync("LICENSE", "utf8");
+            text = text.split("\n").map(function(line, index){
+                return " * " + line;
+            }).join("\n")
+            license = "/**\n" + text + "\n */\n";
+        }
+        return license
+    }
+
+    function writeFile( dest, content ) {
+        grunt.file.write( dest, content );
+        grunt.log.writeln('File "' + dest + '" created.');
+    }
+
+    var gruntConfig = {};
+
+    var getGlobals = function() {
+        var fs = require("fs");
+        var file = "./src/constants.js";
+        var contents = fs.readFileSync(file, "utf8");
+        var rconstantname = /CONSTANT\(\s*([^,]+)/g;
+        var m;
+        var globals = {
+            "console": false,
+            "require": false,
+            "module": false,
+            "define": false
+        };
+        while( ( m = rconstantname.exec( contents ) ) ) {
+            globals[m[1]] = false;
+        }
+        return globals;
+    }
+
+    gruntConfig.pkg = grunt.file.readJSON("package.json");
+
+    gruntConfig.jshint = {
+        all: {
+            options: {
+                globals: getGlobals(),
+
+                "bitwise": false,
+                "camelcase": true,
+                "curly": true,
+                "eqeqeq": true,
+                "es3": true,
+                "forin": true,
+                "immed": true,
+                "latedef": false,
+                "newcap": true,
+                "noarg": true,
+                "noempty": true,
+                "nonew": true,
+                "plusplus": false,
+                "quotmark": "double",
+                "undef": true,
+                "unused": true,
+                "strict": false,
+                "trailing": true,
+                "maxparams": 7,
+                "maxlen": 80,
+
+                "asi": false,
+                "boss": true,
+                "eqnull": true,
+                "evil": true,
+                "expr": false,
+                "funcscope": false,
+                "globalstrict": false,
+                "lastsemic": false,
+                "laxcomma": false,
+                "laxbreak": false,
+                "loopfunc": true,
+                "multistr": true,
+                "proto": false,
+                "scripturl": true,
+                "smarttabs": false,
+                "shadow": true,
+                "sub": true,
+                "supernew": false,
+                "validthis": true,
+
+                "browser": true,
+                "jquery": true,
+                "devel": true,
+
+
+                '-W014': true,
+                '-W116': true,
+                '-W106': true,
+                '-W064': true,
+                '-W097': true
+            },
+
+            files: {
+                src: [
+                    "./src/deque.js"
+                ]
+            }
+        }
+    };
+
+    if( !isCI ) {
+        gruntConfig.jshint.all.options.reporter = require("jshint-stylish");
+    }
+
+    gruntConfig.bump = {
+      options: {
+        files: ['package.json'],
+        updateConfigs: [],
+        commit: true,
+        commitMessage: 'Release v%VERSION%',
+        commitFiles: ['-a'],
+        createTag: true,
+        tagName: 'v%VERSION%',
+        tagMessage: 'Version %VERSION%',
+        false: true,
+        pushTo: 'master',
+        gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe'
+      }
+    };
+
+    grunt.initConfig(gruntConfig);
+    grunt.loadNpmTasks('grunt-contrib-jshint');
+    grunt.loadNpmTasks('grunt-bump');
+
+
+    grunt.registerTask( "build", function() {
+        var fs = require("fs");
+        var CONSTANTS_FILE = "./src/constants.js";
+
+        astPasses.readConstants(fs.readFileSync(CONSTANTS_FILE, "utf8"), CONSTANTS_FILE);
+        var fileNames = ["deque.js"];
+        fileNames.forEach(function(fileName){
+            var src = fs.readFileSync("./src/" + fileName, "utf8");
+            src = astPasses.removeComments(src, fileName);
+            src = astPasses.expandConstants(src, fileName);
+            src = getLicense() + src;
+            writeFile("./js/" + fileName, src);
+        });
+    });
+
+    grunt.registerTask( "testrun", function() {
+        var fs = require("fs");
+        var done = this.async();
+        var Mocha = require("mocha");
+
+        var mochaOpts = {
+            reporter: "spec",
+            timeout: 500,
+            slow: Infinity
+        };
+
+        var mocha = new Mocha(mochaOpts);
+
+        fs.readdirSync("./test").forEach(function(fileName) {
+            mocha.addFile("./test/" + fileName);
+        });
+
+        mocha.run(function(err){
+            if( err ) {
+                process.stderr.write(test.title + "\n" + err.stack + "\n");
+                done(err);
+            }
+            else {
+                done();
+            }
+        }).on( "fail", function( test, err ) {
+            process.stderr.write(test.title + "\n" + err.stack + "\n");
+            done(err);
+        });
+    });
+
+    grunt.registerTask( "test", ["jshint", "build", "testrun"] );
+    grunt.registerTask( "default", ["jshint", "build"] );
+
+};
diff --git a/node_modules/double-ended-queue/LICENSE b/node_modules/double-ended-queue/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..abaadaa061ab0d19eb94303ba8945a33e1c69c48
--- /dev/null
+++ b/node_modules/double-ended-queue/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013 Petka Antonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:</p>
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/double-ended-queue/README.md b/node_modules/double-ended-queue/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b1d115d2448163ef75da9357b62365c73ebc117d
--- /dev/null
+++ b/node_modules/double-ended-queue/README.md
@@ -0,0 +1,293 @@
+#Introduction
+
+Extremely fast [double-ended queue](http://en.wikipedia.org/wiki/Double-ended_queue) implementation. Double-ended queue can also be used as a:
+
+- [Stack](http://en.wikipedia.org/wiki/Stack_\(abstract_data_type\))
+- [Queue](http://en.wikipedia.org/wiki/Queue_\(data_structure\))
+
+The implementation is GC and CPU cache friendly [circular buffer](http://en.wikipedia.org/wiki/Circular_buffer). [It will run circles around any "linked list" implementation](#performance).
+
+Every queue operation is done in constant `O(1)` - including random access from `.get()`.
+
+#Topics
+
+- [Quick start](#quick-start)
+- [Why not use an Array?](#why-not-use-an-array)
+- [Using double-ended queue as a normal queue](#using-double-ended-queue-as-a-normal-queue)
+- [API reference and examples](#api)
+- [Performance](#performance)
+
+#Quick start
+
+    npm install double-ended-queue
+
+```js
+var Deque = require("double-ended-queue");
+
+var deque = new Deque([1,2,3,4]);
+deque.shift(); //1
+deque.pop(); //4
+```
+
+#Why not use an Array?
+
+Arrays take linear `O(N)` time to do `shift` and `unshift` operations. That means in theory that an array with 1000 items is 1000x slower to do those operations than a deque with 1000 items. 10000x slower with 10000 items and so on.
+
+V8 implements [a trick for small arrays](https://code.google.com/p/v8/issues/detail?id=3059) where these operations are done in constant time, however even with this trick deque is still 4x faster.
+
+But arrays use "native" methods, they must be faster!
+
+In V8, there is almost no advantage for a method to be a built-in. In fact many times built-ins are at a severe disadvantage of having to implement far more complex semantics than is actually needed in practice. For example, sparse array handling punishes almost every built-in array method even though nobody uses sparse arrays as is evidenced by the popularity of the underscore library which doesn't handle sparse arrays in the same way across different browsers.
+
+#Using double-ended queue as a normal queue
+
+Queue is a more commonly needed data structure however a separate implementation does not provide any advantage in terms of performance. Aliases are provided specifically for the queue use-case. You may use `.enqueue(items...)` to enqueue item(s) and `.dequeue()` to dequeue an item.
+
+#API
+
+- [`new Deque()`](#new-deque---deque)
+- [`new Deque(Array items)`](#new-dequearray-items---deque)
+- [`new Deque(int capacity)`](#new-dequeint-capacity---deque)
+- [`push(dynamic items...)`](#pushdynamic-items---int)
+- [`unshift(dynamic items...)`](#unshiftdynamic-items---int)
+- [`pop()`](#pop---dynamic)
+- [`shift()`](#shift---dynamic)
+- [`toArray()`](#toarray---array)
+- [`peekBack()`](#peekback---dynamic)
+- [`peekFront()`](#peekfront---dynamic)
+- [`get(int index)`](#getint-index---dynamic)
+- [`isEmpty()`](#isempty---boolean)
+- [`clear()`](#clear---void)
+
+#####`new Deque()` -> `Deque`
+
+Creates an empty double-ended queue with initial capacity of 16. If you know the optimal size before-hand, use [`new Deque(int capacity)`](#new-dequeint-capacity---deque).
+
+```js
+var deque = new Deque();
+deque.push(1, 2, 3);
+deque.shift(); //1
+deque.pop(); //3
+```
+
+<hr>
+
+#####`new Deque(Array items)` -> `Deque`
+
+Creates a double-ended queue from `items`.
+
+```js
+var deque = new Deque([1,2,3,4]);
+deque.shift(); //1
+deque.pop(); //4
+```
+
+<hr>
+
+#####`new Deque(int capacity)` -> `Deque`
+
+Creates an empty double-ended queue with the given `capacity`. `Capacity` should be the maximum amount of items the queue will hold at a given time.
+
+The reason to give an initial capacity is to avoid potentially expensive resizing operations at runtime.
+
+```js
+var deque = new Deque(100);
+deque.push(1, 2, 3);
+deque.shift(); //1
+deque.pop(); //3
+```
+
+<hr>
+
+#####`push(dynamic items...)` -> `int`
+
+Push items to the back of this queue. Returns the amount of items currently in the queue after the operation.
+
+```js
+var deque = new Deque();
+deque.push(1);
+deque.pop(); //1
+deque.push(1, 2, 3);
+deque.shift(); //1
+deque.shift(); //2
+deque.shift(); //3
+```
+
+**Aliases:** `enqueue`, `insertBack`
+
+<hr>
+
+#####`unshift(dynamic items...)` -> `int`
+
+Unshift items to the front of this queue. Returns the amount of items currently in the queue after the operation.
+
+```js
+var deque = new Deque([2,3]);
+deque.unshift(1);
+deque.toString(); //"1,2,3"
+deque.unshift(-2, -1, 0);
+deque.toString(); //"-2,-1,0,1,2,3"
+```
+
+**Aliases:** `insertFront`
+
+<hr>
+
+
+#####`pop()` -> `dynamic`
+
+Pop off the item at the back of this queue.
+
+Note: The item will be removed from the queue. If you simply want to see what's at the back of the queue use [`peekBack()`](#peekback---dynamic) or [`.get(-1)`](#getint-index---dynamic).
+
+If the queue is empty, `undefined` is returned. If you need to differentiate between `undefined` values in the queue and `pop()` return value -
+check the queue `.length` before popping.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.pop(); //3
+deque.pop(); //2
+deque.pop(); //1
+deque.pop(); //undefined
+```
+
+**Aliases:** `removeBack`
+
+<hr>
+
+#####`shift()` -> `dynamic`
+
+Shifts off the item at the front of this queue.
+
+Note: The item will be removed from the queue. If you simply want to see what's at the front of the queue use [`peekFront()`](#peekfront---dynamic) or [`.get(0)`](#getint-index---dynamic).
+
+If the queue is empty, `undefined` is returned. If you need to differentiate between `undefined` values in the queue and `shift()` return value -
+check the queue `.length` before shifting.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.shift(); //1
+deque.shift(); //2
+deque.shift(); //3
+deque.shift(); //undefined
+```
+
+**Aliases:** `removeFront`, `dequeue`
+
+<hr>
+
+#####`toArray()` -> `Array`
+
+Returns the items in the queue as an array. Starting from the item in the front of the queue and ending to the item at the back of the queue.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.push(4);
+deque.unshift(0);
+deque.toArray(); //[0,1,2,3,4]
+```
+
+**Aliases:** `toJSON`
+
+<hr>
+
+#####`peekBack()` -> `dynamic`
+
+Returns the item that is at the back of this queue without removing it.
+
+If the queue is empty, `undefined` is returned.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.push(4);
+deque.peekBack(); //4
+```
+
+<hr>
+
+#####`peekFront()` -> `dynamic`
+
+Returns the item that is at the front of this queue without removing it.
+
+If the queue is empty, `undefined` is returned.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.push(4);
+deque.peekFront(); //1
+```
+
+<hr>
+
+#####`get(int index)` -> `dynamic`
+
+Returns the item that is at the given `index` of this queue without removing it.
+
+The index is zero-based, so `.get(0)` will return the item that is at the front, `.get(1)` will return
+the item that comes after and so on.
+
+The index can be negative to read items at the back of the queue. `.get(-1)` returns the item that is at the back of the queue,
+`.get(-2)` will return the item that comes before and so on.
+
+Returns `undefined` if `index` is not a valid index into the queue.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.get(0); //1
+deque.get(1); //2
+deque.get(2); //3
+
+deque.get(-1); //3
+deque.get(-2); //2
+deque.get(-3); //1
+```
+
+**Note**: Even though indexed accessor (e.g. `queue[0]`) could *appear* to return a correct value *sometimes*, this is completely unreliable. The numeric slots
+of the deque object are internally used as an optimization and have no meaningful order or meaning to outside. Always use `.get()`.
+
+**Note**: The implementation has O(1) random access using `.get()`.
+
+<hr>
+
+#####`isEmpty()` -> `boolean`
+
+Return `true` if this queue is empty, `false` otherwise.
+
+```js
+var deque = new Deque();
+deque.isEmpty(); //true
+deque.push(1);
+deque.isEmpty(); //false
+```
+
+<hr>
+
+#####`clear()` -> `void`
+
+Remove all items from this queue. Does not change the queue's capacity.
+
+```js
+var deque = new Deque([1,2,3]);
+deque.toString(); //"1,2,3"
+deque.clear();
+deque.toString(); //""
+```
+<hr>
+
+#Performance
+
+Clone the repo and `npm install`. Then run the `bench` script.
+
+##1000 items in the queue
+
+    double-ended-queue x 15,532,714 ops/sec ±0.19% (96 runs sampled)
+    built-in array x 6,501,398 ops/sec ±0.87% (95 runs sampled)
+    node-deque x 2,938,068 ops/sec ±3.50% (68 runs sampled)
+
+##2 million items in the queue
+
+    double-ended-queue x 14,425,547 ops/sec ±0.17% (94 runs sampled)
+    node-deque x 2,815,628 ops/sec ±10.56% (76 runs sampled)
+    built-in array x 19.23 ops/sec ±0.35% (51 runs sampled)
+
+Noteworthy is just how bad the degradation can be for built-in array when V8 cannot use the trick.
diff --git a/node_modules/double-ended-queue/js/deque.js b/node_modules/double-ended-queue/js/deque.js
new file mode 100644
index 0000000000000000000000000000000000000000..90a355992e0f45aa5a5390ebb5f4d36a72601165
--- /dev/null
+++ b/node_modules/double-ended-queue/js/deque.js
@@ -0,0 +1,287 @@
+/**
+ * Copyright (c) 2013 Petka Antonov
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:</p>
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+"use strict";
+function Deque(capacity) {
+    this._capacity = getCapacity(capacity);
+    this._length = 0;
+    this._front = 0;
+    this._makeCapacity();
+    if (isArray(capacity)) {
+        var len = capacity.length;
+        for (var i = 0; i < len; ++i) {
+            this[i] = capacity[i];
+        }
+        this._length = len;
+    }
+}
+
+Deque.prototype.toArray = function Deque$toArray() {
+    var len = this._length;
+    var ret = new Array(len);
+    var front = this._front;
+    var capacity = this._capacity;
+    for (var j = 0; j < len; ++j) {
+        ret[j] = this[(front + j) & (capacity - 1)];
+    }
+    return ret;
+};
+
+Deque.prototype.push = function Deque$push(item) {
+    var argsLength = arguments.length;
+    var length = this._length;
+    if (argsLength > 1) {
+        var capacity = this._capacity;
+        if (length + argsLength > capacity) {
+            for (var i = 0; i < argsLength; ++i) {
+                this._checkCapacity(length + 1);
+                var j = (this._front + length) & (this._capacity - 1);
+                this[j] = arguments[i];
+                length++;
+                this._length = length;
+            }
+            return length;
+        }
+        else {
+            var j = this._front;
+            for (var i = 0; i < argsLength; ++i) {
+                this[(j + length) & (capacity - 1)] = arguments[i];
+                j++;
+            }
+            this._length = length + argsLength;
+            return length + argsLength;
+        }
+
+    }
+
+    if (argsLength === 0) return length;
+
+    this._checkCapacity(length + 1);
+    var i = (this._front + length) & (this._capacity - 1);
+    this[i] = item;
+    this._length = length + 1;
+    return length + 1;
+};
+
+Deque.prototype.pop = function Deque$pop() {
+    var length = this._length;
+    if (length === 0) {
+        return void 0;
+    }
+    var i = (this._front + length - 1) & (this._capacity - 1);
+    var ret = this[i];
+    this[i] = void 0;
+    this._length = length - 1;
+    return ret;
+};
+
+Deque.prototype.shift = function Deque$shift() {
+    var length = this._length;
+    if (length === 0) {
+        return void 0;
+    }
+    var front = this._front;
+    var ret = this[front];
+    this[front] = void 0;
+    this._front = (front + 1) & (this._capacity - 1);
+    this._length = length - 1;
+    return ret;
+};
+
+Deque.prototype.unshift = function Deque$unshift(item) {
+    var length = this._length;
+    var argsLength = arguments.length;
+
+
+    if (argsLength > 1) {
+        var capacity = this._capacity;
+        if (length + argsLength > capacity) {
+            for (var i = argsLength - 1; i >= 0; i--) {
+                this._checkCapacity(length + 1);
+                var capacity = this._capacity;
+                var j = (((( this._front - 1 ) &
+                    ( capacity - 1) ) ^ capacity ) - capacity );
+                this[j] = arguments[i];
+                length++;
+                this._length = length;
+                this._front = j;
+            }
+            return length;
+        }
+        else {
+            var front = this._front;
+            for (var i = argsLength - 1; i >= 0; i--) {
+                var j = (((( front - 1 ) &
+                    ( capacity - 1) ) ^ capacity ) - capacity );
+                this[j] = arguments[i];
+                front = j;
+            }
+            this._front = front;
+            this._length = length + argsLength;
+            return length + argsLength;
+        }
+    }
+
+    if (argsLength === 0) return length;
+
+    this._checkCapacity(length + 1);
+    var capacity = this._capacity;
+    var i = (((( this._front - 1 ) &
+        ( capacity - 1) ) ^ capacity ) - capacity );
+    this[i] = item;
+    this._length = length + 1;
+    this._front = i;
+    return length + 1;
+};
+
+Deque.prototype.peekBack = function Deque$peekBack() {
+    var length = this._length;
+    if (length === 0) {
+        return void 0;
+    }
+    var index = (this._front + length - 1) & (this._capacity - 1);
+    return this[index];
+};
+
+Deque.prototype.peekFront = function Deque$peekFront() {
+    if (this._length === 0) {
+        return void 0;
+    }
+    return this[this._front];
+};
+
+Deque.prototype.get = function Deque$get(index) {
+    var i = index;
+    if ((i !== (i | 0))) {
+        return void 0;
+    }
+    var len = this._length;
+    if (i < 0) {
+        i = i + len;
+    }
+    if (i < 0 || i >= len) {
+        return void 0;
+    }
+    return this[(this._front + i) & (this._capacity - 1)];
+};
+
+Deque.prototype.isEmpty = function Deque$isEmpty() {
+    return this._length === 0;
+};
+
+Deque.prototype.clear = function Deque$clear() {
+    this._length = 0;
+    this._front = 0;
+    this._makeCapacity();
+};
+
+Deque.prototype.toString = function Deque$toString() {
+    return this.toArray().toString();
+};
+
+Deque.prototype.valueOf = Deque.prototype.toString;
+Deque.prototype.removeFront = Deque.prototype.shift;
+Deque.prototype.removeBack = Deque.prototype.pop;
+Deque.prototype.insertFront = Deque.prototype.unshift;
+Deque.prototype.insertBack = Deque.prototype.push;
+Deque.prototype.enqueue = Deque.prototype.push;
+Deque.prototype.dequeue = Deque.prototype.shift;
+Deque.prototype.toJSON = Deque.prototype.toArray;
+
+Object.defineProperty(Deque.prototype, "length", {
+    get: function() {
+        return this._length;
+    },
+    set: function() {
+        throw new RangeError("");
+    }
+});
+
+Deque.prototype._makeCapacity = function Deque$_makeCapacity() {
+    var len = this._capacity;
+    for (var i = 0; i < len; ++i) {
+        this[i] = void 0;
+    }
+};
+
+Deque.prototype._checkCapacity = function Deque$_checkCapacity(size) {
+    if (this._capacity < size) {
+        this._resizeTo(getCapacity(this._capacity * 1.5 + 16));
+    }
+};
+
+Deque.prototype._resizeTo = function Deque$_resizeTo(capacity) {
+    var oldFront = this._front;
+    var oldCapacity = this._capacity;
+    var oldDeque = new Array(oldCapacity);
+    var length = this._length;
+
+    arrayCopy(this, 0, oldDeque, 0, oldCapacity);
+    this._capacity = capacity;
+    this._makeCapacity();
+    this._front = 0;
+    if (oldFront + length <= oldCapacity) {
+        arrayCopy(oldDeque, oldFront, this, 0, length);
+    } else {        var lengthBeforeWrapping =
+            length - ((oldFront + length) & (oldCapacity - 1));
+
+        arrayCopy(oldDeque, oldFront, this, 0, lengthBeforeWrapping);
+        arrayCopy(oldDeque, 0, this, lengthBeforeWrapping,
+            length - lengthBeforeWrapping);
+    }
+};
+
+
+var isArray = Array.isArray;
+
+function arrayCopy(src, srcIndex, dst, dstIndex, len) {
+    for (var j = 0; j < len; ++j) {
+        dst[j + dstIndex] = src[j + srcIndex];
+    }
+}
+
+function pow2AtLeast(n) {
+    n = n >>> 0;
+    n = n - 1;
+    n = n | (n >> 1);
+    n = n | (n >> 2);
+    n = n | (n >> 4);
+    n = n | (n >> 8);
+    n = n | (n >> 16);
+    return n + 1;
+}
+
+function getCapacity(capacity) {
+    if (typeof capacity !== "number") {
+        if (isArray(capacity)) {
+            capacity = capacity.length;
+        }
+        else {
+            return 16;
+        }
+    }
+    return pow2AtLeast(
+        Math.min(
+            Math.max(16, capacity), 1073741824)
+    );
+}
+
+module.exports = Deque;
diff --git a/node_modules/double-ended-queue/package.json b/node_modules/double-ended-queue/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..27d83f960a971f83ba41b90f71e936c9308d52c2
--- /dev/null
+++ b/node_modules/double-ended-queue/package.json
@@ -0,0 +1,44 @@
+{
+    "name": "double-ended-queue",
+    "description": "Extremely fast double-ended queue implementation",
+    "version": "2.0.0-0",
+    "keywords": [
+        "data-structure",
+        "data-structures",
+        "queue",
+        "deque",
+        "double-ended-queue"
+    ],
+    "scripts": {
+        "test": "grunt test"
+    },
+    "homepage": "https://github.com/petkaantonov/deque",
+    "repository": {
+        "type": "git",
+        "url": "git://github.com/petkaantonov/deque.git"
+    },
+    "bugs": {
+        "url": "http://github.com/petkaantonov/deque/issues"
+    },
+    "license": "MIT",
+    "author": {
+        "name": "Petka Antonov",
+        "email": "petka_antonov@hotmail.com",
+        "url": "http://github.com/petkaantonov/"
+    },
+    "devDependencies": {
+        "grunt": "~0.4.1",
+        "grunt-contrib-jshint": "~0.6.4",
+        "jshint-stylish": "latest",
+        "acorn": "~0.3.1",
+        "mocha": "~1.12.1",
+        "grunt-cli": "~0.1.9",
+        "bluebird": "~0.11",
+        "benchmark": "~1.0.0",
+        "deque": "0.0.4",
+        "q": "~0.9.7",
+        "semver-utils": "~1.1.0"
+    },
+    "readmeFilename": "README.md",
+    "main": "./js/deque.js"
+}
\ No newline at end of file
diff --git a/node_modules/esprima/README.md b/node_modules/esprima/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a74bd12d6f1a3bedbe329a7981555762469942cd
--- /dev/null
+++ b/node_modules/esprima/README.md
@@ -0,0 +1,73 @@
+**Esprima** ([esprima.org](http://esprima.org)) is a high performance,
+standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
+parser written in ECMAScript (also popularly known as
+[JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript)).
+Esprima is created and maintained by [Ariya Hidayat](http://twitter.com/ariyahidayat),
+with the help of [many contributors](https://github.com/ariya/esprima/contributors).
+
+Esprima runs on web browsers (IE 6+, Firefox 1+, Safari 3+, Chrome 1+, Konqueror 4.6+, Opera 8+) as well as
+[Node.js](http://nodejs.org).
+
+### Features
+
+- Full support for [ECMAScript 5.1](http://www.ecma-international.org/publications/standards/Ecma-262.htm)(ECMA-262)
+- Sensible [syntax tree format](http://esprima.org/doc/index.html#ast) compatible with Mozilla
+[Parser AST](https://developer.mozilla.org/en/SpiderMonkey/Parser_API)
+- Heavily tested (> 550 [unit tests](http://esprima.org/test/) with solid 100% statement coverage)
+- Optional tracking of syntax node location (index-based and line-column)
+- Experimental support for ES6/Harmony (module, class, destructuring, ...)
+
+Esprima is blazing fast (see the [benchmark suite](http://esprima.org/test/benchmarks.html)).
+It is up to 3x faster than UglifyJS v1 and it is still [competitive](http://esprima.org/test/compare.html)
+with the new generation of fast parsers.
+
+### Applications
+
+Esprima serves as the basis for many popular JavaScript development tools:
+
+- Code coverage analysis: [node-cover](https://github.com/itay/node-cover), [Istanbul](https://github.com/yahoo/Istanbul)
+- Documentation tool: [JFDoc](https://github.com/thejohnfreeman/jfdoc), [JSDuck](https://github.com/senchalabs/jsduck)
+- Language extension: [LLJS](http://mbebenita.github.com/LLJS/) (low-level JS),
+[Sweet.js](http://sweetjs.org/) (macro)
+- ES6/Harmony transpiler: [Six](https://github.com/matthewrobb/six), [Harmonizr](https://github.com/jdiamond/harmonizr)
+- Eclipse Orion smart editing ([outline view](https://github.com/aclement/esprima-outline), [content assist](http://contraptionsforprogramming.blogspot.com/2012/02/better-javascript-content-assist-in.html))
+- Source code modification: [Esmorph](https://github.com/ariya/esmorph), [Code Painter](https://github.com/fawek/codepainter),
+- Source transformation: [node-falafel](https://github.com/substack/node-falafel), [Esmangle](https://github.com/Constellation/esmangle), [escodegen](https://github.com/Constellation/escodegen)
+
+### Questions?
+- [Documentation](http://esprima.org/doc)
+- [Issue tracker](http://issues.esprima.org): [known problems](http://code.google.com/p/esprima/issues/list?q=Defect)
+and [future plans](http://code.google.com/p/esprima/issues/list?q=Enhancement)
+- [Mailing list](http://groups.google.com/group/esprima)
+- [Contribution guide](http://esprima.org/doc/index.html#contribution)
+
+Follow [@Esprima](http://twitter.com/Esprima) on Twitter to get the
+development updates.
+Feedback and contribution are welcomed!
+
+### License
+
+Copyright (C) 2012, 2011 [Ariya Hidayat](http://ariya.ofilabs.com/about)
+ and other contributors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/node_modules/esprima/bin/esparse.js b/node_modules/esprima/bin/esparse.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e7bb81ea30800f1f1dd9ce5eb42c4baf1961747
--- /dev/null
+++ b/node_modules/esprima/bin/esparse.js
@@ -0,0 +1,117 @@
+#!/usr/bin/env node
+/*
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint sloppy:true node:true rhino:true */
+
+var fs, esprima, fname, content, options, syntax;
+
+if (typeof require === 'function') {
+    fs = require('fs');
+    esprima = require('esprima');
+} else if (typeof load === 'function') {
+    try {
+        load('esprima.js');
+    } catch (e) {
+        load('../esprima.js');
+    }
+}
+
+// Shims to Node.js objects when running under Rhino.
+if (typeof console === 'undefined' && typeof process === 'undefined') {
+    console = { log: print };
+    fs = { readFileSync: readFile };
+    process = { argv: arguments, exit: quit };
+    process.argv.unshift('esparse.js');
+    process.argv.unshift('rhino');
+}
+
+function showUsage() {
+    console.log('Usage:');
+    console.log('   esparse [options] file.js');
+    console.log();
+    console.log('Available options:');
+    console.log();
+    console.log('  --comment      Gather all line and block comments in an array');
+    console.log('  --loc          Include line-column location info for each syntax node');
+    console.log('  --range        Include index-based range for each syntax node');
+    console.log('  --raw          Display the raw value of literals');
+    console.log('  --tokens       List all tokens in an array');
+    console.log('  --tolerant     Tolerate errors on a best-effort basis (experimental)');
+    console.log('  -v, --version  Shows program version');
+    console.log();
+    process.exit(1);
+}
+
+if (process.argv.length <= 2) {
+    showUsage();
+}
+
+options = {};
+
+process.argv.splice(2).forEach(function (entry) {
+
+    if (entry === '-h' || entry === '--help') {
+        showUsage();
+    } else if (entry === '-v' || entry === '--version') {
+        console.log('ECMAScript Parser (using Esprima version', esprima.version, ')');
+        console.log();
+        process.exit(0);
+    } else if (entry === '--comment') {
+        options.comment = true;
+    } else if (entry === '--loc') {
+        options.loc = true;
+    } else if (entry === '--range') {
+        options.range = true;
+    } else if (entry === '--raw') {
+        options.raw = true;
+    } else if (entry === '--tokens') {
+        options.tokens = true;
+    } else if (entry === '--tolerant') {
+        options.tolerant = true;
+    } else if (entry.slice(0, 2) === '--') {
+        console.log('Error: unknown option ' + entry + '.');
+        process.exit(1);
+    } else if (typeof fname === 'string') {
+        console.log('Error: more than one input file.');
+        process.exit(1);
+    } else {
+        fname = entry;
+    }
+});
+
+if (typeof fname !== 'string') {
+    console.log('Error: no input file.');
+    process.exit(1);
+}
+
+try {
+    content = fs.readFileSync(fname, 'utf-8');
+    syntax = esprima.parse(content, options);
+    console.log(JSON.stringify(syntax, null, 4));
+} catch (e) {
+    console.log('Error: ' + e.message);
+    process.exit(1);
+}
diff --git a/node_modules/esprima/bin/esvalidate.js b/node_modules/esprima/bin/esvalidate.js
new file mode 100644
index 0000000000000000000000000000000000000000..e0af3f70515695e49fc47e242cd112dd73f9b7c1
--- /dev/null
+++ b/node_modules/esprima/bin/esvalidate.js
@@ -0,0 +1,177 @@
+#!/usr/bin/env node
+/*
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint sloppy:true plusplus:true node:true rhino:true */
+
+var fs, esprima, options, fnames, count;
+
+if (typeof require === 'function') {
+    fs = require('fs');
+    esprima = require('esprima');
+} else if (typeof load === 'function') {
+    try {
+        load('esprima.js');
+    } catch (e) {
+        load('../esprima.js');
+    }
+}
+
+// Shims to Node.js objects when running under Rhino.
+if (typeof console === 'undefined' && typeof process === 'undefined') {
+    console = { log: print };
+    fs = { readFileSync: readFile };
+    process = { argv: arguments, exit: quit };
+    process.argv.unshift('esvalidate.js');
+    process.argv.unshift('rhino');
+}
+
+function showUsage() {
+    console.log('Usage:');
+    console.log('   esvalidate [options] file.js');
+    console.log();
+    console.log('Available options:');
+    console.log();
+    console.log('  --format=type  Set the report format, plain (default) or junit');
+    console.log('  -v, --version  Print program version');
+    console.log();
+    process.exit(1);
+}
+
+if (process.argv.length <= 2) {
+    showUsage();
+}
+
+options = {
+    format: 'plain'
+};
+
+fnames = [];
+
+process.argv.splice(2).forEach(function (entry) {
+
+    if (entry === '-h' || entry === '--help') {
+        showUsage();
+    } else if (entry === '-v' || entry === '--version') {
+        console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
+        console.log();
+        process.exit(0);
+    } else if (entry.slice(0, 9) === '--format=') {
+        options.format = entry.slice(9);
+        if (options.format !== 'plain' && options.format !== 'junit') {
+            console.log('Error: unknown report format ' + options.format + '.');
+            process.exit(1);
+        }
+    } else if (entry.slice(0, 2) === '--') {
+        console.log('Error: unknown option ' + entry + '.');
+        process.exit(1);
+    } else {
+        fnames.push(entry);
+    }
+});
+
+if (fnames.length === 0) {
+    console.log('Error: no input file.');
+    process.exit(1);
+}
+
+if (options.format === 'junit') {
+    console.log('<?xml version="1.0" encoding="UTF-8"?>');
+    console.log('<testsuites>');
+}
+
+count = 0;
+fnames.forEach(function (fname) {
+    var content, timestamp, syntax, name;
+    try {
+        content = fs.readFileSync(fname, 'utf-8');
+
+        if (content[0] === '#' && content[1] === '!') {
+            content = '//' + content.substr(2, content.length);
+        }
+
+        timestamp = Date.now();
+        syntax = esprima.parse(content, { tolerant: true });
+
+        if (options.format === 'junit') {
+
+            name = fname;
+            if (name.lastIndexOf('/') >= 0) {
+                name = name.slice(name.lastIndexOf('/') + 1);
+            }
+
+            console.log('<testsuite name="' + fname + '" errors="0" ' +
+                ' failures="' + syntax.errors.length + '" ' +
+                ' tests="' + syntax.errors.length + '" ' +
+                ' time="' + Math.round((Date.now() - timestamp) / 1000) +
+                '">');
+
+            syntax.errors.forEach(function (error) {
+                var msg = error.message;
+                msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
+                console.log('  <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
+                    ' time="0">');
+                console.log('    <error type="SyntaxError" message="' + error.message + '">' +
+                    error.message + '(' + name + ':' + error.lineNumber + ')' +
+                    '</error>');
+                console.log('  </testcase>');
+            });
+
+            console.log('</testsuite>');
+
+        } else if (options.format === 'plain') {
+
+            syntax.errors.forEach(function (error) {
+                var msg = error.message;
+                msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
+                msg = fname + ':' + error.lineNumber + ': ' + msg;
+                console.log(msg);
+                ++count;
+            });
+
+        }
+    } catch (e) {
+        ++count;
+        if (options.format === 'junit') {
+            console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
+                ' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
+            console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
+            console.log(' <error type="ParseError" message="' + e.message + '">' +
+                e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
+                ')</error>');
+            console.log(' </testcase>');
+            console.log('</testsuite>');
+        } else {
+            console.log('Error: ' + e.message);
+        }
+    }
+});
+
+if (options.format === 'junit') {
+    console.log('</testsuites>');
+}
+
+if (count > 0) {
+    process.exit(1);
+}
diff --git a/node_modules/esprima/esprima.js b/node_modules/esprima/esprima.js
new file mode 100644
index 0000000000000000000000000000000000000000..f1320daf9bd1907f968525e2b3a27e42efc14f3d
--- /dev/null
+++ b/node_modules/esprima/esprima.js
@@ -0,0 +1,3908 @@
+/*
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
+  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
+  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
+  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint bitwise:true plusplus:true */
+/*global esprima:true, define:true, exports:true, window: true,
+throwError: true, createLiteral: true, generateStatement: true,
+parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
+parseFunctionDeclaration: true, parseFunctionExpression: true,
+parseFunctionSourceElements: true, parseVariableIdentifier: true,
+parseLeftHandSideExpression: true,
+parseStatement: true, parseSourceElement: true */
+
+(function (root, factory) {
+    'use strict';
+
+    // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
+    // Rhino, and plain browser loading.
+    if (typeof define === 'function' && define.amd) {
+        define(['exports'], factory);
+    } else if (typeof exports !== 'undefined') {
+        factory(exports);
+    } else {
+        factory((root.esprima = {}));
+    }
+}(this, function (exports) {
+    'use strict';
+
+    var Token,
+        TokenName,
+        Syntax,
+        PropertyKind,
+        Messages,
+        Regex,
+        source,
+        strict,
+        index,
+        lineNumber,
+        lineStart,
+        length,
+        buffer,
+        state,
+        extra;
+
+    Token = {
+        BooleanLiteral: 1,
+        EOF: 2,
+        Identifier: 3,
+        Keyword: 4,
+        NullLiteral: 5,
+        NumericLiteral: 6,
+        Punctuator: 7,
+        StringLiteral: 8
+    };
+
+    TokenName = {};
+    TokenName[Token.BooleanLiteral] = 'Boolean';
+    TokenName[Token.EOF] = '<end>';
+    TokenName[Token.Identifier] = 'Identifier';
+    TokenName[Token.Keyword] = 'Keyword';
+    TokenName[Token.NullLiteral] = 'Null';
+    TokenName[Token.NumericLiteral] = 'Numeric';
+    TokenName[Token.Punctuator] = 'Punctuator';
+    TokenName[Token.StringLiteral] = 'String';
+
+    Syntax = {
+        AssignmentExpression: 'AssignmentExpression',
+        ArrayExpression: 'ArrayExpression',
+        BlockStatement: 'BlockStatement',
+        BinaryExpression: 'BinaryExpression',
+        BreakStatement: 'BreakStatement',
+        CallExpression: 'CallExpression',
+        CatchClause: 'CatchClause',
+        ConditionalExpression: 'ConditionalExpression',
+        ContinueStatement: 'ContinueStatement',
+        DoWhileStatement: 'DoWhileStatement',
+        DebuggerStatement: 'DebuggerStatement',
+        EmptyStatement: 'EmptyStatement',
+        ExpressionStatement: 'ExpressionStatement',
+        ForStatement: 'ForStatement',
+        ForInStatement: 'ForInStatement',
+        FunctionDeclaration: 'FunctionDeclaration',
+        FunctionExpression: 'FunctionExpression',
+        Identifier: 'Identifier',
+        IfStatement: 'IfStatement',
+        Literal: 'Literal',
+        LabeledStatement: 'LabeledStatement',
+        LogicalExpression: 'LogicalExpression',
+        MemberExpression: 'MemberExpression',
+        NewExpression: 'NewExpression',
+        ObjectExpression: 'ObjectExpression',
+        Program: 'Program',
+        Property: 'Property',
+        ReturnStatement: 'ReturnStatement',
+        SequenceExpression: 'SequenceExpression',
+        SwitchStatement: 'SwitchStatement',
+        SwitchCase: 'SwitchCase',
+        ThisExpression: 'ThisExpression',
+        ThrowStatement: 'ThrowStatement',
+        TryStatement: 'TryStatement',
+        UnaryExpression: 'UnaryExpression',
+        UpdateExpression: 'UpdateExpression',
+        VariableDeclaration: 'VariableDeclaration',
+        VariableDeclarator: 'VariableDeclarator',
+        WhileStatement: 'WhileStatement',
+        WithStatement: 'WithStatement'
+    };
+
+    PropertyKind = {
+        Data: 1,
+        Get: 2,
+        Set: 4
+    };
+
+    // Error messages should be identical to V8.
+    Messages = {
+        UnexpectedToken:  'Unexpected token %0',
+        UnexpectedNumber:  'Unexpected number',
+        UnexpectedString:  'Unexpected string',
+        UnexpectedIdentifier:  'Unexpected identifier',
+        UnexpectedReserved:  'Unexpected reserved word',
+        UnexpectedEOS:  'Unexpected end of input',
+        NewlineAfterThrow:  'Illegal newline after throw',
+        InvalidRegExp: 'Invalid regular expression',
+        UnterminatedRegExp:  'Invalid regular expression: missing /',
+        InvalidLHSInAssignment:  'Invalid left-hand side in assignment',
+        InvalidLHSInForIn:  'Invalid left-hand side in for-in',
+        MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
+        NoCatchOrFinally:  'Missing catch or finally after try',
+        UnknownLabel: 'Undefined label \'%0\'',
+        Redeclaration: '%0 \'%1\' has already been declared',
+        IllegalContinue: 'Illegal continue statement',
+        IllegalBreak: 'Illegal break statement',
+        IllegalReturn: 'Illegal return statement',
+        StrictModeWith:  'Strict mode code may not include a with statement',
+        StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',
+        StrictVarName:  'Variable name may not be eval or arguments in strict mode',
+        StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',
+        StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
+        StrictFunctionName:  'Function name may not be eval or arguments in strict mode',
+        StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',
+        StrictDelete:  'Delete of an unqualified identifier in strict mode.',
+        StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',
+        AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',
+        AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',
+        StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',
+        StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',
+        StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',
+        StrictReservedWord:  'Use of future reserved word in strict mode'
+    };
+
+    // See also tools/generate-unicode-regex.py.
+    Regex = {
+        NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
+        NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
+    };
+
+    // Ensure the condition is true, otherwise throw an error.
+    // This is only to have a better contract semantic, i.e. another safety net
+    // to catch a logic error. The condition shall be fulfilled in normal case.
+    // Do NOT use this to enforce a certain condition on any user input.
+
+    function assert(condition, message) {
+        if (!condition) {
+            throw new Error('ASSERT: ' + message);
+        }
+    }
+
+    function sliceSource(from, to) {
+        return source.slice(from, to);
+    }
+
+    if (typeof 'esprima'[0] === 'undefined') {
+        sliceSource = function sliceArraySource(from, to) {
+            return source.slice(from, to).join('');
+        };
+    }
+
+    function isDecimalDigit(ch) {
+        return '0123456789'.indexOf(ch) >= 0;
+    }
+
+    function isHexDigit(ch) {
+        return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
+    }
+
+    function isOctalDigit(ch) {
+        return '01234567'.indexOf(ch) >= 0;
+    }
+
+
+    // 7.2 White Space
+
+    function isWhiteSpace(ch) {
+        return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
+            (ch === '\u000C') || (ch === '\u00A0') ||
+            (ch.charCodeAt(0) >= 0x1680 &&
+             '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
+    }
+
+    // 7.3 Line Terminators
+
+    function isLineTerminator(ch) {
+        return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
+    }
+
+    // 7.6 Identifier Names and Identifiers
+
+    function isIdentifierStart(ch) {
+        return (ch === '$') || (ch === '_') || (ch === '\\') ||
+            (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+            ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
+    }
+
+    function isIdentifierPart(ch) {
+        return (ch === '$') || (ch === '_') || (ch === '\\') ||
+            (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+            ((ch >= '0') && (ch <= '9')) ||
+            ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
+    }
+
+    // 7.6.1.2 Future Reserved Words
+
+    function isFutureReservedWord(id) {
+        switch (id) {
+
+        // Future reserved words.
+        case 'class':
+        case 'enum':
+        case 'export':
+        case 'extends':
+        case 'import':
+        case 'super':
+            return true;
+        }
+
+        return false;
+    }
+
+    function isStrictModeReservedWord(id) {
+        switch (id) {
+
+        // Strict Mode reserved words.
+        case 'implements':
+        case 'interface':
+        case 'package':
+        case 'private':
+        case 'protected':
+        case 'public':
+        case 'static':
+        case 'yield':
+        case 'let':
+            return true;
+        }
+
+        return false;
+    }
+
+    function isRestrictedWord(id) {
+        return id === 'eval' || id === 'arguments';
+    }
+
+    // 7.6.1.1 Keywords
+
+    function isKeyword(id) {
+        var keyword = false;
+        switch (id.length) {
+        case 2:
+            keyword = (id === 'if') || (id === 'in') || (id === 'do');
+            break;
+        case 3:
+            keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
+            break;
+        case 4:
+            keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
+            break;
+        case 5:
+            keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
+            break;
+        case 6:
+            keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
+            break;
+        case 7:
+            keyword = (id === 'default') || (id === 'finally');
+            break;
+        case 8:
+            keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
+            break;
+        case 10:
+            keyword = (id === 'instanceof');
+            break;
+        }
+
+        if (keyword) {
+            return true;
+        }
+
+        switch (id) {
+        // Future reserved words.
+        // 'const' is specialized as Keyword in V8.
+        case 'const':
+            return true;
+
+        // For compatiblity to SpiderMonkey and ES.next
+        case 'yield':
+        case 'let':
+            return true;
+        }
+
+        if (strict && isStrictModeReservedWord(id)) {
+            return true;
+        }
+
+        return isFutureReservedWord(id);
+    }
+
+    // 7.4 Comments
+
+    function skipComment() {
+        var ch, blockComment, lineComment;
+
+        blockComment = false;
+        lineComment = false;
+
+        while (index < length) {
+            ch = source[index];
+
+            if (lineComment) {
+                ch = source[index++];
+                if (isLineTerminator(ch)) {
+                    lineComment = false;
+                    if (ch === '\r' && source[index] === '\n') {
+                        ++index;
+                    }
+                    ++lineNumber;
+                    lineStart = index;
+                }
+            } else if (blockComment) {
+                if (isLineTerminator(ch)) {
+                    if (ch === '\r' && source[index + 1] === '\n') {
+                        ++index;
+                    }
+                    ++lineNumber;
+                    ++index;
+                    lineStart = index;
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                } else {
+                    ch = source[index++];
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                    if (ch === '*') {
+                        ch = source[index];
+                        if (ch === '/') {
+                            ++index;
+                            blockComment = false;
+                        }
+                    }
+                }
+            } else if (ch === '/') {
+                ch = source[index + 1];
+                if (ch === '/') {
+                    index += 2;
+                    lineComment = true;
+                } else if (ch === '*') {
+                    index += 2;
+                    blockComment = true;
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                } else {
+                    break;
+                }
+            } else if (isWhiteSpace(ch)) {
+                ++index;
+            } else if (isLineTerminator(ch)) {
+                ++index;
+                if (ch ===  '\r' && source[index] === '\n') {
+                    ++index;
+                }
+                ++lineNumber;
+                lineStart = index;
+            } else {
+                break;
+            }
+        }
+    }
+
+    function scanHexEscape(prefix) {
+        var i, len, ch, code = 0;
+
+        len = (prefix === 'u') ? 4 : 2;
+        for (i = 0; i < len; ++i) {
+            if (index < length && isHexDigit(source[index])) {
+                ch = source[index++];
+                code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+            } else {
+                return '';
+            }
+        }
+        return String.fromCharCode(code);
+    }
+
+    function scanIdentifier() {
+        var ch, start, id, restore;
+
+        ch = source[index];
+        if (!isIdentifierStart(ch)) {
+            return;
+        }
+
+        start = index;
+        if (ch === '\\') {
+            ++index;
+            if (source[index] !== 'u') {
+                return;
+            }
+            ++index;
+            restore = index;
+            ch = scanHexEscape('u');
+            if (ch) {
+                if (ch === '\\' || !isIdentifierStart(ch)) {
+                    return;
+                }
+                id = ch;
+            } else {
+                index = restore;
+                id = 'u';
+            }
+        } else {
+            id = source[index++];
+        }
+
+        while (index < length) {
+            ch = source[index];
+            if (!isIdentifierPart(ch)) {
+                break;
+            }
+            if (ch === '\\') {
+                ++index;
+                if (source[index] !== 'u') {
+                    return;
+                }
+                ++index;
+                restore = index;
+                ch = scanHexEscape('u');
+                if (ch) {
+                    if (ch === '\\' || !isIdentifierPart(ch)) {
+                        return;
+                    }
+                    id += ch;
+                } else {
+                    index = restore;
+                    id += 'u';
+                }
+            } else {
+                id += source[index++];
+            }
+        }
+
+        // There is no keyword or literal with only one character.
+        // Thus, it must be an identifier.
+        if (id.length === 1) {
+            return {
+                type: Token.Identifier,
+                value: id,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (isKeyword(id)) {
+            return {
+                type: Token.Keyword,
+                value: id,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        // 7.8.1 Null Literals
+
+        if (id === 'null') {
+            return {
+                type: Token.NullLiteral,
+                value: id,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        // 7.8.2 Boolean Literals
+
+        if (id === 'true' || id === 'false') {
+            return {
+                type: Token.BooleanLiteral,
+                value: id,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        return {
+            type: Token.Identifier,
+            value: id,
+            lineNumber: lineNumber,
+            lineStart: lineStart,
+            range: [start, index]
+        };
+    }
+
+    // 7.7 Punctuators
+
+    function scanPunctuator() {
+        var start = index,
+            ch1 = source[index],
+            ch2,
+            ch3,
+            ch4;
+
+        // Check for most common single-character punctuators.
+
+        if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
+            ++index;
+            return {
+                type: Token.Punctuator,
+                value: ch1,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
+            ++index;
+            return {
+                type: Token.Punctuator,
+                value: ch1,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        // Dot (.) can also start a floating-point number, hence the need
+        // to check the next character.
+
+        ch2 = source[index + 1];
+        if (ch1 === '.' && !isDecimalDigit(ch2)) {
+            return {
+                type: Token.Punctuator,
+                value: source[index++],
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        // Peek more characters.
+
+        ch3 = source[index + 2];
+        ch4 = source[index + 3];
+
+        // 4-character punctuator: >>>=
+
+        if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
+            if (ch4 === '=') {
+                index += 4;
+                return {
+                    type: Token.Punctuator,
+                    value: '>>>=',
+                    lineNumber: lineNumber,
+                    lineStart: lineStart,
+                    range: [start, index]
+                };
+            }
+        }
+
+        // 3-character punctuators: === !== >>> <<= >>=
+
+        if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
+            index += 3;
+            return {
+                type: Token.Punctuator,
+                value: '===',
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
+            index += 3;
+            return {
+                type: Token.Punctuator,
+                value: '!==',
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
+            index += 3;
+            return {
+                type: Token.Punctuator,
+                value: '>>>',
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
+            index += 3;
+            return {
+                type: Token.Punctuator,
+                value: '<<=',
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
+            index += 3;
+            return {
+                type: Token.Punctuator,
+                value: '>>=',
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+
+        // 2-character punctuators: <= >= == != ++ -- << >> && ||
+        // += -= *= %= &= |= ^= /=
+
+        if (ch2 === '=') {
+            if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
+                index += 2;
+                return {
+                    type: Token.Punctuator,
+                    value: ch1 + ch2,
+                    lineNumber: lineNumber,
+                    lineStart: lineStart,
+                    range: [start, index]
+                };
+            }
+        }
+
+        if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
+            if ('+-<>&|'.indexOf(ch2) >= 0) {
+                index += 2;
+                return {
+                    type: Token.Punctuator,
+                    value: ch1 + ch2,
+                    lineNumber: lineNumber,
+                    lineStart: lineStart,
+                    range: [start, index]
+                };
+            }
+        }
+
+        // The remaining 1-character punctuators.
+
+        if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
+            return {
+                type: Token.Punctuator,
+                value: source[index++],
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [start, index]
+            };
+        }
+    }
+
+    // 7.8.3 Numeric Literals
+
+    function scanNumericLiteral() {
+        var number, start, ch;
+
+        ch = source[index];
+        assert(isDecimalDigit(ch) || (ch === '.'),
+            'Numeric literal must start with a decimal digit or a decimal point');
+
+        start = index;
+        number = '';
+        if (ch !== '.') {
+            number = source[index++];
+            ch = source[index];
+
+            // Hex number starts with '0x'.
+            // Octal number starts with '0'.
+            if (number === '0') {
+                if (ch === 'x' || ch === 'X') {
+                    number += source[index++];
+                    while (index < length) {
+                        ch = source[index];
+                        if (!isHexDigit(ch)) {
+                            break;
+                        }
+                        number += source[index++];
+                    }
+
+                    if (number.length <= 2) {
+                        // only 0x
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+
+                    if (index < length) {
+                        ch = source[index];
+                        if (isIdentifierStart(ch)) {
+                            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                        }
+                    }
+                    return {
+                        type: Token.NumericLiteral,
+                        value: parseInt(number, 16),
+                        lineNumber: lineNumber,
+                        lineStart: lineStart,
+                        range: [start, index]
+                    };
+                } else if (isOctalDigit(ch)) {
+                    number += source[index++];
+                    while (index < length) {
+                        ch = source[index];
+                        if (!isOctalDigit(ch)) {
+                            break;
+                        }
+                        number += source[index++];
+                    }
+
+                    if (index < length) {
+                        ch = source[index];
+                        if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+                            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                        }
+                    }
+                    return {
+                        type: Token.NumericLiteral,
+                        value: parseInt(number, 8),
+                        octal: true,
+                        lineNumber: lineNumber,
+                        lineStart: lineStart,
+                        range: [start, index]
+                    };
+                }
+
+                // decimal number starts with '0' such as '09' is illegal.
+                if (isDecimalDigit(ch)) {
+                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                }
+            }
+
+            while (index < length) {
+                ch = source[index];
+                if (!isDecimalDigit(ch)) {
+                    break;
+                }
+                number += source[index++];
+            }
+        }
+
+        if (ch === '.') {
+            number += source[index++];
+            while (index < length) {
+                ch = source[index];
+                if (!isDecimalDigit(ch)) {
+                    break;
+                }
+                number += source[index++];
+            }
+        }
+
+        if (ch === 'e' || ch === 'E') {
+            number += source[index++];
+
+            ch = source[index];
+            if (ch === '+' || ch === '-') {
+                number += source[index++];
+            }
+
+            ch = source[index];
+            if (isDecimalDigit(ch)) {
+                number += source[index++];
+                while (index < length) {
+                    ch = source[index];
+                    if (!isDecimalDigit(ch)) {
+                        break;
+                    }
+                    number += source[index++];
+                }
+            } else {
+                ch = 'character ' + ch;
+                if (index >= length) {
+                    ch = '<end>';
+                }
+                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+            }
+        }
+
+        if (index < length) {
+            ch = source[index];
+            if (isIdentifierStart(ch)) {
+                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+            }
+        }
+
+        return {
+            type: Token.NumericLiteral,
+            value: parseFloat(number),
+            lineNumber: lineNumber,
+            lineStart: lineStart,
+            range: [start, index]
+        };
+    }
+
+    // 7.8.4 String Literals
+
+    function scanStringLiteral() {
+        var str = '', quote, start, ch, code, unescaped, restore, octal = false;
+
+        quote = source[index];
+        assert((quote === '\'' || quote === '"'),
+            'String literal must starts with a quote');
+
+        start = index;
+        ++index;
+
+        while (index < length) {
+            ch = source[index++];
+
+            if (ch === quote) {
+                quote = '';
+                break;
+            } else if (ch === '\\') {
+                ch = source[index++];
+                if (!isLineTerminator(ch)) {
+                    switch (ch) {
+                    case 'n':
+                        str += '\n';
+                        break;
+                    case 'r':
+                        str += '\r';
+                        break;
+                    case 't':
+                        str += '\t';
+                        break;
+                    case 'u':
+                    case 'x':
+                        restore = index;
+                        unescaped = scanHexEscape(ch);
+                        if (unescaped) {
+                            str += unescaped;
+                        } else {
+                            index = restore;
+                            str += ch;
+                        }
+                        break;
+                    case 'b':
+                        str += '\b';
+                        break;
+                    case 'f':
+                        str += '\f';
+                        break;
+                    case 'v':
+                        str += '\x0B';
+                        break;
+
+                    default:
+                        if (isOctalDigit(ch)) {
+                            code = '01234567'.indexOf(ch);
+
+                            // \0 is not octal escape sequence
+                            if (code !== 0) {
+                                octal = true;
+                            }
+
+                            if (index < length && isOctalDigit(source[index])) {
+                                octal = true;
+                                code = code * 8 + '01234567'.indexOf(source[index++]);
+
+                                // 3 digits are only allowed when string starts
+                                // with 0, 1, 2, 3
+                                if ('0123'.indexOf(ch) >= 0 &&
+                                        index < length &&
+                                        isOctalDigit(source[index])) {
+                                    code = code * 8 + '01234567'.indexOf(source[index++]);
+                                }
+                            }
+                            str += String.fromCharCode(code);
+                        } else {
+                            str += ch;
+                        }
+                        break;
+                    }
+                } else {
+                    ++lineNumber;
+                    if (ch ===  '\r' && source[index] === '\n') {
+                        ++index;
+                    }
+                }
+            } else if (isLineTerminator(ch)) {
+                break;
+            } else {
+                str += ch;
+            }
+        }
+
+        if (quote !== '') {
+            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+        }
+
+        return {
+            type: Token.StringLiteral,
+            value: str,
+            octal: octal,
+            lineNumber: lineNumber,
+            lineStart: lineStart,
+            range: [start, index]
+        };
+    }
+
+    function scanRegExp() {
+        var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
+
+        buffer = null;
+        skipComment();
+
+        start = index;
+        ch = source[index];
+        assert(ch === '/', 'Regular expression literal must start with a slash');
+        str = source[index++];
+
+        while (index < length) {
+            ch = source[index++];
+            str += ch;
+            if (ch === '\\') {
+                ch = source[index++];
+                // ECMA-262 7.8.5
+                if (isLineTerminator(ch)) {
+                    throwError({}, Messages.UnterminatedRegExp);
+                }
+                str += ch;
+            } else if (classMarker) {
+                if (ch === ']') {
+                    classMarker = false;
+                }
+            } else {
+                if (ch === '/') {
+                    terminated = true;
+                    break;
+                } else if (ch === '[') {
+                    classMarker = true;
+                } else if (isLineTerminator(ch)) {
+                    throwError({}, Messages.UnterminatedRegExp);
+                }
+            }
+        }
+
+        if (!terminated) {
+            throwError({}, Messages.UnterminatedRegExp);
+        }
+
+        // Exclude leading and trailing slash.
+        pattern = str.substr(1, str.length - 2);
+
+        flags = '';
+        while (index < length) {
+            ch = source[index];
+            if (!isIdentifierPart(ch)) {
+                break;
+            }
+
+            ++index;
+            if (ch === '\\' && index < length) {
+                ch = source[index];
+                if (ch === 'u') {
+                    ++index;
+                    restore = index;
+                    ch = scanHexEscape('u');
+                    if (ch) {
+                        flags += ch;
+                        str += '\\u';
+                        for (; restore < index; ++restore) {
+                            str += source[restore];
+                        }
+                    } else {
+                        index = restore;
+                        flags += 'u';
+                        str += '\\u';
+                    }
+                } else {
+                    str += '\\';
+                }
+            } else {
+                flags += ch;
+                str += ch;
+            }
+        }
+
+        try {
+            value = new RegExp(pattern, flags);
+        } catch (e) {
+            throwError({}, Messages.InvalidRegExp);
+        }
+
+        return {
+            literal: str,
+            value: value,
+            range: [start, index]
+        };
+    }
+
+    function isIdentifierName(token) {
+        return token.type === Token.Identifier ||
+            token.type === Token.Keyword ||
+            token.type === Token.BooleanLiteral ||
+            token.type === Token.NullLiteral;
+    }
+
+    function advance() {
+        var ch, token;
+
+        skipComment();
+
+        if (index >= length) {
+            return {
+                type: Token.EOF,
+                lineNumber: lineNumber,
+                lineStart: lineStart,
+                range: [index, index]
+            };
+        }
+
+        token = scanPunctuator();
+        if (typeof token !== 'undefined') {
+            return token;
+        }
+
+        ch = source[index];
+
+        if (ch === '\'' || ch === '"') {
+            return scanStringLiteral();
+        }
+
+        if (ch === '.' || isDecimalDigit(ch)) {
+            return scanNumericLiteral();
+        }
+
+        token = scanIdentifier();
+        if (typeof token !== 'undefined') {
+            return token;
+        }
+
+        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+    }
+
+    function lex() {
+        var token;
+
+        if (buffer) {
+            index = buffer.range[1];
+            lineNumber = buffer.lineNumber;
+            lineStart = buffer.lineStart;
+            token = buffer;
+            buffer = null;
+            return token;
+        }
+
+        buffer = null;
+        return advance();
+    }
+
+    function lookahead() {
+        var pos, line, start;
+
+        if (buffer !== null) {
+            return buffer;
+        }
+
+        pos = index;
+        line = lineNumber;
+        start = lineStart;
+        buffer = advance();
+        index = pos;
+        lineNumber = line;
+        lineStart = start;
+
+        return buffer;
+    }
+
+    // Return true if there is a line terminator before the next token.
+
+    function peekLineTerminator() {
+        var pos, line, start, found;
+
+        pos = index;
+        line = lineNumber;
+        start = lineStart;
+        skipComment();
+        found = lineNumber !== line;
+        index = pos;
+        lineNumber = line;
+        lineStart = start;
+
+        return found;
+    }
+
+    // Throw an exception
+
+    function throwError(token, messageFormat) {
+        var error,
+            args = Array.prototype.slice.call(arguments, 2),
+            msg = messageFormat.replace(
+                /%(\d)/g,
+                function (whole, index) {
+                    return args[index] || '';
+                }
+            );
+
+        if (typeof token.lineNumber === 'number') {
+            error = new Error('Line ' + token.lineNumber + ': ' + msg);
+            error.index = token.range[0];
+            error.lineNumber = token.lineNumber;
+            error.column = token.range[0] - lineStart + 1;
+        } else {
+            error = new Error('Line ' + lineNumber + ': ' + msg);
+            error.index = index;
+            error.lineNumber = lineNumber;
+            error.column = index - lineStart + 1;
+        }
+
+        throw error;
+    }
+
+    function throwErrorTolerant() {
+        try {
+            throwError.apply(null, arguments);
+        } catch (e) {
+            if (extra.errors) {
+                extra.errors.push(e);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+
+    // Throw an exception because of the token.
+
+    function throwUnexpected(token) {
+        if (token.type === Token.EOF) {
+            throwError(token, Messages.UnexpectedEOS);
+        }
+
+        if (token.type === Token.NumericLiteral) {
+            throwError(token, Messages.UnexpectedNumber);
+        }
+
+        if (token.type === Token.StringLiteral) {
+            throwError(token, Messages.UnexpectedString);
+        }
+
+        if (token.type === Token.Identifier) {
+            throwError(token, Messages.UnexpectedIdentifier);
+        }
+
+        if (token.type === Token.Keyword) {
+            if (isFutureReservedWord(token.value)) {
+                throwError(token, Messages.UnexpectedReserved);
+            } else if (strict && isStrictModeReservedWord(token.value)) {
+                throwErrorTolerant(token, Messages.StrictReservedWord);
+                return;
+            }
+            throwError(token, Messages.UnexpectedToken, token.value);
+        }
+
+        // BooleanLiteral, NullLiteral, or Punctuator.
+        throwError(token, Messages.UnexpectedToken, token.value);
+    }
+
+    // Expect the next token to match the specified punctuator.
+    // If not, an exception will be thrown.
+
+    function expect(value) {
+        var token = lex();
+        if (token.type !== Token.Punctuator || token.value !== value) {
+            throwUnexpected(token);
+        }
+    }
+
+    // Expect the next token to match the specified keyword.
+    // If not, an exception will be thrown.
+
+    function expectKeyword(keyword) {
+        var token = lex();
+        if (token.type !== Token.Keyword || token.value !== keyword) {
+            throwUnexpected(token);
+        }
+    }
+
+    // Return true if the next token matches the specified punctuator.
+
+    function match(value) {
+        var token = lookahead();
+        return token.type === Token.Punctuator && token.value === value;
+    }
+
+    // Return true if the next token matches the specified keyword
+
+    function matchKeyword(keyword) {
+        var token = lookahead();
+        return token.type === Token.Keyword && token.value === keyword;
+    }
+
+    // Return true if the next token is an assignment operator
+
+    function matchAssign() {
+        var token = lookahead(),
+            op = token.value;
+
+        if (token.type !== Token.Punctuator) {
+            return false;
+        }
+        return op === '=' ||
+            op === '*=' ||
+            op === '/=' ||
+            op === '%=' ||
+            op === '+=' ||
+            op === '-=' ||
+            op === '<<=' ||
+            op === '>>=' ||
+            op === '>>>=' ||
+            op === '&=' ||
+            op === '^=' ||
+            op === '|=';
+    }
+
+    function consumeSemicolon() {
+        var token, line;
+
+        // Catch the very common case first.
+        if (source[index] === ';') {
+            lex();
+            return;
+        }
+
+        line = lineNumber;
+        skipComment();
+        if (lineNumber !== line) {
+            return;
+        }
+
+        if (match(';')) {
+            lex();
+            return;
+        }
+
+        token = lookahead();
+        if (token.type !== Token.EOF && !match('}')) {
+            throwUnexpected(token);
+        }
+    }
+
+    // Return true if provided expression is LeftHandSideExpression
+
+    function isLeftHandSide(expr) {
+        return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
+    }
+
+    // 11.1.4 Array Initialiser
+
+    function parseArrayInitialiser() {
+        var elements = [];
+
+        expect('[');
+
+        while (!match(']')) {
+            if (match(',')) {
+                lex();
+                elements.push(null);
+            } else {
+                elements.push(parseAssignmentExpression());
+
+                if (!match(']')) {
+                    expect(',');
+                }
+            }
+        }
+
+        expect(']');
+
+        return {
+            type: Syntax.ArrayExpression,
+            elements: elements
+        };
+    }
+
+    // 11.1.5 Object Initialiser
+
+    function parsePropertyFunction(param, first) {
+        var previousStrict, body;
+
+        previousStrict = strict;
+        body = parseFunctionSourceElements();
+        if (first && strict && isRestrictedWord(param[0].name)) {
+            throwErrorTolerant(first, Messages.StrictParamName);
+        }
+        strict = previousStrict;
+
+        return {
+            type: Syntax.FunctionExpression,
+            id: null,
+            params: param,
+            defaults: [],
+            body: body,
+            rest: null,
+            generator: false,
+            expression: false
+        };
+    }
+
+    function parseObjectPropertyKey() {
+        var token = lex();
+
+        // Note: This function is called only from parseObjectProperty(), where
+        // EOF and Punctuator tokens are already filtered out.
+
+        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
+            if (strict && token.octal) {
+                throwErrorTolerant(token, Messages.StrictOctalLiteral);
+            }
+            return createLiteral(token);
+        }
+
+        return {
+            type: Syntax.Identifier,
+            name: token.value
+        };
+    }
+
+    function parseObjectProperty() {
+        var token, key, id, param;
+
+        token = lookahead();
+
+        if (token.type === Token.Identifier) {
+
+            id = parseObjectPropertyKey();
+
+            // Property Assignment: Getter and Setter.
+
+            if (token.value === 'get' && !match(':')) {
+                key = parseObjectPropertyKey();
+                expect('(');
+                expect(')');
+                return {
+                    type: Syntax.Property,
+                    key: key,
+                    value: parsePropertyFunction([]),
+                    kind: 'get'
+                };
+            } else if (token.value === 'set' && !match(':')) {
+                key = parseObjectPropertyKey();
+                expect('(');
+                token = lookahead();
+                if (token.type !== Token.Identifier) {
+                    expect(')');
+                    throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
+                    return {
+                        type: Syntax.Property,
+                        key: key,
+                        value: parsePropertyFunction([]),
+                        kind: 'set'
+                    };
+                } else {
+                    param = [ parseVariableIdentifier() ];
+                    expect(')');
+                    return {
+                        type: Syntax.Property,
+                        key: key,
+                        value: parsePropertyFunction(param, token),
+                        kind: 'set'
+                    };
+                }
+            } else {
+                expect(':');
+                return {
+                    type: Syntax.Property,
+                    key: id,
+                    value: parseAssignmentExpression(),
+                    kind: 'init'
+                };
+            }
+        } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
+            throwUnexpected(token);
+        } else {
+            key = parseObjectPropertyKey();
+            expect(':');
+            return {
+                type: Syntax.Property,
+                key: key,
+                value: parseAssignmentExpression(),
+                kind: 'init'
+            };
+        }
+    }
+
+    function parseObjectInitialiser() {
+        var properties = [], property, name, kind, map = {}, toString = String;
+
+        expect('{');
+
+        while (!match('}')) {
+            property = parseObjectProperty();
+
+            if (property.key.type === Syntax.Identifier) {
+                name = property.key.name;
+            } else {
+                name = toString(property.key.value);
+            }
+            kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
+            if (Object.prototype.hasOwnProperty.call(map, name)) {
+                if (map[name] === PropertyKind.Data) {
+                    if (strict && kind === PropertyKind.Data) {
+                        throwErrorTolerant({}, Messages.StrictDuplicateProperty);
+                    } else if (kind !== PropertyKind.Data) {
+                        throwErrorTolerant({}, Messages.AccessorDataProperty);
+                    }
+                } else {
+                    if (kind === PropertyKind.Data) {
+                        throwErrorTolerant({}, Messages.AccessorDataProperty);
+                    } else if (map[name] & kind) {
+                        throwErrorTolerant({}, Messages.AccessorGetSet);
+                    }
+                }
+                map[name] |= kind;
+            } else {
+                map[name] = kind;
+            }
+
+            properties.push(property);
+
+            if (!match('}')) {
+                expect(',');
+            }
+        }
+
+        expect('}');
+
+        return {
+            type: Syntax.ObjectExpression,
+            properties: properties
+        };
+    }
+
+    // 11.1.6 The Grouping Operator
+
+    function parseGroupExpression() {
+        var expr;
+
+        expect('(');
+
+        expr = parseExpression();
+
+        expect(')');
+
+        return expr;
+    }
+
+
+    // 11.1 Primary Expressions
+
+    function parsePrimaryExpression() {
+        var token = lookahead(),
+            type = token.type;
+
+        if (type === Token.Identifier) {
+            return {
+                type: Syntax.Identifier,
+                name: lex().value
+            };
+        }
+
+        if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+            if (strict && token.octal) {
+                throwErrorTolerant(token, Messages.StrictOctalLiteral);
+            }
+            return createLiteral(lex());
+        }
+
+        if (type === Token.Keyword) {
+            if (matchKeyword('this')) {
+                lex();
+                return {
+                    type: Syntax.ThisExpression
+                };
+            }
+
+            if (matchKeyword('function')) {
+                return parseFunctionExpression();
+            }
+        }
+
+        if (type === Token.BooleanLiteral) {
+            lex();
+            token.value = (token.value === 'true');
+            return createLiteral(token);
+        }
+
+        if (type === Token.NullLiteral) {
+            lex();
+            token.value = null;
+            return createLiteral(token);
+        }
+
+        if (match('[')) {
+            return parseArrayInitialiser();
+        }
+
+        if (match('{')) {
+            return parseObjectInitialiser();
+        }
+
+        if (match('(')) {
+            return parseGroupExpression();
+        }
+
+        if (match('/') || match('/=')) {
+            return createLiteral(scanRegExp());
+        }
+
+        return throwUnexpected(lex());
+    }
+
+    // 11.2 Left-Hand-Side Expressions
+
+    function parseArguments() {
+        var args = [];
+
+        expect('(');
+
+        if (!match(')')) {
+            while (index < length) {
+                args.push(parseAssignmentExpression());
+                if (match(')')) {
+                    break;
+                }
+                expect(',');
+            }
+        }
+
+        expect(')');
+
+        return args;
+    }
+
+    function parseNonComputedProperty() {
+        var token = lex();
+
+        if (!isIdentifierName(token)) {
+            throwUnexpected(token);
+        }
+
+        return {
+            type: Syntax.Identifier,
+            name: token.value
+        };
+    }
+
+    function parseNonComputedMember() {
+        expect('.');
+
+        return parseNonComputedProperty();
+    }
+
+    function parseComputedMember() {
+        var expr;
+
+        expect('[');
+
+        expr = parseExpression();
+
+        expect(']');
+
+        return expr;
+    }
+
+    function parseNewExpression() {
+        var expr;
+
+        expectKeyword('new');
+
+        expr = {
+            type: Syntax.NewExpression,
+            callee: parseLeftHandSideExpression(),
+            'arguments': []
+        };
+
+        if (match('(')) {
+            expr['arguments'] = parseArguments();
+        }
+
+        return expr;
+    }
+
+    function parseLeftHandSideExpressionAllowCall() {
+        var expr;
+
+        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+        while (match('.') || match('[') || match('(')) {
+            if (match('(')) {
+                expr = {
+                    type: Syntax.CallExpression,
+                    callee: expr,
+                    'arguments': parseArguments()
+                };
+            } else if (match('[')) {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: true,
+                    object: expr,
+                    property: parseComputedMember()
+                };
+            } else {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: false,
+                    object: expr,
+                    property: parseNonComputedMember()
+                };
+            }
+        }
+
+        return expr;
+    }
+
+
+    function parseLeftHandSideExpression() {
+        var expr;
+
+        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+        while (match('.') || match('[')) {
+            if (match('[')) {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: true,
+                    object: expr,
+                    property: parseComputedMember()
+                };
+            } else {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: false,
+                    object: expr,
+                    property: parseNonComputedMember()
+                };
+            }
+        }
+
+        return expr;
+    }
+
+    // 11.3 Postfix Expressions
+
+    function parsePostfixExpression() {
+        var expr = parseLeftHandSideExpressionAllowCall(), token;
+
+        token = lookahead();
+        if (token.type !== Token.Punctuator) {
+            return expr;
+        }
+
+        if ((match('++') || match('--')) && !peekLineTerminator()) {
+            // 11.3.1, 11.3.2
+            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+                throwErrorTolerant({}, Messages.StrictLHSPostfix);
+            }
+            if (!isLeftHandSide(expr)) {
+                throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+            }
+
+            expr = {
+                type: Syntax.UpdateExpression,
+                operator: lex().value,
+                argument: expr,
+                prefix: false
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.4 Unary Operators
+
+    function parseUnaryExpression() {
+        var token, expr;
+
+        token = lookahead();
+        if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
+            return parsePostfixExpression();
+        }
+
+        if (match('++') || match('--')) {
+            token = lex();
+            expr = parseUnaryExpression();
+            // 11.4.4, 11.4.5
+            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+                throwErrorTolerant({}, Messages.StrictLHSPrefix);
+            }
+
+            if (!isLeftHandSide(expr)) {
+                throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+            }
+
+            expr = {
+                type: Syntax.UpdateExpression,
+                operator: token.value,
+                argument: expr,
+                prefix: true
+            };
+            return expr;
+        }
+
+        if (match('+') || match('-') || match('~') || match('!')) {
+            expr = {
+                type: Syntax.UnaryExpression,
+                operator: lex().value,
+                argument: parseUnaryExpression(),
+                prefix: true
+            };
+            return expr;
+        }
+
+        if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+            expr = {
+                type: Syntax.UnaryExpression,
+                operator: lex().value,
+                argument: parseUnaryExpression(),
+                prefix: true
+            };
+            if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
+                throwErrorTolerant({}, Messages.StrictDelete);
+            }
+            return expr;
+        }
+
+        return parsePostfixExpression();
+    }
+
+    // 11.5 Multiplicative Operators
+
+    function parseMultiplicativeExpression() {
+        var expr = parseUnaryExpression();
+
+        while (match('*') || match('/') || match('%')) {
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseUnaryExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.6 Additive Operators
+
+    function parseAdditiveExpression() {
+        var expr = parseMultiplicativeExpression();
+
+        while (match('+') || match('-')) {
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseMultiplicativeExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.7 Bitwise Shift Operators
+
+    function parseShiftExpression() {
+        var expr = parseAdditiveExpression();
+
+        while (match('<<') || match('>>') || match('>>>')) {
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseAdditiveExpression()
+            };
+        }
+
+        return expr;
+    }
+    // 11.8 Relational Operators
+
+    function parseRelationalExpression() {
+        var expr, previousAllowIn;
+
+        previousAllowIn = state.allowIn;
+        state.allowIn = true;
+
+        expr = parseShiftExpression();
+
+        while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseShiftExpression()
+            };
+        }
+
+        state.allowIn = previousAllowIn;
+        return expr;
+    }
+
+    // 11.9 Equality Operators
+
+    function parseEqualityExpression() {
+        var expr = parseRelationalExpression();
+
+        while (match('==') || match('!=') || match('===') || match('!==')) {
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseRelationalExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.10 Binary Bitwise Operators
+
+    function parseBitwiseANDExpression() {
+        var expr = parseEqualityExpression();
+
+        while (match('&')) {
+            lex();
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: '&',
+                left: expr,
+                right: parseEqualityExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    function parseBitwiseXORExpression() {
+        var expr = parseBitwiseANDExpression();
+
+        while (match('^')) {
+            lex();
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: '^',
+                left: expr,
+                right: parseBitwiseANDExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    function parseBitwiseORExpression() {
+        var expr = parseBitwiseXORExpression();
+
+        while (match('|')) {
+            lex();
+            expr = {
+                type: Syntax.BinaryExpression,
+                operator: '|',
+                left: expr,
+                right: parseBitwiseXORExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.11 Binary Logical Operators
+
+    function parseLogicalANDExpression() {
+        var expr = parseBitwiseORExpression();
+
+        while (match('&&')) {
+            lex();
+            expr = {
+                type: Syntax.LogicalExpression,
+                operator: '&&',
+                left: expr,
+                right: parseBitwiseORExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    function parseLogicalORExpression() {
+        var expr = parseLogicalANDExpression();
+
+        while (match('||')) {
+            lex();
+            expr = {
+                type: Syntax.LogicalExpression,
+                operator: '||',
+                left: expr,
+                right: parseLogicalANDExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.12 Conditional Operator
+
+    function parseConditionalExpression() {
+        var expr, previousAllowIn, consequent;
+
+        expr = parseLogicalORExpression();
+
+        if (match('?')) {
+            lex();
+            previousAllowIn = state.allowIn;
+            state.allowIn = true;
+            consequent = parseAssignmentExpression();
+            state.allowIn = previousAllowIn;
+            expect(':');
+
+            expr = {
+                type: Syntax.ConditionalExpression,
+                test: expr,
+                consequent: consequent,
+                alternate: parseAssignmentExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.13 Assignment Operators
+
+    function parseAssignmentExpression() {
+        var token, expr;
+
+        token = lookahead();
+        expr = parseConditionalExpression();
+
+        if (matchAssign()) {
+            // LeftHandSideExpression
+            if (!isLeftHandSide(expr)) {
+                throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
+            }
+
+            // 11.13.1
+            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+                throwErrorTolerant(token, Messages.StrictLHSAssignment);
+            }
+
+            expr = {
+                type: Syntax.AssignmentExpression,
+                operator: lex().value,
+                left: expr,
+                right: parseAssignmentExpression()
+            };
+        }
+
+        return expr;
+    }
+
+    // 11.14 Comma Operator
+
+    function parseExpression() {
+        var expr = parseAssignmentExpression();
+
+        if (match(',')) {
+            expr = {
+                type: Syntax.SequenceExpression,
+                expressions: [ expr ]
+            };
+
+            while (index < length) {
+                if (!match(',')) {
+                    break;
+                }
+                lex();
+                expr.expressions.push(parseAssignmentExpression());
+            }
+
+        }
+        return expr;
+    }
+
+    // 12.1 Block
+
+    function parseStatementList() {
+        var list = [],
+            statement;
+
+        while (index < length) {
+            if (match('}')) {
+                break;
+            }
+            statement = parseSourceElement();
+            if (typeof statement === 'undefined') {
+                break;
+            }
+            list.push(statement);
+        }
+
+        return list;
+    }
+
+    function parseBlock() {
+        var block;
+
+        expect('{');
+
+        block = parseStatementList();
+
+        expect('}');
+
+        return {
+            type: Syntax.BlockStatement,
+            body: block
+        };
+    }
+
+    // 12.2 Variable Statement
+
+    function parseVariableIdentifier() {
+        var token = lex();
+
+        if (token.type !== Token.Identifier) {
+            throwUnexpected(token);
+        }
+
+        return {
+            type: Syntax.Identifier,
+            name: token.value
+        };
+    }
+
+    function parseVariableDeclaration(kind) {
+        var id = parseVariableIdentifier(),
+            init = null;
+
+        // 12.2.1
+        if (strict && isRestrictedWord(id.name)) {
+            throwErrorTolerant({}, Messages.StrictVarName);
+        }
+
+        if (kind === 'const') {
+            expect('=');
+            init = parseAssignmentExpression();
+        } else if (match('=')) {
+            lex();
+            init = parseAssignmentExpression();
+        }
+
+        return {
+            type: Syntax.VariableDeclarator,
+            id: id,
+            init: init
+        };
+    }
+
+    function parseVariableDeclarationList(kind) {
+        var list = [];
+
+        do {
+            list.push(parseVariableDeclaration(kind));
+            if (!match(',')) {
+                break;
+            }
+            lex();
+        } while (index < length);
+
+        return list;
+    }
+
+    function parseVariableStatement() {
+        var declarations;
+
+        expectKeyword('var');
+
+        declarations = parseVariableDeclarationList();
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.VariableDeclaration,
+            declarations: declarations,
+            kind: 'var'
+        };
+    }
+
+    // kind may be `const` or `let`
+    // Both are experimental and not in the specification yet.
+    // see http://wiki.ecmascript.org/doku.php?id=harmony:const
+    // and http://wiki.ecmascript.org/doku.php?id=harmony:let
+    function parseConstLetDeclaration(kind) {
+        var declarations;
+
+        expectKeyword(kind);
+
+        declarations = parseVariableDeclarationList(kind);
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.VariableDeclaration,
+            declarations: declarations,
+            kind: kind
+        };
+    }
+
+    // 12.3 Empty Statement
+
+    function parseEmptyStatement() {
+        expect(';');
+
+        return {
+            type: Syntax.EmptyStatement
+        };
+    }
+
+    // 12.4 Expression Statement
+
+    function parseExpressionStatement() {
+        var expr = parseExpression();
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.ExpressionStatement,
+            expression: expr
+        };
+    }
+
+    // 12.5 If statement
+
+    function parseIfStatement() {
+        var test, consequent, alternate;
+
+        expectKeyword('if');
+
+        expect('(');
+
+        test = parseExpression();
+
+        expect(')');
+
+        consequent = parseStatement();
+
+        if (matchKeyword('else')) {
+            lex();
+            alternate = parseStatement();
+        } else {
+            alternate = null;
+        }
+
+        return {
+            type: Syntax.IfStatement,
+            test: test,
+            consequent: consequent,
+            alternate: alternate
+        };
+    }
+
+    // 12.6 Iteration Statements
+
+    function parseDoWhileStatement() {
+        var body, test, oldInIteration;
+
+        expectKeyword('do');
+
+        oldInIteration = state.inIteration;
+        state.inIteration = true;
+
+        body = parseStatement();
+
+        state.inIteration = oldInIteration;
+
+        expectKeyword('while');
+
+        expect('(');
+
+        test = parseExpression();
+
+        expect(')');
+
+        if (match(';')) {
+            lex();
+        }
+
+        return {
+            type: Syntax.DoWhileStatement,
+            body: body,
+            test: test
+        };
+    }
+
+    function parseWhileStatement() {
+        var test, body, oldInIteration;
+
+        expectKeyword('while');
+
+        expect('(');
+
+        test = parseExpression();
+
+        expect(')');
+
+        oldInIteration = state.inIteration;
+        state.inIteration = true;
+
+        body = parseStatement();
+
+        state.inIteration = oldInIteration;
+
+        return {
+            type: Syntax.WhileStatement,
+            test: test,
+            body: body
+        };
+    }
+
+    function parseForVariableDeclaration() {
+        var token = lex();
+
+        return {
+            type: Syntax.VariableDeclaration,
+            declarations: parseVariableDeclarationList(),
+            kind: token.value
+        };
+    }
+
+    function parseForStatement() {
+        var init, test, update, left, right, body, oldInIteration;
+
+        init = test = update = null;
+
+        expectKeyword('for');
+
+        expect('(');
+
+        if (match(';')) {
+            lex();
+        } else {
+            if (matchKeyword('var') || matchKeyword('let')) {
+                state.allowIn = false;
+                init = parseForVariableDeclaration();
+                state.allowIn = true;
+
+                if (init.declarations.length === 1 && matchKeyword('in')) {
+                    lex();
+                    left = init;
+                    right = parseExpression();
+                    init = null;
+                }
+            } else {
+                state.allowIn = false;
+                init = parseExpression();
+                state.allowIn = true;
+
+                if (matchKeyword('in')) {
+                    // LeftHandSideExpression
+                    if (!isLeftHandSide(init)) {
+                        throwErrorTolerant({}, Messages.InvalidLHSInForIn);
+                    }
+
+                    lex();
+                    left = init;
+                    right = parseExpression();
+                    init = null;
+                }
+            }
+
+            if (typeof left === 'undefined') {
+                expect(';');
+            }
+        }
+
+        if (typeof left === 'undefined') {
+
+            if (!match(';')) {
+                test = parseExpression();
+            }
+            expect(';');
+
+            if (!match(')')) {
+                update = parseExpression();
+            }
+        }
+
+        expect(')');
+
+        oldInIteration = state.inIteration;
+        state.inIteration = true;
+
+        body = parseStatement();
+
+        state.inIteration = oldInIteration;
+
+        if (typeof left === 'undefined') {
+            return {
+                type: Syntax.ForStatement,
+                init: init,
+                test: test,
+                update: update,
+                body: body
+            };
+        }
+
+        return {
+            type: Syntax.ForInStatement,
+            left: left,
+            right: right,
+            body: body,
+            each: false
+        };
+    }
+
+    // 12.7 The continue statement
+
+    function parseContinueStatement() {
+        var token, label = null;
+
+        expectKeyword('continue');
+
+        // Optimize the most common form: 'continue;'.
+        if (source[index] === ';') {
+            lex();
+
+            if (!state.inIteration) {
+                throwError({}, Messages.IllegalContinue);
+            }
+
+            return {
+                type: Syntax.ContinueStatement,
+                label: null
+            };
+        }
+
+        if (peekLineTerminator()) {
+            if (!state.inIteration) {
+                throwError({}, Messages.IllegalContinue);
+            }
+
+            return {
+                type: Syntax.ContinueStatement,
+                label: null
+            };
+        }
+
+        token = lookahead();
+        if (token.type === Token.Identifier) {
+            label = parseVariableIdentifier();
+
+            if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
+                throwError({}, Messages.UnknownLabel, label.name);
+            }
+        }
+
+        consumeSemicolon();
+
+        if (label === null && !state.inIteration) {
+            throwError({}, Messages.IllegalContinue);
+        }
+
+        return {
+            type: Syntax.ContinueStatement,
+            label: label
+        };
+    }
+
+    // 12.8 The break statement
+
+    function parseBreakStatement() {
+        var token, label = null;
+
+        expectKeyword('break');
+
+        // Optimize the most common form: 'break;'.
+        if (source[index] === ';') {
+            lex();
+
+            if (!(state.inIteration || state.inSwitch)) {
+                throwError({}, Messages.IllegalBreak);
+            }
+
+            return {
+                type: Syntax.BreakStatement,
+                label: null
+            };
+        }
+
+        if (peekLineTerminator()) {
+            if (!(state.inIteration || state.inSwitch)) {
+                throwError({}, Messages.IllegalBreak);
+            }
+
+            return {
+                type: Syntax.BreakStatement,
+                label: null
+            };
+        }
+
+        token = lookahead();
+        if (token.type === Token.Identifier) {
+            label = parseVariableIdentifier();
+
+            if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
+                throwError({}, Messages.UnknownLabel, label.name);
+            }
+        }
+
+        consumeSemicolon();
+
+        if (label === null && !(state.inIteration || state.inSwitch)) {
+            throwError({}, Messages.IllegalBreak);
+        }
+
+        return {
+            type: Syntax.BreakStatement,
+            label: label
+        };
+    }
+
+    // 12.9 The return statement
+
+    function parseReturnStatement() {
+        var token, argument = null;
+
+        expectKeyword('return');
+
+        if (!state.inFunctionBody) {
+            throwErrorTolerant({}, Messages.IllegalReturn);
+        }
+
+        // 'return' followed by a space and an identifier is very common.
+        if (source[index] === ' ') {
+            if (isIdentifierStart(source[index + 1])) {
+                argument = parseExpression();
+                consumeSemicolon();
+                return {
+                    type: Syntax.ReturnStatement,
+                    argument: argument
+                };
+            }
+        }
+
+        if (peekLineTerminator()) {
+            return {
+                type: Syntax.ReturnStatement,
+                argument: null
+            };
+        }
+
+        if (!match(';')) {
+            token = lookahead();
+            if (!match('}') && token.type !== Token.EOF) {
+                argument = parseExpression();
+            }
+        }
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.ReturnStatement,
+            argument: argument
+        };
+    }
+
+    // 12.10 The with statement
+
+    function parseWithStatement() {
+        var object, body;
+
+        if (strict) {
+            throwErrorTolerant({}, Messages.StrictModeWith);
+        }
+
+        expectKeyword('with');
+
+        expect('(');
+
+        object = parseExpression();
+
+        expect(')');
+
+        body = parseStatement();
+
+        return {
+            type: Syntax.WithStatement,
+            object: object,
+            body: body
+        };
+    }
+
+    // 12.10 The swith statement
+
+    function parseSwitchCase() {
+        var test,
+            consequent = [],
+            statement;
+
+        if (matchKeyword('default')) {
+            lex();
+            test = null;
+        } else {
+            expectKeyword('case');
+            test = parseExpression();
+        }
+        expect(':');
+
+        while (index < length) {
+            if (match('}') || matchKeyword('default') || matchKeyword('case')) {
+                break;
+            }
+            statement = parseStatement();
+            if (typeof statement === 'undefined') {
+                break;
+            }
+            consequent.push(statement);
+        }
+
+        return {
+            type: Syntax.SwitchCase,
+            test: test,
+            consequent: consequent
+        };
+    }
+
+    function parseSwitchStatement() {
+        var discriminant, cases, clause, oldInSwitch, defaultFound;
+
+        expectKeyword('switch');
+
+        expect('(');
+
+        discriminant = parseExpression();
+
+        expect(')');
+
+        expect('{');
+
+        cases = [];
+
+        if (match('}')) {
+            lex();
+            return {
+                type: Syntax.SwitchStatement,
+                discriminant: discriminant,
+                cases: cases
+            };
+        }
+
+        oldInSwitch = state.inSwitch;
+        state.inSwitch = true;
+        defaultFound = false;
+
+        while (index < length) {
+            if (match('}')) {
+                break;
+            }
+            clause = parseSwitchCase();
+            if (clause.test === null) {
+                if (defaultFound) {
+                    throwError({}, Messages.MultipleDefaultsInSwitch);
+                }
+                defaultFound = true;
+            }
+            cases.push(clause);
+        }
+
+        state.inSwitch = oldInSwitch;
+
+        expect('}');
+
+        return {
+            type: Syntax.SwitchStatement,
+            discriminant: discriminant,
+            cases: cases
+        };
+    }
+
+    // 12.13 The throw statement
+
+    function parseThrowStatement() {
+        var argument;
+
+        expectKeyword('throw');
+
+        if (peekLineTerminator()) {
+            throwError({}, Messages.NewlineAfterThrow);
+        }
+
+        argument = parseExpression();
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.ThrowStatement,
+            argument: argument
+        };
+    }
+
+    // 12.14 The try statement
+
+    function parseCatchClause() {
+        var param;
+
+        expectKeyword('catch');
+
+        expect('(');
+        if (match(')')) {
+            throwUnexpected(lookahead());
+        }
+
+        param = parseVariableIdentifier();
+        // 12.14.1
+        if (strict && isRestrictedWord(param.name)) {
+            throwErrorTolerant({}, Messages.StrictCatchVariable);
+        }
+
+        expect(')');
+
+        return {
+            type: Syntax.CatchClause,
+            param: param,
+            body: parseBlock()
+        };
+    }
+
+    function parseTryStatement() {
+        var block, handlers = [], finalizer = null;
+
+        expectKeyword('try');
+
+        block = parseBlock();
+
+        if (matchKeyword('catch')) {
+            handlers.push(parseCatchClause());
+        }
+
+        if (matchKeyword('finally')) {
+            lex();
+            finalizer = parseBlock();
+        }
+
+        if (handlers.length === 0 && !finalizer) {
+            throwError({}, Messages.NoCatchOrFinally);
+        }
+
+        return {
+            type: Syntax.TryStatement,
+            block: block,
+            guardedHandlers: [],
+            handlers: handlers,
+            finalizer: finalizer
+        };
+    }
+
+    // 12.15 The debugger statement
+
+    function parseDebuggerStatement() {
+        expectKeyword('debugger');
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.DebuggerStatement
+        };
+    }
+
+    // 12 Statements
+
+    function parseStatement() {
+        var token = lookahead(),
+            expr,
+            labeledBody;
+
+        if (token.type === Token.EOF) {
+            throwUnexpected(token);
+        }
+
+        if (token.type === Token.Punctuator) {
+            switch (token.value) {
+            case ';':
+                return parseEmptyStatement();
+            case '{':
+                return parseBlock();
+            case '(':
+                return parseExpressionStatement();
+            default:
+                break;
+            }
+        }
+
+        if (token.type === Token.Keyword) {
+            switch (token.value) {
+            case 'break':
+                return parseBreakStatement();
+            case 'continue':
+                return parseContinueStatement();
+            case 'debugger':
+                return parseDebuggerStatement();
+            case 'do':
+                return parseDoWhileStatement();
+            case 'for':
+                return parseForStatement();
+            case 'function':
+                return parseFunctionDeclaration();
+            case 'if':
+                return parseIfStatement();
+            case 'return':
+                return parseReturnStatement();
+            case 'switch':
+                return parseSwitchStatement();
+            case 'throw':
+                return parseThrowStatement();
+            case 'try':
+                return parseTryStatement();
+            case 'var':
+                return parseVariableStatement();
+            case 'while':
+                return parseWhileStatement();
+            case 'with':
+                return parseWithStatement();
+            default:
+                break;
+            }
+        }
+
+        expr = parseExpression();
+
+        // 12.12 Labelled Statements
+        if ((expr.type === Syntax.Identifier) && match(':')) {
+            lex();
+
+            if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
+                throwError({}, Messages.Redeclaration, 'Label', expr.name);
+            }
+
+            state.labelSet[expr.name] = true;
+            labeledBody = parseStatement();
+            delete state.labelSet[expr.name];
+
+            return {
+                type: Syntax.LabeledStatement,
+                label: expr,
+                body: labeledBody
+            };
+        }
+
+        consumeSemicolon();
+
+        return {
+            type: Syntax.ExpressionStatement,
+            expression: expr
+        };
+    }
+
+    // 13 Function Definition
+
+    function parseFunctionSourceElements() {
+        var sourceElement, sourceElements = [], token, directive, firstRestricted,
+            oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
+
+        expect('{');
+
+        while (index < length) {
+            token = lookahead();
+            if (token.type !== Token.StringLiteral) {
+                break;
+            }
+
+            sourceElement = parseSourceElement();
+            sourceElements.push(sourceElement);
+            if (sourceElement.expression.type !== Syntax.Literal) {
+                // this is not directive
+                break;
+            }
+            directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
+            if (directive === 'use strict') {
+                strict = true;
+                if (firstRestricted) {
+                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+                }
+            } else {
+                if (!firstRestricted && token.octal) {
+                    firstRestricted = token;
+                }
+            }
+        }
+
+        oldLabelSet = state.labelSet;
+        oldInIteration = state.inIteration;
+        oldInSwitch = state.inSwitch;
+        oldInFunctionBody = state.inFunctionBody;
+
+        state.labelSet = {};
+        state.inIteration = false;
+        state.inSwitch = false;
+        state.inFunctionBody = true;
+
+        while (index < length) {
+            if (match('}')) {
+                break;
+            }
+            sourceElement = parseSourceElement();
+            if (typeof sourceElement === 'undefined') {
+                break;
+            }
+            sourceElements.push(sourceElement);
+        }
+
+        expect('}');
+
+        state.labelSet = oldLabelSet;
+        state.inIteration = oldInIteration;
+        state.inSwitch = oldInSwitch;
+        state.inFunctionBody = oldInFunctionBody;
+
+        return {
+            type: Syntax.BlockStatement,
+            body: sourceElements
+        };
+    }
+
+    function parseFunctionDeclaration() {
+        var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet;
+
+        expectKeyword('function');
+        token = lookahead();
+        id = parseVariableIdentifier();
+        if (strict) {
+            if (isRestrictedWord(token.value)) {
+                throwErrorTolerant(token, Messages.StrictFunctionName);
+            }
+        } else {
+            if (isRestrictedWord(token.value)) {
+                firstRestricted = token;
+                message = Messages.StrictFunctionName;
+            } else if (isStrictModeReservedWord(token.value)) {
+                firstRestricted = token;
+                message = Messages.StrictReservedWord;
+            }
+        }
+
+        expect('(');
+
+        if (!match(')')) {
+            paramSet = {};
+            while (index < length) {
+                token = lookahead();
+                param = parseVariableIdentifier();
+                if (strict) {
+                    if (isRestrictedWord(token.value)) {
+                        stricted = token;
+                        message = Messages.StrictParamName;
+                    }
+                    if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
+                        stricted = token;
+                        message = Messages.StrictParamDupe;
+                    }
+                } else if (!firstRestricted) {
+                    if (isRestrictedWord(token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictParamName;
+                    } else if (isStrictModeReservedWord(token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictReservedWord;
+                    } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictParamDupe;
+                    }
+                }
+                params.push(param);
+                paramSet[param.name] = true;
+                if (match(')')) {
+                    break;
+                }
+                expect(',');
+            }
+        }
+
+        expect(')');
+
+        previousStrict = strict;
+        body = parseFunctionSourceElements();
+        if (strict && firstRestricted) {
+            throwError(firstRestricted, message);
+        }
+        if (strict && stricted) {
+            throwErrorTolerant(stricted, message);
+        }
+        strict = previousStrict;
+
+        return {
+            type: Syntax.FunctionDeclaration,
+            id: id,
+            params: params,
+            defaults: [],
+            body: body,
+            rest: null,
+            generator: false,
+            expression: false
+        };
+    }
+
+    function parseFunctionExpression() {
+        var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
+
+        expectKeyword('function');
+
+        if (!match('(')) {
+            token = lookahead();
+            id = parseVariableIdentifier();
+            if (strict) {
+                if (isRestrictedWord(token.value)) {
+                    throwErrorTolerant(token, Messages.StrictFunctionName);
+                }
+            } else {
+                if (isRestrictedWord(token.value)) {
+                    firstRestricted = token;
+                    message = Messages.StrictFunctionName;
+                } else if (isStrictModeReservedWord(token.value)) {
+                    firstRestricted = token;
+                    message = Messages.StrictReservedWord;
+                }
+            }
+        }
+
+        expect('(');
+
+        if (!match(')')) {
+            paramSet = {};
+            while (index < length) {
+                token = lookahead();
+                param = parseVariableIdentifier();
+                if (strict) {
+                    if (isRestrictedWord(token.value)) {
+                        stricted = token;
+                        message = Messages.StrictParamName;
+                    }
+                    if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
+                        stricted = token;
+                        message = Messages.StrictParamDupe;
+                    }
+                } else if (!firstRestricted) {
+                    if (isRestrictedWord(token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictParamName;
+                    } else if (isStrictModeReservedWord(token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictReservedWord;
+                    } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
+                        firstRestricted = token;
+                        message = Messages.StrictParamDupe;
+                    }
+                }
+                params.push(param);
+                paramSet[param.name] = true;
+                if (match(')')) {
+                    break;
+                }
+                expect(',');
+            }
+        }
+
+        expect(')');
+
+        previousStrict = strict;
+        body = parseFunctionSourceElements();
+        if (strict && firstRestricted) {
+            throwError(firstRestricted, message);
+        }
+        if (strict && stricted) {
+            throwErrorTolerant(stricted, message);
+        }
+        strict = previousStrict;
+
+        return {
+            type: Syntax.FunctionExpression,
+            id: id,
+            params: params,
+            defaults: [],
+            body: body,
+            rest: null,
+            generator: false,
+            expression: false
+        };
+    }
+
+    // 14 Program
+
+    function parseSourceElement() {
+        var token = lookahead();
+
+        if (token.type === Token.Keyword) {
+            switch (token.value) {
+            case 'const':
+            case 'let':
+                return parseConstLetDeclaration(token.value);
+            case 'function':
+                return parseFunctionDeclaration();
+            default:
+                return parseStatement();
+            }
+        }
+
+        if (token.type !== Token.EOF) {
+            return parseStatement();
+        }
+    }
+
+    function parseSourceElements() {
+        var sourceElement, sourceElements = [], token, directive, firstRestricted;
+
+        while (index < length) {
+            token = lookahead();
+            if (token.type !== Token.StringLiteral) {
+                break;
+            }
+
+            sourceElement = parseSourceElement();
+            sourceElements.push(sourceElement);
+            if (sourceElement.expression.type !== Syntax.Literal) {
+                // this is not directive
+                break;
+            }
+            directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
+            if (directive === 'use strict') {
+                strict = true;
+                if (firstRestricted) {
+                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+                }
+            } else {
+                if (!firstRestricted && token.octal) {
+                    firstRestricted = token;
+                }
+            }
+        }
+
+        while (index < length) {
+            sourceElement = parseSourceElement();
+            if (typeof sourceElement === 'undefined') {
+                break;
+            }
+            sourceElements.push(sourceElement);
+        }
+        return sourceElements;
+    }
+
+    function parseProgram() {
+        var program;
+        strict = false;
+        program = {
+            type: Syntax.Program,
+            body: parseSourceElements()
+        };
+        return program;
+    }
+
+    // The following functions are needed only when the option to preserve
+    // the comments is active.
+
+    function addComment(type, value, start, end, loc) {
+        assert(typeof start === 'number', 'Comment must have valid position');
+
+        // Because the way the actual token is scanned, often the comments
+        // (if any) are skipped twice during the lexical analysis.
+        // Thus, we need to skip adding a comment if the comment array already
+        // handled it.
+        if (extra.comments.length > 0) {
+            if (extra.comments[extra.comments.length - 1].range[1] > start) {
+                return;
+            }
+        }
+
+        extra.comments.push({
+            type: type,
+            value: value,
+            range: [start, end],
+            loc: loc
+        });
+    }
+
+    function scanComment() {
+        var comment, ch, loc, start, blockComment, lineComment;
+
+        comment = '';
+        blockComment = false;
+        lineComment = false;
+
+        while (index < length) {
+            ch = source[index];
+
+            if (lineComment) {
+                ch = source[index++];
+                if (isLineTerminator(ch)) {
+                    loc.end = {
+                        line: lineNumber,
+                        column: index - lineStart - 1
+                    };
+                    lineComment = false;
+                    addComment('Line', comment, start, index - 1, loc);
+                    if (ch === '\r' && source[index] === '\n') {
+                        ++index;
+                    }
+                    ++lineNumber;
+                    lineStart = index;
+                    comment = '';
+                } else if (index >= length) {
+                    lineComment = false;
+                    comment += ch;
+                    loc.end = {
+                        line: lineNumber,
+                        column: length - lineStart
+                    };
+                    addComment('Line', comment, start, length, loc);
+                } else {
+                    comment += ch;
+                }
+            } else if (blockComment) {
+                if (isLineTerminator(ch)) {
+                    if (ch === '\r' && source[index + 1] === '\n') {
+                        ++index;
+                        comment += '\r\n';
+                    } else {
+                        comment += ch;
+                    }
+                    ++lineNumber;
+                    ++index;
+                    lineStart = index;
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                } else {
+                    ch = source[index++];
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                    comment += ch;
+                    if (ch === '*') {
+                        ch = source[index];
+                        if (ch === '/') {
+                            comment = comment.substr(0, comment.length - 1);
+                            blockComment = false;
+                            ++index;
+                            loc.end = {
+                                line: lineNumber,
+                                column: index - lineStart
+                            };
+                            addComment('Block', comment, start, index, loc);
+                            comment = '';
+                        }
+                    }
+                }
+            } else if (ch === '/') {
+                ch = source[index + 1];
+                if (ch === '/') {
+                    loc = {
+                        start: {
+                            line: lineNumber,
+                            column: index - lineStart
+                        }
+                    };
+                    start = index;
+                    index += 2;
+                    lineComment = true;
+                    if (index >= length) {
+                        loc.end = {
+                            line: lineNumber,
+                            column: index - lineStart
+                        };
+                        lineComment = false;
+                        addComment('Line', comment, start, index, loc);
+                    }
+                } else if (ch === '*') {
+                    start = index;
+                    index += 2;
+                    blockComment = true;
+                    loc = {
+                        start: {
+                            line: lineNumber,
+                            column: index - lineStart - 2
+                        }
+                    };
+                    if (index >= length) {
+                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                    }
+                } else {
+                    break;
+                }
+            } else if (isWhiteSpace(ch)) {
+                ++index;
+            } else if (isLineTerminator(ch)) {
+                ++index;
+                if (ch ===  '\r' && source[index] === '\n') {
+                    ++index;
+                }
+                ++lineNumber;
+                lineStart = index;
+            } else {
+                break;
+            }
+        }
+    }
+
+    function filterCommentLocation() {
+        var i, entry, comment, comments = [];
+
+        for (i = 0; i < extra.comments.length; ++i) {
+            entry = extra.comments[i];
+            comment = {
+                type: entry.type,
+                value: entry.value
+            };
+            if (extra.range) {
+                comment.range = entry.range;
+            }
+            if (extra.loc) {
+                comment.loc = entry.loc;
+            }
+            comments.push(comment);
+        }
+
+        extra.comments = comments;
+    }
+
+    function collectToken() {
+        var start, loc, token, range, value;
+
+        skipComment();
+        start = index;
+        loc = {
+            start: {
+                line: lineNumber,
+                column: index - lineStart
+            }
+        };
+
+        token = extra.advance();
+        loc.end = {
+            line: lineNumber,
+            column: index - lineStart
+        };
+
+        if (token.type !== Token.EOF) {
+            range = [token.range[0], token.range[1]];
+            value = sliceSource(token.range[0], token.range[1]);
+            extra.tokens.push({
+                type: TokenName[token.type],
+                value: value,
+                range: range,
+                loc: loc
+            });
+        }
+
+        return token;
+    }
+
+    function collectRegex() {
+        var pos, loc, regex, token;
+
+        skipComment();
+
+        pos = index;
+        loc = {
+            start: {
+                line: lineNumber,
+                column: index - lineStart
+            }
+        };
+
+        regex = extra.scanRegExp();
+        loc.end = {
+            line: lineNumber,
+            column: index - lineStart
+        };
+
+        // Pop the previous token, which is likely '/' or '/='
+        if (extra.tokens.length > 0) {
+            token = extra.tokens[extra.tokens.length - 1];
+            if (token.range[0] === pos && token.type === 'Punctuator') {
+                if (token.value === '/' || token.value === '/=') {
+                    extra.tokens.pop();
+                }
+            }
+        }
+
+        extra.tokens.push({
+            type: 'RegularExpression',
+            value: regex.literal,
+            range: [pos, index],
+            loc: loc
+        });
+
+        return regex;
+    }
+
+    function filterTokenLocation() {
+        var i, entry, token, tokens = [];
+
+        for (i = 0; i < extra.tokens.length; ++i) {
+            entry = extra.tokens[i];
+            token = {
+                type: entry.type,
+                value: entry.value
+            };
+            if (extra.range) {
+                token.range = entry.range;
+            }
+            if (extra.loc) {
+                token.loc = entry.loc;
+            }
+            tokens.push(token);
+        }
+
+        extra.tokens = tokens;
+    }
+
+    function createLiteral(token) {
+        return {
+            type: Syntax.Literal,
+            value: token.value
+        };
+    }
+
+    function createRawLiteral(token) {
+        return {
+            type: Syntax.Literal,
+            value: token.value,
+            raw: sliceSource(token.range[0], token.range[1])
+        };
+    }
+
+    function createLocationMarker() {
+        var marker = {};
+
+        marker.range = [index, index];
+        marker.loc = {
+            start: {
+                line: lineNumber,
+                column: index - lineStart
+            },
+            end: {
+                line: lineNumber,
+                column: index - lineStart
+            }
+        };
+
+        marker.end = function () {
+            this.range[1] = index;
+            this.loc.end.line = lineNumber;
+            this.loc.end.column = index - lineStart;
+        };
+
+        marker.applyGroup = function (node) {
+            if (extra.range) {
+                node.groupRange = [this.range[0], this.range[1]];
+            }
+            if (extra.loc) {
+                node.groupLoc = {
+                    start: {
+                        line: this.loc.start.line,
+                        column: this.loc.start.column
+                    },
+                    end: {
+                        line: this.loc.end.line,
+                        column: this.loc.end.column
+                    }
+                };
+            }
+        };
+
+        marker.apply = function (node) {
+            if (extra.range) {
+                node.range = [this.range[0], this.range[1]];
+            }
+            if (extra.loc) {
+                node.loc = {
+                    start: {
+                        line: this.loc.start.line,
+                        column: this.loc.start.column
+                    },
+                    end: {
+                        line: this.loc.end.line,
+                        column: this.loc.end.column
+                    }
+                };
+            }
+        };
+
+        return marker;
+    }
+
+    function trackGroupExpression() {
+        var marker, expr;
+
+        skipComment();
+        marker = createLocationMarker();
+        expect('(');
+
+        expr = parseExpression();
+
+        expect(')');
+
+        marker.end();
+        marker.applyGroup(expr);
+
+        return expr;
+    }
+
+    function trackLeftHandSideExpression() {
+        var marker, expr;
+
+        skipComment();
+        marker = createLocationMarker();
+
+        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+        while (match('.') || match('[')) {
+            if (match('[')) {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: true,
+                    object: expr,
+                    property: parseComputedMember()
+                };
+                marker.end();
+                marker.apply(expr);
+            } else {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: false,
+                    object: expr,
+                    property: parseNonComputedMember()
+                };
+                marker.end();
+                marker.apply(expr);
+            }
+        }
+
+        return expr;
+    }
+
+    function trackLeftHandSideExpressionAllowCall() {
+        var marker, expr;
+
+        skipComment();
+        marker = createLocationMarker();
+
+        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+        while (match('.') || match('[') || match('(')) {
+            if (match('(')) {
+                expr = {
+                    type: Syntax.CallExpression,
+                    callee: expr,
+                    'arguments': parseArguments()
+                };
+                marker.end();
+                marker.apply(expr);
+            } else if (match('[')) {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: true,
+                    object: expr,
+                    property: parseComputedMember()
+                };
+                marker.end();
+                marker.apply(expr);
+            } else {
+                expr = {
+                    type: Syntax.MemberExpression,
+                    computed: false,
+                    object: expr,
+                    property: parseNonComputedMember()
+                };
+                marker.end();
+                marker.apply(expr);
+            }
+        }
+
+        return expr;
+    }
+
+    function filterGroup(node) {
+        var n, i, entry;
+
+        n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
+        for (i in node) {
+            if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
+                entry = node[i];
+                if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
+                    n[i] = entry;
+                } else {
+                    n[i] = filterGroup(entry);
+                }
+            }
+        }
+        return n;
+    }
+
+    function wrapTrackingFunction(range, loc) {
+
+        return function (parseFunction) {
+
+            function isBinary(node) {
+                return node.type === Syntax.LogicalExpression ||
+                    node.type === Syntax.BinaryExpression;
+            }
+
+            function visit(node) {
+                var start, end;
+
+                if (isBinary(node.left)) {
+                    visit(node.left);
+                }
+                if (isBinary(node.right)) {
+                    visit(node.right);
+                }
+
+                if (range) {
+                    if (node.left.groupRange || node.right.groupRange) {
+                        start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
+                        end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
+                        node.range = [start, end];
+                    } else if (typeof node.range === 'undefined') {
+                        start = node.left.range[0];
+                        end = node.right.range[1];
+                        node.range = [start, end];
+                    }
+                }
+                if (loc) {
+                    if (node.left.groupLoc || node.right.groupLoc) {
+                        start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
+                        end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
+                        node.loc = {
+                            start: start,
+                            end: end
+                        };
+                    } else if (typeof node.loc === 'undefined') {
+                        node.loc = {
+                            start: node.left.loc.start,
+                            end: node.right.loc.end
+                        };
+                    }
+                }
+            }
+
+            return function () {
+                var marker, node;
+
+                skipComment();
+
+                marker = createLocationMarker();
+                node = parseFunction.apply(null, arguments);
+                marker.end();
+
+                if (range && typeof node.range === 'undefined') {
+                    marker.apply(node);
+                }
+
+                if (loc && typeof node.loc === 'undefined') {
+                    marker.apply(node);
+                }
+
+                if (isBinary(node)) {
+                    visit(node);
+                }
+
+                return node;
+            };
+        };
+    }
+
+    function patch() {
+
+        var wrapTracking;
+
+        if (extra.comments) {
+            extra.skipComment = skipComment;
+            skipComment = scanComment;
+        }
+
+        if (extra.raw) {
+            extra.createLiteral = createLiteral;
+            createLiteral = createRawLiteral;
+        }
+
+        if (extra.range || extra.loc) {
+
+            extra.parseGroupExpression = parseGroupExpression;
+            extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
+            extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
+            parseGroupExpression = trackGroupExpression;
+            parseLeftHandSideExpression = trackLeftHandSideExpression;
+            parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
+
+            wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
+
+            extra.parseAdditiveExpression = parseAdditiveExpression;
+            extra.parseAssignmentExpression = parseAssignmentExpression;
+            extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
+            extra.parseBitwiseORExpression = parseBitwiseORExpression;
+            extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
+            extra.parseBlock = parseBlock;
+            extra.parseFunctionSourceElements = parseFunctionSourceElements;
+            extra.parseCatchClause = parseCatchClause;
+            extra.parseComputedMember = parseComputedMember;
+            extra.parseConditionalExpression = parseConditionalExpression;
+            extra.parseConstLetDeclaration = parseConstLetDeclaration;
+            extra.parseEqualityExpression = parseEqualityExpression;
+            extra.parseExpression = parseExpression;
+            extra.parseForVariableDeclaration = parseForVariableDeclaration;
+            extra.parseFunctionDeclaration = parseFunctionDeclaration;
+            extra.parseFunctionExpression = parseFunctionExpression;
+            extra.parseLogicalANDExpression = parseLogicalANDExpression;
+            extra.parseLogicalORExpression = parseLogicalORExpression;
+            extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
+            extra.parseNewExpression = parseNewExpression;
+            extra.parseNonComputedProperty = parseNonComputedProperty;
+            extra.parseObjectProperty = parseObjectProperty;
+            extra.parseObjectPropertyKey = parseObjectPropertyKey;
+            extra.parsePostfixExpression = parsePostfixExpression;
+            extra.parsePrimaryExpression = parsePrimaryExpression;
+            extra.parseProgram = parseProgram;
+            extra.parsePropertyFunction = parsePropertyFunction;
+            extra.parseRelationalExpression = parseRelationalExpression;
+            extra.parseStatement = parseStatement;
+            extra.parseShiftExpression = parseShiftExpression;
+            extra.parseSwitchCase = parseSwitchCase;
+            extra.parseUnaryExpression = parseUnaryExpression;
+            extra.parseVariableDeclaration = parseVariableDeclaration;
+            extra.parseVariableIdentifier = parseVariableIdentifier;
+
+            parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
+            parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
+            parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
+            parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
+            parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
+            parseBlock = wrapTracking(extra.parseBlock);
+            parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
+            parseCatchClause = wrapTracking(extra.parseCatchClause);
+            parseComputedMember = wrapTracking(extra.parseComputedMember);
+            parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
+            parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
+            parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
+            parseExpression = wrapTracking(extra.parseExpression);
+            parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
+            parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
+            parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
+            parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
+            parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
+            parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
+            parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
+            parseNewExpression = wrapTracking(extra.parseNewExpression);
+            parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
+            parseObjectProperty = wrapTracking(extra.parseObjectProperty);
+            parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
+            parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
+            parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
+            parseProgram = wrapTracking(extra.parseProgram);
+            parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
+            parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
+            parseStatement = wrapTracking(extra.parseStatement);
+            parseShiftExpression = wrapTracking(extra.parseShiftExpression);
+            parseSwitchCase = wrapTracking(extra.parseSwitchCase);
+            parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
+            parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
+            parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
+        }
+
+        if (typeof extra.tokens !== 'undefined') {
+            extra.advance = advance;
+            extra.scanRegExp = scanRegExp;
+
+            advance = collectToken;
+            scanRegExp = collectRegex;
+        }
+    }
+
+    function unpatch() {
+        if (typeof extra.skipComment === 'function') {
+            skipComment = extra.skipComment;
+        }
+
+        if (extra.raw) {
+            createLiteral = extra.createLiteral;
+        }
+
+        if (extra.range || extra.loc) {
+            parseAdditiveExpression = extra.parseAdditiveExpression;
+            parseAssignmentExpression = extra.parseAssignmentExpression;
+            parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
+            parseBitwiseORExpression = extra.parseBitwiseORExpression;
+            parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
+            parseBlock = extra.parseBlock;
+            parseFunctionSourceElements = extra.parseFunctionSourceElements;
+            parseCatchClause = extra.parseCatchClause;
+            parseComputedMember = extra.parseComputedMember;
+            parseConditionalExpression = extra.parseConditionalExpression;
+            parseConstLetDeclaration = extra.parseConstLetDeclaration;
+            parseEqualityExpression = extra.parseEqualityExpression;
+            parseExpression = extra.parseExpression;
+            parseForVariableDeclaration = extra.parseForVariableDeclaration;
+            parseFunctionDeclaration = extra.parseFunctionDeclaration;
+            parseFunctionExpression = extra.parseFunctionExpression;
+            parseGroupExpression = extra.parseGroupExpression;
+            parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
+            parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
+            parseLogicalANDExpression = extra.parseLogicalANDExpression;
+            parseLogicalORExpression = extra.parseLogicalORExpression;
+            parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
+            parseNewExpression = extra.parseNewExpression;
+            parseNonComputedProperty = extra.parseNonComputedProperty;
+            parseObjectProperty = extra.parseObjectProperty;
+            parseObjectPropertyKey = extra.parseObjectPropertyKey;
+            parsePrimaryExpression = extra.parsePrimaryExpression;
+            parsePostfixExpression = extra.parsePostfixExpression;
+            parseProgram = extra.parseProgram;
+            parsePropertyFunction = extra.parsePropertyFunction;
+            parseRelationalExpression = extra.parseRelationalExpression;
+            parseStatement = extra.parseStatement;
+            parseShiftExpression = extra.parseShiftExpression;
+            parseSwitchCase = extra.parseSwitchCase;
+            parseUnaryExpression = extra.parseUnaryExpression;
+            parseVariableDeclaration = extra.parseVariableDeclaration;
+            parseVariableIdentifier = extra.parseVariableIdentifier;
+        }
+
+        if (typeof extra.scanRegExp === 'function') {
+            advance = extra.advance;
+            scanRegExp = extra.scanRegExp;
+        }
+    }
+
+    function stringToArray(str) {
+        var length = str.length,
+            result = [],
+            i;
+        for (i = 0; i < length; ++i) {
+            result[i] = str.charAt(i);
+        }
+        return result;
+    }
+
+    function parse(code, options) {
+        var program, toString;
+
+        toString = String;
+        if (typeof code !== 'string' && !(code instanceof String)) {
+            code = toString(code);
+        }
+
+        source = code;
+        index = 0;
+        lineNumber = (source.length > 0) ? 1 : 0;
+        lineStart = 0;
+        length = source.length;
+        buffer = null;
+        state = {
+            allowIn: true,
+            labelSet: {},
+            inFunctionBody: false,
+            inIteration: false,
+            inSwitch: false
+        };
+
+        extra = {};
+        if (typeof options !== 'undefined') {
+            extra.range = (typeof options.range === 'boolean') && options.range;
+            extra.loc = (typeof options.loc === 'boolean') && options.loc;
+            extra.raw = (typeof options.raw === 'boolean') && options.raw;
+            if (typeof options.tokens === 'boolean' && options.tokens) {
+                extra.tokens = [];
+            }
+            if (typeof options.comment === 'boolean' && options.comment) {
+                extra.comments = [];
+            }
+            if (typeof options.tolerant === 'boolean' && options.tolerant) {
+                extra.errors = [];
+            }
+        }
+
+        if (length > 0) {
+            if (typeof source[0] === 'undefined') {
+                // Try first to convert to a string. This is good as fast path
+                // for old IE which understands string indexing for string
+                // literals only and not for string object.
+                if (code instanceof String) {
+                    source = code.valueOf();
+                }
+
+                // Force accessing the characters via an array.
+                if (typeof source[0] === 'undefined') {
+                    source = stringToArray(code);
+                }
+            }
+        }
+
+        patch();
+        try {
+            program = parseProgram();
+            if (typeof extra.comments !== 'undefined') {
+                filterCommentLocation();
+                program.comments = extra.comments;
+            }
+            if (typeof extra.tokens !== 'undefined') {
+                filterTokenLocation();
+                program.tokens = extra.tokens;
+            }
+            if (typeof extra.errors !== 'undefined') {
+                program.errors = extra.errors;
+            }
+            if (extra.range || extra.loc) {
+                program.body = filterGroup(program.body);
+            }
+        } catch (e) {
+            throw e;
+        } finally {
+            unpatch();
+            extra = {};
+        }
+
+        return program;
+    }
+
+    // Sync with package.json.
+    exports.version = '1.0.4';
+
+    exports.parse = parse;
+
+    // Deep copy.
+    exports.Syntax = (function () {
+        var name, types = {};
+
+        if (typeof Object.create === 'function') {
+            types = Object.create(null);
+        }
+
+        for (name in Syntax) {
+            if (Syntax.hasOwnProperty(name)) {
+                types[name] = Syntax[name];
+            }
+        }
+
+        if (typeof Object.freeze === 'function') {
+            Object.freeze(types);
+        }
+
+        return types;
+    }());
+
+}));
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/node_modules/esprima/package.json b/node_modules/esprima/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2956fd76df4c88140387a7e25dd3364ec2d640bb
--- /dev/null
+++ b/node_modules/esprima/package.json
@@ -0,0 +1,48 @@
+{
+    "name": "esprima",
+    "description": "ECMAScript parsing infrastructure for multipurpose analysis",
+    "homepage": "http://esprima.org",
+    "main": "esprima.js",
+    "bin": {
+        "esparse": "./bin/esparse.js",
+        "esvalidate": "./bin/esvalidate.js"
+    },
+    "files": [
+        "bin",
+        "test/run.js",
+        "test/runner.js",
+        "test/test.js",
+        "test/compat.js",
+        "test/reflect.js",
+        "esprima.js"
+    ],
+    "version": "1.0.4",
+    "engines": {
+        "node": ">=0.4.0"
+    },
+    "maintainers": [{
+        "name": "Ariya Hidayat",
+        "email": "ariya.hidayat@gmail.com",
+        "web": "http://ariya.ofilabs.com"
+    }],
+    "repository": {
+        "type": "git",
+        "url": "http://github.com/ariya/esprima.git"
+    },
+    "licenses": [{
+        "type": "BSD",
+        "url": "http://github.com/ariya/esprima/raw/master/LICENSE.BSD"
+    }],
+    "keywords": [
+        "ast",
+        "ecmascript",
+        "javascript",
+        "parser",
+        "syntax"
+    ],
+    "scripts": {
+        "test": "node test/run.js",
+        "benchmark": "node test/benchmarks.js",
+        "benchmark-quick": "node test/benchmarks.js quick"
+    }
+}
diff --git a/node_modules/esprima/test/compat.js b/node_modules/esprima/test/compat.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee3a6295eba7ae81536b8f57a99b26a43207e7ff
--- /dev/null
+++ b/node_modules/esprima/test/compat.js
@@ -0,0 +1,239 @@
+/*
+  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint node: true */
+/*global document: true, window:true, esprima: true, testReflect: true */
+
+var runTests;
+
+function getContext(esprima, reportCase, reportFailure) {
+    'use strict';
+
+    var Reflect, Pattern;
+
+    // Maps Mozilla Reflect object to our Esprima parser.
+    Reflect = {
+        parse: function (code) {
+            var result;
+
+            reportCase(code);
+
+            try {
+                result = esprima.parse(code);
+            } catch (error) {
+                result = error;
+            }
+
+            return result;
+        }
+    };
+
+    // This is used by Reflect test suite to match a syntax tree.
+    Pattern = function (obj) {
+        var pattern;
+
+        // Poor man's deep object cloning.
+        pattern = JSON.parse(JSON.stringify(obj));
+
+        // Special handling for regular expression literal since we need to
+        // convert it to a string literal, otherwise it will be decoded
+        // as object "{}" and the regular expression would be lost.
+        if (obj.type && obj.type === 'Literal') {
+            if (obj.value instanceof RegExp) {
+                pattern = {
+                    type: obj.type,
+                    value: obj.value.toString()
+                };
+            }
+        }
+
+        // Special handling for branch statement because SpiderMonkey
+        // prefers to put the 'alternate' property before 'consequent'.
+        if (obj.type && obj.type === 'IfStatement') {
+            pattern = {
+                type: pattern.type,
+                test: pattern.test,
+                consequent: pattern.consequent,
+                alternate: pattern.alternate
+            };
+        }
+
+        // Special handling for do while statement because SpiderMonkey
+        // prefers to put the 'test' property before 'body'.
+        if (obj.type && obj.type === 'DoWhileStatement') {
+            pattern = {
+                type: pattern.type,
+                body: pattern.body,
+                test: pattern.test
+            };
+        }
+
+        function adjustRegexLiteralAndRaw(key, value) {
+            if (key === 'value' && value instanceof RegExp) {
+                value = value.toString();
+            } else if (key === 'raw' && typeof value === "string") {
+                // Ignore Esprima-specific 'raw' property.
+                return undefined;
+            }
+            return value;
+        }
+
+        if (obj.type && (obj.type === 'Program')) {
+            pattern.assert = function (tree) {
+                var actual, expected;
+                actual = JSON.stringify(tree, adjustRegexLiteralAndRaw, 4);
+                expected = JSON.stringify(obj, null, 4);
+
+                if (expected !== actual) {
+                    reportFailure(expected, actual);
+                }
+            };
+        }
+
+        return pattern;
+    };
+
+    return {
+        Reflect: Reflect,
+        Pattern: Pattern
+    };
+}
+
+if (typeof window !== 'undefined') {
+    // Run all tests in a browser environment.
+    runTests = function () {
+        'use strict';
+
+        var total = 0,
+            failures = 0;
+
+        function setText(el, str) {
+            if (typeof el.innerText === 'string') {
+                el.innerText = str;
+            } else {
+                el.textContent = str;
+            }
+        }
+
+        function reportCase(code) {
+            var report, e;
+            report = document.getElementById('report');
+            e = document.createElement('pre');
+            e.setAttribute('class', 'code');
+            setText(e, code);
+            report.appendChild(e);
+            total += 1;
+        }
+
+        function reportFailure(expected, actual) {
+            var report, e;
+
+            failures += 1;
+
+            report = document.getElementById('report');
+
+            e = document.createElement('p');
+            setText(e, 'Expected');
+            report.appendChild(e);
+
+            e = document.createElement('pre');
+            e.setAttribute('class', 'expected');
+            setText(e, expected);
+            report.appendChild(e);
+
+            e = document.createElement('p');
+            setText(e, 'Actual');
+            report.appendChild(e);
+
+            e = document.createElement('pre');
+            e.setAttribute('class', 'actual');
+            setText(e, actual);
+            report.appendChild(e);
+        }
+
+        setText(document.getElementById('version'), esprima.version);
+
+        window.setTimeout(function () {
+            var tick, context = getContext(esprima, reportCase, reportFailure);
+
+            tick = new Date();
+            testReflect(context.Reflect, context.Pattern);
+            tick = (new Date()) - tick;
+
+            if (failures > 0) {
+                setText(document.getElementById('status'), total + ' tests. ' +
+                    'Failures: ' + failures + '. ' + tick + ' ms');
+            } else {
+                setText(document.getElementById('status'), total + ' tests. ' +
+                    'No failure. ' + tick + ' ms');
+            }
+        }, 513);
+    };
+} else {
+    (function (global) {
+        'use strict';
+        var esprima = require('../esprima'),
+            tick,
+            total = 0,
+            failures = [],
+            header,
+            current,
+            context;
+
+        function reportCase(code) {
+            total += 1;
+            current = code;
+        }
+
+        function reportFailure(expected, actual) {
+            failures.push({
+                source: current,
+                expected: expected.toString(),
+                actual: actual.toString()
+            });
+        }
+
+        context = getContext(esprima, reportCase, reportFailure);
+
+        tick = new Date();
+        require('./reflect').testReflect(context.Reflect, context.Pattern);
+        tick = (new Date()) - tick;
+
+        header = total + ' tests. ' + failures.length + ' failures. ' +
+            tick + ' ms';
+        if (failures.length) {
+            console.error(header);
+            failures.forEach(function (failure) {
+                console.error(failure.source + ': Expected\n    ' +
+                    failure.expected.split('\n').join('\n    ') +
+                    '\nto match\n    ' + failure.actual);
+            });
+        } else {
+            console.log(header);
+        }
+        process.exit(failures.length === 0 ? 0 : 1);
+    }(this));
+}
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/node_modules/esprima/test/reflect.js b/node_modules/esprima/test/reflect.js
new file mode 100644
index 0000000000000000000000000000000000000000..dba1ba8f1fe3b687840cc0274157ee38f4ef6ab5
--- /dev/null
+++ b/node_modules/esprima/test/reflect.js
@@ -0,0 +1,422 @@
+// This is modified from Mozilla Reflect.parse test suite (the file is located
+// at js/src/tests/js1_8_5/extensions/reflect-parse.js in the source tree).
+//
+// Some notable changes:
+//   * Removed unsupported features (destructuring, let, comprehensions...).
+//   * Removed tests for E4X (ECMAScript for XML).
+//   * Removed everything related to builder.
+//   * Enclosed every 'Pattern' construct with a scope.
+//   * Tweaked some expected tree to remove generator field.
+//   * Removed the test for bug 632030 and bug 632024.
+
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+(function (exports) {
+
+function testReflect(Reflect, Pattern) {
+
+function program(elts) { return Pattern({ type: "Program", body: elts }) }
+function exprStmt(expr) { return Pattern({ type: "ExpressionStatement", expression: expr }) }
+function throwStmt(expr) { return Pattern({ type: "ThrowStatement", argument: expr }) }
+function returnStmt(expr) { return Pattern({ type: "ReturnStatement", argument: expr }) }
+function yieldExpr(expr) { return Pattern({ type: "YieldExpression", argument: expr }) }
+function lit(val) { return Pattern({ type: "Literal", value: val }) }
+var thisExpr = Pattern({ type: "ThisExpression" });
+function funDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration",
+                                             id: id,
+                                             params: params,
+                                             defaults: [],
+                                             body: body,
+                                             rest: null,
+                                             generator: false,
+                                             expression: false
+                                             }) }
+function genFunDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration",
+                                                id: id,
+                                                params: params,
+                                                defaults: [],
+                                                body: body,
+                                                rest: null,
+                                                generator: false,
+                                                expression: false
+                                                }) }
+function declarator(id, init) { return Pattern({ type: "VariableDeclarator", id: id, init: init }) }
+function varDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" }) }
+function letDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" }) }
+function constDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" }) }
+function ident(name) { return Pattern({ type: "Identifier", name: name }) }
+function dotExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: false, object: obj, property: id }) }
+function memExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: true, object: obj, property: id }) }
+function forStmt(init, test, update, body) { return Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body }) }
+function forInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false }) }
+function forEachInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true }) }
+function breakStmt(lab) { return Pattern({ type: "BreakStatement", label: lab }) }
+function continueStmt(lab) { return Pattern({ type: "ContinueStatement", label: lab }) }
+function blockStmt(body) { return Pattern({ type: "BlockStatement", body: body }) }
+var emptyStmt = Pattern({ type: "EmptyStatement" });
+function ifStmt(test, cons, alt) { return Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons }) }
+function labStmt(lab, stmt) { return Pattern({ type: "LabeledStatement", label: lab, body: stmt }) }
+function withStmt(obj, stmt) { return Pattern({ type: "WithStatement", object: obj, body: stmt }) }
+function whileStmt(test, stmt) { return Pattern({ type: "WhileStatement", test: test, body: stmt }) }
+function doStmt(stmt, test) { return Pattern({ type: "DoWhileStatement", test: test, body: stmt }) }
+function switchStmt(disc, cases) { return Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases }) }
+function caseClause(test, stmts) { return Pattern({ type: "SwitchCase", test: test, consequent: stmts }) }
+function defaultClause(stmts) { return Pattern({ type: "SwitchCase", test: null, consequent: stmts }) }
+function catchClause(id, guard, body) { if (guard) { return Pattern({ type: "GuardedCatchClause", param: id, guard: guard, body: body }) } else { return Pattern({ type: "CatchClause", param: id, body: body }) } }
+function tryStmt(body, guarded, catches, fin) { return Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handlers: catches, finalizer: fin }) }
+function letStmt(head, body) { return Pattern({ type: "LetStatement", head: head, body: body }) }
+function funExpr(id, args, body, gen) { return Pattern({ type: "FunctionExpression",
+                                                id: id,
+                                                params: args,
+                                                defaults: [],
+                                                body: body,
+                                                rest: null,
+                                                generator: false,
+                                                expression: false
+                                                }) }
+function genFunExpr(id, args, body) { return Pattern({ type: "FunctionExpression",
+                                              id: id,
+                                              params: args,
+                                              defaults: [],
+                                              body: body,
+                                              rest: null,
+                                              generator: false,
+                                              expression: false
+                                              }) }
+
+function unExpr(op, arg) { return Pattern({ type: "UnaryExpression", operator: op, argument: arg, prefix: true }) }
+function binExpr(op, left, right) { return Pattern({ type: "BinaryExpression", operator: op, left: left, right: right }) }
+function aExpr(op, left, right) { return Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right }) }
+function updExpr(op, arg, prefix) { return Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix }) }
+function logExpr(op, left, right) { return Pattern({ type: "LogicalExpression", operator: op, left: left, right: right }) }
+
+function condExpr(test, cons, alt) { return Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt }) }
+function seqExpr(exprs) { return Pattern({ type: "SequenceExpression", expressions: exprs }) }
+function newExpr(callee, args) { return Pattern({ type: "NewExpression", callee: callee, arguments: args }) }
+function callExpr(callee, args) { return Pattern({ type: "CallExpression", callee: callee, arguments: args }) }
+function arrExpr(elts) { return Pattern({ type: "ArrayExpression", elements: elts }) }
+function objExpr(elts) { return Pattern({ type: "ObjectExpression", properties: elts }) }
+function objProp(key, value, kind) { return Pattern({ type: "Property", key: key, value: value, kind: kind }) }
+
+function arrPatt(elts) { return Pattern({ type: "ArrayPattern", elements: elts }) }
+function objPatt(elts) { return Pattern({ type: "ObjectPattern", properties: elts }) }
+
+function localSrc(src) { return "(function(){ " + src + " })" }
+function localPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([patt])))]) }
+function blockSrc(src) { return "(function(){ { " + src + " } })" }
+function blockPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))]) }
+
+function assertBlockStmt(src, patt) {
+    blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
+}
+
+function assertBlockExpr(src, patt) {
+    assertBlockStmt(src, exprStmt(patt));
+}
+
+function assertBlockDecl(src, patt, builder) {
+    blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
+}
+
+function assertLocalStmt(src, patt) {
+    localPatt(patt).assert(Reflect.parse(localSrc(src)));
+}
+
+function assertLocalExpr(src, patt) {
+    assertLocalStmt(src, exprStmt(patt));
+}
+
+function assertLocalDecl(src, patt) {
+    localPatt(patt).assert(Reflect.parse(localSrc(src)));
+}
+
+function assertGlobalStmt(src, patt, builder) {
+    program([patt]).assert(Reflect.parse(src, {builder: builder}));
+}
+
+function assertGlobalExpr(src, patt, builder) {
+    program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
+    //assertStmt(src, exprStmt(patt));
+}
+
+function assertGlobalDecl(src, patt) {
+    program([patt]).assert(Reflect.parse(src));
+}
+
+function assertProg(src, patt) {
+    program(patt).assert(Reflect.parse(src));
+}
+
+function assertStmt(src, patt) {
+    assertLocalStmt(src, patt);
+    assertGlobalStmt(src, patt);
+    assertBlockStmt(src, patt);
+}
+
+function assertExpr(src, patt) {
+    assertLocalExpr(src, patt);
+    assertGlobalExpr(src, patt);
+    assertBlockExpr(src, patt);
+}
+
+function assertDecl(src, patt) {
+    assertLocalDecl(src, patt);
+    assertGlobalDecl(src, patt);
+    assertBlockDecl(src, patt);
+}
+
+function assertError(src, errorType) {
+    try {
+        Reflect.parse(src);
+    } catch (e) {
+        return;
+    }
+    throw new Error("expected " + errorType.name + " for " + uneval(src));
+}
+
+
+// general tests
+
+// NB: These are useful but for now jit-test doesn't do I/O reliably.
+
+//program(_).assert(Reflect.parse(snarf('data/flapjax.txt')));
+//program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt')));
+//program(_).assert(Reflect.parse(snarf('data/prototype.js')));
+//program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js')));
+//program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js')));
+
+
+// declarations
+
+assertDecl("var x = 1, y = 2, z = 3",
+           varDecl([declarator(ident("x"), lit(1)),
+                    declarator(ident("y"), lit(2)),
+                    declarator(ident("z"), lit(3))]));
+assertDecl("var x, y, z",
+           varDecl([declarator(ident("x"), null),
+                    declarator(ident("y"), null),
+                    declarator(ident("z"), null)]));
+assertDecl("function foo() { }",
+           funDecl(ident("foo"), [], blockStmt([])));
+assertDecl("function foo() { return 42 }",
+           funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
+
+
+// Bug 591437: rebound args have their defs turned into uses
+assertDecl("function f(a) { function a() { } }",
+           funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
+assertDecl("function f(a,b,c) { function b() { } }",
+           funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
+
+// expressions
+
+assertExpr("true", lit(true));
+assertExpr("false", lit(false));
+assertExpr("42", lit(42));
+assertExpr("(/asdf/)", lit(/asdf/));
+assertExpr("this", thisExpr);
+assertExpr("foo", ident("foo"));
+assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
+assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
+assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
+assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
+assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
+assertExpr("(++x)", updExpr("++", ident("x"), true));
+assertExpr("(x++)", updExpr("++", ident("x"), false));
+assertExpr("(+x)", unExpr("+", ident("x")));
+assertExpr("(-x)", unExpr("-", ident("x")));
+assertExpr("(!x)", unExpr("!", ident("x")));
+assertExpr("(~x)", unExpr("~", ident("x")));
+assertExpr("(delete x)", unExpr("delete", ident("x")));
+assertExpr("(typeof x)", unExpr("typeof", ident("x")));
+assertExpr("(void x)", unExpr("void", ident("x")));
+assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
+assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
+assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
+assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
+assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
+assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
+assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
+assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
+assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
+assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
+assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
+assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
+assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z")));
+assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
+assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z")));
+assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
+assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
+assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
+assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
+assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
+assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
+assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
+assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
+assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
+assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
+assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
+assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
+assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
+assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
+assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
+assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
+assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
+assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
+assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
+assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
+assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
+assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
+assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
+assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
+assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
+assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
+assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
+assertExpr("(new Object)", newExpr(ident("Object"), []));
+assertExpr("(new Object())", newExpr(ident("Object"), []));
+assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
+assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
+assertExpr("(String())", callExpr(ident("String"), []));
+assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
+assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
+assertExpr("[]", arrExpr([]));
+assertExpr("[1]", arrExpr([lit(1)]));
+assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
+assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
+assertExpr("[1,,2,3]", arrExpr([lit(1),,lit(2),lit(3)]));
+assertExpr("[1,,,2,3]", arrExpr([lit(1),,,lit(2),lit(3)]));
+assertExpr("[1,,,2,,3]", arrExpr([lit(1),,,lit(2),,lit(3)]));
+assertExpr("[1,,,2,,,3]", arrExpr([lit(1),,,lit(2),,,lit(3)]));
+assertExpr("[,1,2,3]", arrExpr([,lit(1),lit(2),lit(3)]));
+assertExpr("[,,1,2,3]", arrExpr([,,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3]", arrExpr([,,,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3,]", arrExpr([,,,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined]));
+assertExpr("[,,,1,2,3,,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined,undefined]));
+assertExpr("[,,,,,]", arrExpr([undefined,undefined,undefined,undefined,undefined]));
+assertExpr("({})", objExpr([]));
+assertExpr("({x:1})", objExpr([objProp(ident("x"), lit(1), "init")]));
+assertExpr("({x:1, y:2})", objExpr([objProp(ident("x"), lit(1), "init"),
+                                    objProp(ident("y"), lit(2), "init")]));
+assertExpr("({x:1, y:2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"),
+                                         objProp(ident("y"), lit(2), "init"),
+                                         objProp(ident("z"), lit(3), "init") ]));
+assertExpr("({x:1, 'y':2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"),
+                                           objProp(lit("y"), lit(2), "init"),
+                                           objProp(ident("z"), lit(3), "init") ]));
+assertExpr("({'x':1, 'y':2, z:3})", objExpr([objProp(lit("x"), lit(1), "init"),
+                                             objProp(lit("y"), lit(2), "init"),
+                                             objProp(ident("z"), lit(3), "init") ]));
+assertExpr("({'x':1, 'y':2, 3:3})", objExpr([objProp(lit("x"), lit(1), "init"),
+                                             objProp(lit("y"), lit(2), "init"),
+                                             objProp(lit(3), lit(3), "init") ]));
+
+// Bug 571617: eliminate constant-folding
+assertExpr("2 + 3", binExpr("+", lit(2), lit(3)));
+
+// Bug 632026: constant-folding
+assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a"))));
+
+// Bug 632056: constant-folding
+program([exprStmt(ident("f")),
+         ifStmt(lit(1),
+                funDecl(ident("f"), [], blockStmt([])),
+                null)]).assert(Reflect.parse("f; if (1) function f(){}"));
+
+// statements
+
+assertStmt("throw 42", throwStmt(lit(42)));
+assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
+assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (var x; y; z) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
+assertStmt("for (var x; ; z) break", forStmt(varDecl([declarator(ident("x"), null)]), null, ident("z"), breakStmt(null)));
+assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), null, ident("z"), breakStmt(null)));
+assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x; y; ) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([declarator(ident("x"),lit(42))]), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x in y) break", forInStmt(varDecl([declarator(ident("x"),null)]), ident("y"), breakStmt(null)));
+assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
+assertStmt("{ }", blockStmt([]));
+assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
+assertStmt(";", emptyStmt);
+assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
+assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
+assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
+           ifStmt(ident("foo"),
+                  blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
+                  null));
+assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
+           ifStmt(ident("foo"),
+                  blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
+                  exprStmt(lit(true))));
+assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
+assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
+assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
+assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
+assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
+assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
+assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
+assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
+assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
+           switchStmt(ident("foo"),
+                      [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
+                        caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
+                        defaultClause([ exprStmt(lit(3)) ]) ]));
+assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
+           switchStmt(ident("foo"),
+                      [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
+                        caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
+                        defaultClause([ exprStmt(lit(3)) ]),
+                        caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
+assertStmt("try { } catch (e) { }",
+           tryStmt(blockStmt([]),
+                   [],
+                   [ catchClause(ident("e"), null, blockStmt([])) ],
+                   null));
+assertStmt("try { } catch (e) { } finally { }",
+           tryStmt(blockStmt([]),
+                   [],
+                   [ catchClause(ident("e"), null, blockStmt([])) ],
+                   blockStmt([])));
+assertStmt("try { } finally { }",
+           tryStmt(blockStmt([]),
+                   [],
+                   [],
+                   blockStmt([])));
+
+// redeclarations (TOK_NAME nodes with lexdef)
+
+assertStmt("function f() { function g() { } function g() { } }",
+           funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
+                                              funDecl(ident("g"), [], blockStmt([]))])));
+
+assertStmt("function f() { function g() { } function g() { return 42 } }",
+           funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
+                                              funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
+
+assertStmt("function f() { var x = 42; var x = 43; }",
+           funDecl(ident("f"), [], blockStmt([varDecl([declarator(ident("x"),lit(42))]),
+                                              varDecl([declarator(ident("x"),lit(43))])])));
+
+// getters and setters
+
+ assertExpr("({ get x() { return 42 } })",
+            objExpr([ objProp(ident("x"),
+                              funExpr(null, [], blockStmt([returnStmt(lit(42))])),
+                              "get" ) ]));
+ assertExpr("({ set x(v) { return 42 } })",
+            objExpr([ objProp(ident("x"),
+                              funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])),
+                              "set" ) ]));
+
+}
+
+exports.testReflect = testReflect;
+
+}(typeof exports === 'undefined' ? this : exports));
diff --git a/node_modules/esprima/test/run.js b/node_modules/esprima/test/run.js
new file mode 100644
index 0000000000000000000000000000000000000000..32ca3faa4f6581dc0f7824d3fb7199cdf666b5a1
--- /dev/null
+++ b/node_modules/esprima/test/run.js
@@ -0,0 +1,66 @@
+/*
+  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint node:true */
+
+(function () {
+    'use strict';
+
+    var child = require('child_process'),
+        nodejs = '"' + process.execPath + '"',
+        ret = 0,
+        suites,
+        index;
+
+    suites = [
+        'runner',
+        'compat'
+    ];
+
+    function nextTest() {
+        var suite = suites[index];
+
+        if (index < suites.length) {
+            child.exec(nodejs + ' ./test/' + suite + '.js', function (err, stdout, stderr) {
+                if (stdout) {
+                    process.stdout.write(suite + ': ' + stdout);
+                }
+                if (stderr) {
+                    process.stderr.write(suite + ': ' + stderr);
+                }
+                if (err) {
+                    ret = err.code;
+                }
+                index += 1;
+                nextTest();
+            });
+        } else {
+            process.exit(ret);
+        }
+    }
+
+    index = 0;
+    nextTest();
+}());
diff --git a/node_modules/esprima/test/runner.js b/node_modules/esprima/test/runner.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1a3fc9bf05d489efa7ba13c00b6ba21756120db
--- /dev/null
+++ b/node_modules/esprima/test/runner.js
@@ -0,0 +1,387 @@
+/*
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
+  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2011 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2011 Arpad Borsos <arpad.borsos@googlemail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint browser:true node:true */
+/*global esprima:true, testFixture:true */
+
+var runTests;
+
+// Special handling for regular expression literal since we need to
+// convert it to a string literal, otherwise it will be decoded
+// as object "{}" and the regular expression would be lost.
+function adjustRegexLiteral(key, value) {
+    'use strict';
+    if (key === 'value' && value instanceof RegExp) {
+        value = value.toString();
+    }
+    return value;
+}
+
+function NotMatchingError(expected, actual) {
+    'use strict';
+    Error.call(this, 'Expected ');
+    this.expected = expected;
+    this.actual = actual;
+}
+NotMatchingError.prototype = new Error();
+
+function errorToObject(e) {
+    'use strict';
+    var msg = e.toString();
+
+    // Opera 9.64 produces an non-standard string in toString().
+    if (msg.substr(0, 6) !== 'Error:') {
+        if (typeof e.message === 'string') {
+            msg = 'Error: ' + e.message;
+        }
+    }
+
+    return {
+        index: e.index,
+        lineNumber: e.lineNumber,
+        column: e.column,
+        message: msg
+    };
+}
+
+function testParse(esprima, code, syntax) {
+    'use strict';
+    var expected, tree, actual, options, StringObject, i, len, err;
+
+    // alias, so that JSLint does not complain.
+    StringObject = String;
+
+    options = {
+        comment: (typeof syntax.comments !== 'undefined'),
+        range: true,
+        loc: true,
+        tokens: (typeof syntax.tokens !== 'undefined'),
+        raw: true,
+        tolerant: (typeof syntax.errors !== 'undefined')
+    };
+
+    if (typeof syntax.tokens !== 'undefined') {
+        if (syntax.tokens.length > 0) {
+            options.range = (typeof syntax.tokens[0].range !== 'undefined');
+            options.loc = (typeof syntax.tokens[0].loc !== 'undefined');
+        }
+    }
+
+    if (typeof syntax.comments !== 'undefined') {
+        if (syntax.comments.length > 0) {
+            options.range = (typeof syntax.comments[0].range !== 'undefined');
+            options.loc = (typeof syntax.comments[0].loc !== 'undefined');
+        }
+    }
+
+    expected = JSON.stringify(syntax, null, 4);
+    try {
+        tree = esprima.parse(code, options);
+        tree = (options.comment || options.tokens || options.tolerant) ? tree : tree.body[0];
+
+        if (options.tolerant) {
+            for (i = 0, len = tree.errors.length; i < len; i += 1) {
+                tree.errors[i] = errorToObject(tree.errors[i]);
+            }
+        }
+
+        actual = JSON.stringify(tree, adjustRegexLiteral, 4);
+
+        // Only to ensure that there is no error when using string object.
+        esprima.parse(new StringObject(code), options);
+
+    } catch (e) {
+        throw new NotMatchingError(expected, e.toString());
+    }
+    if (expected !== actual) {
+        throw new NotMatchingError(expected, actual);
+    }
+
+    function filter(key, value) {
+        if (key === 'value' && value instanceof RegExp) {
+            value = value.toString();
+        }
+        return (key === 'loc' || key === 'range') ? undefined : value;
+    }
+
+    if (options.tolerant) {
+        return;
+    }
+
+
+    // Check again without any location info.
+    options.range = false;
+    options.loc = false;
+    expected = JSON.stringify(syntax, filter, 4);
+    try {
+        tree = esprima.parse(code, options);
+        tree = (options.comment || options.tokens) ? tree : tree.body[0];
+
+        if (options.tolerant) {
+            for (i = 0, len = tree.errors.length; i < len; i += 1) {
+                tree.errors[i] = errorToObject(tree.errors[i]);
+            }
+        }
+
+        actual = JSON.stringify(tree, filter, 4);
+    } catch (e) {
+        throw new NotMatchingError(expected, e.toString());
+    }
+    if (expected !== actual) {
+        throw new NotMatchingError(expected, actual);
+    }
+}
+
+function testError(esprima, code, exception) {
+    'use strict';
+    var i, options, expected, actual, handleInvalidRegexFlag;
+
+    // Different parsing options should give the same error.
+    options = [
+        {},
+        { comment: true },
+        { raw: true },
+        { raw: true, comment: true }
+    ];
+
+    // If handleInvalidRegexFlag is true, an invalid flag in a regular expression
+    // will throw an exception. In some old version V8, this is not the case
+    // and hence handleInvalidRegexFlag is false.
+    handleInvalidRegexFlag = false;
+    try {
+        'test'.match(new RegExp('[a-z]', 'x'));
+    } catch (e) {
+        handleInvalidRegexFlag = true;
+    }
+
+    expected = JSON.stringify(exception);
+
+    for (i = 0; i < options.length; i += 1) {
+
+        try {
+            esprima.parse(code, options[i]);
+        } catch (e) {
+            actual = JSON.stringify(errorToObject(e));
+        }
+
+        if (expected !== actual) {
+
+            // Compensate for old V8 which does not handle invalid flag.
+            if (exception.message.indexOf('Invalid regular expression') > 0) {
+                if (typeof actual === 'undefined' && !handleInvalidRegexFlag) {
+                    return;
+                }
+            }
+
+            throw new NotMatchingError(expected, actual);
+        }
+
+    }
+}
+
+function testAPI(esprima, code, result) {
+    'use strict';
+    var expected, res, actual;
+
+    expected = JSON.stringify(result.result, null, 4);
+    try {
+        if (typeof result.property !== 'undefined') {
+            res = esprima[result.property];
+        } else {
+            res = esprima[result.call].apply(esprima, result.args);
+        }
+        actual = JSON.stringify(res, adjustRegexLiteral, 4);
+    } catch (e) {
+        throw new NotMatchingError(expected, e.toString());
+    }
+    if (expected !== actual) {
+        throw new NotMatchingError(expected, actual);
+    }
+}
+
+function runTest(esprima, code, result) {
+    'use strict';
+    if (result.hasOwnProperty('lineNumber')) {
+        testError(esprima, code, result);
+    } else if (result.hasOwnProperty('result')) {
+        testAPI(esprima, code, result);
+    } else {
+        testParse(esprima, code, result);
+    }
+}
+
+if (typeof window !== 'undefined') {
+    // Run all tests in a browser environment.
+    runTests = function () {
+        'use strict';
+        var total = 0,
+            failures = 0,
+            category,
+            fixture,
+            source,
+            tick,
+            expected,
+            index,
+            len;
+
+        function setText(el, str) {
+            if (typeof el.innerText === 'string') {
+                el.innerText = str;
+            } else {
+                el.textContent = str;
+            }
+        }
+
+        function startCategory(category) {
+            var report, e;
+            report = document.getElementById('report');
+            e = document.createElement('h4');
+            setText(e, category);
+            report.appendChild(e);
+        }
+
+        function reportSuccess(code) {
+            var report, e;
+            report = document.getElementById('report');
+            e = document.createElement('pre');
+            e.setAttribute('class', 'code');
+            setText(e, code);
+            report.appendChild(e);
+        }
+
+        function reportFailure(code, expected, actual) {
+            var report, e;
+
+            report = document.getElementById('report');
+
+            e = document.createElement('p');
+            setText(e, 'Code:');
+            report.appendChild(e);
+
+            e = document.createElement('pre');
+            e.setAttribute('class', 'code');
+            setText(e, code);
+            report.appendChild(e);
+
+            e = document.createElement('p');
+            setText(e, 'Expected');
+            report.appendChild(e);
+
+            e = document.createElement('pre');
+            e.setAttribute('class', 'expected');
+            setText(e, expected);
+            report.appendChild(e);
+
+            e = document.createElement('p');
+            setText(e, 'Actual');
+            report.appendChild(e);
+
+            e = document.createElement('pre');
+            e.setAttribute('class', 'actual');
+            setText(e, actual);
+            report.appendChild(e);
+        }
+
+        setText(document.getElementById('version'), esprima.version);
+
+        tick = new Date();
+        for (category in testFixture) {
+            if (testFixture.hasOwnProperty(category)) {
+                startCategory(category);
+                fixture = testFixture[category];
+                for (source in fixture) {
+                    if (fixture.hasOwnProperty(source)) {
+                        expected = fixture[source];
+                        total += 1;
+                        try {
+                            runTest(esprima, source, expected);
+                            reportSuccess(source, JSON.stringify(expected, null, 4));
+                        } catch (e) {
+                            failures += 1;
+                            reportFailure(source, e.expected, e.actual);
+                        }
+                    }
+                }
+            }
+        }
+        tick = (new Date()) - tick;
+
+        if (failures > 0) {
+            setText(document.getElementById('status'), total + ' tests. ' +
+                'Failures: ' + failures + '. ' + tick + ' ms');
+        } else {
+            setText(document.getElementById('status'), total + ' tests. ' +
+                'No failure. ' + tick + ' ms');
+        }
+    };
+} else {
+    (function () {
+        'use strict';
+
+        var esprima = require('../esprima'),
+            vm = require('vm'),
+            fs = require('fs'),
+            total = 0,
+            failures = [],
+            tick = new Date(),
+            expected,
+            header;
+
+        vm.runInThisContext(fs.readFileSync(__dirname + '/test.js', 'utf-8'));
+
+        Object.keys(testFixture).forEach(function (category) {
+            Object.keys(testFixture[category]).forEach(function (source) {
+                total += 1;
+                expected = testFixture[category][source];
+                try {
+                    runTest(esprima, source, expected);
+                } catch (e) {
+                    e.source = source;
+                    failures.push(e);
+                }
+            });
+        });
+        tick = (new Date()) - tick;
+
+        header = total + ' tests. ' + failures.length + ' failures. ' +
+            tick + ' ms';
+        if (failures.length) {
+            console.error(header);
+            failures.forEach(function (failure) {
+                console.error(failure.source + ': Expected\n    ' +
+                    failure.expected.split('\n').join('\n    ') +
+                    '\nto match\n    ' + failure.actual);
+            });
+        } else {
+            console.log(header);
+        }
+        process.exit(failures.length === 0 ? 0 : 1);
+    }());
+}
diff --git a/node_modules/esprima/test/test.js b/node_modules/esprima/test/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ceee54b749716bac4b4e159ca4f5e01e88cdc67
--- /dev/null
+++ b/node_modules/esprima/test/test.js
@@ -0,0 +1,20238 @@
+/*
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
+  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2011 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2011 Arpad Borsos <arpad.borsos@googlemail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+var testFixture = {
+
+    'Primary Expression': {
+
+        'this\n': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'ThisExpression',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 0 }
+                }
+            }],
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 0 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'this',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            }]
+        },
+
+        'null\n': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: null,
+                    raw: 'null',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 0 }
+                }
+            }],
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 0 }
+            },
+            tokens: [{
+                type: 'Null',
+                value: 'null',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            }]
+        },
+
+        '\n    42\n\n': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 2, column: 4 },
+                        end: { line: 2, column: 6 }
+                    }
+                },
+                range: [5, 9],
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 4, column: 0 }
+                }
+            }],
+            range: [5, 9],
+            loc: {
+                start: { line: 2, column: 4 },
+                end: { line: 4, column: 0 }
+            },
+            tokens: [{
+                type: 'Numeric',
+                value: '42',
+                range: [5, 7],
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 2, column: 6 }
+                }
+            }]
+        },
+
+        '(1 + 2 ) * 3': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '*',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '+',
+                    left: {
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [1, 2],
+                        loc: {
+                            start: { line: 1, column: 1 },
+                            end: { line: 1, column: 2 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 2,
+                        raw: '2',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [1, 6],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 3,
+                    raw: '3',
+                    range: [11, 12],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 12],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 12 }
+                }
+            },
+            range: [0, 12],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 12 }
+            }
+        }
+
+    },
+
+    'Grouping Operator': {
+
+        '(1) + (2  ) + 3': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '+',
+                    left: {
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [1, 2],
+                        loc: {
+                            start: { line: 1, column: 1 },
+                            end: { line: 1, column: 2 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 2,
+                        raw: '2',
+                        range: [7, 8],
+                        loc: {
+                            start: { line: 1, column: 7 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    range: [0, 11],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 3,
+                    raw: '3',
+                    range: [14, 15],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 15 }
+                    }
+                },
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        },
+
+        '4 + 5 << (6)': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<<',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '+',
+                    left: {
+                        type: 'Literal',
+                        value: 4,
+                        raw: '4',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 5,
+                        raw: '5',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 6,
+                    raw: '6',
+                    range: [10, 11],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 12],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 12 }
+                }
+            },
+            range: [0, 12],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 12 }
+            }
+        }
+
+    },
+
+    'Array Initializer': {
+
+        'x = []': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'ArrayExpression',
+                        elements: [],
+                        range: [4, 6],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [0, 6],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            }],
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            },
+            tokens: [{
+                type: 'Identifier',
+                value: 'x',
+                range: [0, 1],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 1 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [2, 3],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '[',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: ']',
+                range: [5, 6],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 6 }
+                }
+            }]
+        },
+
+        'x = [ ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [4, 7],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x = [ 42 ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [{
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [6, 8],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 8 }
+                        }
+                    }],
+                    range: [4, 10],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                range: [0, 10],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            range: [0, 10],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 10 }
+            }
+        },
+
+        'x = [ 42, ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [{
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [6, 8],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 8 }
+                        }
+                    }],
+                    range: [4, 11],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'x = [ ,, 42 ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [
+                        null,
+                        null,
+                        {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [9, 11],
+                            loc: {
+                                start: { line: 1, column: 9 },
+                                end: { line: 1, column: 11 }
+                            }
+                        }],
+                    range: [4, 13],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'x = [ 1, 2, 3, ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [{
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    }, {
+                        type: 'Literal',
+                        value: 2,
+                        raw: '2',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    }, {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [12, 13],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 13 }
+                        }
+                    }],
+                    range: [4, 16],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        'x = [ 1, 2,, 3, ]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [{
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    }, {
+                        type: 'Literal',
+                        value: 2,
+                        raw: '2',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    }, null, {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [13, 14],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 14 }
+                        }
+                    }],
+                    range: [4, 17],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        '日本語 = []': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: '日本語',
+                    range: [0, 3],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [6, 8],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'T\u203F = []': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'T\u203F',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'T\u200C = []': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'T\u200C',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'T\u200D = []': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'T\u200D',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '\u2163\u2161 = []': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: '\u2163\u2161',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '\u2163\u2161\u200A=\u2009[]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: '\u2163\u2161',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        }
+
+    },
+
+    'Object Initializer': {
+
+        'x = {}': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [],
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x = { }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [],
+                    range: [4, 7],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x = { answer: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'answer',
+                            range: [6, 12],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [14, 16],
+                            loc: {
+                                start: { line: 1, column: 14 },
+                                end: { line: 1, column: 16 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 16],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 16 }
+                        }
+                    }],
+                    range: [4, 18],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                range: [0, 18],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            }
+        },
+
+        'x = { if: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'if',
+                            range: [6, 8],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 8 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [10, 12],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 12],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 12 }
+                        }
+                    }],
+                    range: [4, 14],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        'x = { true: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'true',
+                            range: [6, 10],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 10 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [12, 14],
+                            loc: {
+                                start: { line: 1, column: 12 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 14],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 14 }
+                        }
+                    }],
+                    range: [4, 16],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        'x = { false: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'false',
+                            range: [6, 11],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 11 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [13, 15],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 15],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 15 }
+                        }
+                    }],
+                    range: [4, 17],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        'x = { null: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'null',
+                            range: [6, 10],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 10 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [12, 14],
+                            loc: {
+                                start: { line: 1, column: 12 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 14],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 14 }
+                        }
+                    }],
+                    range: [4, 16],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        'x = { "answer": 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Literal',
+                            value: 'answer',
+                            raw: '"answer"',
+                            range: [6, 14],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [16, 18],
+                            loc: {
+                                start: { line: 1, column: 16 },
+                                end: { line: 1, column: 18 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 18],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 18 }
+                        }
+                    }],
+                    range: [4, 20],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                range: [0, 20],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 20 }
+                }
+            },
+            range: [0, 20],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 20 }
+            }
+        },
+
+        'x = { x: 1, x: 2 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [
+                        {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [6, 7],
+                                loc: {
+                                    start: { line: 1, column: 6 },
+                                    end: { line: 1, column: 7 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 1,
+                                raw: '1',
+                                range: [9, 10],
+                                loc: {
+                                    start: { line: 1, column: 9 },
+                                    end: { line: 1, column: 10 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [6, 10],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 10 }
+                            }
+                        },
+                        {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [12, 13],
+                                loc: {
+                                    start: { line: 1, column: 12 },
+                                    end: { line: 1, column: 13 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 2,
+                                raw: '2',
+                                range: [15, 16],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 16 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [12, 16],
+                            loc: {
+                                start: { line: 1, column: 12 },
+                                end: { line: 1, column: 16 }
+                            }
+                        }
+                    ],
+                    range: [4, 18],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                range: [0, 18],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            }
+        },
+
+        'x = { get width() { return m_width } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'width',
+                            range: [10, 15],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ReturnStatement',
+                                    argument: {
+                                        type: 'Identifier',
+                                        name: 'm_width',
+                                        range: [27, 34],
+                                        loc: {
+                                            start: { line: 1, column: 27 },
+                                            end: { line: 1, column: 34 }
+                                        }
+                                    },
+                                    range: [20, 35],
+                                    loc: {
+                                        start: { line: 1, column: 20 },
+                                        end: { line: 1, column: 35 }
+                                    }
+                                }],
+                                range: [18, 36],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 36 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [18, 36],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 36 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 36],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 36 }
+                        }
+                    }],
+                    range: [4, 38],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                range: [0, 38],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 38 }
+                }
+            },
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            }
+        },
+
+        'x = { get undef() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'undef',
+                            range: [10, 15],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [18, 20],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 20 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [18, 20],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 20 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 20],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 20 }
+                        }
+                    }],
+                    range: [4, 22],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                range: [0, 22],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        'x = { get if() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'if',
+                            range: [10, 12],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [15, 17],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 17 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [15, 17],
+                            loc: {
+                                start: { line: 1, column: 15 },
+                                end: { line: 1, column: 17 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 17],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 17 }
+                        }
+                    }],
+                    range: [4, 19],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 19 }
+                    }
+                },
+                range: [0, 19],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 19 }
+                }
+            },
+            range: [0, 19],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 19 }
+            }
+        },
+
+        'x = { get true() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'true',
+                            range: [10, 14],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [17, 19],
+                                loc: {
+                                    start: { line: 1, column: 17 },
+                                    end: { line: 1, column: 19 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [17, 19],
+                            loc: {
+                                start: { line: 1, column: 17 },
+                                end: { line: 1, column: 19 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 19],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 19 }
+                        }
+                    }],
+                    range: [4, 21],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            },
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            }
+        },
+
+        'x = { get false() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'false',
+                            range: [10, 15],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [18, 20],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 20 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [18, 20],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 20 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 20],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 20 }
+                        }
+                    }],
+                    range: [4, 22],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                range: [0, 22],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        'x = { get null() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'null',
+                            range: [10, 14],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [17, 19],
+                                loc: {
+                                    start: { line: 1, column: 17 },
+                                    end: { line: 1, column: 19 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [17, 19],
+                            loc: {
+                                start: { line: 1, column: 17 },
+                                end: { line: 1, column: 19 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 19],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 19 }
+                        }
+                    }],
+                    range: [4, 21],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            },
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            }
+        },
+
+        'x = { get "undef"() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Literal',
+                            value: 'undef',
+                            raw: '"undef"',
+                            range: [10, 17],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 17 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [20, 22],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 22 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [20, 22],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 22 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 22],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 22 }
+                        }
+                    }],
+                    range: [4, 24],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                range: [0, 24],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'x = { get 10() {} }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Literal',
+                            value: 10,
+                            raw: '10',
+                            range: [10, 12],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [15, 17],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 17 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [15, 17],
+                            loc: {
+                                start: { line: 1, column: 15 },
+                                end: { line: 1, column: 17 }
+                            }
+                        },
+                        kind: 'get',
+                        range: [6, 17],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 17 }
+                        }
+                    }],
+                    range: [4, 19],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 19 }
+                    }
+                },
+                range: [0, 19],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 19 }
+                }
+            },
+            range: [0, 19],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 19 }
+            }
+        },
+
+        'x = { set width(w) { m_width = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'width',
+                            range: [10, 15],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [16, 17],
+                                loc: {
+                                    start: { line: 1, column: 16 },
+                                    end: { line: 1, column: 17 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_width',
+                                            range: [21, 28],
+                                            loc: {
+                                                start: { line: 1, column: 21 },
+                                                end: { line: 1, column: 28 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [31, 32],
+                                            loc: {
+                                                start: { line: 1, column: 31 },
+                                                end: { line: 1, column: 32 }
+                                            }
+                                        },
+                                        range: [21, 32],
+                                        loc: {
+                                            start: { line: 1, column: 21 },
+                                            end: { line: 1, column: 32 }
+                                        }
+                                    },
+                                    range: [21, 33],
+                                    loc: {
+                                        start: { line: 1, column: 21 },
+                                        end: { line: 1, column: 33 }
+                                    }
+                                }],
+                                range: [19, 34],
+                                loc: {
+                                    start: { line: 1, column: 19 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [19, 34],
+                            loc: {
+                                start: { line: 1, column: 19 },
+                                end: { line: 1, column: 34 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 34],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 34 }
+                        }
+                    }],
+                    range: [4, 36],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [0, 36],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'x = { set if(w) { m_if = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'if',
+                            range: [10, 12],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [13, 14],
+                                loc: {
+                                    start: { line: 1, column: 13 },
+                                    end: { line: 1, column: 14 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_if',
+                                            range: [18, 22],
+                                            loc: {
+                                                start: { line: 1, column: 18 },
+                                                end: { line: 1, column: 22 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [25, 26],
+                                            loc: {
+                                                start: { line: 1, column: 25 },
+                                                end: { line: 1, column: 26 }
+                                            }
+                                        },
+                                        range: [18, 26],
+                                        loc: {
+                                            start: { line: 1, column: 18 },
+                                            end: { line: 1, column: 26 }
+                                        }
+                                    },
+                                    range: [18, 27],
+                                    loc: {
+                                        start: { line: 1, column: 18 },
+                                        end: { line: 1, column: 27 }
+                                    }
+                                }],
+                                range: [16, 28],
+                                loc: {
+                                    start: { line: 1, column: 16 },
+                                    end: { line: 1, column: 28 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [16, 28],
+                            loc: {
+                                start: { line: 1, column: 16 },
+                                end: { line: 1, column: 28 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 28],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 28 }
+                        }
+                    }],
+                    range: [4, 30],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 30 }
+                    }
+                },
+                range: [0, 30],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 30 }
+                }
+            },
+            range: [0, 30],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 30 }
+            }
+        },
+
+        'x = { set true(w) { m_true = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'true',
+                            range: [10, 14],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [15, 16],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 16 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_true',
+                                            range: [20, 26],
+                                            loc: {
+                                                start: { line: 1, column: 20 },
+                                                end: { line: 1, column: 26 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [29, 30],
+                                            loc: {
+                                                start: { line: 1, column: 29 },
+                                                end: { line: 1, column: 30 }
+                                            }
+                                        },
+                                        range: [20, 30],
+                                        loc: {
+                                            start: { line: 1, column: 20 },
+                                            end: { line: 1, column: 30 }
+                                        }
+                                    },
+                                    range: [20, 31],
+                                    loc: {
+                                        start: { line: 1, column: 20 },
+                                        end: { line: 1, column: 31 }
+                                    }
+                                }],
+                                range: [18, 32],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 32 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [18, 32],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 32 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 32],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 32 }
+                        }
+                    }],
+                    range: [4, 34],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                range: [0, 34],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 34 }
+                }
+            },
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        },
+
+        'x = { set false(w) { m_false = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'false',
+                            range: [10, 15],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 15 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [16, 17],
+                                loc: {
+                                    start: { line: 1, column: 16 },
+                                    end: { line: 1, column: 17 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_false',
+                                            range: [21, 28],
+                                            loc: {
+                                                start: { line: 1, column: 21 },
+                                                end: { line: 1, column: 28 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [31, 32],
+                                            loc: {
+                                                start: { line: 1, column: 31 },
+                                                end: { line: 1, column: 32 }
+                                            }
+                                        },
+                                        range: [21, 32],
+                                        loc: {
+                                            start: { line: 1, column: 21 },
+                                            end: { line: 1, column: 32 }
+                                        }
+                                    },
+                                    range: [21, 33],
+                                    loc: {
+                                        start: { line: 1, column: 21 },
+                                        end: { line: 1, column: 33 }
+                                    }
+                                }],
+                                range: [19, 34],
+                                loc: {
+                                    start: { line: 1, column: 19 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [19, 34],
+                            loc: {
+                                start: { line: 1, column: 19 },
+                                end: { line: 1, column: 34 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 34],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 34 }
+                        }
+                    }],
+                    range: [4, 36],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [0, 36],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'x = { set null(w) { m_null = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'null',
+                            range: [10, 14],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [15, 16],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 16 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_null',
+                                            range: [20, 26],
+                                            loc: {
+                                                start: { line: 1, column: 20 },
+                                                end: { line: 1, column: 26 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [29, 30],
+                                            loc: {
+                                                start: { line: 1, column: 29 },
+                                                end: { line: 1, column: 30 }
+                                            }
+                                        },
+                                        range: [20, 30],
+                                        loc: {
+                                            start: { line: 1, column: 20 },
+                                            end: { line: 1, column: 30 }
+                                        }
+                                    },
+                                    range: [20, 31],
+                                    loc: {
+                                        start: { line: 1, column: 20 },
+                                        end: { line: 1, column: 31 }
+                                    }
+                                }],
+                                range: [18, 32],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 32 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [18, 32],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 32 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 32],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 32 }
+                        }
+                    }],
+                    range: [4, 34],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                range: [0, 34],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 34 }
+                }
+            },
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        },
+
+        'x = { set "null"(w) { m_null = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Literal',
+                            value: 'null',
+                            raw: '"null"',
+                            range: [10, 16],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 16 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [17, 18],
+                                loc: {
+                                    start: { line: 1, column: 17 },
+                                    end: { line: 1, column: 18 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_null',
+                                            range: [22, 28],
+                                            loc: {
+                                                start: { line: 1, column: 22 },
+                                                end: { line: 1, column: 28 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [31, 32],
+                                            loc: {
+                                                start: { line: 1, column: 31 },
+                                                end: { line: 1, column: 32 }
+                                            }
+                                        },
+                                        range: [22, 32],
+                                        loc: {
+                                            start: { line: 1, column: 22 },
+                                            end: { line: 1, column: 32 }
+                                        }
+                                    },
+                                    range: [22, 33],
+                                    loc: {
+                                        start: { line: 1, column: 22 },
+                                        end: { line: 1, column: 33 }
+                                    }
+                                }],
+                                range: [20, 34],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [20, 34],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 34 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 34],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 34 }
+                        }
+                    }],
+                    range: [4, 36],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [0, 36],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'x = { set 10(w) { m_null = w } }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Literal',
+                            value: 10,
+                            raw: '10',
+                            range: [10, 12],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [{
+                                type: 'Identifier',
+                                name: 'w',
+                                range: [13, 14],
+                                loc: {
+                                    start: { line: 1, column: 13 },
+                                    end: { line: 1, column: 14 }
+                                }
+                            }],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [{
+                                    type: 'ExpressionStatement',
+                                    expression: {
+                                        type: 'AssignmentExpression',
+                                        operator: '=',
+                                        left: {
+                                            type: 'Identifier',
+                                            name: 'm_null',
+                                            range: [18, 24],
+                                            loc: {
+                                                start: { line: 1, column: 18 },
+                                                end: { line: 1, column: 24 }
+                                            }
+                                        },
+                                        right: {
+                                            type: 'Identifier',
+                                            name: 'w',
+                                            range: [27, 28],
+                                            loc: {
+                                                start: { line: 1, column: 27 },
+                                                end: { line: 1, column: 28 }
+                                            }
+                                        },
+                                        range: [18, 28],
+                                        loc: {
+                                            start: { line: 1, column: 18 },
+                                            end: { line: 1, column: 28 }
+                                        }
+                                    },
+                                    range: [18, 29],
+                                    loc: {
+                                        start: { line: 1, column: 18 },
+                                        end: { line: 1, column: 29 }
+                                    }
+                                }],
+                                range: [16, 30],
+                                loc: {
+                                    start: { line: 1, column: 16 },
+                                    end: { line: 1, column: 30 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [16, 30],
+                            loc: {
+                                start: { line: 1, column: 16 },
+                                end: { line: 1, column: 30 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [6, 30],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 30 }
+                        }
+                    }],
+                    range: [4, 32],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 32 }
+                    }
+                },
+                range: [0, 32],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 32 }
+                }
+            },
+            range: [0, 32],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 32 }
+            }
+        },
+
+        'x = { get: 42 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'get',
+                            range: [6, 9],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 9 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 42,
+                            raw: '42',
+                            range: [11, 13],
+                            loc: {
+                                start: { line: 1, column: 11 },
+                                end: { line: 1, column: 13 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 13],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 13 }
+                        }
+                    }],
+                    range: [4, 15],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 15 }
+                    }
+                },
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        },
+
+        'x = { set: 43 }': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 'set',
+                            range: [6, 9],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 9 }
+                            }
+                        },
+                        value: {
+                            type: 'Literal',
+                            value: 43,
+                            raw: '43',
+                            range: [11, 13],
+                            loc: {
+                                start: { line: 1, column: 11 },
+                                end: { line: 1, column: 13 }
+                            }
+                        },
+                        kind: 'init',
+                        range: [6, 13],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 13 }
+                        }
+                    }],
+                    range: [4, 15],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 15 }
+                    }
+                },
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        }
+
+    },
+
+    'Comments': {
+
+        '/* block comment */ 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 42,
+                raw: '42',
+                range: [20, 22],
+                loc: {
+                    start: { line: 1, column: 20 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [20, 22],
+            loc: {
+                start: { line: 1, column: 20 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        '42 /*The*/ /*Answer*/': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            },
+            comments: [{
+                type: 'Block',
+                value: 'The',
+                range: [3, 10],
+                loc: {
+                    start: { line: 1, column: 3 },
+                    end: { line: 1, column: 10 }
+                }
+            }, {
+                type: 'Block',
+                value: 'Answer',
+                range: [11, 21],
+                loc: {
+                    start: { line: 1, column: 11 },
+                    end: { line: 1, column: 21 }
+                }
+            }]
+        },
+
+        '42 /*the*/ /*answer*/': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [0, 2]
+                },
+                range: [0, 21]
+            }],
+            range: [0, 21],
+            comments: [{
+                type: 'Block',
+                value: 'the',
+                range: [3, 10]
+            }, {
+                type: 'Block',
+                value: 'answer',
+                range: [11, 21]
+            }]
+        },
+
+        '/* multiline\ncomment\nshould\nbe\nignored */ 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 42,
+                raw: '42',
+                range: [42, 44],
+                loc: {
+                    start: { line: 5, column: 11 },
+                    end: { line: 5, column: 13 }
+                }
+            },
+            range: [42, 44],
+            loc: {
+                start: { line: 5, column: 11 },
+                end: { line: 5, column: 13 }
+            }
+        },
+
+        '/*a\r\nb*/ 42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [9, 11],
+                    loc: {
+                        start: { line: 2, column: 4 },
+                        end: { line: 2, column: 6 }
+                    }
+                },
+                range: [9, 11],
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            range: [9, 11],
+            loc: {
+                start: { line: 2, column: 4 },
+                end: { line: 2, column: 6 }
+            },
+            comments: [{
+                type: 'Block',
+                value: 'a\r\nb',
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 3 }
+                }
+            }]
+        },
+
+        '/*a\rb*/ 42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [8, 10],
+                    loc: {
+                        start: { line: 2, column: 4 },
+                        end: { line: 2, column: 6 }
+                    }
+                },
+                range: [8, 10],
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            range: [8, 10],
+            loc: {
+                start: { line: 2, column: 4 },
+                end: { line: 2, column: 6 }
+            },
+            comments: [{
+                type: 'Block',
+                value: 'a\rb',
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 3 }
+                }
+            }]
+        },
+
+        '/*a\nb*/ 42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [8, 10],
+                    loc: {
+                        start: { line: 2, column: 4 },
+                        end: { line: 2, column: 6 }
+                    }
+                },
+                range: [8, 10],
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            range: [8, 10],
+            loc: {
+                start: { line: 2, column: 4 },
+                end: { line: 2, column: 6 }
+            },
+            comments: [{
+                type: 'Block',
+                value: 'a\nb',
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 3 }
+                }
+            }]
+        },
+
+        '/*a\nc*/ 42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    loc: {
+                        start: { line: 2, column: 4 },
+                        end: { line: 2, column: 6 }
+                    }
+                },
+                loc: {
+                    start: { line: 2, column: 4 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            loc: {
+                start: { line: 2, column: 4 },
+                end: { line: 2, column: 6 }
+            },
+            comments: [{
+                type: 'Block',
+                value: 'a\nc',
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 3 }
+                }
+            }]
+        },
+
+        '// line comment\n42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 42,
+                raw: '42',
+                range: [16, 18],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 2 }
+                }
+            },
+            range: [16, 18],
+            loc: {
+                start: { line: 2, column: 0 },
+                end: { line: 2, column: 2 }
+            }
+        },
+
+        '42 // line comment': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [0, 2],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                range: [0, 18],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 18 }
+                }
+            }],
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' line comment',
+                range: [3, 18],
+                loc: {
+                    start: { line: 1, column: 3 },
+                    end: { line: 1, column: 18 }
+                }
+            }]
+        },
+
+        '// Hello, world!\n42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [17, 19],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 2 }
+                    }
+                },
+                range: [17, 19],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 2 }
+                }
+            }],
+            range: [17, 19],
+            loc: {
+                start: { line: 2, column: 0 },
+                end: { line: 2, column: 2 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' Hello, world!',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }]
+        },
+
+        '// Hello, world!\n': {
+            type: 'Program',
+            body: [],
+            range: [17, 17],
+            loc: {
+                start: { line: 2, column: 0 },
+                end: { line: 2, column: 0 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' Hello, world!',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }]
+        },
+
+        '// Hallo, world!\n': {
+            type: 'Program',
+            body: [],
+            loc: {
+                start: { line: 2, column: 0 },
+                end: { line: 2, column: 0 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' Hallo, world!',
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }]
+        },
+
+        '//\n42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [3, 5],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 2 }
+                    }
+                },
+                range: [3, 5],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 2 }
+                }
+            }],
+            range: [3, 5],
+            loc: {
+                start: { line: 2, column: 0 },
+                end: { line: 2, column: 2 }
+            },
+            comments: [{
+                type: 'Line',
+                value: '',
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            }]
+        },
+
+        '//': {
+            type: 'Program',
+            body: [],
+            range: [2, 2],
+            loc: {
+                start: { line: 1, column: 2 },
+                end: { line: 1, column: 2 }
+            },
+            comments: [{
+                type: 'Line',
+                value: '',
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            }]
+        },
+
+        '// ': {
+            type: 'Program',
+            body: [],
+            range: [3, 3],
+            comments: [{
+                type: 'Line',
+                value: ' ',
+                range: [0, 3]
+            }]
+        },
+
+        '/**/42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [4, 6],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 6 }
+                }
+            }],
+            range: [4, 6],
+            loc: {
+                start: { line: 1, column: 4 },
+                end: { line: 1, column: 6 }
+            },
+            comments: [{
+                type: 'Block',
+                value: '',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            }]
+        },
+
+        '// Hello, world!\n\n//   Another hello\n42': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [37, 39],
+                    loc: {
+                        start: { line: 4, column: 0 },
+                        end: { line: 4, column: 2 }
+                    }
+                },
+                range: [37, 39],
+                loc: {
+                    start: { line: 4, column: 0 },
+                    end: { line: 4, column: 2 }
+                }
+            }],
+            range: [37, 39],
+            loc: {
+                start: { line: 4, column: 0 },
+                end: { line: 4, column: 2 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' Hello, world!',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }, {
+                type: 'Line',
+                value: '   Another hello',
+                range: [18, 36],
+                loc: {
+                    start: { line: 3, column: 0 },
+                    end: { line: 3, column: 18 }
+                }
+            }]
+        },
+
+        'if (x) { // Some comment\ndoThat(); }': {
+            type: 'Program',
+            body: [{
+                type: 'IfStatement',
+                test: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                consequent: {
+                    type: 'BlockStatement',
+                    body: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'doThat',
+                                range: [25, 31],
+                                loc: {
+                                    start: { line: 2, column: 0 },
+                                    end: { line: 2, column: 6 }
+                                }
+                            },
+                            'arguments': [],
+                            range: [25, 33],
+                            loc: {
+                                start: { line: 2, column: 0 },
+                                end: { line: 2, column: 8 }
+                            }
+                        },
+                        range: [25, 34],
+                        loc: {
+                            start: { line: 2, column: 0 },
+                            end: { line: 2, column: 9 }
+                        }
+                    }],
+                    range: [7, 36],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 2, column: 11 }
+                    }
+                },
+                alternate: null,
+                range: [0, 36],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 11 }
+                }
+            }],
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 11 }
+            },
+            comments: [{
+                type: 'Line',
+                value: ' Some comment',
+                range: [9, 24],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 24 }
+                }
+            }]
+        },
+
+        'switch (answer) { case 42: /* perfect */ bingo() }': {
+            type: 'Program',
+            body: [{
+                type: 'SwitchStatement',
+                discriminant: {
+                    type: 'Identifier',
+                    name: 'answer',
+                    range: [8, 14],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                cases: [{
+                    type: 'SwitchCase',
+                    test: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [23, 25],
+                        loc: {
+                            start: { line: 1, column: 23 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    consequent: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'bingo',
+                                range: [41, 46],
+                                loc: {
+                                    start: { line: 1, column: 41 },
+                                    end: { line: 1, column: 46 }
+                                }
+                            },
+                            'arguments': [],
+                            range: [41, 48],
+                            loc: {
+                                start: { line: 1, column: 41 },
+                                end: { line: 1, column: 48 }
+                            }
+                        },
+                        range: [41, 49],
+                        loc: {
+                            start: { line: 1, column: 41 },
+                            end: { line: 1, column: 49 }
+                        }
+                    }],
+                    range: [18, 49],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 49 }
+                    }
+                }],
+                range: [0, 50],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 50 }
+                }
+            }],
+            range: [0, 50],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 50 }
+            },
+            comments: [{
+                type: 'Block',
+                value: ' perfect ',
+                range: [27, 40],
+                loc: {
+                    start: { line: 1, column: 27 },
+                    end: { line: 1, column: 40 }
+                }
+            }]
+        }
+
+    },
+
+    'Numeric Literals': {
+
+        '0': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0,
+                raw: '0',
+                range: [0, 1],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 1 }
+                }
+            },
+            range: [0, 1],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 1 }
+            }
+        },
+
+        '42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 42,
+                raw: '42',
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        '3': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 3,
+                    raw: '3',
+                    range: [0, 1]
+                },
+                range: [0, 1]
+            }],
+            range: [0, 1],
+            tokens: [{
+                type: 'Numeric',
+                value: '3',
+                range: [0, 1]
+            }]
+        },
+
+        '5': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 5,
+                    raw: '5',
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 1 }
+                }
+            }],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 1 }
+            },
+            tokens: [{
+                type: 'Numeric',
+                value: '5',
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 1 }
+                }
+            }]
+        },
+
+        '.14': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0.14,
+                raw: '.14',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        '3.14159': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 3.14159,
+                raw: '3.14159',
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '6.02214179e+23': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 6.02214179e+23,
+                raw: '6.02214179e+23',
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        '1.492417830e-10': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 1.49241783e-10,
+                raw: '1.492417830e-10',
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        },
+
+        '0x0': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0,
+                raw: '0x0',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        '0e+100': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0,
+                raw: '0e+100',
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        '0xabc': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0xabc,
+                raw: '0xabc',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        '0xdef': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0xdef,
+                raw: '0xdef',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        '0X1A': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0x1A,
+                raw: '0X1A',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            range: [0, 4],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 4 }
+            }
+        },
+
+        '0x10': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0x10,
+                raw: '0x10',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            range: [0, 4],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 4 }
+            }
+        },
+
+        '0x100': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0x100,
+                raw: '0x100',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        '0X04': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 0X04,
+                raw: '0X04',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            range: [0, 4],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 4 }
+            }
+        },
+
+        '02': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 2,
+                raw: '02',
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        '012': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 10,
+                raw: '012',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        '0012': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 10,
+                raw: '0012',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            range: [0, 4],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 4 }
+            }
+        }
+
+    },
+
+    'String Literals': {
+
+        '"Hello"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello',
+                raw: '"Hello"',
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '"\\n\\r\\t\\v\\b\\f\\\\\\\'\\"\\0"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: '\n\r\t\x0B\b\f\\\'"\x00',
+                raw: '"\\n\\r\\t\\v\\b\\f\\\\\\\'\\"\\0"',
+                range: [0, 22],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        '"\\u0061"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'a',
+                raw: '"\\u0061"',
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        '"\\x61"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'a',
+                raw: '"\\x61"',
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        '"\\u00"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'u00',
+                raw: '"\\u00"',
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        '"\\xt"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'xt',
+                raw: '"\\xt"',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        '"Hello\\nworld"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\nworld',
+                raw: '"Hello\\nworld"',
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        '"Hello\\\nworld"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Helloworld',
+                raw: '"Hello\\\nworld"',
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 14 }
+            }
+        },
+
+        '"Hello\\02World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u0002World',
+                raw: '"Hello\\02World"',
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        },
+
+        '"Hello\\012World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u000AWorld',
+                raw: '"Hello\\012World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\122World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\122World',
+                raw: '"Hello\\122World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\0122World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u000A2World',
+                raw: '"Hello\\0122World"',
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        '"Hello\\312World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u00CAWorld',
+                raw: '"Hello\\312World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\412World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\412World',
+                raw: '"Hello\\412World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\812World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello812World',
+                raw: '"Hello\\812World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\712World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\712World',
+                raw: '"Hello\\712World"',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '"Hello\\0World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u0000World',
+                raw: '"Hello\\0World"',
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        '"Hello\\\r\nworld"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Helloworld',
+                raw: '"Hello\\\r\nworld"',
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 2, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 15 }
+            }
+        },
+
+        '"Hello\\1World"': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Literal',
+                value: 'Hello\u0001World',
+                raw: '"Hello\\1World"',
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        }
+    },
+
+    'Regular Expression Literals': {
+
+        'var x = /[a-z]/i': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[a-z]/i',
+                        raw: '/[a-z]/i',
+                        range: [8, 16],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 16 }
+                        }
+                    },
+                    range: [4, 16],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 16 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }],
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[a-z]/i',
+                range: [8, 16],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 16 }
+                }
+            }]
+        },
+
+        'var x = /[x-z]/i': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5]
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[x-z]/i',
+                        raw: '/[x-z]/i',
+                        range: [8, 16]
+                    },
+                    range: [4, 16]
+                }],
+                kind: 'var',
+                range: [0, 16]
+            }],
+            range: [0, 16],
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3]
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5]
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7]
+            }, {
+                type: 'RegularExpression',
+                value: '/[x-z]/i',
+                range: [8, 16]
+            }]
+        },
+
+        'var x = /[a-c]/i': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[a-c]/i',
+                        raw: '/[a-c]/i',
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 16 }
+                        }
+                    },
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 16 }
+                    }
+                }],
+                kind: 'var',
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[a-c]/i',
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 16 }
+                }
+            }]
+        },
+
+        'var x = /[P QR]/i': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[P QR]/i',
+                        raw: '/[P QR]/i',
+                        range: [8, 17],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 17 }
+                        }
+                    },
+                    range: [4, 17],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 17 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            }],
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[P QR]/i',
+                range: [8, 17],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 17 }
+                }
+            }]
+        },
+
+        'var x = /[\\]/]/': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: new RegExp('[\\]/]').toString(),
+                        raw: '/[\\]/]/',
+                        range: [8, 15],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    range: [4, 15],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 15 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            }],
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[\\]/]/',
+                range: [8, 15],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 15 }
+                }
+            }]
+        },
+
+        'var x = /foo\\/bar/': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/foo\\/bar/',
+                        raw: '/foo\\/bar/',
+                        range: [8, 18],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    range: [4, 18],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 18 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 18],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 18 }
+                }
+            }],
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/foo\\/bar/',
+                range: [8, 18],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 18 }
+                }
+            }]
+        },
+
+        'var x = /=([^=\\s])+/g': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/=([^=\\s])+/g',
+                        raw: '/=([^=\\s])+/g',
+                        range: [8, 21],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 21 }
+                        }
+                    },
+                    range: [4, 21],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 21 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/=([^=\\s])+/g',
+                range: [8, 21],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 21 }
+                }
+            }]
+        },
+
+        'var x = /[P QR]/\\u0067': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[P QR]/g',
+                        raw: '/[P QR]/\\u0067',
+                        range: [8, 22],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    range: [4, 22],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 22 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 22],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 22 }
+                }
+            }],
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[P QR]/\\u0067',
+                range: [8, 22],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 22 }
+                }
+            }]
+        },
+
+        'var x = /[P QR]/\\g': {
+            type: 'Program',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: '/[P QR]/g',
+                        raw: '/[P QR]/\\g',
+                        range: [8, 18],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    range: [4, 18],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 18 }
+                    }
+                }],
+                kind: 'var',
+                range: [0, 18],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 18 }
+                }
+            }],
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            },
+            tokens: [{
+                type: 'Keyword',
+                value: 'var',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }, {
+                type: 'Identifier',
+                value: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'Punctuator',
+                value: '=',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            }, {
+                type: 'RegularExpression',
+                value: '/[P QR]/\\g',
+                range: [8, 18],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 18 }
+                }
+            }]
+        }
+
+    },
+
+    'Left-Hand-Side Expression': {
+
+        'new Button': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'Identifier',
+                    name: 'Button',
+                    range: [4, 10],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 10],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            range: [0, 10],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 10 }
+            }
+        },
+
+        'new Button()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'Identifier',
+                    name: 'Button',
+                    range: [4, 10],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 12],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 12 }
+                }
+            },
+            range: [0, 12],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 12 }
+            }
+        },
+
+        'new new foo': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'NewExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [8, 11],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [4, 11],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'new new foo()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'NewExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [8, 11],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [4, 13],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'new foo().bar()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'CallExpression',
+                callee: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'NewExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'foo',
+                            range: [4, 7],
+                            loc: {
+                                start: { line: 1, column: 4 },
+                                end: { line: 1, column: 7 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [0, 9],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [10, 13],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 13 }
+                        }
+                    },
+                    range: [0, 13],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 15],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            range: [0, 15],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 15 }
+            }
+        },
+
+        'new foo[bar]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'MemberExpression',
+                    computed: true,
+                    object: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [4, 7],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [8, 11],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    range: [4, 12],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 12],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 12 }
+                }
+            },
+            range: [0, 12],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 12 }
+            }
+        },
+
+        'new foo.bar()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'NewExpression',
+                callee: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [4, 7],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [8, 11],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    range: [4, 11],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        '( new foo).bar()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'CallExpression',
+                callee: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'NewExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'foo',
+                            range: [6, 9],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 9 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [2, 9],
+                        loc: {
+                            start: { line: 1, column: 2 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [11, 14],
+                        loc: {
+                            start: { line: 1, column: 11 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    range: [0, 14],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        'foo(bar, baz)': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'CallExpression',
+                callee: {
+                    type: 'Identifier',
+                    name: 'foo',
+                    range: [0, 3],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                'arguments': [{
+                    type: 'Identifier',
+                    name: 'bar',
+                    range: [4, 7],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 7 }
+                    }
+                }, {
+                    type: 'Identifier',
+                    name: 'baz',
+                    range: [9, 12],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 12 }
+                    }
+                }],
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        '(    foo  )()': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'CallExpression',
+                callee: {
+                    type: 'Identifier',
+                    name: 'foo',
+                    range: [5, 8],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                'arguments': [],
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'universe.milkyway': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'milkyway',
+                    range: [9, 17],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        'universe.milkyway.solarsystem': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'Identifier',
+                        name: 'universe',
+                        range: [0, 8],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'milkyway',
+                        range: [9, 17],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 17 }
+                        }
+                    },
+                    range: [0, 17],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'solarsystem',
+                    range: [18, 29],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 29 }
+                    }
+                },
+                range: [0, 29],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 29 }
+                }
+            },
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 29 }
+            }
+        },
+
+        'universe.milkyway.solarsystem.Earth': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'MemberExpression',
+                        computed: false,
+                        object: {
+                            type: 'Identifier',
+                            name: 'universe',
+                            range: [0, 8],
+                            loc: {
+                                start: { line: 1, column: 0 },
+                                end: { line: 1, column: 8 }
+                            }
+                        },
+                        property: {
+                            type: 'Identifier',
+                            name: 'milkyway',
+                            range: [9, 17],
+                            loc: {
+                                start: { line: 1, column: 9 },
+                                end: { line: 1, column: 17 }
+                            }
+                        },
+                        range: [0, 17],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 17 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'solarsystem',
+                        range: [18, 29],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 29 }
+                        }
+                    },
+                    range: [0, 29],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 29 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'Earth',
+                    range: [30, 35],
+                    loc: {
+                        start: { line: 1, column: 30 },
+                        end: { line: 1, column: 35 }
+                    }
+                },
+                range: [0, 35],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 35 }
+                }
+            },
+            range: [0, 35],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 35 }
+            }
+        },
+
+        'universe[galaxyName, otherUselessName]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: true,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'SequenceExpression',
+                    expressions: [{
+                        type: 'Identifier',
+                        name: 'galaxyName',
+                        range: [9, 19],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 19 }
+                        }
+                    }, {
+                        type: 'Identifier',
+                        name: 'otherUselessName',
+                        range: [21, 37],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 37 }
+                        }
+                    }],
+                    range: [9, 37],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 37 }
+                    }
+                },
+                range: [0, 38],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 38 }
+                }
+            },
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            }
+        },
+
+        'universe[galaxyName]': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: true,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'galaxyName',
+                    range: [9, 19],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 19 }
+                    }
+                },
+                range: [0, 20],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 20 }
+                }
+            },
+            range: [0, 20],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 20 }
+            }
+        },
+
+        'universe[42].galaxies': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'MemberExpression',
+                    computed: true,
+                    object: {
+                        type: 'Identifier',
+                        name: 'universe',
+                        range: [0, 8],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    property: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [9, 11],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'galaxies',
+                    range: [13, 21],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            },
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            }
+        },
+
+        'universe(42).galaxies': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'universe',
+                        range: [0, 8],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [9, 11],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 11 }
+                        }
+                    }],
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'galaxies',
+                    range: [13, 21],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [0, 21],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 21 }
+                }
+            },
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            }
+        },
+
+        'universe(42).galaxies(14, 3, 77).milkyway': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'MemberExpression',
+                        computed: false,
+                        object: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'universe',
+                                range: [0, 8],
+                                loc: {
+                                    start: { line: 1, column: 0 },
+                                    end: { line: 1, column: 8 }
+                                }
+                            },
+                            'arguments': [{
+                                type: 'Literal',
+                                value: 42,
+                                raw: '42',
+                                range: [9, 11],
+                                loc: {
+                                    start: { line: 1, column: 9 },
+                                    end: { line: 1, column: 11 }
+                                }
+                            }],
+                            range: [0, 12],
+                            loc: {
+                                start: { line: 1, column: 0 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        property: {
+                            type: 'Identifier',
+                            name: 'galaxies',
+                            range: [13, 21],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 21 }
+                            }
+                        },
+                        range: [0, 21],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 21 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Literal',
+                        value: 14,
+                        raw: '14',
+                        range: [22, 24],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 24 }
+                        }
+                    }, {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [26, 27],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 27 }
+                        }
+                    }, {
+                        type: 'Literal',
+                        value: 77,
+                        raw: '77',
+                        range: [29, 31],
+                        loc: {
+                            start: { line: 1, column: 29 },
+                            end: { line: 1, column: 31 }
+                        }
+                    }],
+                    range: [0, 32],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 32 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'milkyway',
+                    range: [33, 41],
+                    loc: {
+                        start: { line: 1, column: 33 },
+                        end: { line: 1, column: 41 }
+                    }
+                },
+                range: [0, 41],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 41 }
+                }
+            },
+            range: [0, 41],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 41 }
+            }
+        },
+
+        'earth.asia.Indonesia.prepareForElection(2014)': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'CallExpression',
+                callee: {
+                    type: 'MemberExpression',
+                    computed: false,
+                    object: {
+                        type: 'MemberExpression',
+                        computed: false,
+                        object: {
+                            type: 'MemberExpression',
+                            computed: false,
+                            object: {
+                                type: 'Identifier',
+                                name: 'earth',
+                                range: [0, 5],
+                                loc: {
+                                    start: { line: 1, column: 0 },
+                                    end: { line: 1, column: 5 }
+                                }
+                            },
+                            property: {
+                                type: 'Identifier',
+                                name: 'asia',
+                                range: [6, 10],
+                                loc: {
+                                    start: { line: 1, column: 6 },
+                                    end: { line: 1, column: 10 }
+                                }
+                            },
+                            range: [0, 10],
+                            loc: {
+                                start: { line: 1, column: 0 },
+                                end: { line: 1, column: 10 }
+                            }
+                        },
+                        property: {
+                            type: 'Identifier',
+                            name: 'Indonesia',
+                            range: [11, 20],
+                            loc: {
+                                start: { line: 1, column: 11 },
+                                end: { line: 1, column: 20 }
+                            }
+                        },
+                        range: [0, 20],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 20 }
+                        }
+                    },
+                    property: {
+                        type: 'Identifier',
+                        name: 'prepareForElection',
+                        range: [21, 39],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 39 }
+                        }
+                    },
+                    range: [0, 39],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 39 }
+                    }
+                },
+                'arguments': [{
+                    type: 'Literal',
+                    value: 2014,
+                    raw: '2014',
+                    range: [40, 44],
+                    loc: {
+                        start: { line: 1, column: 40 },
+                        end: { line: 1, column: 44 }
+                    }
+                }],
+                range: [0, 45],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 45 }
+                }
+            },
+            range: [0, 45],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 45 }
+            }
+        },
+
+        'universe.if': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'if',
+                    range: [9, 11],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'universe.true': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'true',
+                    range: [9, 13],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'universe.false': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'false',
+                    range: [9, 14],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        'universe.null': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'MemberExpression',
+                computed: false,
+                object: {
+                    type: 'Identifier',
+                    name: 'universe',
+                    range: [0, 8],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                property: {
+                    type: 'Identifier',
+                    name: 'null',
+                    range: [9, 13],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        }
+
+    },
+
+    'Postfix Expressions': {
+
+        'x++': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                prefix: false,
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        'x--': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                prefix: false,
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        'eval++': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                prefix: false,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'eval--': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                prefix: false,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'arguments++': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [0, 9],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                prefix: false,
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'arguments--': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [0, 9],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                prefix: false,
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        }
+
+    },
+
+    'Unary Operators': {
+
+        '++x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [2, 3],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                prefix: true,
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        '--x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [2, 3],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                prefix: true,
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        '++eval': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [2, 6],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                prefix: true,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        '--eval': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [2, 6],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                prefix: true,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        '++arguments': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [2, 11],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                prefix: true,
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        '--arguments': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UpdateExpression',
+                operator: '--',
+                argument: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [2, 11],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                prefix: true,
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        '+x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: '+',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [1, 2],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                prefix: true,
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        '-x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: '-',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [1, 2],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                prefix: true,
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        '~x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: '~',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [1, 2],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                prefix: true,
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        '!x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: '!',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [1, 2],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 2 }
+                    }
+                },
+                prefix: true,
+                range: [0, 2],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 2 }
+                }
+            },
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        },
+
+        'void x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: 'void',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                prefix: true,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'delete x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: 'delete',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [7, 8],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                prefix: true,
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'typeof x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'UnaryExpression',
+                operator: 'typeof',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [7, 8],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                prefix: true,
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        }
+
+    },
+
+    'Multiplicative Operators': {
+
+        'x * y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '*',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x / y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '/',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x % y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '%',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        }
+
+    },
+
+    'Additive Operators': {
+
+        'x + y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x - y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '-',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        }
+
+    },
+
+    'Bitwise Shift Operator': {
+
+        'x << y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x >> y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '>>',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x >>> y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '>>>',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        }
+
+    },
+
+    'Relational Operators': {
+
+        'x < y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x > y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '>',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x <= y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x >= y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '>=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x in y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: 'in',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x instanceof y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: 'instanceof',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [13, 14],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        'x < y < z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '<',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        }
+
+    },
+
+    'Equality Operators': {
+
+        'x == y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '==',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x != y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '!=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x === y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '===',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x !== y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '!==',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        }
+
+    },
+
+    'Binary Bitwise Operators': {
+
+        'x & y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '&',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x ^ y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '^',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'x | y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '|',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        }
+
+    },
+
+    'Binary Expressions': {
+
+        'x + y + z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '+',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x - y + z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '-',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x + y - z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '-',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '+',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x - y - z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '-',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '-',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x + y * z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '*',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x + y / z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '+',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '/',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x - y % z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '-',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '%',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x * y * z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '*',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '*',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x * y / z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '/',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '*',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x * y % z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '%',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '*',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x % y * z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '*',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '%',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x << y << z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '<<',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '<<',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [0, 6],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [10, 11],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'x | y | z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '|',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '|',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x & y & z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '&',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x ^ y ^ z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '^',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '^',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x & y | z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '|',
+                left: {
+                    type: 'BinaryExpression',
+                    operator: '&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x | y ^ z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '|',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '^',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x | y & z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'BinaryExpression',
+                operator: '|',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        }
+
+    },
+
+    'Binary Logical Operators': {
+
+        'x || y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '||',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x && y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '&&',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'x || y || z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '||',
+                left: {
+                    type: 'LogicalExpression',
+                    operator: '||',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [0, 6],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [10, 11],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'x && y && z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '&&',
+                left: {
+                    type: 'LogicalExpression',
+                    operator: '&&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [0, 6],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [10, 11],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'x || y && z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '||',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'LogicalExpression',
+                    operator: '&&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [10, 11],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 11 }
+                        }
+                    },
+                    range: [5, 11],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [0, 11],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'x || y ^ z': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'LogicalExpression',
+                operator: '||',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'BinaryExpression',
+                    operator: '^',
+                    left: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    range: [5, 10],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                range: [0, 10],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            range: [0, 10],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 10 }
+            }
+        }
+
+    },
+
+    'Conditional Operator': {
+
+        'y ? 1 : 2': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'ConditionalExpression',
+                test: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                consequent: {
+                    type: 'Literal',
+                    value: 1,
+                    raw: '1',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                alternate: {
+                    type: 'Literal',
+                    value: 2,
+                    raw: '2',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x && y ? 1 : 2': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'ConditionalExpression',
+                test: {
+                    type: 'LogicalExpression',
+                    operator: '&&',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [5, 6],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 6 }
+                        }
+                    },
+                    range: [0, 6],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                consequent: {
+                    type: 'Literal',
+                    value: 1,
+                    raw: '1',
+                    range: [9, 10],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                alternate: {
+                    type: 'Literal',
+                    value: 2,
+                    raw: '2',
+                    range: [13, 14],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        }
+
+    },
+
+    'Assignment Operators': {
+
+        'x = 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'eval = 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [7, 9],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'arguments = 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [0, 9],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [12, 14],
+                    loc: {
+                        start: { line: 1, column: 12 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                range: [0, 14],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        'x *= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '*=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x /= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '/=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x %= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '%=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x += 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '+=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x -= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '-=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x <<= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '<<=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [6, 8],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'x >>= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '>>=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [6, 8],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                range: [0, 8],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'x >>>= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '>>>=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [7, 9],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [0, 9],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'x &= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '&=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x ^= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '^=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        'x |= 42': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'AssignmentExpression',
+                operator: '|=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [5, 7],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        }
+
+    },
+
+    'Block': {
+
+        '{ foo }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'foo',
+                    range: [2, 5],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [2, 6],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 6 }
+                }
+            }],
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '{ doThis(); doThat(); }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'doThis',
+                        range: [2, 8],
+                        loc: {
+                            start: { line: 1, column: 2 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [2, 10],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                range: [2, 11],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 11 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'doThat',
+                        range: [12, 18],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [12, 20],
+                    loc: {
+                        start: { line: 1, column: 12 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                range: [12, 21],
+                loc: {
+                    start: { line: 1, column: 12 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            }
+        },
+
+        '{}': {
+            type: 'BlockStatement',
+            body: [],
+            range: [0, 2],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 2 }
+            }
+        }
+
+    },
+
+    'Variable Statement': {
+
+        'var x': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: null,
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        'var x, y;': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: null,
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [7, 8],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                init: null,
+                range: [7, 8],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 8 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'var x = 42': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [8, 10],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                range: [4, 10],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 10 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 10],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 10 }
+            }
+        },
+
+        'var eval = 42, arguments = 42': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [4, 8],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [11, 13],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [4, 13],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [15, 24],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [27, 29],
+                    loc: {
+                        start: { line: 1, column: 27 },
+                        end: { line: 1, column: 29 }
+                    }
+                },
+                range: [15, 29],
+                loc: {
+                    start: { line: 1, column: 15 },
+                    end: { line: 1, column: 29 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 29 }
+            }
+        },
+
+        'var x = 14, y = 3, z = 1977': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 14,
+                    raw: '14',
+                    range: [8, 10],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 10 }
+                    }
+                },
+                range: [4, 10],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 10 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [12, 13],
+                    loc: {
+                        start: { line: 1, column: 12 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 3,
+                    raw: '3',
+                    range: [16, 17],
+                    loc: {
+                        start: { line: 1, column: 16 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [12, 17],
+                loc: {
+                    start: { line: 1, column: 12 },
+                    end: { line: 1, column: 17 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [19, 20],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 1977,
+                    raw: '1977',
+                    range: [23, 27],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                range: [19, 27],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 27 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 27],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 27 }
+            }
+        },
+
+        'var implements, interface, package': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'implements',
+                    range: [4, 14],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                init: null,
+                range: [4, 14],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 14 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'interface',
+                    range: [16, 25],
+                    loc: {
+                        start: { line: 1, column: 16 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                init: null,
+                range: [16, 25],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 25 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'package',
+                    range: [27, 34],
+                    loc: {
+                        start: { line: 1, column: 27 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                init: null,
+                range: [27, 34],
+                loc: {
+                    start: { line: 1, column: 27 },
+                    end: { line: 1, column: 34 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        },
+
+        'var private, protected, public, static': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'private',
+                    range: [4, 11],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                init: null,
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'protected',
+                    range: [13, 22],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                init: null,
+                range: [13, 22],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 22 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'public',
+                    range: [24, 30],
+                    loc: {
+                        start: { line: 1, column: 24 },
+                        end: { line: 1, column: 30 }
+                    }
+                },
+                init: null,
+                range: [24, 30],
+                loc: {
+                    start: { line: 1, column: 24 },
+                    end: { line: 1, column: 30 }
+                }
+            }, {
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'static',
+                    range: [32, 38],
+                    loc: {
+                        start: { line: 1, column: 32 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                init: null,
+                range: [32, 38],
+                loc: {
+                    start: { line: 1, column: 32 },
+                    end: { line: 1, column: 38 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            }
+        }
+
+    },
+
+    'Let Statement': {
+
+        'let x': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: null,
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }],
+            kind: 'let',
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            }
+        },
+
+        '{ let x }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    init: null,
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                }],
+                kind: 'let',
+                range: [2, 8],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 8 }
+                }
+            }],
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        '{ let x = 42 }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [10, 12],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 12 }
+                        }
+                    },
+                    range: [6, 12],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 12 }
+                    }
+                }],
+                kind: 'let',
+                range: [2, 13],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 13 }
+                }
+            }],
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        },
+
+        '{ let x = 14, y = 3, z = 1977 }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 14,
+                        raw: '14',
+                        range: [10, 12],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 12 }
+                        }
+                    },
+                    range: [6, 12],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 12 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [14, 15],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    range: [14, 19],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 19 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [21, 22],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 1977,
+                        raw: '1977',
+                        range: [25, 29],
+                        loc: {
+                            start: { line: 1, column: 25 },
+                            end: { line: 1, column: 29 }
+                        }
+                    },
+                    range: [21, 29],
+                    loc: {
+                        start: { line: 1, column: 21 },
+                        end: { line: 1, column: 29 }
+                    }
+                }],
+                kind: 'let',
+                range: [2, 30],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 30 }
+                }
+            }],
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            }
+        }
+
+    },
+
+    'Const Statement': {
+
+        'const x = 42': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                init: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [10, 12],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [6, 12],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 12 }
+                }
+            }],
+            kind: 'const',
+            range: [0, 12],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 12 }
+            }
+        },
+
+        '{ const x = 42 }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [12, 14],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    range: [8, 14],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 14 }
+                    }
+                }],
+                kind: 'const',
+                range: [2, 15],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 15 }
+                }
+            }],
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            }
+        },
+
+        '{ const x = 14, y = 3, z = 1977 }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 14,
+                        raw: '14',
+                        range: [12, 14],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    range: [8, 14],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 14 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [16, 17],
+                        loc: {
+                            start: { line: 1, column: 16 },
+                            end: { line: 1, column: 17 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [20, 21],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 21 }
+                        }
+                    },
+                    range: [16, 21],
+                    loc: {
+                        start: { line: 1, column: 16 },
+                        end: { line: 1, column: 21 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'z',
+                        range: [23, 24],
+                        loc: {
+                            start: { line: 1, column: 23 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 1977,
+                        raw: '1977',
+                        range: [27, 31],
+                        loc: {
+                            start: { line: 1, column: 27 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    range: [23, 31],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 31 }
+                    }
+                }],
+                kind: 'const',
+                range: [2, 32],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 32 }
+                }
+            }],
+            range: [0, 33],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 33 }
+            }
+        }
+
+    },
+
+    'Empty Statement': {
+
+        ';': {
+            type: 'EmptyStatement',
+            range: [0, 1],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 1 }
+            }
+        }
+
+    },
+
+    'Expression Statement': {
+
+        'x': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Identifier',
+                name: 'x',
+                range: [0, 1],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 1 }
+                }
+            },
+            range: [0, 1],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 1 }
+            }
+        },
+
+        'x, y': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'SequenceExpression',
+                expressions: [{
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [0, 1],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 1 }
+                    }
+                }, {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [3, 4],
+                    loc: {
+                        start: { line: 1, column: 3 },
+                        end: { line: 1, column: 4 }
+                    }
+                }],
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            range: [0, 4],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 4 }
+            }
+        },
+
+        '\\u0061': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Identifier',
+                name: 'a',
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            },
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            }
+        },
+
+        'a\\u0061': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Identifier',
+                name: 'aa',
+                range: [0, 7],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 7],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 7 }
+            }
+        },
+
+        '\\ua': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Identifier',
+                name: 'ua',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        },
+
+        'a\\u': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'Identifier',
+                name: 'au',
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            },
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            }
+        }
+
+    },
+
+    'If Statement': {
+
+        'if (morning) goodMorning()': {
+            type: 'IfStatement',
+            test: {
+                type: 'Identifier',
+                name: 'morning',
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            consequent: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'goodMorning',
+                        range: [13, 24],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [13, 26],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                range: [13, 26],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 26 }
+                }
+            },
+            alternate: null,
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            }
+        },
+
+        'if (morning) (function(){})': {
+            type: 'IfStatement',
+            test: {
+                type: 'Identifier',
+                name: 'morning',
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            consequent: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: null,
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [24, 26],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 26 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [14, 26],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                range: [13, 27],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 27 }
+                }
+            },
+            alternate: null,
+            range: [0, 27],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 27 }
+            }
+        },
+
+        'if (morning) var x = 0;': {
+            type: 'IfStatement',
+            test: {
+                type: 'Identifier',
+                name: 'morning',
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            consequent: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [17, 18],
+                        loc: {
+                            start: { line: 1, column: 17 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [21, 22],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    range: [17, 22],
+                    loc: {
+                        start: { line: 1, column: 17 },
+                        end: { line: 1, column: 22 }
+                    }
+                }],
+                kind: 'var',
+                range: [13, 23],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 23 }
+                }
+            },
+            alternate: null,
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            }
+        },
+
+        'if (morning) function a(){}': {
+            type: 'IfStatement',
+            test: {
+                type: 'Identifier',
+                name: 'morning',
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            consequent: {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'a',
+                    range: [22, 23],
+                    loc: {
+                        start: { line: 1, column: 22 },
+                        end: { line: 1, column: 23 }
+                    }
+                },
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [25, 27],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [13, 27],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 27 }
+                }
+            },
+            alternate: null,
+            range: [0, 27],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 27 }
+            }
+        },
+
+        'if (morning) goodMorning(); else goodDay()': {
+            type: 'IfStatement',
+            test: {
+                type: 'Identifier',
+                name: 'morning',
+                range: [4, 11],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            consequent: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'goodMorning',
+                        range: [13, 24],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [13, 26],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                range: [13, 27],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 27 }
+                }
+            },
+            alternate: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'goodDay',
+                        range: [33, 40],
+                        loc: {
+                            start: { line: 1, column: 33 },
+                            end: { line: 1, column: 40 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [33, 42],
+                    loc: {
+                        start: { line: 1, column: 33 },
+                        end: { line: 1, column: 42 }
+                    }
+                },
+                range: [33, 42],
+                loc: {
+                    start: { line: 1, column: 33 },
+                    end: { line: 1, column: 42 }
+                }
+            },
+            range: [0, 42],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 42 }
+            }
+        }
+
+    },
+
+    'Iteration Statements': {
+
+        'do keep(); while (true)': {
+            type: 'DoWhileStatement',
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'keep',
+                        range: [3, 7],
+                        loc: {
+                            start: { line: 1, column: 3 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [3, 9],
+                    loc: {
+                        start: { line: 1, column: 3 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [3, 10],
+                loc: {
+                    start: { line: 1, column: 3 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [18, 22],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            }
+        },
+
+        'do keep(); while (true);': {
+            type: 'DoWhileStatement',
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'keep',
+                        range: [3, 7],
+                        loc: {
+                            start: { line: 1, column: 3 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [3, 9],
+                    loc: {
+                        start: { line: 1, column: 3 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [3, 10],
+                loc: {
+                    start: { line: 1, column: 3 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [18, 22],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'do { x++; y--; } while (x < 10)': {
+            type: 'DoWhileStatement',
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'UpdateExpression',
+                        operator: '++',
+                        argument: {
+                            type: 'Identifier',
+                            name: 'x',
+                            range: [5, 6],
+                            loc: {
+                                start: { line: 1, column: 5 },
+                                end: { line: 1, column: 6 }
+                            }
+                        },
+                        prefix: false,
+                        range: [5, 8],
+                        loc: {
+                            start: { line: 1, column: 5 },
+                            end: { line: 1, column: 8 }
+                        }
+                    },
+                    range: [5, 9],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 9 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'UpdateExpression',
+                        operator: '--',
+                        argument: {
+                            type: 'Identifier',
+                            name: 'y',
+                            range: [10, 11],
+                            loc: {
+                                start: { line: 1, column: 10 },
+                                end: { line: 1, column: 11 }
+                            }
+                        },
+                        prefix: false,
+                        range: [10, 13],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 13 }
+                        }
+                    },
+                    range: [10, 14],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 14 }
+                    }
+                }],
+                range: [3, 16],
+                loc: {
+                    start: { line: 1, column: 3 },
+                    end: { line: 1, column: 16 }
+                }
+            },
+            test: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [24, 25],
+                    loc: {
+                        start: { line: 1, column: 24 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 10,
+                    raw: '10',
+                    range: [28, 30],
+                    loc: {
+                        start: { line: 1, column: 28 },
+                        end: { line: 1, column: 30 }
+                    }
+                },
+                range: [24, 30],
+                loc: {
+                    start: { line: 1, column: 24 },
+                    end: { line: 1, column: 30 }
+                }
+            },
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            }
+        },
+
+        '{ do { } while (false) false }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'DoWhileStatement',
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [5, 8],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                test: {
+                    type: 'Literal',
+                    value: false,
+                    raw: 'false',
+                    range: [16, 21],
+                    loc: {
+                        start: { line: 1, column: 16 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [2, 22],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 1, column: 22 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: false,
+                    raw: 'false',
+                    range: [23, 28],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 28 }
+                    }
+                },
+                range: [23, 29],
+                loc: {
+                    start: { line: 1, column: 23 },
+                    end: { line: 1, column: 29 }
+                }
+            }],
+            range: [0, 30],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 30 }
+            }
+        },
+
+        'while (true) doSomething()': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'doSomething',
+                        range: [13, 24],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [13, 26],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                range: [13, 26],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 26 }
+                }
+            },
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            }
+        },
+
+        'while (x < 10) { x++; y--; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [7, 8],
+                    loc: {
+                        start: { line: 1, column: 7 },
+                        end: { line: 1, column: 8 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 10,
+                    raw: '10',
+                    range: [11, 13],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [7, 13],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'UpdateExpression',
+                        operator: '++',
+                        argument: {
+                            type: 'Identifier',
+                            name: 'x',
+                            range: [17, 18],
+                            loc: {
+                                start: { line: 1, column: 17 },
+                                end: { line: 1, column: 18 }
+                            }
+                        },
+                        prefix: false,
+                        range: [17, 20],
+                        loc: {
+                            start: { line: 1, column: 17 },
+                            end: { line: 1, column: 20 }
+                        }
+                    },
+                    range: [17, 21],
+                    loc: {
+                        start: { line: 1, column: 17 },
+                        end: { line: 1, column: 21 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'UpdateExpression',
+                        operator: '--',
+                        argument: {
+                            type: 'Identifier',
+                            name: 'y',
+                            range: [22, 23],
+                            loc: {
+                                start: { line: 1, column: 22 },
+                                end: { line: 1, column: 23 }
+                            }
+                        },
+                        prefix: false,
+                        range: [22, 25],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    range: [22, 26],
+                    loc: {
+                        start: { line: 1, column: 22 },
+                        end: { line: 1, column: 26 }
+                    }
+                }],
+                range: [15, 28],
+                loc: {
+                    start: { line: 1, column: 15 },
+                    end: { line: 1, column: 28 }
+                }
+            },
+            range: [0, 28],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 28 }
+            }
+        },
+
+        'for(;;);': {
+            type: 'ForStatement',
+            init: null,
+            test: null,
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [7, 8],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 8 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'for(;;){}': {
+            type: 'ForStatement',
+            init: null,
+            test: null,
+            update: null,
+            body: {
+                type: 'BlockStatement',
+                body: [],
+                range: [7, 9],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        },
+
+        'for(x = 0;;);': {
+            type: 'ForStatement',
+            init: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 0,
+                    raw: '0',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [4, 9],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            test: null,
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [12, 13],
+                loc: {
+                    start: { line: 1, column: 12 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'for(var x = 0;;);': {
+            type: 'ForStatement',
+            init: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [12, 13],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 13 }
+                        }
+                    },
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                }],
+                kind: 'var',
+                range: [4, 13],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            test: null,
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [16, 17],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        'for(let x = 0;;);': {
+            type: 'ForStatement',
+            init: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [12, 13],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 13 }
+                        }
+                    },
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                }],
+                kind: 'let',
+                range: [4, 13],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            test: null,
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [16, 17],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            }
+        },
+
+        'for(var x = 0, y = 1;;);': {
+            type: 'ForStatement',
+            init: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [8, 9],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 9 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [12, 13],
+                        loc: {
+                            start: { line: 1, column: 12 },
+                            end: { line: 1, column: 13 }
+                        }
+                    },
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [15, 16],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 16 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [19, 20],
+                        loc: {
+                            start: { line: 1, column: 19 },
+                            end: { line: 1, column: 20 }
+                        }
+                    },
+                    range: [15, 20],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 20 }
+                    }
+                }],
+                kind: 'var',
+                range: [4, 20],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 20 }
+                }
+            },
+            test: null,
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [23, 24],
+                loc: {
+                    start: { line: 1, column: 23 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'for(x = 0; x < 42;);': {
+            type: 'ForStatement',
+            init: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 0,
+                    raw: '0',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [4, 9],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            test: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [11, 12],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [15, 17],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [11, 17],
+                loc: {
+                    start: { line: 1, column: 11 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            update: null,
+            body: {
+                type: 'EmptyStatement',
+                range: [19, 20],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 20 }
+                }
+            },
+            range: [0, 20],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 20 }
+            }
+        },
+
+        'for(x = 0; x < 42; x++);': {
+            type: 'ForStatement',
+            init: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 0,
+                    raw: '0',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [4, 9],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            test: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [11, 12],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [15, 17],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [11, 17],
+                loc: {
+                    start: { line: 1, column: 11 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            update: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [19, 20],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                prefix: false,
+                range: [19, 22],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            body: {
+                type: 'EmptyStatement',
+                range: [23, 24],
+                loc: {
+                    start: { line: 1, column: 23 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'for(x = 0; x < 42; x++) process(x);': {
+            type: 'ForStatement',
+            init: {
+                type: 'AssignmentExpression',
+                operator: '=',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 0,
+                    raw: '0',
+                    range: [8, 9],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                range: [4, 9],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            test: {
+                type: 'BinaryExpression',
+                operator: '<',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [11, 12],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                right: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [15, 17],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                range: [11, 17],
+                loc: {
+                    start: { line: 1, column: 11 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            update: {
+                type: 'UpdateExpression',
+                operator: '++',
+                argument: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [19, 20],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                prefix: false,
+                range: [19, 22],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [24, 31],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [32, 33],
+                        loc: {
+                            start: { line: 1, column: 32 },
+                            end: { line: 1, column: 33 }
+                        }
+                    }],
+                    range: [24, 34],
+                    loc: {
+                        start: { line: 1, column: 24 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                range: [24, 35],
+                loc: {
+                    start: { line: 1, column: 24 },
+                    end: { line: 1, column: 35 }
+                }
+            },
+            range: [0, 35],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 35 }
+            }
+        },
+
+        'for(x in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'Identifier',
+                name: 'x',
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [9, 13],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [15, 22],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [23, 24],
+                        loc: {
+                            start: { line: 1, column: 23 },
+                            end: { line: 1, column: 24 }
+                        }
+                    }],
+                    range: [15, 25],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                range: [15, 26],
+                loc: {
+                    start: { line: 1, column: 15 },
+                    end: { line: 1, column: 26 }
+                }
+            },
+            each: false,
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            }
+        },
+
+        'for (var x in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    init: null,
+                    range: [9, 10],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 10 }
+                    }
+                }],
+                kind: 'var',
+                range: [5, 10],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [14, 18],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [20, 27],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [28, 29],
+                        loc: {
+                            start: { line: 1, column: 28 },
+                            end: { line: 1, column: 29 }
+                        }
+                    }],
+                    range: [20, 30],
+                    loc: {
+                        start: { line: 1, column: 20 },
+                        end: { line: 1, column: 30 }
+                    }
+                },
+                range: [20, 31],
+                loc: {
+                    start: { line: 1, column: 20 },
+                    end: { line: 1, column: 31 }
+                }
+            },
+            each: false,
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            }
+        },
+
+        'for (var x = 42 in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [13, 15],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    range: [9, 15],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 15 }
+                    }
+                }],
+                kind: 'var',
+                range: [5, 15],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [19, 23],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 23 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [25, 32],
+                        loc: {
+                            start: { line: 1, column: 25 },
+                            end: { line: 1, column: 32 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [33, 34],
+                        loc: {
+                            start: { line: 1, column: 33 },
+                            end: { line: 1, column: 34 }
+                        }
+                    }],
+                    range: [25, 35],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 35 }
+                    }
+                },
+                range: [25, 36],
+                loc: {
+                    start: { line: 1, column: 25 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            each: false,
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'for (let x in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    init: null,
+                    range: [9, 10],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 10 }
+                    }
+                }],
+                kind: 'let',
+                range: [5, 10],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 10 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [14, 18],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [20, 27],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [28, 29],
+                        loc: {
+                            start: { line: 1, column: 28 },
+                            end: { line: 1, column: 29 }
+                        }
+                    }],
+                    range: [20, 30],
+                    loc: {
+                        start: { line: 1, column: 20 },
+                        end: { line: 1, column: 30 }
+                    }
+                },
+                range: [20, 31],
+                loc: {
+                    start: { line: 1, column: 20 },
+                    end: { line: 1, column: 31 }
+                }
+            },
+            each: false,
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            }
+        },
+
+        'for (let x = 42 in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 42,
+                        raw: '42',
+                        range: [13, 15],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    range: [9, 15],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 15 }
+                    }
+                }],
+                kind: 'let',
+                range: [5, 15],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 15 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [19, 23],
+                loc: {
+                    start: { line: 1, column: 19 },
+                    end: { line: 1, column: 23 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [25, 32],
+                        loc: {
+                            start: { line: 1, column: 25 },
+                            end: { line: 1, column: 32 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [33, 34],
+                        loc: {
+                            start: { line: 1, column: 33 },
+                            end: { line: 1, column: 34 }
+                        }
+                    }],
+                    range: [25, 35],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 35 }
+                    }
+                },
+                range: [25, 36],
+                loc: {
+                    start: { line: 1, column: 25 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            each: false,
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'for (var i = function() { return 10 in [] } in list) process(x);': {
+            type: 'ForInStatement',
+            left: {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'i',
+                        range: [9, 10],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    init: {
+                        type: 'FunctionExpression',
+                        id: null,
+                        params: [],
+                        defaults: [],
+                        body: {
+                            type: 'BlockStatement',
+                            body: [{
+                                type: 'ReturnStatement',
+                                argument: {
+                                    type: 'BinaryExpression',
+                                    operator: 'in',
+                                    left: {
+                                        type: 'Literal',
+                                        value: 10,
+                                        raw: '10',
+                                        range: [33, 35],
+                                        loc: {
+                                            start: { line: 1, column: 33 },
+                                            end: { line: 1, column: 35 }
+                                        }
+                                    },
+                                    right: {
+                                        type: 'ArrayExpression',
+                                        elements: [],
+                                        range: [39, 41],
+                                        loc: {
+                                            start: { line: 1, column: 39 },
+                                            end: { line: 1, column: 41 }
+                                        }
+                                    },
+                                    range: [33, 41],
+                                    loc: {
+                                        start: { line: 1, column: 33 },
+                                        end: { line: 1, column: 41 }
+                                    }
+                                },
+                                range: [26, 42],
+                                loc: {
+                                    start: { line: 1, column: 26 },
+                                    end: { line: 1, column: 42 }
+                                }
+                            }],
+                            range: [24, 43],
+                            loc: {
+                                start: { line: 1, column: 24 },
+                                end: { line: 1, column: 43 }
+                            }
+                        },
+                        rest: null,
+                        generator: false,
+                        expression: false,
+                        range: [13, 43],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 43 }
+                        }
+                    },
+                    range: [9, 43],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 43 }
+                    }
+                }],
+                kind: 'var',
+                range: [5, 43],
+                loc: {
+                    start: { line: 1, column: 5 },
+                    end: { line: 1, column: 43 }
+                }
+            },
+            right: {
+                type: 'Identifier',
+                name: 'list',
+                range: [47, 51],
+                loc: {
+                    start: { line: 1, column: 47 },
+                    end: { line: 1, column: 51 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'Identifier',
+                        name: 'process',
+                        range: [53, 60],
+                        loc: {
+                            start: { line: 1, column: 53 },
+                            end: { line: 1, column: 60 }
+                        }
+                    },
+                    'arguments': [{
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [61, 62],
+                        loc: {
+                            start: { line: 1, column: 61 },
+                            end: { line: 1, column: 62 }
+                        }
+                    }],
+                    range: [53, 63],
+                    loc: {
+                        start: { line: 1, column: 53 },
+                        end: { line: 1, column: 63 }
+                    }
+                },
+                range: [53, 64],
+                loc: {
+                    start: { line: 1, column: 53 },
+                    end: { line: 1, column: 64 }
+                }
+            },
+            each: false,
+            range: [0, 64],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 64 }
+            }
+        }
+
+    },
+
+    'continue statement': {
+
+        'while (true) { continue; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [
+                    {
+                        type: 'ContinueStatement',
+                        label: null,
+                        range: [15, 24],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 24 }
+                        }
+                    }
+                ],
+                range: [13, 26],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 26 }
+                }
+            },
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            }
+        },
+
+        'while (true) { continue }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [
+                    {
+                        type: 'ContinueStatement',
+                        label: null,
+                        range: [15, 24],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 24 }
+                        }
+                    }
+                ],
+                range: [13, 25],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 25 }
+                }
+            },
+            range: [0, 25],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 25 }
+            }
+        },
+
+        'done: while (true) { continue done }': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'done',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            body: {
+                type: 'WhileStatement',
+                test: {
+                    type: 'Literal',
+                    value: true,
+                    raw: 'true',
+                    range: [13, 17],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ContinueStatement',
+                            label: {
+                                type: 'Identifier',
+                                name: 'done',
+                                range: [30, 34],
+                                loc: {
+                                    start: { line: 1, column: 30 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            range: [21, 35],
+                            loc: {
+                                start: { line: 1, column: 21 },
+                                end: { line: 1, column: 35 }
+                            }
+                        }
+                    ],
+                    range: [19, 36],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [6, 36],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 36 }
+                }
+            },
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            }
+        },
+
+        'done: while (true) { continue done; }': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'done',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            body: {
+                type: 'WhileStatement',
+                test: {
+                    type: 'Literal',
+                    value: true,
+                    raw: 'true',
+                    range: [13, 17],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ContinueStatement',
+                            label: {
+                                type: 'Identifier',
+                                name: 'done',
+                                range: [30, 34],
+                                loc: {
+                                    start: { line: 1, column: 30 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            range: [21, 35],
+                            loc: {
+                                start: { line: 1, column: 21 },
+                                end: { line: 1, column: 35 }
+                            }
+                        }
+                    ],
+                    range: [19, 37],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 37 }
+                    }
+                },
+                range: [6, 37],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 37 }
+                }
+            },
+            range: [0, 37],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 37 }
+            }
+        }
+
+    },
+
+    'break statement': {
+
+        'while (true) { break }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [
+                    {
+                        type: 'BreakStatement',
+                        label: null,
+                        range: [15, 21],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 21 }
+                        }
+                    }
+                ],
+                range: [13, 22],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        'done: while (true) { break done }': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'done',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            body: {
+                type: 'WhileStatement',
+                test: {
+                    type: 'Literal',
+                    value: true,
+                    raw: 'true',
+                    range: [13, 17],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'BreakStatement',
+                            label: {
+                                type: 'Identifier',
+                                name: 'done',
+                                range: [27, 31],
+                                loc: {
+                                    start: { line: 1, column: 27 },
+                                    end: { line: 1, column: 31 }
+                                }
+                            },
+                            range: [21, 32],
+                            loc: {
+                                start: { line: 1, column: 21 },
+                                end: { line: 1, column: 32 }
+                            }
+                        }
+                    ],
+                    range: [19, 33],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 33 }
+                    }
+                },
+                range: [6, 33],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 33 }
+                }
+            },
+            range: [0, 33],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 33 }
+            }
+        },
+
+        'done: while (true) { break done; }': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'done',
+                range: [0, 4],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 4 }
+                }
+            },
+            body: {
+                type: 'WhileStatement',
+                test: {
+                    type: 'Literal',
+                    value: true,
+                    raw: 'true',
+                    range: [13, 17],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 17 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'BreakStatement',
+                            label: {
+                                type: 'Identifier',
+                                name: 'done',
+                                range: [27, 31],
+                                loc: {
+                                    start: { line: 1, column: 27 },
+                                    end: { line: 1, column: 31 }
+                                }
+                            },
+                            range: [21, 32],
+                            loc: {
+                                start: { line: 1, column: 21 },
+                                end: { line: 1, column: 32 }
+                            }
+                        }
+                    ],
+                    range: [19, 34],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                range: [6, 34],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 34 }
+                }
+            },
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        }
+
+    },
+
+    'return statement': {
+
+        '(function(){ return })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: null,
+                            range: [13, 20],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 20 }
+                            }
+                        }
+                    ],
+                    range: [11, 21],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 21],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 21 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        },
+
+        '(function(){ return; })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: null,
+                            range: [13, 20],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 20 }
+                            }
+                        }
+                    ],
+                    range: [11, 22],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 22],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            }
+        },
+
+        '(function(){ return x; })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [20, 21],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 21 }
+                                }
+                            },
+                            range: [13, 22],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 22 }
+                            }
+                        }
+                    ],
+                    range: [11, 24],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 24],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            range: [0, 25],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 25 }
+            }
+        },
+
+        '(function(){ return x * y })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: {
+                                type: 'BinaryExpression',
+                                operator: '*',
+                                left: {
+                                    type: 'Identifier',
+                                    name: 'x',
+                                    range: [20, 21],
+                                    loc: {
+                                        start: { line: 1, column: 20 },
+                                        end: { line: 1, column: 21 }
+                                    }
+                                },
+                                right: {
+                                    type: 'Identifier',
+                                    name: 'y',
+                                    range: [24, 25],
+                                    loc: {
+                                        start: { line: 1, column: 24 },
+                                        end: { line: 1, column: 25 }
+                                    }
+                                },
+                                range: [20, 25],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 25 }
+                                }
+                            },
+                            range: [13, 26],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 26 }
+                            }
+                        }
+                    ],
+                    range: [11, 27],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 27],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 27 }
+                }
+            },
+            range: [0, 28],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 28 }
+            }
+        }
+    },
+
+    'with statement': {
+
+        'with (x) foo = bar': {
+            type: 'WithStatement',
+            object: {
+                type: 'Identifier',
+                name: 'x',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [9, 12],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 12 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [15, 18],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    range: [9, 18],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                range: [9, 18],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            range: [0, 18],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 18 }
+            }
+        },
+
+        'with (x) foo = bar;': {
+            type: 'WithStatement',
+            object: {
+                type: 'Identifier',
+                name: 'x',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            body: {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [9, 12],
+                        loc: {
+                            start: { line: 1, column: 9 },
+                            end: { line: 1, column: 12 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'bar',
+                        range: [15, 18],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    range: [9, 18],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                range: [9, 19],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 19 }
+                }
+            },
+            range: [0, 19],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 19 }
+            }
+        },
+
+        'with (x) { foo = bar }': {
+            type: 'WithStatement',
+            object: {
+                type: 'Identifier',
+                name: 'x',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'AssignmentExpression',
+                        operator: '=',
+                        left: {
+                            type: 'Identifier',
+                            name: 'foo',
+                            range: [11, 14],
+                            loc: {
+                                start: { line: 1, column: 11 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        right: {
+                            type: 'Identifier',
+                            name: 'bar',
+                            range: [17, 20],
+                            loc: {
+                                start: { line: 1, column: 17 },
+                                end: { line: 1, column: 20 }
+                            }
+                        },
+                        range: [11, 20],
+                        loc: {
+                            start: { line: 1, column: 11 },
+                            end: { line: 1, column: 20 }
+                        }
+                    },
+                    range: [11, 21],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 21 }
+                    }
+                }],
+                range: [9, 22],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 22 }
+                }
+            },
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            }
+        }
+
+    },
+
+    'switch statement': {
+
+        'switch (x) {}': {
+            type: 'SwitchStatement',
+            discriminant: {
+                type: 'Identifier',
+                name: 'x',
+                range: [8, 9],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 9 }
+                }
+            },
+            cases:[],
+            range: [0, 13],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 13 }
+            }
+        },
+
+        'switch (answer) { case 42: hi(); break; }': {
+            type: 'SwitchStatement',
+            discriminant: {
+                type: 'Identifier',
+                name: 'answer',
+                range: [8, 14],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            cases: [{
+                type: 'SwitchCase',
+                test: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [23, 25],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                consequent: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'hi',
+                            range: [27, 29],
+                            loc: {
+                                start: { line: 1, column: 27 },
+                                end: { line: 1, column: 29 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [27, 31],
+                        loc: {
+                            start: { line: 1, column: 27 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    range: [27, 32],
+                    loc: {
+                        start: { line: 1, column: 27 },
+                        end: { line: 1, column: 32 }
+                    }
+                }, {
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [33, 39],
+                    loc: {
+                        start: { line: 1, column: 33 },
+                        end: { line: 1, column: 39 }
+                    }
+                }],
+                range: [18, 39],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 39 }
+                }
+            }],
+            range: [0, 41],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 41 }
+            }
+        },
+
+        'switch (answer) { case 42: hi(); break; default: break }': {
+            type: 'SwitchStatement',
+            discriminant: {
+                type: 'Identifier',
+                name: 'answer',
+                range: [8, 14],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            cases: [{
+                type: 'SwitchCase',
+                test: {
+                    type: 'Literal',
+                    value: 42,
+                    raw: '42',
+                    range: [23, 25],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                consequent: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'hi',
+                            range: [27, 29],
+                            loc: {
+                                start: { line: 1, column: 27 },
+                                end: { line: 1, column: 29 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [27, 31],
+                        loc: {
+                            start: { line: 1, column: 27 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    range: [27, 32],
+                    loc: {
+                        start: { line: 1, column: 27 },
+                        end: { line: 1, column: 32 }
+                    }
+                }, {
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [33, 39],
+                    loc: {
+                        start: { line: 1, column: 33 },
+                        end: { line: 1, column: 39 }
+                    }
+                }],
+                range: [18, 39],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 39 }
+                }
+            }, {
+                type: 'SwitchCase',
+                test: null,
+                consequent: [{
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [49, 55],
+                    loc: {
+                        start: { line: 1, column: 49 },
+                        end: { line: 1, column: 55 }
+                    }
+                }],
+                range: [40, 55],
+                loc: {
+                    start: { line: 1, column: 40 },
+                    end: { line: 1, column: 55 }
+                }
+            }],
+            range: [0, 56],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 56 }
+            }
+        }
+
+    },
+
+    'Labelled Statements': {
+
+        'start: for (;;) break start': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'start',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            body: {
+                type: 'ForStatement',
+                init: null,
+                test: null,
+                update: null,
+                body: {
+                    type: 'BreakStatement',
+                    label: {
+                        type: 'Identifier',
+                        name: 'start',
+                        range: [22, 27],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    range: [16, 27],
+                    loc: {
+                        start: { line: 1, column: 16 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                range: [7, 27],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 27 }
+                }
+            },
+            range: [0, 27],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 27 }
+            }
+        },
+
+        'start: while (true) break start': {
+            type: 'LabeledStatement',
+            label: {
+                type: 'Identifier',
+                name: 'start',
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            },
+            body: {
+                type: 'WhileStatement',
+                test: {
+                    type: 'Literal',
+                    value: true,
+                    raw: 'true',
+                    range: [14, 18],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                body: {
+                    type: 'BreakStatement',
+                    label: {
+                        type: 'Identifier',
+                        name: 'start',
+                        range: [26, 31],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    range: [20, 31],
+                    loc: {
+                        start: { line: 1, column: 20 },
+                        end: { line: 1, column: 31 }
+                    }
+                },
+                range: [7, 31],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 31 }
+                }
+            },
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            }
+        }
+
+    },
+
+    'throw statement': {
+
+        'throw x;': {
+            type: 'ThrowStatement',
+            argument: {
+                type: 'Identifier',
+                name: 'x',
+                range: [6, 7],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            range: [0, 8],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 8 }
+            }
+        },
+
+        'throw x * y': {
+            type: 'ThrowStatement',
+            argument: {
+                type: 'BinaryExpression',
+                operator: '*',
+                left: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [6, 7],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 7 }
+                    }
+                },
+                right: {
+                    type: 'Identifier',
+                    name: 'y',
+                    range: [10, 11],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 11 }
+                    }
+                },
+                range: [6, 11],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            range: [0, 11],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 11 }
+            }
+        },
+
+        'throw { message: "Error" }': {
+            type: 'ThrowStatement',
+            argument: {
+                type: 'ObjectExpression',
+                properties: [{
+                    type: 'Property',
+                    key: {
+                        type: 'Identifier',
+                        name: 'message',
+                        range: [8, 15],
+                        loc: {
+                            start: { line: 1, column: 8 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    value: {
+                        type: 'Literal',
+                        value: 'Error',
+                        raw: '"Error"',
+                        range: [17, 24],
+                        loc: {
+                            start: { line: 1, column: 17 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    kind: 'init',
+                    range: [8, 24],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 24 }
+                    }
+                }],
+                range: [6, 26],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 26 }
+                }
+            },
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            }
+        }
+
+    },
+
+    'try statement': {
+
+        'try { } catch (e) { }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [],
+                range: [4, 7],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'e',
+                    range: [15, 16],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [18, 21],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 21 }
+                    }
+                },
+                range: [8, 21],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            finalizer: null,
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            }
+        },
+
+        'try { } catch (eval) { }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [],
+                range: [4, 7],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [15, 19],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 19 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [21, 24],
+                    loc: {
+                        start: { line: 1, column: 21 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                range: [8, 24],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 24 }
+                }
+            }],
+            finalizer: null,
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'try { } catch (arguments) { }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [],
+                range: [4, 7],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [15, 24],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [26, 29],
+                    loc: {
+                        start: { line: 1, column: 26 },
+                        end: { line: 1, column: 29 }
+                    }
+                },
+                range: [8, 29],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 29 }
+                }
+            }],
+            finalizer: null,
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 29 }
+            }
+        },
+
+        'try { } catch (e) { say(e) }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [],
+                range: [4, 7],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'e',
+                    range: [15, 16],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'say',
+                                range: [20, 23],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 23 }
+                                }
+                            },
+                            'arguments': [{
+                                type: 'Identifier',
+                                name: 'e',
+                                range: [24, 25],
+                                loc: {
+                                    start: { line: 1, column: 24 },
+                                    end: { line: 1, column: 25 }
+                                }
+                            }],
+                            range: [20, 26],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 26 }
+                            }
+                        },
+                        range: [20, 27],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 27 }
+                        }
+                    }],
+                    range: [18, 28],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 28 }
+                    }
+                },
+                range: [8, 28],
+                loc: {
+                    start: { line: 1, column: 8 },
+                    end: { line: 1, column: 28 }
+                }
+            }],
+            finalizer: null,
+            range: [0, 28],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 28 }
+            }
+        },
+
+        'try { } finally { cleanup(stuff) }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [],
+                range: [4, 7],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 7 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [],
+            finalizer: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'cleanup',
+                            range: [18, 25],
+                            loc: {
+                                start: { line: 1, column: 18 },
+                                end: { line: 1, column: 25 }
+                            }
+                        },
+                        'arguments': [{
+                            type: 'Identifier',
+                            name: 'stuff',
+                            range: [26, 31],
+                            loc: {
+                                start: { line: 1, column: 26 },
+                                end: { line: 1, column: 31 }
+                            }
+                        }],
+                        range: [18, 32],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 32 }
+                        }
+                    },
+                    range: [18, 33],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 33 }
+                    }
+                }],
+                range: [16, 34],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 34 }
+                }
+            },
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        },
+
+        'try { doThat(); } catch (e) { say(e) }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'doThat',
+                            range: [6, 12],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [6, 14],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    range: [6, 15],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 15 }
+                    }
+                }],
+                range: [4, 17],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'e',
+                    range: [25, 26],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'say',
+                                range: [30, 33],
+                                loc: {
+                                    start: { line: 1, column: 30 },
+                                    end: { line: 1, column: 33 }
+                                }
+                            },
+                            'arguments': [{
+                                type: 'Identifier',
+                                name: 'e',
+                                range: [34, 35],
+                                loc: {
+                                    start: { line: 1, column: 34 },
+                                    end: { line: 1, column: 35 }
+                                }
+                            }],
+                            range: [30, 36],
+                            loc: {
+                                start: { line: 1, column: 30 },
+                                end: { line: 1, column: 36 }
+                            }
+                        },
+                        range: [30, 37],
+                        loc: {
+                            start: { line: 1, column: 30 },
+                            end: { line: 1, column: 37 }
+                        }
+                    }],
+                    range: [28, 38],
+                    loc: {
+                        start: { line: 1, column: 28 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                range: [18, 38],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 38 }
+                }
+            }],
+            finalizer: null,
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            }
+        },
+
+        'try { doThat(); } catch (e) { say(e) } finally { cleanup(stuff) }': {
+            type: 'TryStatement',
+            block: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'doThat',
+                            range: [6, 12],
+                            loc: {
+                                start: { line: 1, column: 6 },
+                                end: { line: 1, column: 12 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [6, 14],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    range: [6, 15],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 15 }
+                    }
+                }],
+                range: [4, 17],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 17 }
+                }
+            },
+            guardedHandlers: [],
+            handlers: [{
+                type: 'CatchClause',
+                param: {
+                    type: 'Identifier',
+                    name: 'e',
+                    range: [25, 26],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 26 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'CallExpression',
+                            callee: {
+                                type: 'Identifier',
+                                name: 'say',
+                                range: [30, 33],
+                                loc: {
+                                    start: { line: 1, column: 30 },
+                                    end: { line: 1, column: 33 }
+                                }
+                            },
+                            'arguments': [{
+                                type: 'Identifier',
+                                name: 'e',
+                                range: [34, 35],
+                                loc: {
+                                    start: { line: 1, column: 34 },
+                                    end: { line: 1, column: 35 }
+                                }
+                            }],
+                            range: [30, 36],
+                            loc: {
+                                start: { line: 1, column: 30 },
+                                end: { line: 1, column: 36 }
+                            }
+                        },
+                        range: [30, 37],
+                        loc: {
+                            start: { line: 1, column: 30 },
+                            end: { line: 1, column: 37 }
+                        }
+                    }],
+                    range: [28, 38],
+                    loc: {
+                        start: { line: 1, column: 28 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                range: [18, 38],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 38 }
+                }
+            }],
+            finalizer: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'cleanup',
+                            range: [49, 56],
+                            loc: {
+                                start: { line: 1, column: 49 },
+                                end: { line: 1, column: 56 }
+                            }
+                        },
+                        'arguments': [{
+                            type: 'Identifier',
+                            name: 'stuff',
+                            range: [57, 62],
+                            loc: {
+                                start: { line: 1, column: 57 },
+                                end: { line: 1, column: 62 }
+                            }
+                        }],
+                        range: [49, 63],
+                        loc: {
+                            start: { line: 1, column: 49 },
+                            end: { line: 1, column: 63 }
+                        }
+                    },
+                    range: [49, 64],
+                    loc: {
+                        start: { line: 1, column: 49 },
+                        end: { line: 1, column: 64 }
+                    }
+                }],
+                range: [47, 65],
+                loc: {
+                    start: { line: 1, column: 47 },
+                    end: { line: 1, column: 65 }
+                }
+            },
+            range: [0, 65],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 65 }
+            }
+        }
+
+    },
+
+    'debugger statement': {
+
+        'debugger;': {
+            type: 'DebuggerStatement',
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 9 }
+            }
+        }
+
+    },
+
+    'Function Definition': {
+
+        'function hello() { sayHi(); }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'hello',
+                range: [9, 14],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            params: [],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'sayHi',
+                            range: [19, 24],
+                            loc: {
+                                start: { line: 1, column: 19 },
+                                end: { line: 1, column: 24 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [19, 26],
+                        loc: {
+                            start: { line: 1, column: 19 },
+                            end: { line: 1, column: 26 }
+                        }
+                    },
+                    range: [19, 27],
+                    loc: {
+                        start: { line: 1, column: 19 },
+                        end: { line: 1, column: 27 }
+                    }
+                }],
+                range: [17, 29],
+                loc: {
+                    start: { line: 1, column: 17 },
+                    end: { line: 1, column: 29 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 29 }
+            }
+        },
+
+        'function eval() { }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'eval',
+                range: [9, 13],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            params: [],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [],
+                range: [16, 19],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 19 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 19],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 19 }
+            }
+        },
+
+        'function arguments() { }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'arguments',
+                range: [9, 18],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 18 }
+                }
+            },
+            params: [],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [],
+                range: [21, 24],
+                loc: {
+                    start: { line: 1, column: 21 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            }
+        },
+
+        'function test(t, t) { }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'test',
+                range: [9, 13],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            params: [{
+                type: 'Identifier',
+                name: 't',
+                range: [14, 15],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 15 }
+                }
+            }, {
+                type: 'Identifier',
+                name: 't',
+                range: [17, 18],
+                loc: {
+                    start: { line: 1, column: 17 },
+                    end: { line: 1, column: 18 }
+                }
+            }],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [],
+                range: [20, 23],
+                loc: {
+                    start: { line: 1, column: 20 },
+                    end: { line: 1, column: 23 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            }
+        },
+
+        '(function test(t, t) { })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: {
+                    type: 'Identifier',
+                    name: 'test',
+                    range: [10, 14],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                params: [{
+                    type: 'Identifier',
+                    name: 't',
+                    range: [15, 16],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 16 }
+                    }
+                }, {
+                    type: 'Identifier',
+                    name: 't',
+                    range: [18, 19],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 19 }
+                    }
+                }],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [21, 24],
+                    loc: {
+                        start: { line: 1, column: 21 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 24],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 24 }
+                }
+            },
+            range: [0, 25],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 25 }
+            }
+        },
+
+        'function eval() { function inner() { "use strict" } }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'eval',
+                range: [9, 13],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            params: [],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'FunctionDeclaration',
+                    id: {
+                        type: 'Identifier',
+                        name: 'inner',
+                        range: [27, 32],
+                        loc: {
+                            start: { line: 1, column: 27 },
+                            end: { line: 1, column: 32 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [{
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'Literal',
+                                value: 'use strict',
+                                raw: '\"use strict\"',
+                                range: [37, 49],
+                                loc: {
+                                    start: { line: 1, column: 37 },
+                                    end: { line: 1, column: 49 }
+                                }
+                            },
+                            range: [37, 50],
+                            loc: {
+                                start: { line: 1, column: 37 },
+                                end: { line: 1, column: 50 }
+                            }
+                        }],
+                        range: [35, 51],
+                        loc: {
+                            start: { line: 1, column: 35 },
+                            end: { line: 1, column: 51 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [18, 51],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 51 }
+                    }
+                }],
+                range: [16, 53],
+                loc: {
+                    start: { line: 1, column: 16 },
+                    end: { line: 1, column: 53 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 53],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 53 }
+            }
+        },
+
+        'function hello(a) { sayHi(); }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'hello',
+                range: [9, 14],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            params: [{
+                type: 'Identifier',
+                name: 'a',
+                range: [15, 16],
+                loc: {
+                    start: { line: 1, column: 15 },
+                    end: { line: 1, column: 16 }
+                }
+            }],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'sayHi',
+                            range: [20, 25],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 25 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [20, 27],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    range: [20, 28],
+                    loc: {
+                        start: { line: 1, column: 20 },
+                        end: { line: 1, column: 28 }
+                    }
+                }],
+                range: [18, 30],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 30 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 30],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 30 }
+            }
+        },
+
+        'function hello(a, b) { sayHi(); }': {
+            type: 'FunctionDeclaration',
+            id: {
+                type: 'Identifier',
+                name: 'hello',
+                range: [9, 14],
+                loc: {
+                    start: { line: 1, column: 9 },
+                    end: { line: 1, column: 14 }
+                }
+            },
+            params: [{
+                type: 'Identifier',
+                name: 'a',
+                range: [15, 16],
+                loc: {
+                    start: { line: 1, column: 15 },
+                    end: { line: 1, column: 16 }
+                }
+            }, {
+                type: 'Identifier',
+                name: 'b',
+                range: [18, 19],
+                loc: {
+                    start: { line: 1, column: 18 },
+                    end: { line: 1, column: 19 }
+                }
+            }],
+            defaults: [],
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'sayHi',
+                            range: [23, 28],
+                            loc: {
+                                start: { line: 1, column: 23 },
+                                end: { line: 1, column: 28 }
+                            }
+                        },
+                        'arguments': [],
+                        range: [23, 30],
+                        loc: {
+                            start: { line: 1, column: 23 },
+                            end: { line: 1, column: 30 }
+                        }
+                    },
+                    range: [23, 31],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 31 }
+                    }
+                }],
+                range: [21, 33],
+                loc: {
+                    start: { line: 1, column: 21 },
+                    end: { line: 1, column: 33 }
+                }
+            },
+            rest: null,
+            generator: false,
+            expression: false,
+            range: [0, 33],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 33 }
+            }
+        },
+
+        'var hi = function() { sayHi() };': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'hi',
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                init: {
+                    type: 'FunctionExpression',
+                    id: null,
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [{
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'CallExpression',
+                                callee: {
+                                    type: 'Identifier',
+                                    name: 'sayHi',
+                                    range: [22, 27],
+                                    loc: {
+                                        start: { line: 1, column: 22 },
+                                        end: { line: 1, column: 27 }
+                                    }
+                                },
+                                'arguments': [],
+                                range: [22, 29],
+                                loc: {
+                                    start: { line: 1, column: 22 },
+                                    end: { line: 1, column: 29 }
+                                }
+                            },
+                            range: [22, 30],
+                            loc: {
+                                start: { line: 1, column: 22 },
+                                end: { line: 1, column: 30 }
+                            }
+                        }],
+                        range: [20, 31],
+                        loc: {
+                            start: { line: 1, column: 20 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [9, 31],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 31 }
+                    }
+                },
+                range: [4, 31],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 31 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 32],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 32 }
+            }
+        },
+
+        'var hi = function eval() { };': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'hi',
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                init: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [18, 22],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [25, 28],
+                        loc: {
+                            start: { line: 1, column: 25 },
+                            end: { line: 1, column: 28 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [9, 28],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 28 }
+                    }
+                },
+                range: [4, 28],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 28 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 29 }
+            }
+        },
+
+        'var hi = function arguments() { };': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'hi',
+                    range: [4, 6],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                init: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [18, 27],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [30, 33],
+                        loc: {
+                            start: { line: 1, column: 30 },
+                            end: { line: 1, column: 33 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [9, 33],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 33 }
+                    }
+                },
+                range: [4, 33],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 33 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            }
+        },
+
+        'var hello = function hi() { sayHi() };': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'hello',
+                    range: [4, 9],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 9 }
+                    }
+                },
+                init: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'hi',
+                        range: [21, 23],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 23 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [{
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'CallExpression',
+                                callee: {
+                                    type: 'Identifier',
+                                    name: 'sayHi',
+                                    range: [28, 33],
+                                    loc: {
+                                        start: { line: 1, column: 28 },
+                                        end: { line: 1, column: 33 }
+                                    }
+                                },
+                                'arguments': [],
+                                range: [28, 35],
+                                loc: {
+                                    start: { line: 1, column: 28 },
+                                    end: { line: 1, column: 35 }
+                                }
+                            },
+                            range: [28, 36],
+                            loc: {
+                                start: { line: 1, column: 28 },
+                                end: { line: 1, column: 36 }
+                            }
+                        }],
+                        range: [26, 37],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 37 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [12, 37],
+                    loc: {
+                        start: { line: 1, column: 12 },
+                        end: { line: 1, column: 37 }
+                    }
+                },
+                range: [4, 37],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 37 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            }
+        },
+
+        '(function(){})': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [11, 13],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 13],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 1, column: 13 }
+                }
+            },
+            range: [0, 14],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 14 }
+            }
+        }
+
+    },
+
+    'Automatic semicolon insertion': {
+
+        '{ x\n++y }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [2, 3],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                range: [2, 4],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 0 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '++',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 2, column: 2 },
+                            end: { line: 2, column: 3 }
+                        }
+                    },
+                    prefix: true,
+                    range: [4, 7],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 3 }
+                    }
+                },
+                range: [4, 8],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 4 }
+                }
+            }],
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 5 }
+            }
+        },
+
+        '{ x\n--y }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [2, 3],
+                    loc: {
+                        start: { line: 1, column: 2 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                range: [2, 4],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 0 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '--',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 2, column: 2 },
+                            end: { line: 2, column: 3 }
+                        }
+                    },
+                    prefix: true,
+                    range: [4, 7],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 3 }
+                    }
+                },
+                range: [4, 8],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 4 }
+                }
+            }],
+            range: [0, 9],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 5 }
+            }
+        },
+
+        'var x /* comment */;': {
+            type: 'VariableDeclaration',
+            declarations: [{
+                type: 'VariableDeclarator',
+                id: {
+                    type: 'Identifier',
+                    name: 'x',
+                    range: [4, 5],
+                    loc: {
+                        start: { line: 1, column: 4 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                init: null,
+                range: [4, 5],
+                loc: {
+                    start: { line: 1, column: 4 },
+                    end: { line: 1, column: 5 }
+                }
+            }],
+            kind: 'var',
+            range: [0, 20],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 20 }
+            }
+        },
+
+        '{ var x = 14, y = 3\nz; }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [6, 7],
+                        loc: {
+                            start: { line: 1, column: 6 },
+                            end: { line: 1, column: 7 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 14,
+                        raw: '14',
+                        range: [10, 12],
+                        loc: {
+                            start: { line: 1, column: 10 },
+                            end: { line: 1, column: 12 }
+                        }
+                    },
+                    range: [6, 12],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 12 }
+                    }
+                }, {
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'y',
+                        range: [14, 15],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    init: {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    range: [14, 19],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 19 }
+                    }
+                }],
+                kind: 'var',
+                range: [2, 20],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 0 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'z',
+                    range: [20, 21],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 1 }
+                    }
+                },
+                range: [20, 22],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 2 }
+                }
+            }],
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 4 }
+            }
+        },
+
+        'while (true) { continue\nthere; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ContinueStatement',
+                    label: null,
+                    range: [15, 23],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 23 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [24, 29],
+                        loc: {
+                            start: { line: 2, column: 0 },
+                            end: { line: 2, column: 5 }
+                        }
+                    },
+                    range: [24, 30],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 6 }
+                    }
+                }],
+                range: [13, 32],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 8 }
+                }
+            },
+            range: [0, 32],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        'while (true) { continue // Comment\nthere; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ContinueStatement',
+                    label: null,
+                    range: [15, 23],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 23 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [35, 40],
+                        loc: {
+                            start: { line: 2, column: 0 },
+                            end: { line: 2, column: 5 }
+                        }
+                    },
+                    range: [35, 41],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 6 }
+                    }
+                }],
+                range: [13, 43],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 8 }
+                }
+            },
+            range: [0, 43],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        'while (true) { continue /* Multiline\nComment */there; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'ContinueStatement',
+                    label: null,
+                    range: [15, 23],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 23 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [47, 52],
+                        loc: {
+                            start: { line: 2, column: 10 },
+                            end: { line: 2, column: 15 }
+                        }
+                    },
+                    range: [47, 53],
+                    loc: {
+                        start: { line: 2, column: 10 },
+                        end: { line: 2, column: 16 }
+                    }
+                }],
+                range: [13, 55],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 18 }
+                }
+            },
+            range: [0, 55],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 18 }
+            }
+        },
+
+        'while (true) { break\nthere; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [15, 20],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 20 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [21, 26],
+                        loc: {
+                            start: { line: 2, column: 0 },
+                            end: { line: 2, column: 5 }
+                        }
+                    },
+                    range: [21, 27],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 6 }
+                    }
+                }],
+                range: [13, 29],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 8 }
+                }
+            },
+            range: [0, 29],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        'while (true) { break // Comment\nthere; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [15, 20],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 20 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [32, 37],
+                        loc: {
+                            start: { line: 2, column: 0 },
+                            end: { line: 2, column: 5 }
+                        }
+                    },
+                    range: [32, 38],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 6 }
+                    }
+                }],
+                range: [13, 40],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 8 }
+                }
+            },
+            range: [0, 40],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        'while (true) { break /* Multiline\nComment */there; }': {
+            type: 'WhileStatement',
+            test: {
+                type: 'Literal',
+                value: true,
+                raw: 'true',
+                range: [7, 11],
+                loc: {
+                    start: { line: 1, column: 7 },
+                    end: { line: 1, column: 11 }
+                }
+            },
+            body: {
+                type: 'BlockStatement',
+                body: [{
+                    type: 'BreakStatement',
+                    label: null,
+                    range: [15, 20],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 20 }
+                    }
+                }, {
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'there',
+                        range: [44, 49],
+                        loc: {
+                            start: { line: 2, column: 10 },
+                            end: { line: 2, column: 15 }
+                        }
+                    },
+                    range: [44, 50],
+                    loc: {
+                        start: { line: 2, column: 10 },
+                        end: { line: 2, column: 16 }
+                    }
+                }],
+                range: [13, 52],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 2, column: 18 }
+                }
+            },
+            range: [0, 52],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 18 }
+            }
+        },
+
+        '(function(){ return\nx; })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: null,
+                            range: [13, 19],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 19 }
+                            }
+                        },
+                        {
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [20, 21],
+                                loc: {
+                                    start: { line: 2, column: 0 },
+                                    end: { line: 2, column: 1 }
+                                }
+                            },
+                            range: [20, 22],
+                            loc: {
+                                start: { line: 2, column: 0 },
+                                end: { line: 2, column: 2 }
+                            }
+                        }
+                    ],
+                    range: [11, 24],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 2, column: 4 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 24],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 2, column: 4 }
+                }
+            },
+            range: [0, 25],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 5 }
+            }
+        },
+
+        '(function(){ return // Comment\nx; })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: null,
+                            range: [13, 19],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 19 }
+                            }
+                        },
+                        {
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [31, 32],
+                                loc: {
+                                    start: { line: 2, column: 0 },
+                                    end: { line: 2, column: 1 }
+                                }
+                            },
+                            range: [31, 33],
+                            loc: {
+                                start: { line: 2, column: 0 },
+                                end: { line: 2, column: 2 }
+                            }
+                        }
+                    ],
+                    range: [11, 35],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 2, column: 4 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 35],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 2, column: 4 }
+                }
+            },
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 5 }
+            }
+        },
+
+        '(function(){ return/* Multiline\nComment */x; })': {
+            type: 'ExpressionStatement',
+            expression: {
+                type: 'FunctionExpression',
+                id: null,
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [
+                        {
+                            type: 'ReturnStatement',
+                            argument: null,
+                            range: [13, 19],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 19 }
+                            }
+                        },
+                        {
+                            type: 'ExpressionStatement',
+                            expression: {
+                                type: 'Identifier',
+                                name: 'x',
+                                range: [42, 43],
+                                loc: {
+                                    start: { line: 2, column: 10 },
+                                    end: { line: 2, column: 11 }
+                                }
+                            },
+                            range: [42, 44],
+                            loc: {
+                                start: { line: 2, column: 10 },
+                                end: { line: 2, column: 12 }
+                            }
+                        }
+                    ],
+                    range: [11, 46],
+                    loc: {
+                        start: { line: 1, column: 11 },
+                        end: { line: 2, column: 14 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [1, 46],
+                loc: {
+                    start: { line: 1, column: 1 },
+                    end: { line: 2, column: 14 }
+                }
+            },
+            range: [0, 47],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 15 }
+            }
+        },
+
+        '{ throw error\nerror; }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ThrowStatement',
+                argument: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [2, 14],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 0 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [14, 19],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 5 }
+                    }
+                },
+                range: [14, 20],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        '{ throw error// Comment\nerror; }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ThrowStatement',
+                argument: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [2, 24],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 0 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [24, 29],
+                    loc: {
+                        start: { line: 2, column: 0 },
+                        end: { line: 2, column: 5 }
+                    }
+                },
+                range: [24, 30],
+                loc: {
+                    start: { line: 2, column: 0 },
+                    end: { line: 2, column: 6 }
+                }
+            }],
+            range: [0, 32],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 8 }
+            }
+        },
+
+        '{ throw error/* Multiline\nComment */error; }': {
+            type: 'BlockStatement',
+            body: [{
+                type: 'ThrowStatement',
+                argument: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [8, 13],
+                    loc: {
+                        start: { line: 1, column: 8 },
+                        end: { line: 1, column: 13 }
+                    }
+                },
+                range: [2, 36],
+                loc: {
+                    start: { line: 1, column: 2 },
+                    end: { line: 2, column: 10 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Identifier',
+                    name: 'error',
+                    range: [36, 41],
+                    loc: {
+                        start: { line: 2, column: 10 },
+                        end: { line: 2, column: 15 }
+                    }
+                },
+                range: [36, 42],
+                loc: {
+                    start: { line: 2, column: 10 },
+                    end: { line: 2, column: 16 }
+                }
+            }],
+            range: [0, 44],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 2, column: 18 }
+            }
+        }
+
+    },
+
+    'Source elements': {
+
+        '': {
+            type: 'Program',
+            body: [],
+            range: [0, 0],
+            loc: {
+                start: { line: 0, column: 0 },
+                end: { line: 0, column: 0 }
+            },
+            tokens: []
+        }
+    },
+
+    'Invalid syntax': {
+
+        '{': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '}': {
+            index: 0,
+            lineNumber: 1,
+            column: 1,
+            message: 'Error: Line 1: Unexpected token }'
+        },
+
+        '3ea': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3in []': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3e': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3e+': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3e-': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3x': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3x0': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '0x': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '09': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '018': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '01a': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '3in[]': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '0x3in[]': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '"Hello\nWorld"': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'x\\': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'x\\u005c': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'x\\u002a': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'var x = /(s/g': {
+            index: 13,
+            lineNumber: 1,
+            column: 14,
+            message: 'Error: Line 1: Invalid regular expression'
+        },
+
+        '/': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Invalid regular expression: missing /'
+        },
+
+        '/test': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Invalid regular expression: missing /'
+        },
+
+        'var x = /[a-z]/\\ux': {
+            index: 18,
+            lineNumber: 1,
+            column: 19,
+            message: 'Error: Line 1: Invalid regular expression'
+        },
+
+        '3 = 4': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        'func() = 4': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '(1 + 1) = 10': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '1++': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '1--': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '++1': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '--1': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        'for((1 + 1) in list) process(x);': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Invalid left-hand side in for-in'
+        },
+
+        '[': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '[,': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '1 + {': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '1 + { t:t ': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '1 + { t:t,': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'var x = /\n/': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Invalid regular expression: missing /'
+        },
+
+        'var x = "\n': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'var if = 42': {
+            index: 4,
+            lineNumber: 1,
+            column: 5,
+            message: 'Error: Line 1: Unexpected token if'
+        },
+
+        'i + 2 = 42': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '+i = 42': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Invalid left-hand side in assignment'
+        },
+
+        '1 + (': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        '\n\n\n{': {
+            index: 4,
+            lineNumber: 4,
+            column: 2,
+            message: 'Error: Line 4: Unexpected end of input'
+        },
+
+        '\n/* Some multiline\ncomment */\n)': {
+            index: 30,
+            lineNumber: 4,
+            column: 1,
+            message: 'Error: Line 4: Unexpected token )'
+        },
+
+        '{ set 1 }': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Unexpected number'
+        },
+
+        '{ get 2 }': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Unexpected number'
+        },
+
+        '({ set: s(if) { } })': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Unexpected token if'
+        },
+
+        '({ set s(.) { } })': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token .'
+        },
+
+        '({ set s() { } })': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token )'
+        },
+
+        '({ set: s() { } })': {
+            index: 12,
+            lineNumber: 1,
+            column: 13,
+            message: 'Error: Line 1: Unexpected token {'
+        },
+
+        '({ set: s(a, b) { } })': {
+            index: 16,
+            lineNumber: 1,
+            column: 17,
+            message: 'Error: Line 1: Unexpected token {'
+        },
+
+        '({ get: g(d) { } })': {
+            index: 13,
+            lineNumber: 1,
+            column: 14,
+            message: 'Error: Line 1: Unexpected token {'
+        },
+
+        '({ get i() { }, i: 42 })': {
+            index: 21,
+            lineNumber: 1,
+            column: 22,
+            message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+        },
+
+        '({ i: 42, get i() { } })': {
+            index: 21,
+            lineNumber: 1,
+            column: 22,
+            message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+        },
+
+        '({ set i(x) { }, i: 42 })': {
+            index: 22,
+            lineNumber: 1,
+            column: 23,
+            message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+        },
+
+        '({ i: 42, set i(x) { } })': {
+            index: 22,
+            lineNumber: 1,
+            column: 23,
+            message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+        },
+
+        '({ get i() { }, get i() { } })': {
+            index: 27,
+            lineNumber: 1,
+            column: 28,
+            message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name'
+        },
+
+        '({ set i(x) { }, set i(x) { } })': {
+            index: 29,
+            lineNumber: 1,
+            column: 30,
+            message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name'
+        },
+
+        'function t(if) { }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Unexpected token if'
+        },
+
+        'function t(true) { }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Unexpected token true'
+        },
+
+        'function t(false) { }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Unexpected token false'
+        },
+
+        'function t(null) { }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Unexpected token null'
+        },
+
+        'function null() { }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token null'
+        },
+
+        'function true() { }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token true'
+        },
+
+        'function false() { }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token false'
+        },
+
+        'function if() { }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token if'
+        },
+
+        'a b;': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected identifier'
+        },
+
+        'if.a;': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token .'
+        },
+
+        'a if;': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token if'
+        },
+
+        'a class;': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected reserved word'
+        },
+
+        'break\n': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Illegal break statement'
+        },
+
+        'break 1;': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Unexpected number'
+        },
+
+        'continue\n': {
+            index: 8,
+            lineNumber: 1,
+            column: 9,
+            message: 'Error: Line 1: Illegal continue statement'
+        },
+
+        'continue 2;': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected number'
+        },
+
+        'throw': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'throw;': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Unexpected token ;'
+        },
+
+        'throw\n': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Illegal newline after throw'
+        },
+
+        'for (var i, i2 in {});': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Unexpected token in'
+        },
+
+        'for ((i in {}));': {
+            index: 14,
+            lineNumber: 1,
+            column: 15,
+            message: 'Error: Line 1: Unexpected token )'
+        },
+
+        'for (i + 1 in {});': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Invalid left-hand side in for-in'
+        },
+
+        'for (+i in {});': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Invalid left-hand side in for-in'
+        },
+
+        'if(false)': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'if(false) doThis(); else': {
+            index: 24,
+            lineNumber: 1,
+            column: 25,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'do': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'while(false)': {
+            index: 12,
+            lineNumber: 1,
+            column: 13,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'for(;;)': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'with(x)': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'try { }': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Missing catch or finally after try'
+        },
+
+        'try {} catch (42) {} ': {
+            index: 14,
+            lineNumber: 1,
+            column: 15,
+            message: 'Error: Line 1: Unexpected number'
+        },
+
+        'try {} catch (answer()) {} ': {
+            index: 20,
+            lineNumber: 1,
+            column: 21,
+            message: 'Error: Line 1: Unexpected token ('
+        },
+
+        'try {} catch (-x) {} ': {
+            index: 14,
+            lineNumber: 1,
+            column: 15,
+            message: 'Error: Line 1: Unexpected token -'
+        },
+
+
+        '\u203F = 10': {
+            index: 0,
+            lineNumber: 1,
+            column: 1,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'const x = 12, y;': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Unexpected token ;'
+        },
+
+        'const x, y = 12;': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ,'
+        },
+
+        'const x;': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ;'
+        },
+
+        'if(true) let a = 1;': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token let'
+        },
+
+        'if(true) const a = 1;': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token const'
+        },
+
+        'switch (c) { default: default: }': {
+            index: 30,
+            lineNumber: 1,
+            column: 31,
+            message: 'Error: Line 1: More than one default clause in switch statement'
+        },
+
+        'new X()."s"': {
+            index: 8,
+            lineNumber: 1,
+            column: 9,
+            message: 'Error: Line 1: Unexpected string'
+        },
+
+        '/*': {
+            index: 2,
+            lineNumber: 1,
+            column: 3,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '/*\n\n\n': {
+            index: 5,
+            lineNumber: 4,
+            column: 1,
+            message: 'Error: Line 4: Unexpected token ILLEGAL'
+        },
+
+        '/**': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '/*\n\n*': {
+            index: 5,
+            lineNumber: 3,
+            column: 2,
+            message: 'Error: Line 3: Unexpected token ILLEGAL'
+        },
+
+        '/*hello': {
+            index: 7,
+            lineNumber: 1,
+            column: 8,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '/*hello  *': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '\n]': {
+            index: 1,
+            lineNumber: 2,
+            column: 1,
+            message: 'Error: Line 2: Unexpected token ]'
+        },
+
+        '\r]': {
+            index: 1,
+            lineNumber: 2,
+            column: 1,
+            message: 'Error: Line 2: Unexpected token ]'
+        },
+
+        '\r\n]': {
+            index: 2,
+            lineNumber: 2,
+            column: 1,
+            message: 'Error: Line 2: Unexpected token ]'
+        },
+
+        '\n\r]': {
+            index: 2,
+            lineNumber: 3,
+            column: 1,
+            message: 'Error: Line 3: Unexpected token ]'
+        },
+
+        '//\r\n]': {
+            index: 4,
+            lineNumber: 2,
+            column: 1,
+            message: 'Error: Line 2: Unexpected token ]'
+        },
+
+        '//\n\r]': {
+            index: 4,
+            lineNumber: 3,
+            column: 1,
+            message: 'Error: Line 3: Unexpected token ]'
+        },
+
+        '/a\\\n/': {
+            index: 4,
+            lineNumber: 1,
+            column: 5,
+            message: 'Error: Line 1: Invalid regular expression: missing /'
+        },
+        
+        '//\r \n]': {
+            index: 5,
+            lineNumber: 3,
+            column: 1,
+            message: 'Error: Line 3: Unexpected token ]'
+        },
+
+        '/*\r\n*/]': {
+            index: 6,
+            lineNumber: 2,
+            column: 3,
+            message: 'Error: Line 2: Unexpected token ]'
+        },
+
+        '/*\n\r*/]': {
+            index: 6,
+            lineNumber: 3,
+            column: 3,
+            message: 'Error: Line 3: Unexpected token ]'
+        },
+
+        '/*\r \n*/]': {
+            index: 7,
+            lineNumber: 3,
+            column: 3,
+            message: 'Error: Line 3: Unexpected token ]'
+        },
+
+        '\\\\': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '\\u005c': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+
+        '\\x': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '\\u0000': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '\u200C = []': {
+            index: 0,
+            lineNumber: 1,
+            column: 1,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '\u200D = []': {
+            index: 0,
+            lineNumber: 1,
+            column: 1,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '"\\': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        '"\\u': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected token ILLEGAL'
+        },
+
+        'try { } catch() {}': {
+            index: 14,
+            lineNumber: 1,
+            column: 15,
+            message: 'Error: Line 1: Unexpected token )'
+        },
+
+        'return': {
+            index: 6,
+            lineNumber: 1,
+            column: 7,
+            message: 'Error: Line 1: Illegal return statement'
+        },
+
+        'break': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Illegal break statement'
+        },
+
+        'continue': {
+            index: 8,
+            lineNumber: 1,
+            column: 9,
+            message: 'Error: Line 1: Illegal continue statement'
+        },
+
+        'switch (x) { default: continue; }': {
+            index: 31,
+            lineNumber: 1,
+            column: 32,
+            message: 'Error: Line 1: Illegal continue statement'
+        },
+
+        'do { x } *': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Unexpected token *'
+        },
+
+        'while (true) { break x; }': {
+            index: 22,
+            lineNumber: 1,
+            column: 23,
+            message: 'Error: Line 1: Undefined label \'x\''
+        },
+
+        'while (true) { continue x; }': {
+            index: 25,
+            lineNumber: 1,
+            column: 26,
+            message: 'Error: Line 1: Undefined label \'x\''
+        },
+
+        'x: while (true) { (function () { break x; }); }': {
+            index: 40,
+            lineNumber: 1,
+            column: 41,
+            message: 'Error: Line 1: Undefined label \'x\''
+        },
+
+        'x: while (true) { (function () { continue x; }); }': {
+            index: 43,
+            lineNumber: 1,
+            column: 44,
+            message: 'Error: Line 1: Undefined label \'x\''
+        },
+
+        'x: while (true) { (function () { break; }); }': {
+            index: 39,
+            lineNumber: 1,
+            column: 40,
+            message: 'Error: Line 1: Illegal break statement'
+        },
+
+        'x: while (true) { (function () { continue; }); }': {
+            index: 42,
+            lineNumber: 1,
+            column: 43,
+            message: 'Error: Line 1: Illegal continue statement'
+        },
+
+        'x: while (true) { x: while (true) { } }': {
+            index: 20,
+            lineNumber: 1,
+            column: 21,
+            message: 'Error: Line 1: Label \'x\' has already been declared'
+        },
+
+        '(function () { \'use strict\'; delete i; }())': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Delete of an unqualified identifier in strict mode.'
+        },
+
+        '(function () { \'use strict\'; with (i); }())': {
+            index: 28,
+            lineNumber: 1,
+            column: 29,
+            message: 'Error: Line 1: Strict mode code may not include a with statement'
+        },
+
+        'function hello() {\'use strict\'; ({ i: 42, i: 42 }) }': {
+            index: 47,
+            lineNumber: 1,
+            column: 48,
+            message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ({ hasOwnProperty: 42, hasOwnProperty: 42 }) }': {
+            index: 73,
+            lineNumber: 1,
+            column: 74,
+            message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; var eval = 10; }': {
+            index: 40,
+            lineNumber: 1,
+            column: 41,
+            message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; var arguments = 10; }': {
+            index: 45,
+            lineNumber: 1,
+            column: 46,
+            message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; try { } catch (eval) { } }': {
+            index: 51,
+            lineNumber: 1,
+            column: 52,
+            message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; try { } catch (arguments) { } }': {
+            index: 56,
+            lineNumber: 1,
+            column: 57,
+            message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; eval = 10; }': {
+            index: 32,
+            lineNumber: 1,
+            column: 33,
+            message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; arguments = 10; }': {
+            index: 32,
+            lineNumber: 1,
+            column: 33,
+            message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ++eval; }': {
+            index: 38,
+            lineNumber: 1,
+            column: 39,
+            message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; --eval; }': {
+            index: 38,
+            lineNumber: 1,
+            column: 39,
+            message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ++arguments; }': {
+            index: 43,
+            lineNumber: 1,
+            column: 44,
+            message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; --arguments; }': {
+            index: 43,
+            lineNumber: 1,
+            column: 44,
+            message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; eval++; }': {
+            index: 36,
+            lineNumber: 1,
+            column: 37,
+            message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; eval--; }': {
+            index: 36,
+            lineNumber: 1,
+            column: 37,
+            message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; arguments++; }': {
+            index: 41,
+            lineNumber: 1,
+            column: 42,
+            message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; arguments--; }': {
+            index: 41,
+            lineNumber: 1,
+            column: 42,
+            message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+        },
+
+        'function hello() {\'use strict\'; function eval() { } }': {
+            index: 41,
+            lineNumber: 1,
+            column: 42,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; function arguments() { } }': {
+            index: 41,
+            lineNumber: 1,
+            column: 42,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function eval() {\'use strict\'; }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function arguments() {\'use strict\'; }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; (function eval() { }()) }': {
+            index: 42,
+            lineNumber: 1,
+            column: 43,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; (function arguments() { }()) }': {
+            index: 42,
+            lineNumber: 1,
+            column: 43,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        '(function eval() {\'use strict\'; })()': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        '(function arguments() {\'use strict\'; })()': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ({ s: function eval() { } }); }': {
+            index: 47,
+            lineNumber: 1,
+            column: 48,
+            message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+        },
+
+        '(function package() {\'use strict\'; })()': {
+            index: 10,
+            lineNumber: 1,
+            column: 11,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ({ i: 10, set s(eval) { } }); }': {
+            index: 48,
+            lineNumber: 1,
+            column: 49,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ({ set s(eval) { } }); }': {
+            index: 41,
+            lineNumber: 1,
+            column: 42,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() {\'use strict\'; ({ s: function s(eval) { } }); }': {
+            index: 49,
+            lineNumber: 1,
+            column: 50,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello(eval) {\'use strict\';}': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello(arguments) {\'use strict\';}': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() { \'use strict\'; function inner(eval) {} }': {
+            index: 48,
+            lineNumber: 1,
+            column: 49,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function hello() { \'use strict\'; function inner(arguments) {} }': {
+            index: 48,
+            lineNumber: 1,
+            column: 49,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        ' "\\1"; \'use strict\';': {
+            index: 1,
+            lineNumber: 1,
+            column: 2,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { \'use strict\'; "\\1"; }': {
+            index: 33,
+            lineNumber: 1,
+            column: 34,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { \'use strict\'; 021; }': {
+            index: 33,
+            lineNumber: 1,
+            column: 34,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { \'use strict\'; ({ "\\1": 42 }); }': {
+            index: 36,
+            lineNumber: 1,
+            column: 37,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { \'use strict\'; ({ 021: 42 }); }': {
+            index: 36,
+            lineNumber: 1,
+            column: 37,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { "octal directive\\1"; "use strict"; }': {
+            index: 19,
+            lineNumber: 1,
+            column: 20,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { "octal directive\\1"; "octal directive\\2"; "use strict"; }': {
+            index: 19,
+            lineNumber: 1,
+            column: 20,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { "use strict"; function inner() { "octal directive\\1"; } }': {
+            index: 52,
+            lineNumber: 1,
+            column: 53,
+            message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+        },
+
+        'function hello() { "use strict"; var implements; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var interface; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var package; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var private; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var protected; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var public; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var static; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var yield; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello() { "use strict"; var let; }': {
+            index: 37,
+            lineNumber: 1,
+            column: 38,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function hello(static) { "use strict"; }': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function static() { "use strict"; }': {
+            index: 9,
+            lineNumber: 1,
+            column: 10,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'var yield': {
+            index: 4,
+            lineNumber: 1,
+            column: 5,
+            message: 'Error: Line 1: Unexpected token yield'
+        },
+
+        'var let': {
+            index: 4,
+            lineNumber: 1,
+            column: 5,
+            message: 'Error: Line 1: Unexpected token let'
+        },
+
+        '"use strict"; function static() { }': {
+            index: 23,
+            lineNumber: 1,
+            column: 24,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function a(t, t) { "use strict"; }': {
+            index: 14,
+            lineNumber: 1,
+            column: 15,
+            message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+        },
+
+        'function a(eval) { "use strict"; }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        'function a(package) { "use strict"; }': {
+            index: 11,
+            lineNumber: 1,
+            column: 12,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'function a() { "use strict"; function b(t, t) { }; }': {
+            index: 43,
+            lineNumber: 1,
+            column: 44,
+            message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+        },
+
+        '(function a(t, t) { "use strict"; })': {
+            index: 15,
+            lineNumber: 1,
+            column: 16,
+            message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+        },
+
+        'function a() { "use strict"; (function b(t, t) { }); }': {
+            index: 44,
+            lineNumber: 1,
+            column: 45,
+            message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+        },
+
+        '(function a(eval) { "use strict"; })': {
+            index: 12,
+            lineNumber: 1,
+            column: 13,
+            message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+        },
+
+        '(function a(package) { "use strict"; })': {
+            index: 12,
+            lineNumber: 1,
+            column: 13,
+            message: 'Error: Line 1: Use of future reserved word in strict mode'
+        },
+
+        'var': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'let': {
+            index: 3,
+            lineNumber: 1,
+            column: 4,
+            message: 'Error: Line 1: Unexpected end of input'
+        },
+
+        'const': {
+            index: 5,
+            lineNumber: 1,
+            column: 6,
+            message: 'Error: Line 1: Unexpected end of input'
+        }
+
+    },
+
+    'API': {
+        'parse()': {
+            call: 'parse',
+            args: [],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'undefined'
+                    }
+                }]
+            }
+        },
+
+        'parse(null)': {
+            call: 'parse',
+            args: [null],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Literal',
+                        value: null
+                    }
+                }]
+            }
+        },
+
+        'parse(42)': {
+            call: 'parse',
+            args: [42],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Literal',
+                        value: 42
+                    }
+                }]
+            }
+        },
+
+        'parse(true)': {
+            call: 'parse',
+            args: [true],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Literal',
+                        value: true
+                    }
+                }]
+            }
+        },
+
+        'parse(undefined)': {
+            call: 'parse',
+            args: [void 0],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'undefined'
+                    }
+                }]
+            }
+        },
+
+        'parse(new String("test"))': {
+            call: 'parse',
+            args: [new String('test')],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Identifier',
+                        name: 'test'
+                    }
+                }]
+            }
+        },
+
+        'parse(new Number(42))': {
+            call: 'parse',
+            args: [new Number(42)],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Literal',
+                        value: 42
+                    }
+                }]
+            }
+        },
+
+        'parse(new Boolean(true))': {
+            call: 'parse',
+            args: [new Boolean(true)],
+            result: {
+                type: 'Program',
+                body: [{
+                    type: 'ExpressionStatement',
+                    expression: {
+                        type: 'Literal',
+                        value: true
+                    }
+                }]
+            }
+        },
+
+        'Syntax': {
+            property: 'Syntax',
+            result: {
+                AssignmentExpression: 'AssignmentExpression',
+                ArrayExpression: 'ArrayExpression',
+                BlockStatement: 'BlockStatement',
+                BinaryExpression: 'BinaryExpression',
+                BreakStatement: 'BreakStatement',
+                CallExpression: 'CallExpression',
+                CatchClause: 'CatchClause',
+                ConditionalExpression: 'ConditionalExpression',
+                ContinueStatement: 'ContinueStatement',
+                DoWhileStatement: 'DoWhileStatement',
+                DebuggerStatement: 'DebuggerStatement',
+                EmptyStatement: 'EmptyStatement',
+                ExpressionStatement: 'ExpressionStatement',
+                ForStatement: 'ForStatement',
+                ForInStatement: 'ForInStatement',
+                FunctionDeclaration: 'FunctionDeclaration',
+                FunctionExpression: 'FunctionExpression',
+                Identifier: 'Identifier',
+                IfStatement: 'IfStatement',
+                Literal: 'Literal',
+                LabeledStatement: 'LabeledStatement',
+                LogicalExpression: 'LogicalExpression',
+                MemberExpression: 'MemberExpression',
+                NewExpression: 'NewExpression',
+                ObjectExpression: 'ObjectExpression',
+                Program: 'Program',
+                Property: 'Property',
+                ReturnStatement: 'ReturnStatement',
+                SequenceExpression: 'SequenceExpression',
+                SwitchStatement: 'SwitchStatement',
+                SwitchCase: 'SwitchCase',
+                ThisExpression: 'ThisExpression',
+                ThrowStatement: 'ThrowStatement',
+                TryStatement: 'TryStatement',
+                UnaryExpression: 'UnaryExpression',
+                UpdateExpression: 'UpdateExpression',
+                VariableDeclaration: 'VariableDeclaration',
+                VariableDeclarator: 'VariableDeclarator',
+                WhileStatement: 'WhileStatement',
+                WithStatement: 'WithStatement'
+            }
+        }
+
+    },
+
+    'Tolerant parse': {
+        'return': {
+            type: 'Program',
+            body: [{
+                type: 'ReturnStatement',
+                'argument': null,
+                range: [0, 6],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 6 }
+                }
+            }],
+            range: [0, 6],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 6 }
+            },
+            errors: [{
+                index: 6,
+                lineNumber: 1,
+                column: 7,
+                message: 'Error: Line 1: Illegal return statement'
+            }]
+        },
+
+        '(function () { \'use strict\'; with (i); }())': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'FunctionExpression',
+                        id: null,
+                        params: [],
+                        defaults: [],
+                        body: {
+                            type: 'BlockStatement',
+                            body: [{
+                                type: 'ExpressionStatement',
+                                expression: {
+                                    type: 'Literal',
+                                    value: 'use strict',
+                                    raw: '\'use strict\'',
+                                    range: [15, 27],
+                                    loc: {
+                                        start: { line: 1, column: 15 },
+                                        end: { line: 1, column: 27 }
+                                    }
+                                },
+                                range: [15, 28],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 28 }
+                                }
+                            }, {
+                                type: 'WithStatement',
+                                object: {
+                                    type: 'Identifier',
+                                    name: 'i',
+                                    range: [35, 36],
+                                    loc: {
+                                        start: { line: 1, column: 35 },
+                                        end: { line: 1, column: 36 }
+                                    }
+                                },
+                                body: {
+                                    type: 'EmptyStatement',
+                                    range: [37, 38],
+                                    loc: {
+                                        start: { line: 1, column: 37 },
+                                        end: { line: 1, column: 38 }
+                                    }
+                                },
+                                range: [29, 38],
+                                loc: {
+                                    start: { line: 1, column: 29 },
+                                    end: { line: 1, column: 38 }
+                                }
+                            }],
+                            range: [13, 40],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 40 }
+                            }
+                        },
+                        rest: null,
+                        generator: false,
+                        expression: false,
+                        range: [1, 40],
+                        loc: {
+                            start: { line: 1, column: 1 },
+                            end: { line: 1, column: 40 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [1, 42],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 42 }
+                    }
+                },
+                range: [0, 43],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 43 }
+                }
+            }],
+            range: [0, 43],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 43 }
+            },
+            errors: [{
+                index: 29,
+                lineNumber: 1,
+                column: 30,
+                message: 'Error: Line 1: Strict mode code may not include a with statement'
+            }]
+        },
+
+        '(function () { \'use strict\'; 021 }())': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'CallExpression',
+                    callee: {
+                        type: 'FunctionExpression',
+                        id: null,
+                        params: [],
+                        defaults: [],
+                        body: {
+                            type: 'BlockStatement',
+                            body: [{
+                                type: 'ExpressionStatement',
+                                expression: {
+                                    type: 'Literal',
+                                    value: 'use strict',
+                                    raw: '\'use strict\'',
+                                    range: [15, 27],
+                                    loc: {
+                                        start: { line: 1, column: 15 },
+                                        end: { line: 1, column: 27 }
+                                    }
+                                },
+                                range: [15, 28],
+                                loc: {
+                                    start: { line: 1, column: 15 },
+                                    end: { line: 1, column: 28 }
+                                }
+                            }, {
+                                type: 'ExpressionStatement',
+                                expression: {
+                                    type: 'Literal',
+                                    value: 17,
+                                    raw: "021",
+                                    range: [29, 32],
+                                    loc: {
+                                        start: { line: 1, column: 29 },
+                                        end: { line: 1, column: 32 }
+                                    }
+                                },
+                                range: [29, 33],
+                                loc: {
+                                    start: { line: 1, column: 29 },
+                                    end: { line: 1, column: 33 }
+                                }
+                            }],
+                            range: [13, 34],
+                            loc: {
+                                start: { line: 1, column: 13 },
+                                end: { line: 1, column: 34 }
+                            }
+                        },
+                        rest: null,
+                        generator: false,
+                        expression: false,
+                        range: [1, 34],
+                        loc: {
+                            start: { line: 1, column: 1 },
+                            end: { line: 1, column: 34 }
+                        }
+                    },
+                    'arguments': [],
+                    range: [1, 36],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [0, 37],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 37 }
+                }
+            }],
+            range: [0, 37],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 37 }
+            },
+            errors: [{
+                index: 29,
+                lineNumber: 1,
+                column: 30,
+                message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+            }]
+        },
+
+        '"use strict"; delete x': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UnaryExpression',
+                    operator: 'delete',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [21, 22],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    prefix: true,
+                    range: [14, 22],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                range: [14, 22],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 22 }
+                }
+            }],
+            range: [0, 22],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 22 }
+            },
+            errors: [{
+                index: 22,
+                lineNumber: 1,
+                column: 23,
+                message: 'Error: Line 1: Delete of an unqualified identifier in strict mode.'
+            }]
+        },
+
+        '"use strict"; try {} catch (eval) {}': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'TryStatement',
+                block: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [18, 20],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                guardedHandlers: [],
+                handlers: [{
+                    type: 'CatchClause',
+                    param: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [28, 32],
+                        loc: {
+                            start: { line: 1, column: 28 },
+                            end: { line: 1, column: 32 }
+                        }
+                    },
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [34, 36],
+                        loc: {
+                            start: { line: 1, column: 34 },
+                            end: { line: 1, column: 36 }
+                        }
+                    },
+                    range: [21, 36],
+                    loc: {
+                        start: { line: 1, column: 21 },
+                        end: { line: 1, column: 36 }
+                    }
+                }],
+                finalizer: null,
+                range: [14, 36],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 36 }
+                }
+            }],
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            },
+            errors: [{
+                index: 32,
+                lineNumber: 1,
+                column: 33,
+                message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; try {} catch (arguments) {}': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'TryStatement',
+                block: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [18, 20],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                guardedHandlers: [],
+                handlers: [{
+                    type: 'CatchClause',
+                    param: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [28, 37],
+                        loc: {
+                            start: { line: 1, column: 28 },
+                            end: { line: 1, column: 37 }
+                        }
+                    },
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [39, 41],
+                        loc: {
+                            start: { line: 1, column: 39 },
+                            end: { line: 1, column: 41 }
+                        }
+                    },
+                    range: [21, 41],
+                    loc: {
+                        start: { line: 1, column: 21 },
+                        end: { line: 1, column: 41 }
+                    }
+                }],
+                finalizer: null,
+                range: [14, 41],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 41 }
+                }
+            }],
+            range: [0, 41],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 41 }
+            },
+            errors: [{
+                index: 37,
+                lineNumber: 1,
+                column: 38,
+                message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; var eval;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [18, 22],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    init: null,
+                    range: [18, 22],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 22 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 23],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 23 }
+                }
+            }],
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            },
+            errors: [{
+                index: 22,
+                lineNumber: 1,
+                column: 23,
+                message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; var arguments;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [18, 27],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    init: null,
+                    range: [18, 27],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 27 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 28],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 28 }
+                }
+            }],
+            range: [0, 28],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 28 }
+            },
+            errors: [{
+                index: 27,
+                lineNumber: 1,
+                column: 28,
+                message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; eval = 0;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [14, 18],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [21, 22],
+                        loc: {
+                            start: { line: 1, column: 21 },
+                            end: { line: 1, column: 22 }
+                        }
+                    },
+                    range: [14, 22],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 22 }
+                    }
+                },
+                range: [14, 23],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 23 }
+                }
+            }],
+            range: [0, 23],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 23 }
+            },
+            errors: [{
+                index: 14,
+                lineNumber: 1,
+                column: 15,
+                message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; eval++;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '++',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [14, 18],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 18 }
+                        }
+                    },
+                    prefix: false,
+                    range: [14, 20],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                range: [14, 21],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            },
+            errors: [{
+                index: 18,
+                lineNumber: 1,
+                column: 19,
+                message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+            }]
+        },
+
+        '"use strict"; --eval;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '--',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [16, 20],
+                        loc: {
+                            start: { line: 1, column: 16 },
+                            end: { line: 1, column: 20 }
+                        }
+                    },
+                    prefix: true,
+                    range: [14, 20],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 20 }
+                    }
+                },
+                range: [14, 21],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 21 }
+                }
+            }],
+            range: [0, 21],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 21 }
+            },
+            errors: [{
+                index: 20,
+                lineNumber: 1,
+                column: 21,
+                message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+            }]
+        },
+
+        '"use strict"; arguments = 0;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [14, 23],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 23 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 0,
+                        raw: '0',
+                        range: [26, 27],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 27 }
+                        }
+                    },
+                    range: [14, 27],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                range: [14, 28],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 28 }
+                }
+            }],
+            range: [0, 28],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 28 }
+            },
+            errors: [{
+                index: 14,
+                lineNumber: 1,
+                column: 15,
+                message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; arguments--;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '--',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [14, 23],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 23 }
+                        }
+                    },
+                    prefix: false,
+                    range: [14, 25],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                range: [14, 26],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 26 }
+                }
+            }],
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            },
+            errors: [{
+                index: 23,
+                lineNumber: 1,
+                column: 24,
+                message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode'
+            }]
+        },
+
+        '"use strict"; ++arguments;': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '++',
+                    argument: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [16, 25],
+                        loc: {
+                            start: { line: 1, column: 16 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    prefix: true,
+                    range: [14, 25],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 25 }
+                    }
+                },
+                range: [14, 26],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 26 }
+                }
+            }],
+            range: [0, 26],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 26 }
+            },
+            errors: [{
+                index: 25,
+                lineNumber: 1,
+                column: 26,
+                message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode'
+            }]
+        },
+
+
+        '"use strict";x={y:1,y:1}': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [13, 14],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 14 }
+                        }
+                    },
+                    right: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'y',
+                                range: [16, 17],
+                                loc: {
+                                    start: { line: 1, column: 16 },
+                                    end: { line: 1, column: 17 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 1,
+                                raw: '1',
+                                range: [18, 19],
+                                loc: {
+                                    start: { line: 1, column: 18 },
+                                    end: { line: 1, column: 19 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [16, 19],
+                            loc: {
+                                start: { line: 1, column: 16 },
+                                end: { line: 1, column: 19 }
+                            }
+                        }, {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'y',
+                                range: [20, 21],
+                                loc: {
+                                    start: { line: 1, column: 20 },
+                                    end: { line: 1, column: 21 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 1,
+                                raw: '1',
+                                range: [22, 23],
+                                loc: {
+                                    start: { line: 1, column: 22 },
+                                    end: { line: 1, column: 23 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [20, 23],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 23 }
+                            }
+                        }],
+                        range: [15, 24],
+                        loc: {
+                            start: { line: 1, column: 15 },
+                            end: { line: 1, column: 24 }
+                        }
+                    },
+                    range: [13, 24],
+                    loc: {
+                        start: { line: 1, column: 13 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                range: [13, 24],
+                loc: {
+                    start: { line: 1, column: 13 },
+                    end: { line: 1, column: 24 }
+                }
+            }],
+            range: [0, 24],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 24 }
+            },
+            errors: [{
+                index: 23,
+                lineNumber: 1,
+                column: 24,
+                message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; function eval() {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [23, 27],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 27 }
+                    }
+                },
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [30, 32],
+                    loc: {
+                        start: { line: 1, column: 30 },
+                        end: { line: 1, column: 32 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 32],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 32 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [32, 33],
+                loc: {
+                    start: { line: 1, column: 32 },
+                    end: { line: 1, column: 33 }
+                }
+            }],
+            range: [0, 33],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 33 }
+            },
+            errors: [{
+                index: 23,
+                lineNumber: 1,
+                column: 24,
+                message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; function arguments() {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [23, 32],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 32 }
+                    }
+                },
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [35, 37],
+                    loc: {
+                        start: { line: 1, column: 35 },
+                        end: { line: 1, column: 37 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 37],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 37 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [37, 38],
+                loc: {
+                    start: { line: 1, column: 37 },
+                    end: { line: 1, column: 38 }
+                }
+            }],
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            },
+            errors: [{
+                index: 23,
+                lineNumber: 1,
+                column: 24,
+                message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; function interface() {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'interface',
+                    range: [23, 32],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 32 }
+                    }
+                },
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [35, 37],
+                    loc: {
+                        start: { line: 1, column: 35 },
+                        end: { line: 1, column: 37 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 37],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 37 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [37, 38],
+                loc: {
+                    start: { line: 1, column: 37 },
+                    end: { line: 1, column: 38 }
+                }
+            }],
+            range: [0, 38],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 38 }
+            },
+            errors: [{
+                index: 23,
+                lineNumber: 1,
+                column: 24,
+                message: 'Error: Line 1: Use of future reserved word in strict mode'
+            }]
+        },
+
+        '"use strict"; (function eval() {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [24, 28],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 28 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [31, 33],
+                        loc: {
+                            start: { line: 1, column: 31 },
+                            end: { line: 1, column: 33 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 33],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 33 }
+                    }
+                },
+                range: [14, 35],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 35 }
+                }
+            }],
+            range: [0, 35],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 35 }
+            },
+            errors: [{
+                index: 24,
+                lineNumber: 1,
+                column: 25,
+                message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; (function arguments() {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [24, 33],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 33 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [36, 38],
+                        loc: {
+                            start: { line: 1, column: 36 },
+                            end: { line: 1, column: 38 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 38],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                range: [14, 40],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 40 }
+                }
+            }],
+            range: [0, 40],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 40 }
+            },
+            errors: [{
+                index: 24,
+                lineNumber: 1,
+                column: 25,
+                message: 'Error: Line 1: Function name may not be eval or arguments in strict mode'
+            }]
+        },
+
+        '"use strict"; (function interface() {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'interface',
+                        range: [24, 33],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 33 }
+                        }
+                    },
+                    params: [],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [36, 38],
+                        loc: {
+                            start: { line: 1, column: 36 },
+                            end: { line: 1, column: 38 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 38],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                range: [14, 40],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 40 }
+                }
+            }],
+            range: [0, 40],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 40 }
+            },
+            errors: [{
+                index: 24,
+                lineNumber: 1,
+                column: 25,
+                message: 'Error: Line 1: Use of future reserved word in strict mode'
+            }]
+        },
+
+        '"use strict"; function f(eval) {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'f',
+                    range: [23, 24],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                params: [{
+                    type: 'Identifier',
+                    name: 'eval',
+                    range: [25, 29],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 29 }
+                    }
+                }],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [31, 33],
+                    loc: {
+                        start: { line: 1, column: 31 },
+                        end: { line: 1, column: 33 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 33],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 33 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [33, 34],
+                loc: {
+                    start: { line: 1, column: 33 },
+                    end: { line: 1, column: 34 }
+                }
+            }],
+            range: [0, 34],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 34 }
+            },
+            errors: [{
+                index: 25,
+                lineNumber: 1,
+                column: 26,
+                message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; function f(arguments) {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'f',
+                    range: [23, 24],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                params: [{
+                    type: 'Identifier',
+                    name: 'arguments',
+                    range: [25, 34],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 34 }
+                    }
+                }],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [36, 38],
+                    loc: {
+                        start: { line: 1, column: 36 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 38],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 38 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [38, 39],
+                loc: {
+                    start: { line: 1, column: 38 },
+                    end: { line: 1, column: 39 }
+                }
+            }],
+            range: [0, 39],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 39 }
+            },
+            errors: [{
+                index: 25,
+                lineNumber: 1,
+                column: 26,
+                message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; function f(foo,  foo) {};': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'f',
+                    range: [23, 24],
+                    loc: {
+                        start: { line: 1, column: 23 },
+                        end: { line: 1, column: 24 }
+                    }
+                },
+                params: [{
+                    type: 'Identifier',
+                    name: 'foo',
+                    range: [25, 28],
+                    loc: {
+                        start: { line: 1, column: 25 },
+                        end: { line: 1, column: 28 }
+                    }
+                }, {
+                    type: 'Identifier',
+                    name: 'foo',
+                    range: [31, 34],
+                    loc: {
+                        start: { line: 1, column: 31 },
+                        end: { line: 1, column: 34 }
+                    }
+                }],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [36, 38],
+                    loc: {
+                        start: { line: 1, column: 36 },
+                        end: { line: 1, column: 38 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [14, 38],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 38 }
+                }
+            }, {
+                type: 'EmptyStatement',
+                range: [38, 39],
+                loc: {
+                    start: { line: 1, column: 38 },
+                    end: { line: 1, column: 39 }
+                }
+            }],
+            range: [0, 39],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 39 }
+            },
+            errors: [{
+                index: 31,
+                lineNumber: 1,
+                column: 32,
+                message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+            }]
+        },
+
+        '"use strict"; (function f(eval) {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'f',
+                        range: [24, 25],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    params: [{
+                        type: 'Identifier',
+                        name: 'eval',
+                        range: [26, 30],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 30 }
+                        }
+                    }],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [32, 34],
+                        loc: {
+                            start: { line: 1, column: 32 },
+                            end: { line: 1, column: 34 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 34],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 34 }
+                    }
+                },
+                range: [14, 36],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 36 }
+                }
+            }],
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            },
+            errors: [{
+                index: 26,
+                lineNumber: 1,
+                column: 27,
+                message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+
+        '"use strict"; (function f(arguments) {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'f',
+                        range: [24, 25],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    params: [{
+                        type: 'Identifier',
+                        name: 'arguments',
+                        range: [26, 35],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 35 }
+                        }
+                    }],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [37, 39],
+                        loc: {
+                            start: { line: 1, column: 37 },
+                            end: { line: 1, column: 39 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 39],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 39 }
+                    }
+                },
+                range: [14, 41],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 41 }
+                }
+            }],
+            range: [0, 41],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 41 }
+            },
+            errors: [{
+                index: 26,
+                lineNumber: 1,
+                column: 27,
+                message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        '"use strict"; (function f(foo,  foo) {});': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'FunctionExpression',
+                    id: {
+                        type: 'Identifier',
+                        name: 'f',
+                        range: [24, 25],
+                        loc: {
+                            start: { line: 1, column: 24 },
+                            end: { line: 1, column: 25 }
+                        }
+                    },
+                    params: [{
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [26, 29],
+                        loc: {
+                            start: { line: 1, column: 26 },
+                            end: { line: 1, column: 29 }
+                        }
+                    }, {
+                        type: 'Identifier',
+                        name: 'foo',
+                        range: [32, 35],
+                        loc: {
+                            start: { line: 1, column: 32 },
+                            end: { line: 1, column: 35 }
+                        }
+                    }],
+                    defaults: [],
+                    body: {
+                        type: 'BlockStatement',
+                        body: [],
+                        range: [37, 39],
+                        loc: {
+                            start: { line: 1, column: 37 },
+                            end: { line: 1, column: 39 }
+                        }
+                    },
+                    rest: null,
+                    generator: false,
+                    expression: false,
+                    range: [15, 39],
+                    loc: {
+                        start: { line: 1, column: 15 },
+                        end: { line: 1, column: 39 }
+                    }
+                },
+                range: [14, 41],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 41 }
+                }
+            }],
+            range: [0, 41],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 41 }
+            },
+            errors: [{
+                index: 32,
+                lineNumber: 1,
+                column: 33,
+                message: 'Error: Line 1: Strict mode function may not have duplicate parameter names'
+            }]
+        },
+
+        '"use strict"; x = { set f(eval) {} }' : {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [14, 15],
+                        loc: {
+                            start: { line: 1, column: 14 },
+                            end: { line: 1, column: 15 }
+                        }
+                    },
+                    right: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'f',
+                                range: [24, 25],
+                                loc: {
+                                    start: { line: 1, column: 24 },
+                                    end: { line: 1, column: 25 }
+                                }
+                            },
+                            value : {
+                                type: 'FunctionExpression',
+                                id: null,
+                                params: [{
+                                    type: 'Identifier',
+                                    name: 'eval',
+                                    range: [26, 30],
+                                    loc: {
+                                        start: { line: 1, column: 26 },
+                                        end: { line: 1, column: 30 }
+                                    }
+                                }],
+                                defaults: [],
+                                body: {
+                                    type: 'BlockStatement',
+                                    body: [],
+                                    range: [32, 34],
+                                    loc: {
+                                        start: { line: 1, column: 32 },
+                                        end: { line: 1, column: 34 }
+                                    }
+                                },
+                                rest: null,
+                                generator: false,
+                                expression: false,
+                                range: [32, 34],
+                                loc: {
+                                    start: { line: 1, column: 32 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            kind: 'set',
+                            range: [20, 34],
+                            loc: {
+                                start: { line: 1, column: 20 },
+                                end: { line: 1, column: 34 }
+                            }
+                        }],
+                        range: [18, 36],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 36 }
+                        }
+                    },
+                    range: [14, 36],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 36 }
+                    }
+                },
+                range: [14, 36],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 36 }
+                }
+            }],
+            range: [0, 36],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 36 }
+            },
+            errors: [{
+                index: 26,
+                lineNumber: 1,
+                column: 27,
+                message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode'
+            }]
+        },
+
+        'function hello() { "octal directive\\1"; "use strict"; }': {
+            type: 'Program',
+            body: [{
+                type: 'FunctionDeclaration',
+                id: {
+                    type: 'Identifier',
+                    name: 'hello',
+                    range: [9, 14],
+                    loc: {
+                        start: { line: 1, column: 9 },
+                        end: { line: 1, column: 14 }
+                    }
+                },
+                params: [],
+                defaults: [],
+                body: {
+                    type: 'BlockStatement',
+                    body: [{
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'Literal',
+                            value: 'octal directive\u0001',
+                            raw: '"octal directive\\1"',
+                            range: [19, 38],
+                            loc: {
+                                start: { line: 1, column: 19 },
+                                end: { line: 1, column: 38 }
+                            }
+                        },
+                        range: [19, 39],
+                        loc: {
+                            start: { line: 1, column: 19 },
+                            end: { line: 1, column: 39 }
+                        }
+                    }, {
+                        type: 'ExpressionStatement',
+                        expression: {
+                            type: 'Literal',
+                            value: 'use strict',
+                            raw: '"use strict"',
+                            range: [40, 52],
+                            loc: {
+                                start: { line: 1, column: 40 },
+                                end: { line: 1, column: 52 }
+                            }
+                        },
+                        range: [40, 53],
+                        loc: {
+                            start: { line: 1, column: 40 },
+                            end: { line: 1, column: 53 }
+                        }
+                    }],
+                    range: [17, 55],
+                    loc: {
+                        start: { line: 1, column: 17 },
+                        end: { line: 1, column: 55 }
+                    }
+                },
+                rest: null,
+                generator: false,
+                expression: false,
+                range: [0, 55],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 55 }
+                }
+            }],
+            range: [0, 55],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 55 }
+            },
+            errors: [{
+                index: 19,
+                lineNumber: 1,
+                column: 20,
+                message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+            }]
+        },
+
+        '"\\1"; \'use strict\';': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: '\u0001',
+                    raw: '"\\1"',
+                    range: [0, 4],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 4 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            }, {
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '\'use strict\'',
+                    range: [6, 18],
+                    loc: {
+                        start: { line: 1, column: 6 },
+                        end: { line: 1, column: 18 }
+                    }
+                },
+                range: [6, 19],
+                loc: {
+                    start: { line: 1, column: 6 },
+                    end: { line: 1, column: 19 }
+                }
+            }],
+            range: [0, 19],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 19 }
+            },
+            errors: [{
+                index: 0,
+                lineNumber: 1,
+                column: 1,
+                message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+            }]
+        },
+
+        '"use strict"; var x = { 014: 3}': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    init: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Literal',
+                                value: 12,
+                                raw: '014',
+                                range: [24, 27],
+                                loc: {
+                                    start: { line: 1, column: 24 },
+                                    end: { line: 1, column: 27 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 3,
+                                raw: '3',
+                                range: [29, 30],
+                                loc: {
+                                    start: { line: 1, column: 29 },
+                                    end: { line: 1, column: 30 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [24, 30],
+                            loc: {
+                                start: { line: 1, column: 24 },
+                                end: { line: 1, column: 30 }
+                            }
+                        }],
+                        range: [22, 31],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 31 }
+                        }
+                    },
+                    range: [18, 31],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 31 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 31],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 31 }
+                }
+            }],
+            range: [0, 31],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 31 }
+            },
+            errors: [{
+                index: 24,
+                lineNumber: 1,
+                column: 25,
+                message: 'Error: Line 1: Octal literals are not allowed in strict mode.'
+            }]
+        },
+
+        '"use strict"; var x = { get i() {}, get i() {} }': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    init: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [28, 29],
+                                loc: {
+                                    start: { line: 1, column: 28 },
+                                    end: { line: 1, column: 29 }
+                                }
+                            },
+                            value: {
+                                type: 'FunctionExpression',
+                                id: null,
+                                params: [],
+                                defaults: [],
+                                body: {
+                                    type: 'BlockStatement',
+                                    body: [],
+                                    range: [32, 34],
+                                    loc: {
+                                        start: { line: 1, column: 32 },
+                                        end: { line: 1, column: 34 }
+                                    }
+                                },
+                                rest: null,
+                                generator: false,
+                                expression: false,
+                                range: [32, 34],
+                                loc: {
+                                    start: { line: 1, column: 32 },
+                                    end: { line: 1, column: 34 }
+                                }
+                            },
+                            kind: 'get',
+                            range: [24, 34],
+                            loc: {
+                                start: { line: 1, column: 24 },
+                                end: { line: 1, column: 34 }
+                            }
+                        }, {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [40, 41],
+                                loc: {
+                                    start: { line: 1, column: 40 },
+                                    end: { line: 1, column: 41 }
+                                }
+                            },
+                            value: {
+                                type: 'FunctionExpression',
+                                id: null,
+                                params: [],
+                                defaults: [],
+                                body: {
+                                    type: 'BlockStatement',
+                                    body: [],
+                                    range: [44, 46],
+                                    loc: {
+                                        start: { line: 1, column: 44 },
+                                        end: { line: 1, column: 46 }
+                                    }
+                                },
+                                rest: null,
+                                generator: false,
+                                expression: false,
+                                range: [44, 46],
+                                loc: {
+                                    start: { line: 1, column: 44 },
+                                    end: { line: 1, column: 46 }
+                                }
+                            },
+                            kind: 'get',
+                            range: [36, 46],
+                            loc: {
+                                start: { line: 1, column: 36 },
+                                end: { line: 1, column: 46 }
+                            }
+                        }],
+                        range: [22, 48],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 48 }
+                        }
+                    },
+                    range: [18, 48],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 48 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 48],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 48 }
+                }
+            }],
+            range: [0, 48],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 48 }
+            },
+            errors: [{
+                index: 46,
+                lineNumber: 1,
+                column: 47,
+                message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name'
+            }]
+        },
+
+        '"use strict"; var x = { i: 42, get i() {} }': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    init: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [24, 25],
+                                loc: {
+                                    start: { line: 1, column: 24 },
+                                    end: { line: 1, column: 25 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 42,
+                                raw: '42',
+                                range: [27, 29],
+                                loc: {
+                                    start: { line: 1, column: 27 },
+                                    end: { line: 1, column: 29 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [24, 29],
+                            loc: {
+                                start: { line: 1, column: 24 },
+                                end: { line: 1, column: 29 }
+                            }
+                        }, {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [35, 36],
+                                loc: {
+                                    start: { line: 1, column: 35 },
+                                    end: { line: 1, column: 36 }
+                                }
+                            },
+                            value: {
+                                type: 'FunctionExpression',
+                                id: null,
+                                params: [],
+                                defaults: [],
+                                body: {
+                                    type: 'BlockStatement',
+                                    body: [],
+                                    range: [39, 41],
+                                    loc: {
+                                        start: { line: 1, column: 39 },
+                                        end: { line: 1, column: 41 }
+                                    }
+                                },
+                                rest: null,
+                                generator: false,
+                                expression: false,
+                                range: [39, 41],
+                                loc: {
+                                    start: { line: 1, column: 39 },
+                                    end: { line: 1, column: 41 }
+                                }
+                            },
+                            kind: 'get',
+                            range: [31, 41],
+                            loc: {
+                                start: { line: 1, column: 31 },
+                                end: { line: 1, column: 41 }
+                            }
+                        }],
+                        range: [22, 43],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 43 }
+                        }
+                    },
+                    range: [18, 43],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 43 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 43],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 43 }
+                }
+            }],
+            range: [0, 43],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 43 }
+            },
+            errors: [{
+                index: 41,
+                lineNumber: 1,
+                column: 42,
+                message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+            }]
+        },
+
+        '"use strict"; var x = { set i(x) {}, i: 42 }': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'Literal',
+                    value: 'use strict',
+                    raw: '"use strict"',
+                    range: [0, 12],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                range: [0, 13],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 13 }
+                }
+            }, {
+                type: 'VariableDeclaration',
+                declarations: [{
+                    type: 'VariableDeclarator',
+                    id: {
+                        type: 'Identifier',
+                        name: 'x',
+                        range: [18, 19],
+                        loc: {
+                            start: { line: 1, column: 18 },
+                            end: { line: 1, column: 19 }
+                        }
+                    },
+                    init: {
+                        type: 'ObjectExpression',
+                        properties: [{
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [28, 29],
+                                loc: {
+                                    start: { line: 1, column: 28 },
+                                    end: { line: 1, column: 29 }
+                                }
+                            },
+                            value: {
+                                type: 'FunctionExpression',
+                                id: null,
+                                params: [{
+                                    type: 'Identifier',
+                                    name: 'x',
+                                    range: [30, 31],
+                                    loc: {
+                                        start: { line: 1, column: 30 },
+                                        end: { line: 1, column: 31 }
+                                    }
+                                }],
+                                defaults: [],
+                                body: {
+                                    type: 'BlockStatement',
+                                    body: [],
+                                    range: [33, 35],
+                                    loc: {
+                                        start: { line: 1, column: 33 },
+                                        end: { line: 1, column: 35 }
+                                    }
+                                },
+                                rest: null,
+                                generator: false,
+                                expression: false,
+                                range: [33, 35],
+                                loc: {
+                                    start: { line: 1, column: 33 },
+                                    end: { line: 1, column: 35 }
+                                }
+                            },
+                            kind: 'set',
+                            range: [24, 35],
+                            loc: {
+                                start: { line: 1, column: 24 },
+                                end: { line: 1, column: 35 }
+                            }
+                        }, {
+                            type: 'Property',
+                            key: {
+                                type: 'Identifier',
+                                name: 'i',
+                                range: [37, 38],
+                                loc: {
+                                    start: { line: 1, column: 37 },
+                                    end: { line: 1, column: 38 }
+                                }
+                            },
+                            value: {
+                                type: 'Literal',
+                                value: 42,
+                                raw: '42',
+                                range: [40, 42],
+                                loc: {
+                                    start: { line: 1, column: 40 },
+                                    end: { line: 1, column: 42 }
+                                }
+                            },
+                            kind: 'init',
+                            range: [37, 42],
+                            loc: {
+                                start: { line: 1, column: 37 },
+                                end: { line: 1, column: 42 }
+                            }
+                        }],
+                        range: [22, 44],
+                        loc: {
+                            start: { line: 1, column: 22 },
+                            end: { line: 1, column: 44 }
+                        }
+                    },
+                    range: [18, 44],
+                    loc: {
+                        start: { line: 1, column: 18 },
+                        end: { line: 1, column: 44 }
+                    }
+                }],
+                kind: 'var',
+                range: [14, 44],
+                loc: {
+                    start: { line: 1, column: 14 },
+                    end: { line: 1, column: 44 }
+                }
+            }],
+            range: [0, 44],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 44 }
+            },
+            errors: [{
+                index: 42,
+                lineNumber: 1,
+                column: 43,
+                message: 'Error: Line 1: Object literal may not have data and accessor property with the same name'
+            }]
+
+
+        },
+
+        '({ set s() { } })': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'ObjectExpression',
+                    properties: [{
+                        type: 'Property',
+                        key: {
+                            type: 'Identifier',
+                            name: 's',
+                            range: [7, 8],
+                            loc: {
+                                start: { line: 1, column: 7 },
+                                end: { line: 1, column: 8 }
+                            }
+                        },
+                        value: {
+                            type: 'FunctionExpression',
+                            id: null,
+                            params: [],
+                            defaults: [],
+                            body: {
+                                type: 'BlockStatement',
+                                body: [],
+                                range: [11, 14],
+                                loc: {
+                                    start: { line: 1, column: 11 },
+                                    end: { line: 1, column: 14 }
+                                }
+                            },
+                            rest: null,
+                            generator: false,
+                            expression: false,
+                            range: [11, 14],
+                            loc: {
+                                start: { line: 1, column: 11 },
+                                end: { line: 1, column: 14 }
+                            }
+                        },
+                        kind: 'set',
+                        range: [3, 14],
+                        loc: {
+                            start: { line: 1, column: 3 },
+                            end: { line: 1, column: 14 }
+                        }
+                    }],
+                    range: [1, 16],
+                    loc: {
+                        start: { line: 1, column: 1 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                range: [0, 17],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 17 }
+                }
+            }],
+            range: [0, 17],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 17 }
+            },
+            errors: [{
+                index: 9,
+                lineNumber: 1,
+                column: 10,
+                message: 'Error: Line 1: Unexpected token )'
+            }]
+        },
+
+        'foo("bar") = baz': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'CallExpression',
+                        callee: {
+                            type: 'Identifier',
+                            name: 'foo',
+                            range: [0, 3],
+                            loc: {
+                                start: { line: 1, column: 0 },
+                                end: { line: 1, column: 3 }
+                            }
+                        },
+                        'arguments': [{
+                            type: 'Literal',
+                            value: 'bar',
+                            raw: '"bar"',
+                            range: [4, 9],
+                            loc: {
+                                start: { line: 1, column: 4 },
+                                end: { line: 1, column: 9 }
+                            }
+                        }],
+                        range: [0, 10],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 10 }
+                        }
+                    },
+                    right: {
+                        type: 'Identifier',
+                        name: 'baz',
+                        range: [13, 16],
+                        loc: {
+                            start: { line: 1, column: 13 },
+                            end: { line: 1, column: 16 }
+                        }
+                    },
+                    range: [0, 16],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }],
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            },
+            errors: [{
+                index: 10,
+                lineNumber: 1,
+                column: 11,
+                message: 'Error: Line 1: Invalid left-hand side in assignment'
+            }]
+        },
+
+        '1 = 2': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'AssignmentExpression',
+                    operator: '=',
+                    left: {
+                        type: 'Literal',
+                        value: 1,
+                        raw: '1',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    right: {
+                        type: 'Literal',
+                        value: 2,
+                        raw: '2',
+                        range: [4, 5],
+                        loc: {
+                            start: { line: 1, column: 4 },
+                            end: { line: 1, column: 5 }
+                        }
+                    },
+                    range: [0, 5],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 5 }
+                    }
+                },
+                range: [0, 5],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 5 }
+                }
+            }],
+            range: [0, 5],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 5 }
+            },
+            errors: [{
+                index: 1,
+                lineNumber: 1,
+                column: 2,
+                message: 'Error: Line 1: Invalid left-hand side in assignment'
+            }]
+        },
+
+        '3++': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '++',
+                    argument: {
+                        type: 'Literal',
+                        value: 3,
+                        raw: '3',
+                        range: [0, 1],
+                        loc: {
+                            start: { line: 1, column: 0 },
+                            end: { line: 1, column: 1 }
+                        }
+                    },
+                    prefix: false,
+                    range: [0, 3],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }],
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            },
+            errors: [{
+                index: 1,
+                lineNumber: 1,
+                column: 2,
+                message: 'Error: Line 1: Invalid left-hand side in assignment'
+            }]
+        },
+
+        '--4': {
+            type: 'Program',
+            body: [{
+                type: 'ExpressionStatement',
+                expression: {
+                    type: 'UpdateExpression',
+                    operator: '--',
+                    argument: {
+                        type: 'Literal',
+                        value: 4,
+                        raw: '4',
+                        range: [2, 3],
+                        loc: {
+                            start: { line: 1, column: 2 },
+                            end: { line: 1, column: 3 }
+                        }
+                    },
+                    prefix: true,
+                    range: [0, 3],
+                    loc: {
+                        start: { line: 1, column: 0 },
+                        end: { line: 1, column: 3 }
+                    }
+                },
+                range: [0, 3],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 3 }
+                }
+            }],
+            range: [0, 3],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 3 }
+            },
+            errors: [{
+                index: 3,
+                lineNumber: 1,
+                column: 4,
+                message: 'Error: Line 1: Invalid left-hand side in assignment'
+            }]
+        },
+
+        'for (5 in []) {}': {
+            type: 'Program',
+            body: [{
+                type: 'ForInStatement',
+                left: {
+                    type: 'Literal',
+                    value: 5,
+                    raw: '5',
+                    range: [5, 6],
+                    loc: {
+                        start: { line: 1, column: 5 },
+                        end: { line: 1, column: 6 }
+                    }
+                },
+                right: {
+                    type: 'ArrayExpression',
+                    elements: [],
+                    range: [10, 12],
+                    loc: {
+                        start: { line: 1, column: 10 },
+                        end: { line: 1, column: 12 }
+                    }
+                },
+                body: {
+                    type: 'BlockStatement',
+                    body: [],
+                    range: [14, 16],
+                    loc: {
+                        start: { line: 1, column: 14 },
+                        end: { line: 1, column: 16 }
+                    }
+                },
+                each: false,
+                range: [0, 16],
+                loc: {
+                    start: { line: 1, column: 0 },
+                    end: { line: 1, column: 16 }
+                }
+            }],
+            range: [0, 16],
+            loc: {
+                start: { line: 1, column: 0 },
+                end: { line: 1, column: 16 }
+            },
+            errors: [{
+                index: 6,
+                lineNumber: 1,
+                column: 7,
+                message: 'Error: Line 1: Invalid left-hand side in for-in'
+            }]
+        }
+
+
+    }
+};
+
diff --git a/node_modules/isarray/README.md b/node_modules/isarray/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..052a62b8d7b7ae2c6016d173319db607453659f8
--- /dev/null
+++ b/node_modules/isarray/README.md
@@ -0,0 +1,54 @@
+
+# isarray
+
+`Array#isArray` for older browsers.
+
+## Usage
+
+```js
+var isArray = require('isarray');
+
+console.log(isArray([])); // => true
+console.log(isArray({})); // => false
+```
+
+## Installation
+
+With [npm](http://npmjs.org) do
+
+```bash
+$ npm install isarray
+```
+
+Then bundle for the browser with
+[browserify](https://github.com/substack/browserify).
+
+With [component](http://component.io) do
+
+```bash
+$ component install juliangruber/isarray
+```
+
+## License
+
+(MIT)
+
+Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/isarray/build/build.js b/node_modules/isarray/build/build.js
new file mode 100644
index 0000000000000000000000000000000000000000..ec58596aeebe4eadcd7b5eeb5bd992233391d422
--- /dev/null
+++ b/node_modules/isarray/build/build.js
@@ -0,0 +1,209 @@
+
+/**
+ * Require the given path.
+ *
+ * @param {String} path
+ * @return {Object} exports
+ * @api public
+ */
+
+function require(path, parent, orig) {
+  var resolved = require.resolve(path);
+
+  // lookup failed
+  if (null == resolved) {
+    orig = orig || path;
+    parent = parent || 'root';
+    var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
+    err.path = orig;
+    err.parent = parent;
+    err.require = true;
+    throw err;
+  }
+
+  var module = require.modules[resolved];
+
+  // perform real require()
+  // by invoking the module's
+  // registered function
+  if (!module.exports) {
+    module.exports = {};
+    module.client = module.component = true;
+    module.call(this, module.exports, require.relative(resolved), module);
+  }
+
+  return module.exports;
+}
+
+/**
+ * Registered modules.
+ */
+
+require.modules = {};
+
+/**
+ * Registered aliases.
+ */
+
+require.aliases = {};
+
+/**
+ * Resolve `path`.
+ *
+ * Lookup:
+ *
+ *   - PATH/index.js
+ *   - PATH.js
+ *   - PATH
+ *
+ * @param {String} path
+ * @return {String} path or null
+ * @api private
+ */
+
+require.resolve = function(path) {
+  if (path.charAt(0) === '/') path = path.slice(1);
+  var index = path + '/index.js';
+
+  var paths = [
+    path,
+    path + '.js',
+    path + '.json',
+    path + '/index.js',
+    path + '/index.json'
+  ];
+
+  for (var i = 0; i < paths.length; i++) {
+    var path = paths[i];
+    if (require.modules.hasOwnProperty(path)) return path;
+  }
+
+  if (require.aliases.hasOwnProperty(index)) {
+    return require.aliases[index];
+  }
+};
+
+/**
+ * Normalize `path` relative to the current path.
+ *
+ * @param {String} curr
+ * @param {String} path
+ * @return {String}
+ * @api private
+ */
+
+require.normalize = function(curr, path) {
+  var segs = [];
+
+  if ('.' != path.charAt(0)) return path;
+
+  curr = curr.split('/');
+  path = path.split('/');
+
+  for (var i = 0; i < path.length; ++i) {
+    if ('..' == path[i]) {
+      curr.pop();
+    } else if ('.' != path[i] && '' != path[i]) {
+      segs.push(path[i]);
+    }
+  }
+
+  return curr.concat(segs).join('/');
+};
+
+/**
+ * Register module at `path` with callback `definition`.
+ *
+ * @param {String} path
+ * @param {Function} definition
+ * @api private
+ */
+
+require.register = function(path, definition) {
+  require.modules[path] = definition;
+};
+
+/**
+ * Alias a module definition.
+ *
+ * @param {String} from
+ * @param {String} to
+ * @api private
+ */
+
+require.alias = function(from, to) {
+  if (!require.modules.hasOwnProperty(from)) {
+    throw new Error('Failed to alias "' + from + '", it does not exist');
+  }
+  require.aliases[to] = from;
+};
+
+/**
+ * Return a require function relative to the `parent` path.
+ *
+ * @param {String} parent
+ * @return {Function}
+ * @api private
+ */
+
+require.relative = function(parent) {
+  var p = require.normalize(parent, '..');
+
+  /**
+   * lastIndexOf helper.
+   */
+
+  function lastIndexOf(arr, obj) {
+    var i = arr.length;
+    while (i--) {
+      if (arr[i] === obj) return i;
+    }
+    return -1;
+  }
+
+  /**
+   * The relative require() itself.
+   */
+
+  function localRequire(path) {
+    var resolved = localRequire.resolve(path);
+    return require(resolved, parent, path);
+  }
+
+  /**
+   * Resolve relative to the parent.
+   */
+
+  localRequire.resolve = function(path) {
+    var c = path.charAt(0);
+    if ('/' == c) return path.slice(1);
+    if ('.' == c) return require.normalize(p, path);
+
+    // resolve deps by returning
+    // the dep in the nearest "deps"
+    // directory
+    var segs = parent.split('/');
+    var i = lastIndexOf(segs, 'deps') + 1;
+    if (!i) i = 0;
+    path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
+    return path;
+  };
+
+  /**
+   * Check if module is defined at `path`.
+   */
+
+  localRequire.exists = function(path) {
+    return require.modules.hasOwnProperty(localRequire.resolve(path));
+  };
+
+  return localRequire;
+};
+require.register("isarray/index.js", function(exports, require, module){
+module.exports = Array.isArray || function (arr) {
+  return Object.prototype.toString.call(arr) == '[object Array]';
+};
+
+});
+require.alias("isarray/index.js", "isarray/index.js");
+
diff --git a/node_modules/isarray/component.json b/node_modules/isarray/component.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e31b6838890159e397063bdd2ea7de80b4e4a42
--- /dev/null
+++ b/node_modules/isarray/component.json
@@ -0,0 +1,19 @@
+{
+  "name" : "isarray",
+  "description" : "Array#isArray for older browsers",
+  "version" : "0.0.1",
+  "repository" : "juliangruber/isarray",
+  "homepage": "https://github.com/juliangruber/isarray",
+  "main" : "index.js",
+  "scripts" : [
+    "index.js"
+  ],
+  "dependencies" : {},
+  "keywords": ["browser","isarray","array"],
+  "author": {
+    "name": "Julian Gruber",
+    "email": "mail@juliangruber.com",
+    "url": "http://juliangruber.com"
+  },
+  "license": "MIT"
+}
diff --git a/node_modules/isarray/index.js b/node_modules/isarray/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f5ad45d46dda97cc2ae37932e0dacf25d06352d
--- /dev/null
+++ b/node_modules/isarray/index.js
@@ -0,0 +1,3 @@
+module.exports = Array.isArray || function (arr) {
+  return Object.prototype.toString.call(arr) == '[object Array]';
+};
diff --git a/node_modules/isarray/package.json b/node_modules/isarray/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..5a1e9c1098d0ff8bdb4955e5e714bb2270e6a25c
--- /dev/null
+++ b/node_modules/isarray/package.json
@@ -0,0 +1,25 @@
+{
+  "name" : "isarray",
+  "description" : "Array#isArray for older browsers",
+  "version" : "0.0.1",
+  "repository" : {
+    "type" : "git",
+    "url" : "git://github.com/juliangruber/isarray.git"
+  },
+  "homepage": "https://github.com/juliangruber/isarray",
+  "main" : "index.js",
+  "scripts" : {
+    "test" : "tap test/*.js"
+  },
+  "dependencies" : {},
+  "devDependencies" : {
+    "tap" : "*"
+  },
+  "keywords": ["browser","isarray","array"],
+  "author": {
+    "name": "Julian Gruber",
+    "email": "mail@juliangruber.com",
+    "url": "http://juliangruber.com"
+  },
+  "license": "MIT"
+}
diff --git a/node_modules/mysql2-promise/.idea/copyright/profiles_settings.xml b/node_modules/mysql2-promise/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e7bedf3377d40335424fd605124d4761390218bb
--- /dev/null
+++ b/node_modules/mysql2-promise/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+  <settings default="" />
+</component>
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.idea/modules.xml b/node_modules/mysql2-promise/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c1c1b4f67d555d4d7e1bdc254682a3d020aec65d
--- /dev/null
+++ b/node_modules/mysql2-promise/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/node-mysql2-promise.iml" filepath="$PROJECT_DIR$/.idea/node-mysql2-promise.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.idea/node-mysql2-promise.iml b/node_modules/mysql2-promise/.idea/node-mysql2-promise.iml
new file mode 100644
index 0000000000000000000000000000000000000000..c956989b29ad0767edc6cf3a202545927c3d1e76
--- /dev/null
+++ b/node_modules/mysql2-promise/.idea/node-mysql2-promise.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.idea/vcs.xml b/node_modules/mysql2-promise/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94a25f7f4cb416c083d265558da75d457237d671
--- /dev/null
+++ b/node_modules/mysql2-promise/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.idea/workspace.xml b/node_modules/mysql2-promise/.idea/workspace.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eff435bf902dc486690c09a895001dfe6e40c6db
--- /dev/null
+++ b/node_modules/mysql2-promise/.idea/workspace.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="b88757a0-d7e9-46c9-9990-7bb15467a648" name="Default" comment="" />
+    <ignored path="node-mysql2-promise.iws" />
+    <ignored path=".idea/workspace.xml" />
+    <ignored path=".idea/dataSources.local.xml" />
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="TRACKING_ENABLED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="CreatePatchCommitExecutor">
+    <option name="PATCH_PATH" value="" />
+  </component>
+  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
+  <component name="FavoritesManager">
+    <favorites_list name="node-mysql2-promise" />
+  </component>
+  <component name="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file leaf-file-name="index.js" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/index.js">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="193">
+              <caret line="60" column="20" selection-start-line="60" selection-start-column="20" selection-end-line="60" selection-end-column="20" />
+              <folding>
+                <element signature="n#!!doc" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="npm-debug.log" pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/npm-debug.log">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="553">
+              <caret line="97" column="33" selection-start-line="97" selection-start-column="24" selection-end-line="97" selection-end-column="33" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+  </component>
+  <component name="IdeDocumentHistory">
+    <option name="CHANGED_PATHS">
+      <list>
+        <option value="$PROJECT_DIR$/package.json" />
+        <option value="$PROJECT_DIR$/index.js" />
+        <option value="$PROJECT_DIR$/npm-debug.log" />
+      </list>
+    </option>
+  </component>
+  <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
+  <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER">
+    <package-json value="$PROJECT_DIR$/package.json" />
+  </component>
+  <component name="JsGulpfileManager">
+    <detection-done>true</detection-done>
+    <sorting>DEFINITION_ORDER</sorting>
+  </component>
+  <component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" />
+  <component name="ProjectFrameBounds">
+    <option name="x" value="65" />
+    <option name="y" value="24" />
+    <option name="width" value="1845" />
+    <option name="height" value="1054" />
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectView">
+    <navigator currentView="ProjectPane" proportions="" version="1">
+      <flattenPackages />
+      <showMembers />
+      <showModules />
+      <showLibraryContents />
+      <hideEmptyPackages />
+      <abbreviatePackageNames />
+      <autoscrollToSource />
+      <autoscrollFromSource />
+      <sortByType />
+      <manualOrder />
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="ProjectPane">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="node-mysql2-promise" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+          </PATH>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="node-mysql2-promise" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="node-mysql2-promise" />
+              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="Scratches" />
+      <pane id="Scope" />
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$/../cerberus" />
+    <property name="nodejs_interpreter_path" value="/usr/bin/node" />
+  </component>
+  <component name="RunManager">
+    <configuration default="true" type="BashConfigurationType" factoryName="Bash">
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="INTERPRETER_PATH" value="/bin/bash" />
+      <option name="WORKING_DIRECTORY" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <option name="SCRIPT_NAME" value="" />
+      <option name="PARAMETERS" value="" />
+      <module name="" />
+      <envs />
+      <method />
+    </configuration>
+    <configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
+      <method />
+    </configuration>
+    <configuration default="true" type="NodeJSConfigurationType" factoryName="Node.js" path-to-node="project" working-dir="">
+      <method />
+    </configuration>
+    <configuration default="true" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
+      <TestRunner />
+      <method />
+    </configuration>
+    <configuration default="true" type="PhpLocalRunConfigurationType" factoryName="PHP Console">
+      <method />
+    </configuration>
+    <configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
+      <node-interpreter>project</node-interpreter>
+      <node-options />
+      <gulpfile />
+      <tasks />
+      <arguments />
+      <envs />
+      <method />
+    </configuration>
+    <configuration default="true" type="js.build_tools.npm" factoryName="npm">
+      <command value="run-script" />
+      <scripts />
+      <node-interpreter value="project" />
+      <envs />
+      <method />
+    </configuration>
+    <configuration default="true" type="mocha-javascript-test-runner" factoryName="Mocha">
+      <node-interpreter>project</node-interpreter>
+      <node-options />
+      <working-directory />
+      <pass-parent-env>true</pass-parent-env>
+      <envs />
+      <ui />
+      <extra-mocha-options />
+      <test-kind>DIRECTORY</test-kind>
+      <test-directory />
+      <recursive>false</recursive>
+      <method />
+    </configuration>
+  </component>
+  <component name="ShelveChangesManager" show_recycled="false">
+    <option name="remove_strategy" value="false" />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="b88757a0-d7e9-46c9-9990-7bb15467a648" name="Default" comment="" />
+      <created>1472370576014</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1472370576014</updated>
+      <workItem from="1472370577168" duration="2074000" />
+      <workItem from="1472378210391" duration="358000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TimeTrackingManager">
+    <option name="totallyTimeSpent" value="2432000" />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="65" y="24" width="1845" height="1054" extended-state="0" />
+    <editor active="false" />
+    <layout>
+      <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25291827" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
+      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
+      <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
+      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
+      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
+      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+    </layout>
+  </component>
+  <component name="Vcs.Log.UiProperties">
+    <option name="RECENTLY_FILTERED_USER_GROUPS">
+      <collection />
+    </option>
+    <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
+      <collection />
+    </option>
+  </component>
+  <component name="VcsContentAnnotationSettings">
+    <option name="myLimit" value="2678400000" />
+  </component>
+  <component name="XDebuggerManager">
+    <breakpoint-manager />
+    <watches-manager />
+  </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/index.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding>
+            <element signature="n#!!doc" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/package.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="660">
+          <caret line="44" column="0" selection-start-line="44" selection-start-column="0" selection-end-line="44" selection-end-column="0" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/index.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="193">
+          <caret line="60" column="20" selection-start-line="60" selection-start-column="20" selection-end-line="60" selection-end-column="20" />
+          <folding>
+            <element signature="n#!!doc" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/npm-debug.log">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="553">
+          <caret line="97" column="33" selection-start-line="97" selection-start-column="24" selection-end-line="97" selection-end-column="33" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+  </component>
+</project>
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.jshintrc b/node_modules/mysql2-promise/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..443b102928d4df5fd8fc35019aab7a84b6e4bb98
--- /dev/null
+++ b/node_modules/mysql2-promise/.jshintrc
@@ -0,0 +1,35 @@
+{
+    "node":         true,
+    "bitwise":      true,
+    "browser":      true,
+    "camelcase":    true,
+    "curly":        true,
+    "eqeqeq":       true,
+    "esnext":       true,
+    "immed":        true,
+    "indent":       2,
+    "latedef":      true,
+    "newcap":       true,
+    "noarg":        true,
+    "quotmark":     "single",
+    "regexp":       true,
+    "smarttabs":    true,
+    "strict":       true,
+    "sub":          true,
+    "trailing":     true,
+    "undef":        true,
+    "unused":       true,
+    "jquery":       true,
+    "globalstrict": true,
+    "laxcomma":     true,
+    "predef":   {
+        "vpo":          true,
+        "_":            true,
+        "angular":      true,
+        "window":       true,
+        "app":          true,
+        "moment":       true,
+        "inject":       true,
+        "alert":        true
+    }
+}
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/.npmignore b/node_modules/mysql2-promise/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..c2658d7d1b31848c3b71960543cb0368e56cd4c7
--- /dev/null
+++ b/node_modules/mysql2-promise/.npmignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/node_modules/mysql2-promise/.travis.yml b/node_modules/mysql2-promise/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..12e3c228bf70d082bc42fe10ac171351eded2ca7
--- /dev/null
+++ b/node_modules/mysql2-promise/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+  - "0.10"
+script:
+  - npm test
+notifications:
+  email: dev@namshi.com
+
diff --git a/node_modules/mysql2-promise/README.md b/node_modules/mysql2-promise/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..383ae0f97b8fca5be86c4e64c4362b06db6199b5
--- /dev/null
+++ b/node_modules/mysql2-promise/README.md
@@ -0,0 +1,97 @@
+# mysql-promise
+
+Small promises wrapper for [`mysql2`](https://github.com/sidorares/node-mysql2), 
+it's forked and compatible with [`mysql-promise`](https://github.com/martinj/node-mysql-promise).
+
+[![build status](https://travis-ci.org/namshi/node-mysql2-promise.svg)](http://travis-ci.org/namshi/node-mysql2-promise)
+[![NPM](https://img.shields.io/npm/v/mysql2-promise.svg)](https://www.npmjs.com/package/mysql2-promise)
+[![NPM](https://img.shields.io/npm/dm/mysql2-promise.svg)](https://www.npmjs.com/package/mysql2-promise)
+
+## Installation
+
+This module is installed via npm:
+
+``` bash
+$ npm install mysql2-promise --save
+```
+
+## Example Usage of query
+
+``` js
+var db = require('mysql2-promise')();
+
+db.configure({
+	"host": "localhost",
+	"user": "foo",
+	"password": "bar",
+	"database": "db"
+});
+
+db.query('UPDATE foo SET key = ?', ['value']).then(function () {
+	return db.query('SELECT * FROM foo');
+}).spread(function (rows) {
+	console.log('Look at all the foo', rows);
+});
+
+//using multiple databases, giving it a name 'second-db' so it can be retrieved inside other modules/files.
+var db2 = require('mysql-promise')('second-db');
+
+db2.configure({
+	"host": "localhost",
+	"user": "foo",
+	"password": "bar",
+	"database": "another-db"
+});
+
+db2.query('SELECT * FROM users').spread(function (users) {
+	console.log('Hello users', users);
+});
+
+
+```
+
+## Example Usage of execute
+
+`execute()` function is similar to `query` but it use [prepared-statements](https://github.com/sidorares/node-mysql2#prepared-statements).
+
+``` js
+var db = require('mysql2-promise')();
+
+db.configure({
+	"host": "localhost",
+	"user": "foo",
+	"password": "bar",
+	"database": "db"
+});
+
+db.execute('SELECT * FROM users WHERE LIMIT = ?', [10]).spread(function (users) {
+	console.log('Hello users', users);
+});
+
+```
+
+## Example usage of [namedPlaceholders]((https://github.com/sidorares/node-mysql2#named-placeholders))
+
+``` js
+var db = require('mysql2-promise')();
+
+db.configure({
+	"host": "localhost",
+	"user": "foo",
+	"password": "bar",
+	"database": "db"
+});
+
+db.pool.on('connection', function (poolConnection) {
+    poolConnection.config.namedPlaceholders = true;
+});
+
+db.execute('SELECT * FROM users WHERE LIMIT = :limit', {limit: 10}).spread(function (users) {
+	console.log('Hello users', users);
+});
+
+```
+
+## Credits
+
+This library is forked from [`mysql-promise`](https://github.com/martinj/node-mysql-promise)
diff --git a/node_modules/mysql2-promise/index.js b/node_modules/mysql2-promise/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6d3c0cb429821a1e50421a6782a36965b3b246ec
--- /dev/null
+++ b/node_modules/mysql2-promise/index.js
@@ -0,0 +1,103 @@
+/* jshint strict: true */
+
+'use strict';
+
+var Q = require('q');
+var mysql2 = require('mysql2');
+var instances = {};
+
+function DB() {
+  this.pool = null;
+}
+
+/**
+ * Setup the Database connection pool for this instance
+ * @param  {Object} config
+ */
+DB.prototype.configure = function (config) {
+  this.pool = mysql2.createPool(config);
+};
+
+/**
+ * Run DB query
+ * @param  {String} query
+ * @param  {Object} [params]
+ * @return {Promise}
+ */
+DB.prototype.query = function (query, params) {
+  params = params || {};
+  var db = this;
+
+  return Q.Promise(function (resolve, reject) {
+    db.pool.getConnection(function (err, con) {
+      if (err) {
+        if (con) {
+          con.release();
+        }
+
+        return reject(err);
+      }
+
+      con.query(query, params, function (err) {
+        if (err) {
+          if (con) {
+            con.release();
+          }
+
+          return reject(err);
+        }
+
+        resolve([].splice.call(arguments, 1));
+        con.release();
+      });
+    });
+  });
+};
+
+/**
+ * Run DB execute
+ * @param  {String} query
+ * @param  {Object} [params]
+ * @return {Promise}
+ */
+DB.prototype.execute = function (query, params) {
+  params = params || {};
+  var db = this;
+
+  return Q.Promise(function (resolve, reject) {
+    db.pool.getConnection(function (err, con) {
+      if (err) {
+        if (con) {
+          con.release();
+        }
+
+        return reject(err);
+      }
+
+      con.execute(query, params, function (err) {
+        if (err) {
+          if (con) {
+            con.unprepare(query);
+            con.release();
+          }
+
+          return reject(err);
+        }
+
+        resolve([].splice.call(arguments, 1));
+        con.unprepare(query);
+        con.release();
+      });
+    });
+  });
+};
+
+module.exports = function (name) {
+  name = name || '_default_';
+
+  if (!instances[name]) {
+    instances[name] = new DB();
+  }
+
+  return instances[name];
+};
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/.npmignore b/node_modules/mysql2-promise/node_modules/lru-cache/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..07e6e472cc75fafa944e2a6d4b0f101bc476c060
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/.npmignore
@@ -0,0 +1 @@
+/node_modules
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/CONTRIBUTORS b/node_modules/mysql2-promise/node_modules/lru-cache/CONTRIBUTORS
new file mode 100644
index 0000000000000000000000000000000000000000..4a0bc5033a06e76a9cf5c42a0357946825a4f613
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/CONTRIBUTORS
@@ -0,0 +1,14 @@
+# Authors, sorted by whether or not they are me
+Isaac Z. Schlueter <i@izs.me>
+Brian Cottingham <spiffytech@gmail.com>
+Carlos Brito Lage <carlos@carloslage.net>
+Jesse Dailey <jesse.dailey@gmail.com>
+Kevin O'Hara <kevinohara80@gmail.com>
+Marco Rogers <marco.rogers@gmail.com>
+Mark Cavage <mcavage@gmail.com>
+Marko Mikulicic <marko.mikulicic@isti.cnr.it>
+Nathan Rajlich <nathan@tootallnate.net>
+Satheesh Natesan <snateshan@myspace-inc.com>
+Trent Mick <trentm@gmail.com>
+ashleybrener <ashley@starlogik.com>
+n4kz <n4kz@n4kz.com>
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/LICENSE b/node_modules/mysql2-promise/node_modules/lru-cache/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..05a4010949cac33c91988978137261559ed853f8
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/README.md b/node_modules/mysql2-promise/node_modules/lru-cache/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..03ee0f9850237428b1fb99b93592e9a5cee85205
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/README.md
@@ -0,0 +1,97 @@
+# lru cache
+
+A cache object that deletes the least-recently-used items.
+
+## Usage:
+
+```javascript
+var LRU = require("lru-cache")
+  , options = { max: 500
+              , length: function (n) { return n * 2 }
+              , dispose: function (key, n) { n.close() }
+              , maxAge: 1000 * 60 * 60 }
+  , cache = LRU(options)
+  , otherCache = LRU(50) // sets just the max size
+
+cache.set("key", "value")
+cache.get("key") // "value"
+
+cache.reset()    // empty the cache
+```
+
+If you put more stuff in it, then items will fall out.
+
+If you try to put an oversized thing in it, then it'll fall out right
+away.
+
+## Options
+
+* `max` The maximum size of the cache, checked by applying the length
+  function to all values in the cache.  Not setting this is kind of
+  silly, since that's the whole purpose of this lib, but it defaults
+  to `Infinity`.
+* `maxAge` Maximum age in ms.  Items are not pro-actively pruned out
+  as they age, but if you try to get an item that is too old, it'll
+  drop it and return undefined instead of giving it to you.
+* `length` Function that is used to calculate the length of stored
+  items.  If you're storing strings or buffers, then you probably want
+  to do something like `function(n){return n.length}`.  The default is
+  `function(n){return 1}`, which is fine if you want to store `n`
+  like-sized things.
+* `dispose` Function that is called on items when they are dropped
+  from the cache.  This can be handy if you want to close file
+  descriptors or do other cleanup tasks when items are no longer
+  accessible.  Called with `key, value`.  It's called *before*
+  actually removing the item from the internal cache, so if you want
+  to immediately put it back in, you'll have to do that in a
+  `nextTick` or `setTimeout` callback or it won't do anything.
+* `stale` By default, if you set a `maxAge`, it'll only actually pull
+  stale items out of the cache when you `get(key)`.  (That is, it's
+  not pre-emptively doing a `setTimeout` or anything.)  If you set
+  `stale:true`, it'll return the stale value before deleting it.  If
+  you don't set this, then it'll return `undefined` when you try to
+  get a stale entry, as if it had already been deleted.
+
+## API
+
+* `set(key, value)`
+* `get(key) => value`
+
+    Both of these will update the "recently used"-ness of the key.
+    They do what you think.
+
+* `peek(key)`
+
+    Returns the key value (or `undefined` if not found) without
+    updating the "recently used"-ness of the key.
+
+    (If you find yourself using this a lot, you *might* be using the
+    wrong sort of data structure, but there are some use cases where
+    it's handy.)
+
+* `del(key)`
+
+    Deletes a key out of the cache.
+
+* `reset()`
+
+    Clear the cache entirely, throwing away all values.
+
+* `has(key)`
+
+    Check if a key is in the cache, without updating the recent-ness
+    or deleting it for being stale.
+
+* `forEach(function(value,key,cache), [thisp])`
+
+    Just like `Array.prototype.forEach`.  Iterates over all the keys
+    in the cache, in order of recent-ness.  (Ie, more recently used
+    items are iterated over first.)
+
+* `keys()`
+
+    Return an array of the keys in the cache.
+
+* `values()`
+
+    Return an array of the values in the cache.
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/lib/lru-cache.js b/node_modules/mysql2-promise/node_modules/lru-cache/lib/lru-cache.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1d1381720cd749c562cc4a5504d9b2b9f6ca3bf
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/lib/lru-cache.js
@@ -0,0 +1,252 @@
+;(function () { // closure for web browsers
+
+if (typeof module === 'object' && module.exports) {
+  module.exports = LRUCache
+} else {
+  // just set the global for non-node platforms.
+  this.LRUCache = LRUCache
+}
+
+function hOP (obj, key) {
+  return Object.prototype.hasOwnProperty.call(obj, key)
+}
+
+function naiveLength () { return 1 }
+
+function LRUCache (options) {
+  if (!(this instanceof LRUCache))
+    return new LRUCache(options)
+
+  if (typeof options === 'number')
+    options = { max: options }
+
+  if (!options)
+    options = {}
+
+  this._max = options.max
+  // Kind of weird to have a default max of Infinity, but oh well.
+  if (!this._max || !(typeof this._max === "number") || this._max <= 0 )
+    this._max = Infinity
+
+  this._lengthCalculator = options.length || naiveLength
+  if (typeof this._lengthCalculator !== "function")
+    this._lengthCalculator = naiveLength
+
+  this._allowStale = options.stale || false
+  this._maxAge = options.maxAge || null
+  this._dispose = options.dispose
+  this.reset()
+}
+
+// resize the cache when the max changes.
+Object.defineProperty(LRUCache.prototype, "max",
+  { set : function (mL) {
+      if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity
+      this._max = mL
+      if (this._length > this._max) trim(this)
+    }
+  , get : function () { return this._max }
+  , enumerable : true
+  })
+
+// resize the cache when the lengthCalculator changes.
+Object.defineProperty(LRUCache.prototype, "lengthCalculator",
+  { set : function (lC) {
+      if (typeof lC !== "function") {
+        this._lengthCalculator = naiveLength
+        this._length = this._itemCount
+        for (var key in this._cache) {
+          this._cache[key].length = 1
+        }
+      } else {
+        this._lengthCalculator = lC
+        this._length = 0
+        for (var key in this._cache) {
+          this._cache[key].length = this._lengthCalculator(this._cache[key].value)
+          this._length += this._cache[key].length
+        }
+      }
+
+      if (this._length > this._max) trim(this)
+    }
+  , get : function () { return this._lengthCalculator }
+  , enumerable : true
+  })
+
+Object.defineProperty(LRUCache.prototype, "length",
+  { get : function () { return this._length }
+  , enumerable : true
+  })
+
+
+Object.defineProperty(LRUCache.prototype, "itemCount",
+  { get : function () { return this._itemCount }
+  , enumerable : true
+  })
+
+LRUCache.prototype.forEach = function (fn, thisp) {
+  thisp = thisp || this
+  var i = 0;
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    i++
+    var hit = this._lruList[k]
+    if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
+      del(this, hit)
+      if (!this._allowStale) hit = undefined
+    }
+    if (hit) {
+      fn.call(thisp, hit.value, hit.key, this)
+    }
+  }
+}
+
+LRUCache.prototype.keys = function () {
+  var keys = new Array(this._itemCount)
+  var i = 0
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    var hit = this._lruList[k]
+    keys[i++] = hit.key
+  }
+  return keys
+}
+
+LRUCache.prototype.values = function () {
+  var values = new Array(this._itemCount)
+  var i = 0
+  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
+    var hit = this._lruList[k]
+    values[i++] = hit.value
+  }
+  return values
+}
+
+LRUCache.prototype.reset = function () {
+  if (this._dispose && this._cache) {
+    for (var k in this._cache) {
+      this._dispose(k, this._cache[k].value)
+    }
+  }
+
+  this._cache = Object.create(null) // hash of items by key
+  this._lruList = Object.create(null) // list of items in order of use recency
+  this._mru = 0 // most recently used
+  this._lru = 0 // least recently used
+  this._length = 0 // number of items in the list
+  this._itemCount = 0
+}
+
+// Provided for debugging/dev purposes only. No promises whatsoever that
+// this API stays stable.
+LRUCache.prototype.dump = function () {
+  return this._cache
+}
+
+LRUCache.prototype.dumpLru = function () {
+  return this._lruList
+}
+
+LRUCache.prototype.set = function (key, value) {
+  if (hOP(this._cache, key)) {
+    // dispose of the old one before overwriting
+    if (this._dispose) this._dispose(key, this._cache[key].value)
+    if (this._maxAge) this._cache[key].now = Date.now()
+    this._cache[key].value = value
+    this.get(key)
+    return true
+  }
+
+  var len = this._lengthCalculator(value)
+  var age = this._maxAge ? Date.now() : 0
+  var hit = new Entry(key, value, this._mru++, len, age)
+
+  // oversized objects fall out of cache automatically.
+  if (hit.length > this._max) {
+    if (this._dispose) this._dispose(key, value)
+    return false
+  }
+
+  this._length += hit.length
+  this._lruList[hit.lu] = this._cache[key] = hit
+  this._itemCount ++
+
+  if (this._length > this._max) trim(this)
+  return true
+}
+
+LRUCache.prototype.has = function (key) {
+  if (!hOP(this._cache, key)) return false
+  var hit = this._cache[key]
+  if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
+    return false
+  }
+  return true
+}
+
+LRUCache.prototype.get = function (key) {
+  return get(this, key, true)
+}
+
+LRUCache.prototype.peek = function (key) {
+  return get(this, key, false)
+}
+
+LRUCache.prototype.pop = function () {
+  var hit = this._lruList[this._lru]
+  del(this, hit)
+  return hit || null
+}
+
+LRUCache.prototype.del = function (key) {
+  del(this, this._cache[key])
+}
+
+function get (self, key, doUse) {
+  var hit = self._cache[key]
+  if (hit) {
+    if (self._maxAge && (Date.now() - hit.now > self._maxAge)) {
+      del(self, hit)
+      if (!self._allowStale) hit = undefined
+    } else {
+      if (doUse) use(self, hit)
+    }
+    if (hit) hit = hit.value
+  }
+  return hit
+}
+
+function use (self, hit) {
+  shiftLU(self, hit)
+  hit.lu = self._mru ++
+  self._lruList[hit.lu] = hit
+}
+
+function trim (self) {
+  while (self._lru < self._mru && self._length > self._max)
+    del(self, self._lruList[self._lru])
+}
+
+function shiftLU (self, hit) {
+  delete self._lruList[ hit.lu ]
+  while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++
+}
+
+function del (self, hit) {
+  if (hit) {
+    if (self._dispose) self._dispose(hit.key, hit.value)
+    self._length -= hit.length
+    self._itemCount --
+    delete self._cache[ hit.key ]
+    shiftLU(self, hit)
+  }
+}
+
+// classy, since V8 prefers predictable objects.
+function Entry (key, value, lu, length, now) {
+  this.key = key
+  this.value = value
+  this.lu = lu
+  this.length = length
+  this.now = now
+}
+
+})()
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/package.json b/node_modules/mysql2-promise/node_modules/lru-cache/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..24b0a6604f321e641721aef4bb7947b0c130f01d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "lru-cache",
+  "description": "A cache object that deletes the least-recently-used items.",
+  "version": "2.5.0",
+  "author": "Isaac Z. Schlueter <i@izs.me>",
+  "scripts": {
+    "test": "tap test --gc"
+  },
+  "main": "lib/lru-cache.js",
+  "repository": "git://github.com/isaacs/node-lru-cache.git",
+  "devDependencies": {
+    "tap": "",
+    "weak": ""
+  },
+  "license": {
+    "type": "MIT",
+    "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE"
+  }
+}
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/test/basic.js b/node_modules/mysql2-promise/node_modules/lru-cache/test/basic.js
new file mode 100644
index 0000000000000000000000000000000000000000..f72697c4611a3cbb282c281cfa46cc6723d584f3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/test/basic.js
@@ -0,0 +1,369 @@
+var test = require("tap").test
+  , LRU = require("../")
+
+test("basic", function (t) {
+  var cache = new LRU({max: 10})
+  cache.set("key", "value")
+  t.equal(cache.get("key"), "value")
+  t.equal(cache.get("nada"), undefined)
+  t.equal(cache.length, 1)
+  t.equal(cache.max, 10)
+  t.end()
+})
+
+test("least recently set", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), "B")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("lru recently gotten", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.get("a")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), undefined)
+  t.equal(cache.get("a"), "A")
+  t.end()
+})
+
+test("del", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.del("a")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("max", function (t) {
+  var cache = new LRU(3)
+
+  // test changing the max, verify that the LRU items get dropped.
+  cache.max = 100
+  for (var i = 0; i < 100; i ++) cache.set(i, i)
+  t.equal(cache.length, 100)
+  for (var i = 0; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  cache.max = 3
+  t.equal(cache.length, 3)
+  for (var i = 0; i < 97; i ++) {
+    t.equal(cache.get(i), undefined)
+  }
+  for (var i = 98; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+
+  // now remove the max restriction, and try again.
+  cache.max = "hello"
+  for (var i = 0; i < 100; i ++) cache.set(i, i)
+  t.equal(cache.length, 100)
+  for (var i = 0; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  // should trigger an immediate resize
+  cache.max = 3
+  t.equal(cache.length, 3)
+  for (var i = 0; i < 97; i ++) {
+    t.equal(cache.get(i), undefined)
+  }
+  for (var i = 98; i < 100; i ++) {
+    t.equal(cache.get(i), i)
+  }
+  t.end()
+})
+
+test("reset", function (t) {
+  var cache = new LRU(10)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.reset()
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 10)
+  t.equal(cache.get("a"), undefined)
+  t.equal(cache.get("b"), undefined)
+  t.end()
+})
+
+
+// Note: `<cache>.dump()` is a debugging tool only. No guarantees are made
+// about the format/layout of the response.
+test("dump", function (t) {
+  var cache = new LRU(10)
+  var d = cache.dump();
+  t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache")
+  cache.set("a", "A")
+  var d = cache.dump()  // { a: { key: "a", value: "A", lu: 0 } }
+  t.ok(d.a)
+  t.equal(d.a.key, "a")
+  t.equal(d.a.value, "A")
+  t.equal(d.a.lu, 0)
+
+  cache.set("b", "B")
+  cache.get("b")
+  d = cache.dump()
+  t.ok(d.b)
+  t.equal(d.b.key, "b")
+  t.equal(d.b.value, "B")
+  t.equal(d.b.lu, 2)
+
+  t.end()
+})
+
+
+test("basic with weighed length", function (t) {
+  var cache = new LRU({
+    max: 100,
+    length: function (item) { return item.size }
+  })
+  cache.set("key", {val: "value", size: 50})
+  t.equal(cache.get("key").val, "value")
+  t.equal(cache.get("nada"), undefined)
+  t.equal(cache.lengthCalculator(cache.get("key")), 50)
+  t.equal(cache.length, 50)
+  t.equal(cache.max, 100)
+  t.end()
+})
+
+
+test("weighed length item too large", function (t) {
+  var cache = new LRU({
+    max: 10,
+    length: function (item) { return item.size }
+  })
+  t.equal(cache.max, 10)
+
+  // should fall out immediately
+  cache.set("key", {val: "value", size: 50})
+
+  t.equal(cache.length, 0)
+  t.equal(cache.get("key"), undefined)
+  t.end()
+})
+
+test("least recently set with weighed length", function (t) {
+  var cache = new LRU({
+    max:8,
+    length: function (item) { return item.length }
+  })
+  cache.set("a", "A")
+  cache.set("b", "BB")
+  cache.set("c", "CCC")
+  cache.set("d", "DDDD")
+  t.equal(cache.get("d"), "DDDD")
+  t.equal(cache.get("c"), "CCC")
+  t.equal(cache.get("b"), undefined)
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("lru recently gotten with weighed length", function (t) {
+  var cache = new LRU({
+    max: 8,
+    length: function (item) { return item.length }
+  })
+  cache.set("a", "A")
+  cache.set("b", "BB")
+  cache.set("c", "CCC")
+  cache.get("a")
+  cache.get("b")
+  cache.set("d", "DDDD")
+  t.equal(cache.get("c"), undefined)
+  t.equal(cache.get("d"), "DDDD")
+  t.equal(cache.get("b"), "BB")
+  t.equal(cache.get("a"), "A")
+  t.end()
+})
+
+test("set returns proper booleans", function(t) {
+  var cache = new LRU({
+    max: 5,
+    length: function (item) { return item.length }
+  })
+
+  t.equal(cache.set("a", "A"), true)
+
+  // should return false for max exceeded
+  t.equal(cache.set("b", "donuts"), false)
+
+  t.equal(cache.set("b", "B"), true)
+  t.equal(cache.set("c", "CCCC"), true)
+  t.end()
+})
+
+test("drop the old items", function(t) {
+  var cache = new LRU({
+    max: 5,
+    maxAge: 50
+  })
+
+  cache.set("a", "A")
+
+  setTimeout(function () {
+    cache.set("b", "b")
+    t.equal(cache.get("a"), "A")
+  }, 25)
+
+  setTimeout(function () {
+    cache.set("c", "C")
+    // timed out
+    t.notOk(cache.get("a"))
+  }, 60)
+
+  setTimeout(function () {
+    t.notOk(cache.get("b"))
+    t.equal(cache.get("c"), "C")
+  }, 90)
+
+  setTimeout(function () {
+    t.notOk(cache.get("c"))
+    t.end()
+  }, 155)
+})
+
+test("disposal function", function(t) {
+  var disposed = false
+  var cache = new LRU({
+    max: 1,
+    dispose: function (k, n) {
+      disposed = n
+    }
+  })
+
+  cache.set(1, 1)
+  cache.set(2, 2)
+  t.equal(disposed, 1)
+  cache.set(3, 3)
+  t.equal(disposed, 2)
+  cache.reset()
+  t.equal(disposed, 3)
+  t.end()
+})
+
+test("disposal function on too big of item", function(t) {
+  var disposed = false
+  var cache = new LRU({
+    max: 1,
+    length: function (k) {
+      return k.length
+    },
+    dispose: function (k, n) {
+      disposed = n
+    }
+  })
+  var obj = [ 1, 2 ]
+
+  t.equal(disposed, false)
+  cache.set("obj", obj)
+  t.equal(disposed, obj)
+  t.end()
+})
+
+test("has()", function(t) {
+  var cache = new LRU({
+    max: 1,
+    maxAge: 10
+  })
+
+  cache.set('foo', 'bar')
+  t.equal(cache.has('foo'), true)
+  cache.set('blu', 'baz')
+  t.equal(cache.has('foo'), false)
+  t.equal(cache.has('blu'), true)
+  setTimeout(function() {
+    t.equal(cache.has('blu'), false)
+    t.end()
+  }, 15)
+})
+
+test("stale", function(t) {
+  var cache = new LRU({
+    maxAge: 10,
+    stale: true
+  })
+
+  cache.set('foo', 'bar')
+  t.equal(cache.get('foo'), 'bar')
+  t.equal(cache.has('foo'), true)
+  setTimeout(function() {
+    t.equal(cache.has('foo'), false)
+    t.equal(cache.get('foo'), 'bar')
+    t.equal(cache.get('foo'), undefined)
+    t.end()
+  }, 15)
+})
+
+test("lru update via set", function(t) {
+  var cache = LRU({ max: 2 });
+
+  cache.set('foo', 1);
+  cache.set('bar', 2);
+  cache.del('bar');
+  cache.set('baz', 3);
+  cache.set('qux', 4);
+
+  t.equal(cache.get('foo'), undefined)
+  t.equal(cache.get('bar'), undefined)
+  t.equal(cache.get('baz'), 3)
+  t.equal(cache.get('qux'), 4)
+  t.end()
+})
+
+test("least recently set w/ peek", function (t) {
+  var cache = new LRU(2)
+  cache.set("a", "A")
+  cache.set("b", "B")
+  t.equal(cache.peek("a"), "A")
+  cache.set("c", "C")
+  t.equal(cache.get("c"), "C")
+  t.equal(cache.get("b"), "B")
+  t.equal(cache.get("a"), undefined)
+  t.end()
+})
+
+test("pop the least used item", function (t) {
+  var cache = new LRU(3)
+  , last
+
+  cache.set("a", "A")
+  cache.set("b", "B")
+  cache.set("c", "C")
+
+  t.equal(cache.length, 3)
+  t.equal(cache.max, 3)
+
+  // Ensure we pop a, c, b
+  cache.get("b", "B")
+
+  last = cache.pop()
+  t.equal(last.key, "a")
+  t.equal(last.value, "A")
+  t.equal(cache.length, 2)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last.key, "c")
+  t.equal(last.value, "C")
+  t.equal(cache.length, 1)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last.key, "b")
+  t.equal(last.value, "B")
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 3)
+
+  last = cache.pop()
+  t.equal(last, null)
+  t.equal(cache.length, 0)
+  t.equal(cache.max, 3)
+
+  t.end()
+})
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/test/foreach.js b/node_modules/mysql2-promise/node_modules/lru-cache/test/foreach.js
new file mode 100644
index 0000000000000000000000000000000000000000..eefb80d9d1564424f483a355136363bf6816be63
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/test/foreach.js
@@ -0,0 +1,52 @@
+var test = require('tap').test
+var LRU = require('../')
+
+test('forEach', function (t) {
+  var l = new LRU(5)
+  for (var i = 0; i < 10; i ++) {
+    l.set(i.toString(), i.toString(2))
+  }
+
+  var i = 9
+  l.forEach(function (val, key, cache) {
+    t.equal(cache, l)
+    t.equal(key, i.toString())
+    t.equal(val, i.toString(2))
+    i -= 1
+  })
+
+  // get in order of most recently used
+  l.get(6)
+  l.get(8)
+
+  var order = [ 8, 6, 9, 7, 5 ]
+  var i = 0
+
+  l.forEach(function (val, key, cache) {
+    var j = order[i ++]
+    t.equal(cache, l)
+    t.equal(key, j.toString())
+    t.equal(val, j.toString(2))
+  })
+
+  t.end()
+})
+
+test('keys() and values()', function (t) {
+  var l = new LRU(5)
+  for (var i = 0; i < 10; i ++) {
+    l.set(i.toString(), i.toString(2))
+  }
+
+  t.similar(l.keys(), ['9', '8', '7', '6', '5'])
+  t.similar(l.values(), ['1001', '1000', '111', '110', '101'])
+
+  // get in order of most recently used
+  l.get(6)
+  l.get(8)
+
+  t.similar(l.keys(), ['8', '6', '9', '7', '5'])
+  t.similar(l.values(), ['1000', '110', '1001', '111', '101'])
+
+  t.end()
+})
diff --git a/node_modules/mysql2-promise/node_modules/lru-cache/test/memory-leak.js b/node_modules/mysql2-promise/node_modules/lru-cache/test/memory-leak.js
new file mode 100644
index 0000000000000000000000000000000000000000..7af45b0221c1ff93b188c398ff31669f06f7ce0e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/lru-cache/test/memory-leak.js
@@ -0,0 +1,50 @@
+#!/usr/bin/env node --expose_gc
+
+var weak = require('weak');
+var test = require('tap').test
+var LRU = require('../')
+var l = new LRU({ max: 10 })
+var refs = 0
+function X() {
+  refs ++
+  weak(this, deref)
+}
+
+function deref() {
+  refs --
+}
+
+test('no leaks', function (t) {
+  // fill up the cache
+  for (var i = 0; i < 100; i++) {
+    l.set(i, new X);
+    // throw some gets in there, too.
+    if (i % 2 === 0)
+      l.get(i / 2)
+  }
+
+  gc()
+
+  var start = process.memoryUsage()
+
+  // capture the memory
+  var startRefs = refs
+
+  // do it again, but more
+  for (var i = 0; i < 10000; i++) {
+    l.set(i, new X);
+    // throw some gets in there, too.
+    if (i % 2 === 0)
+      l.get(i / 2)
+  }
+
+  gc()
+
+  var end = process.memoryUsage()
+  t.equal(refs, startRefs, 'no leaky refs')
+
+  console.error('start: %j\n' +
+                'end:   %j', start, end);
+  t.pass();
+  t.end();
+})
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/.npmignore b/node_modules/mysql2-promise/node_modules/mysql2/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..59ee6765f9ca3cebfa7c0e0258f22512333455c3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/.npmignore
@@ -0,0 +1,17 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+.DS_Store
+
+tmp
+pids
+logs
+
+node_modules
+npm-debug.log
+
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/.travis.yml b/node_modules/mysql2-promise/node_modules/mysql2/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..322cc7c888bb6b09c8f81f5151a0e86a18db6e3b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/.travis.yml
@@ -0,0 +1,9 @@
+language: node_js
+before_script:
+  - mysql -e 'create database if not exists test;'
+node_js:
+  - '0.8'
+  - '0.10'
+  - '0.12'
+  - '1.0'
+  - '2.3'
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/Changelog.md b/node_modules/mysql2-promise/node_modules/mysql2/Changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..88b757cf86b67472e0788761e97bf9140104fdb9
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/Changelog.md
@@ -0,0 +1,187 @@
+0.15.7 - 22/06/2015
+- Add .escapeId() to Connection and Pool                     #180
+- Build: iojs 2.2.1 & 2.3.0
+- Binary protocol: fix crash when server return null
+  for 'NOT NULL' column                                      #178
+
+0.15.6 - 04/06/2015
+- Include errno in error object                              #168
+- server: fix fields in OK and column header packets
+  (fix errors when connecting with node-mysql)
+- build: add iojs 1.8.x to matrix
+
+0.15.5 - 08/04/2015
+- fix broken 'stream rows' functionality                     #165, #166
+- add io.js 1.6 to build matrix
+
+0.15.4 - 11/03/2015
+- added COM_QUIT command, sent from conn.end()               #163, #150
+- io.js 1.5
+- don't crash on unexpected protocol packets, emit           #164, #160
+  connection error event instead
+
+0.15.3 - 24/02/2015
+ - multiple results support in binary protocol               #157 #26 #27
+ - add io.js 1.4 to CI matrix
+
+0.15.2 - 24/02/2015
+ - update Amazon RDS certificates                           #154
+ - add io.js 1.3 to CI matrix
+ - fix packet parser bug                                     #155
+
+0.15.1 - 18/02/2015
+ - add io.js 1.0 - 1.2 to build matrix
+ - add windows CI using Appveyor                             #151 #152
+
+0.15.0 - 1/10/2015
+ - connection.threadId
+ - connection.changeUser()                                   #63
+ - named placeholders                                        #117
+ - new prepared statements api                               #132 #139
+ - support LOAD INFILE                                       #64 #142
+ - refactored faster packet parser                           #140
+ - lazy parse rarely used column definition fields           #137
+
+0.14.1 - 9/12/2014
+ - stream connection option now can be a function            #80
+ - bugfix/prepared statements: fix case when no columns
+   in statement header but there are columns in results      #130
+
+0.14.0 - 26/11/2014
+  - added connection.pause() and connection.resume()         #129
+
+0.13.0
+  - connection errors sent to all commands in queue
+  - server-side authentication support                       #122
+  - server.listen() is now chainable (returns server)
+  - allow to login using sha1(password)                      #124
+  - Query.sql as alias to Query.query                        #121
+
+0.12.5 - 30/07/2014
+  - add 'execute' pool method similar to Pool##query         #114
+  - more debug output behind debug flag
+
+0.12.4 - 17/07/2014
+  - 'debug' connection option now result in lots of
+     debug output                                            #112 #77
+  - send corectly compression flag if compression is on      #102
+
+
+0.12.3 - 11/07/2014
+  - fix node 0.8 - incompatible dependency version
+
+0.12.2 - 11/07/2014
+
+  - output milliseconds in date type                         #107
+  - deserialise length coded int with > 24 bit numbers
+    to js int / float (and not throw "Bignts not supported") #108
+  - support for Bigint numbers in insertId
+
+0.12.1 - 30/04/2014
+
+  - 'dateStrings' connection option support                  #99
+  - use anonymous function for packet routing instead
+    of .bind() 3-5% speed improvement
+  - GEOMETRY type support in binary protocol                 #97
+
+0.12.0 - 29/04/2014
+
+  - route connection time errors from handshke command to
+    connection                                               #96
+
+  - support for nestTables and rowsAsArray options in query()
+    and execute()                                            #95, #94
+
+  - bugfix: date as parameter in prepared statement,
+    day of week was used incorrectly
+    instead of day of month                                  #89     ab28dfca839728dfe40d941091902185d7c19b57
+
+   - GEOMETRY type support ported from node-mysql            #93     ebd30fd12b3b7f53d97b9d09f947b12f61e0c2c5
+
+0.11.8
+
+  - add DATE type support                                    #84     1d49651d8e40bf43b79937d9de9b2909126b892c
+  - faster DATE parsing in text protocol                             cdfed2881462798bd85fbf906ea604875a3bd625
+
+
+0.11.7
+  - initial implementaion of binlog protocol            #83 #78      c8d45da6fc13a56d95ce6d57c3c8aa9524548770
+  - interpret null DOUBLE values as null instead 0 #85               4c03b23f30949be0608d9543d69243944d79bb4a
+  - use srcEscape for null values (bunary parser)                    ef50bcafa452588eda4a40037b41f6b961085046
+
+0.11.6
+  - minor cleanups
+
+0.11.5
+  - fix for non-utf strings serialisation (binary protocol only)     cf9594aaab5b3d51a112bd1f43b39a55f508eef7
+
+0.11.4
+  - support YEAR type in prepared statements                         a0f33b5a4de4529130b3c4137f7a1dd3c02aed9e
+
+0.11.3
+  - add transaction helpers                             #56, #76     cc0a9f9b721900d3a22c7fc84a5244c74cd33dd5
+
+0.11.2
+
+  - wrap callbacks in nextTick for exception safety                  b73ac9868804b603a0ab6df6129cf3682476d118
+  - domains support                                          #73     36cba61359c83018a847ac4e7748d920b6f863c4
+
+0.11.1
+
+  - buxfix: connection.connect callback was called more than once
+                                                             #72      0352eefdafc0986f1ec79c0ce285f722ca12af16
+
+0.11.0
+  - Bundle Amazon RDS cert and allow to connect using                 e6af097b5facc089f1999c1fb076ada0ce2e7e99
+    'Amazon RDS' as ssl value
+
+0.10.7
+
+  - Amazon RDS+ssl example and public CA cert                         709394a4afbbaf0500439e72caec5d37e949fe26
+  - pool updated from node-mysql                   #71, #68, #61      db561dbe10a55bb0f9893eb0e2c4b429edd6ee3a
+
+0.10.6
+  - handle TIMESTAMP type                                    #59      6dd6fc82d95a16e18092c4db4e8da225b37e9314
+  - rename pool's connection.end() to connection.release()   #53      c63b2442e3c0fb5ea3953725ba9c1b3e08b2b831
+
+0.10.5
+
+  - node-mysql compatibility: remove 'number of results in response'
+    callback argument (Brian White)                          #46       40af0530403a3892743d32974055c5ea23cbd3ec
+  - node 0.11 (use on('data') instead of ondata )                      39906c78b85a77e468694814a50f99714d7bbbd6
+  - fix again ssl (#41)                                                713051bf997a186774b618cde583707320a1d551
+
+0.10.4
+  - node-mysql compatibility: remove 'number of results in response'
+    callback argument (Brian White)                          #45       c9cb926360da5e4028f7d2f83f4b4e94897cd8b8
+  - 'resultIndex' parameter for non-multiple results query             8879bdde397b6cd730d234383fa322becd1134de
+
+0.10.3
+  - various ssl fixes and refactoring (ssl was broken for some time)   213d375f7263cb6f5e724fdac3ea156ccee4bbd4
+  - Server protocol: handle null values serialisation
+     (Michael Muturi Njonge)                                 #36       831b2a100795f36649f0c3d79b7839a95f771a05
+
+0.10.2
+  - return DECIMAL and NEWDECIMAL as string in binary prot   #40       969fba6ff1dbf14d53d3efc9f94083b8306cf0b5
+
+0.10.1
+  - Added ping command                                       #38       cbca8648d1282fb57e55b3735c3b4d9a46d89d7b
+
+0.9.2
+  - correctly parse NULL result for string and number        #35       0a4ac65ec812f75861dc00c9243921d5d6602914
+  - do not pollute global namespace from evaled parser       #11       4b6ddaf0f70150945d0fea804db9106f343a0e51
+
+0.9.1
+  - PoolClaster ported from node-mysql                       #34
+
+0.8.21
+  - Fix in error message parsing (Noam Wasersprung)          #31       6cc80a67eaa3baac7dd8eee7182c9eb00977e81a
+  - return insert/delete header for insert/delete commands   #32       72aa8fe70981d7410a10edb9d7921e5d6ce1d3ca
+
+0.8.20
+  - Make packet parser work with 0.11 ondata(buffer) with no start,end 9005fd1
+  - Allow to use Date-like objects as date parameters (Amir Livneh)    6138dad0581fd5e2c45e1ce0b999e334db8979cf
+
+0.8.19
+  - Multiple results support in text protocol #15                      4812adaf1aa5b1dfa775a6cf0fa3bae54a7827d0
+  - Use connection flags from createConnection parameters/url string   9218f055ceeb95ae7205348e06c07b89b799d031
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/License b/node_modules/mysql2-promise/node_modules/mysql2/License
new file mode 100644
index 0000000000000000000000000000000000000000..51c1bf402f76b04b4dbed4bc1cec49c34758b1ad
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/License
@@ -0,0 +1,19 @@
+Copyright (c) 2013 Andrey Sidorov (sidorares@yandex.ru) and contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/README.md b/node_modules/mysql2-promise/node_modules/mysql2/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..158f6d6fb314a21dc07431325dd61fa2a578e9ba
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/README.md
@@ -0,0 +1,340 @@
+#node-mysql2
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Linux Build][travis-image]][travis-url]
+[![Windows Build][appveyor-image]][appveyor-url]
+
+Mysql client for node.js. Written in native JavaScript and aims to be mostly api compatible with [node-mysql](https://github.com/felixge/node-mysql)
+
+[![NPM](https://nodei.co/npm/mysql2.png?downloads=true&stars=true)](https://nodei.co/npm/mysql2/)
+[![NPM](https://nodei.co/npm-dl/mysql2.png?months=6)](https://nodei.co/npm/mysql2/)
+
+## Features
+
+ In addition to client-side query/escape and connection pooling
+
+  - [fast](https://gist.github.com/sidorares/ffe9ee9c423f763e3b6b)
+  - MySQL server API for proxies and mocks
+  - SSL and compression
+  - prepared statements
+  - binlog protocol client
+
+## Documentation
+
+See [node-mysql](https://github.com/felixge/node-mysql) documentation. If you see api incompatibilities, please report via github issue.
+
+Below is a list of extensions not supported by node-mysql:
+
+### Named placeholders
+
+You can use named placeholders for parameters by setting `namedPlaceholders` config value or query/execute time option. Named placeholders are converted to unnamed `?` on the client (mysql protocol does not support named parameters). If you reference parameter multiple times under the same name it is sent to server multiple times.
+
+```js
+   connection.config.namedPlaceholders = true;
+   connection.execute('select :x + :y as z', { x: 1, y: 2}, function(err, rows) {
+     // statement prepared as "select ? + ? as z" and executed with [1,2] values
+     // rows returned: [ { z: 3 } ]
+   });
+
+   connection.execute('select :x + :x as z', { x: 1 }, function(err, rows) {
+     // select ? + ? as z, execute with [1, 1]
+   });
+
+   connection.query('select :x + :x as z', { x: 1 }, function(err, rows) {
+     // query select 1 + 1 as z
+   });
+```
+
+### Prepared statements
+
+#### Automatic creation, cached and re-used by connection
+
+Similar to `connection.query()`.
+
+```js
+connection.execute('select 1 + ? + ? as result', [5, 6], function(err, rows) {
+  // rows: [ { result: 12 } ]
+  // internally 'select 1 + ? + ? as result' is prepared first. On subsequent calls cached statement is re-used
+});
+
+// close cached statement for 'select 1 + ? + ? as result'. noop if not in cache
+connection.unprepare('select 1 + ? + ? as result');
+```
+
+#### Manual prepare / execute
+
+```js
+connection.prepare('select ? + ? as tests', function(err, statement) {
+   // statement.parameters - array of column definitions, length === number of params, here 2
+   // statement.columns - array of result column definitions. Can be empty if result schema is dynamic / not known
+   // statement.id
+   // statement.query
+
+   statement.execute([1, 2], function(err, rows, columns) {
+    // -> [ { tests: 3 } ]
+   });
+
+   // note that there is no callback here. There is no statement close ack at protocol level.
+   statement.close();
+});
+```
+Note that you should not use statement after connection reset (`changeUser()` or disconnect). Statement scope is connection, you need to prepare statement for each new connection in order to use it.
+
+### Receiving rows as array of columns instead of hash with column name as key:
+
+```js
+var options = {sql: 'select A,B,C,D from foo', rowsAsArray: true};
+connection.query(options, function(err, results) {
+  /* results will be an array of arrays like this now:
+  [[
+     'field A value',
+     'field B value',
+     'field C value',
+     'field D value',
+  ], ...]
+  */
+});
+```
+
+### Sending tabular data with 'load infile' and local stream:
+
+In addition to sending local fs files you can send any stream using `infileStreamFactory` query option. If set, it has to be a function that return a readable stream. It gets file path from query as a parameter.
+
+```js
+// local file
+connection.query('LOAD DATA LOCAL INFILE "/tmp/data.csv" INTO TABLE test FIELDS TERMINATED BY ? (id, title)', onInserted1);
+// local stream
+var sql = 'LOAD DATA LOCAL INFILE "mystream" INTO TABLE test FIELDS TERMINATED BY ? (id, title)';
+connection.query({
+  sql: sql,
+  infileStreamFactory: function(path) { return getStream(); }
+}, onInserted2);
+```
+
+### Connecting using custom stream:
+
+```js
+var net        = require('net');
+var mysql      = require('mysql2');
+var shape      = require('shaper');
+var connection = mysql.createConnection({
+   user: 'test',
+   database: 'test',
+   stream: net.connect('/tmp/mysql.sock').pipe(shape(10)) // emulate 10 bytes/sec link
+});
+connection.query('SELECT 1+1 as test1', console.log);
+```
+`stream` also can be a function. In that case function result has to be duplex stream, and it is used for connection transport. This is required if you connect pool using custom transport as new pooled connection needs new stream. [Example](https://github.com/sidorares/node-mysql2/issues/80) connecting over socks5 proxy:
+
+```js
+var mysql      = require('mysql2');
+var SocksConnection = require('socksjs');
+var pool = mysql.createPool({
+  database: 'test',
+  user: 'foo',
+  password: 'bar'
+  stream: function(cb) {
+    cb(null, new SocksConnection({ host: 'remote.host', port: 3306}, { host: 'localhost', port: 1080 }));
+  }
+ });
+```
+
+In addition to password `createConnection()`, `createPool()` and `changeUser()` accept `passwordSha1` option. This is useful when implementing proxies as plaintext password might be not available.
+
+## Known incompatibilities with node-mysql
+
+In contrast to node-mysql, `zeroFill` flag is ignored in type conversion.
+You need to check corresponding field zeroFill flag and convert to string manually if this is of importance to you.
+
+DECIMAL and NEWDECIMAL types always returned as string
+
+## Examples
+
+Simple select:
+
+```js
+var mysql      = require('mysql2');
+var connection = mysql.createConnection({ user: 'test', database: 'test'});
+
+connection.query('SELECT 1+1 as test1', function(err, rows) {
+  //
+});
+```
+
+Prepared statement and parameters:
+
+```js
+var mysql      = require('mysql2');
+var connection = mysql.createConnection({ user: 'test', database: 'test'});
+
+connection.execute('SELECT 1+? as test1', [10], function(err, rows) {
+  //
+});
+```
+
+Connecting over encrypted connection:
+
+```js
+var fs         = require('fs');
+var mysql      = require('mysql2');
+var connection = mysql.createConnection({
+   user: 'test',
+   database: 'test',
+   ssl: {
+     key: fs.readFileSync('./certs/client-key.pem'),
+     cert: fs.readFileSync('./certs/client-cert.pem')
+   }
+});
+connection.query('SELECT 1+1 as test1', console.log);
+```
+
+You can use 'Amazon RDS' string as value to ssl property to connect to Amazon RDS mysql over ssl (in that case http://s3.amazonaws.com/rds-downloads/mysql-ssl-ca-cert.pem CA cert is used)
+
+```js
+var mysql      = require('mysql2');
+var connection = mysql.createConnection({
+   user: 'foo',
+   password: 'bar',
+   host: 'db.id.ap-southeast-2.rds.amazonaws.com',
+   ssl: 'Amazon RDS'
+});
+
+conn.query('show status like \'Ssl_cipher\'', function(err, res) {
+  console.log(err, res);
+  conn.end();
+});
+```
+
+
+Simple mysql proxy server:
+
+```js
+var mysql = require('mysql2');
+
+var server = mysql.createServer();
+server.listen(3307);
+server.on('connection', function(conn) {
+  console.log('connection');
+
+  conn.serverHandshake({
+    protocolVersion: 10,
+    serverVersion: 'node.js rocks',
+    connectionId: 1234,
+    statusFlags: 2,
+    characterSet: 8,
+    capabilityFlags: 0xffffff
+  });
+
+  conn.on('field_list', function(table, fields) {
+    console.log('field list:', table, fields);
+    conn.writeEof();
+  });
+
+  var remote = mysql.createConnection({user: 'root', database: 'dbname', host:'server.example.com', password: 'secret'});
+
+  conn.on('query', function(sql) {
+    console.log('proxying query:' + sql);
+    remote.query(sql, function(err) { // overloaded args, either (err, result :object)
+                                      // or (err, rows :array, columns :array)
+      if (Array.isArray(arguments[1])) {
+        // response to a 'select', 'show' or similar
+        var rows = arguments[1], columns = arguments[2];
+        console.log('rows', rows);
+        console.log('columns', columns);
+        conn.writeTextResult(rows, columns);
+      } else {
+        // response to an 'insert', 'update' or 'delete'
+        var result = arguments[1];
+        console.log('result', result);
+        conn.writeOk(result);
+      }
+    });
+  });
+
+  conn.on('end', remote.end.bind(remote));
+});
+```
+## MySQL Server API
+
+### Server
+
+  *  **createServer()** - creates server instance
+  *  **Server.listen**  - listen port / unix socket (same arguments as [net.Server.listen](http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback))
+
+events:
+
+  *  **connect** - new incoming connection.
+
+### Connection
+
+  *  **serverHandshake({serverVersion, protocolVersion, connectionId, statusFlags, characterSet, capabilityFlags})** - send server handshake initialisation packet, wait handshake response and start listening for commands
+  *  **writeOk({affectedRows: num, insertId: num})** - send [OK packet](http://dev.mysql.com/doc/internals/en/overview.html#packet-OK_Packet) to client
+  *  **writeEof(warnings, statusFlags)** - send EOF packet
+  *  **writeTextResult(rows, fields)** - write query result to client. Rows and fields are in the same format as in `connection.query` callback.
+  *  **writeColumns(fields)** - write fields + EOF packets.
+  *  **writeTextRow(row)**  - write array (not hash!) ov values as result row
+  *  TODO: binary protocol
+
+events:
+
+   *  **query(sql)** - query from client
+
+
+## License
+
+ MIT
+
+## Acknowledgements
+
+  - Internal protocol is written from scratch using my experience with [mysql-native](https://github.com/sidorares/nodejs-mysql-native)
+  - constants, sql parameters interpolation, pool, connection config class taken from [node-mysql](https://github.com/felixge/node-mysql) (I tried to preserve git history)
+  - SSL upgrade code based on @TooTallNate [code](https://gist.github.com/TooTallNate/848444)
+  - Secure connection / compressed connection api flags compatible to [mariasql](https://github.com/mscdex/node-mariasql/) client.
+  - [contributors](https://github.com/sidorares/node-mysql2/graphs/contributors)
+
+## Benchmarks
+  - https://gist.github.com/sidorares/ffe9ee9c423f763e3b6b
+  - `npm run benchmarks`
+  - [node-mysql-benchmarks](https://github.com/mscdex/node-mysql-benchmarks)
+  - try to run example [benchmarks](https://github.com/sidorares/node-mysql2/tree/master/benchmarks) on your system
+
+## Examples using MySQL server API:
+
+  - [Mysql-pg-proxy](https://github.com/sidorares/mysql-pg-proxy)  - mysql to postgres proxy server.
+  - [Mysqlite.js](https://github.com/sidorares/mysqlite.js) - mysql server with JS-only (emscripten compiled) sqlite backend.
+  - [sql-engine](https://github.com/eugeneware/sql-engine) - mysql server with leveldb backend.
+
+## See also:
+
+  - [wire protocol documentation](http://dev.mysql.com/doc/internals/en/client-server-protocol.html)
+  - [node-mysql](https://github.com/felixge/node-mysql) - most popular node.js mysql client library
+  - [node-mariasql](https://github.com/mscdex/node-mariasql/) - bindings to libmariasql. One of the fastest clients
+  - [node-libmysqlclident](https://github.com/Sannis/node-mysql-libmysqlclient) - bindings to libmysqlclient
+  - [go-mysql](https://github.com/siddontang/go-mysql) - Mysql Go client (prepared statements, binlog protocol, server)
+
+## Contributing
+
+Feel free to create pull requests.
+TODO in order of importance:
+
+  - node-mysql api incompatibility fixes
+  - documentation
+  - tests
+  - benchmarks
+  - bug fixes
+  - TODOs in source code
+  - performance improvements
+  - features
+
+[npm-image]: https://img.shields.io/npm/v/mysql2.svg
+[npm-url]: https://npmjs.org/package/mysql2
+[node-version-image]: http://img.shields.io/node/v/mysql2.svg
+[node-version-url]: http://nodejs.org/download/
+[travis-image]: https://img.shields.io/travis/sidorares/node-mysql2/master.svg?label=linux
+[travis-url]: https://travis-ci.org/sidorares/node-mysql2
+[appveyor-image]: https://img.shields.io/appveyor/ci/sidorares/node-mysql2/master.svg?label=windows
+[appveyor-url]: https://ci.appveyor.com/project/sidorares/node-mysql2
+[downloads-image]: https://img.shields.io/npm/dm/mysql2.svg
+[downloads-url]: https://npmjs.org/package/mysql2
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/appveyor.yml b/node_modules/mysql2-promise/node_modules/mysql2/appveyor.yml
new file mode 100644
index 0000000000000000000000000000000000000000..21793f0308a9cb93ee624b3c4988da12e3fd7e9f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/appveyor.yml
@@ -0,0 +1,35 @@
+environment:
+  MYSQL_DATABASE: node_mysql
+  MYSQL_HOST: localhost
+  MYSQL_USER: root
+  MYSQL_PASSWORD: Password12!
+  MYSQL_PATH: C:\Program Files\MySQL\MySQL Server 5.6
+
+  matrix:
+    - nodejs_version: "0.8"
+    - nodejs_version: "0.10"
+    - nodejs_version: "0.12"
+    # io.js
+    - nodejs_version: "1.0"
+    - nodejs_version: "2.3"
+
+services:
+  - mysql
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm install
+
+build: off
+
+before_test:
+  - SET PATH=%MYSQL_PATH%\bin;%PATH%
+  - mysqladmin --host=%MYSQL_HOST% --user=%MYSQL_USER% --password=%MYSQL_PASSWORD% create %MYSQL_DATABASE%
+
+test_script:
+  - mysql --version
+  - node --version
+  - npm --version
+  - node test/run.js
+
+version: "{build}"
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/create.sql b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/create.sql
new file mode 100644
index 0000000000000000000000000000000000000000..258bfe6bb08d7470cacaf9ed34cdda309c42502b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/create.sql
@@ -0,0 +1,58 @@
+# create benchmark user
+GRANT ALL ON *.* TO 'benchmarkdbuser'@'%' IDENTIFIED BY 'benchmarkdbpass';
+
+# modified from SO answer http://stackoverflow.com/questions/5125096/for-loop-in-mysql
+DROP DATABASE IF EXISTS hello_world;
+CREATE DATABASE hello_world;
+USE hello_world;
+
+DROP TABLE IF EXISTS World;
+CREATE TABLE  World (
+  id int(10) unsigned NOT NULL auto_increment,
+  randomNumber int NOT NULL default 0,
+  PRIMARY KEY  (id)
+)
+ENGINE=INNODB;
+
+DROP PROCEDURE IF EXISTS load_data;
+
+DELIMITER #
+CREATE PROCEDURE load_data()
+BEGIN
+
+declare v_max int unsigned default 10000;
+declare v_counter int unsigned default 0;
+
+  TRUNCATE TABLE World;
+  START TRANSACTION;
+  while v_counter < v_max do
+    INSERT INTO World (randomNumber) VALUES ( floor(0 + (rand() * 10000)) );
+    SET v_counter=v_counter+1;
+  end while;
+  commit;
+END #
+
+DELIMITER ;
+
+CALL load_data();
+
+DROP TABLE IF EXISTS Fortune;
+CREATE TABLE  Fortune (
+  id int(10) unsigned NOT NULL auto_increment,
+  message varchar(2048) CHARACTER SET 'utf8' NOT NULL,
+  PRIMARY KEY  (id)
+)
+ENGINE=INNODB;
+
+INSERT INTO Fortune (message) VALUES ('fortune: No such file or directory');
+INSERT INTO Fortune (message) VALUES ('A computer scientist is someone who fixes things that aren''t broken.');
+INSERT INTO Fortune (message) VALUES ('After enough decimal places, nobody gives a damn.');
+INSERT INTO Fortune (message) VALUES ('A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1');
+INSERT INTO Fortune (message) VALUES ('A computer program does what you tell it to do, not what you want it to do.');
+INSERT INTO Fortune (message) VALUES ('Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen');
+INSERT INTO Fortune (message) VALUES ('Any program that runs right is obsolete.');
+INSERT INTO Fortune (message) VALUES ('A list is only as strong as its weakest link. — Donald Knuth');
+INSERT INTO Fortune (message) VALUES ('Feature: A bug with seniority.');
+INSERT INTO Fortune (message) VALUES ('Computers make very fast, very accurate mistakes.');
+INSERT INTO Fortune (message) VALUES ('<script>alert("This should not be displayed in a browser alert box.");</script>');
+INSERT INTO Fortune (message) VALUES ('フレームワークのベンチマーク');
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/fortunes.jade b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/fortunes.jade
new file mode 100644
index 0000000000000000000000000000000000000000..31e18646db850bcfdf41c07db4ac64b702b20836
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/fortunes.jade
@@ -0,0 +1,10 @@
+!!! 5
+html
+  head
+    title Fortunes
+  body
+    table
+      for fortune in fortunes
+        tr
+          td= fortune.id
+          td= fortune.message
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/hello.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/hello.js
new file mode 100644
index 0000000000000000000000000000000000000000..318e27161466eb7ccfb06e980b1fd9f2b3fbba9f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/hello.js
@@ -0,0 +1,292 @@
+var cluster = require('cluster');
+var numCPUs = require('os').cpus().length;
+
+if(cluster.isMaster) {
+  // Fork workers.
+  for (var i = 0; i < numCPUs; i++) {
+    cluster.fork();
+  }
+
+  cluster.on('exit', function(worker, code, signal) {
+    console.log('worker ' + worker.pid + ' died');
+  });
+
+  return;
+}
+
+var http     = require('http');
+var url      = require('url');
+var libmysql = require('mysql-libmysqlclient').createConnectionSync();
+var mysql2   = require('../..');
+var mysql    = require('mysql');
+var mariasql = require('mariasql');
+var async    = require('async');
+var Mapper   = require('mapper');
+var jade     = require('jade');
+var fs       = require('fs');
+var connMap  = { user: 'root', password: '', database: 'hello_world', host: 'localhost' };
+
+Mapper.connect(connMap, {verbose: false, strict: false});
+var World = Mapper.map("World", "id", "randomNumber");
+
+var template = jade.compile(fs.readFileSync('./fortunes.jade'));
+
+libmysql.connectSync('localhost', 'root', '', 'hello_world');
+pool2 = mysql2.createPool(connMap);
+pool1 = mysql.createPool(connMap);
+mysql2conn = mysql2.createConnection(connMap);
+mysql1conn = mysql.createConnection(connMap);
+mariaconn = new mariasql();
+mariaconn.connect({
+  host: connMap.host,
+  user: connMap.user,
+  password: connMap.password,
+  db: connMap.database
+});
+
+function getRandomNumber() {
+  return Math.floor(Math.random() * 10000) + 1;
+}
+
+function sequelizeQuery(callback) {
+  World.findById(getRandomNumber(), function (err, world) {
+    callback(null, world);
+  });
+}
+
+function handlePrepared(req, res) {
+  var values = url.parse(req.url, true);
+  var queries = values.query.queries || 1;
+  var results = [];
+  for (var i=0; i < queries; ++i) {
+    mysql2conn.execute("SELECT * FROM world WHERE id = ?", [getRandomNumber()], function (err, rows) {
+      results.push(rows[0]);
+      if (results.length == queries)
+        res.end(JSON.stringify(results));
+    });
+  }
+}
+
+function handleMysqlIsh(conn, req, res) {
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    //pool.getConnection(function(err, conn) {
+      //console.log(conn, conn.query, '===============');
+      var results = [];
+      for (var i=0; i < queries; ++i) {
+        mysql2conn.query("SELECT * FROM world WHERE id = ?", [getRandomNumber()], function (err, rows) {
+          results.push(rows[0]);
+          if (results.length == queries)
+            res.end(JSON.stringify(results));
+        });
+      }
+    //});
+}
+
+function handleMysqlIshPool(pool, req, res) {
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var results = [];
+    for (var i=0; i < queries; ++i) {
+      pool.getConnection(function(err, conn) {
+        mysql2conn.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, rows) {
+          results.push(rows[0]);
+          if (results.length == queries)
+            res.end(JSON.stringify(results));
+        });
+      });
+    }
+}
+
+function handleMaria(req, res)
+{
+  var values = url.parse(req.url, true);
+  var queries = values.query.queries || 1;
+  var results = [];
+  for (var i=0; i < queries; ++i) {
+    mariaconn.query("SELECT * FROM world WHERE id = :id", { id: getRandomNumber() } )
+      .on('result', function (dbres) {
+        dbres.on('row', function(row) {
+          results.push(row);
+          if (results.length == queries)
+            res.end(JSON.stringify(results));
+        });
+      });
+  }
+}
+
+function fortuneMysql(conn, res) {
+  var fortunes = [];
+  res.writeHead(200, {'Content-Type': 'text/html'});
+  conn.query('select * from Fortune', function(err, fortunes) {
+    fortunes.push({id: 0, message: "Additional fortune added at request time."});
+    fortunes.sort(sortFortunes);
+    res.end(template({fortunes: fortunes}));
+  });
+}
+
+function fortuneMaria(res) {
+  fortunes = [];
+  res.writeHead(200, {'Content-Type': 'text/html'});
+  mariaconn.query("SELECT * from Fortune")
+       .on('result', function (dbres) {
+         dbres.on('row', function(row) { fortunes.push(row); });
+         dbres.on('end', function() {
+           fortunes.push({id: 0, message: "Additional fortune added at request time."});
+           fortunes.sort(sortFortunes);
+           res.end(template({fortunes: fortunes}));
+         });
+  });
+}
+
+function sortFortunes(a, b) {
+  return (a.message < b.message) ? -1 : (a.message > b.message) ? 1 : 0;
+}
+
+http.createServer(function (req, res) {
+  // JSON response object
+  var hello = {message: "Hello, world"};
+
+  var path = url.parse(req.url).pathname;
+
+  switch (path) {
+  case '/json':
+    // JSON Response Test
+    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+    // Write JSON object to response
+    res.end(JSON.stringify(hello));
+    break;
+
+  case '/mysql-orm':
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
+
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = sequelizeQuery;
+    }
+
+    res.writeHead(200, {'Content-Type': 'application/json'});
+
+    async.parallel(queryFunctions, function(err, results) {
+      res.end(JSON.stringify(results));
+    });
+    break;
+
+  case '/mysql':
+    res.writeHead(200, {'Content-Type': 'application/json'});
+
+    function libmysqlQuery(callback) {
+      libmysql.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, res) {
+        if (err) {
+	        throw err;
+	      }
+
+	      res.fetchAll(function(err, rows) {
+      	  if (err) {
+      	    throw err;
+      	  }
+
+      	  res.freeSync();
+      	  callback(null, rows[0]);
+        });
+      });
+    }
+
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
+
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = libmysqlQuery;
+    }
+    async.parallel(queryFunctions, function(err, results) {
+      if (err) {
+        res.writeHead(500);
+        return res.end('MYSQL CONNECTION ERROR.');
+      }
+      res.end(JSON.stringify(results));
+    });
+    break;
+
+  case '/mysql2':
+    handleMysqlIsh(mysql2conn, req, res);
+    break;
+
+  case '/fortunes-mysql2':
+    fortuneMysql(mysql2conn, res);
+    break;
+
+  case '/fortunes-mysql1':
+    fortuneMysql(mysql1conn, res);
+    break;
+
+  case '/fortunes-maria':
+    fortuneMaria(res);
+    break;
+
+  case '/mysql2pool':
+    handleMysqlIshPool(pool2, req, res);
+    break;
+
+  case '/mysql2ps':
+    handlePrepared(req, res);
+    break;
+
+  case '/mysql1':
+    handleMysqlIsh(mysql1conn, req, res);
+    break;
+
+  case '/maria':
+    handleMaria(req, res);
+    break;
+
+  case '/update':
+    res.writeHead(200, {'Content-Type': 'application/json'});
+
+    function libmysqlQuery(callback) {
+      libmysql.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, res) {
+        if (err) {
+          throw err;
+        }
+
+        res.fetchAll(function(err, rows) {
+          if (err) {
+            throw err;
+          }
+
+          res.freeSync();
+
+          rows[0].randomNumber = getRandomNumber();
+          libmysql.query("UPDATE World SET randomNumber = " + rows[0].randomNumber + " WHERE id = " + rows[0]['id'], function (err, res) {
+            if (err) {
+              throw err;
+            }
+          });
+          callback(null, rows[0]);
+        });
+      });
+    }
+
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
+
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = libmysqlQuery;
+    }
+    async.parallel(queryFunctions, function(err, results) {
+      if (err) {
+        res.writeHead(500);
+        return res.end('MYSQL CONNECTION ERROR.');
+      }
+      res.end(JSON.stringify(results));
+    });
+    break;
+
+  default:
+    // File not found handler
+    res.writeHead(404, {'Content-Type': 'text/html; charset=UTF-8'});
+    res.end("NOT IMPLEMENTED");
+  }
+}).listen(8080);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/package.json b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..e501365ea84f19939d2b9f3354e4b7461fa035f3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/FB/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "application-name",
+  "version": "0.0.1",
+  "private": true,
+  "dependencies": {
+    "async": "0.2.5",
+    "mysql-libmysqlclient": "1.5.2",
+    "mysql2": "0.7.0",
+    "mariasql": "0.1.18",
+    "mapper": "0.2.4-pre",
+    "jade": "~0.30.0"
+  },
+  "main": "hello.js"
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server-maria.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server-maria.js
new file mode 100644
index 0000000000000000000000000000000000000000..d167cbe0c89f08a4d2b6a72ef8e6b1c99bea06f7
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server-maria.js
@@ -0,0 +1,63 @@
+var common     = require('../test/common');
+
+    var Client = require('mariasql');
+    var connection = new Client();
+    connection.connect({
+      host: '127.0.0.1',
+      port: 3333,
+      user: 'root',
+      password: '',
+      db: 'test'
+    });
+
+
+var assert     = require('assert');
+
+function benchmarkSelect(numLeft, callback) {
+    numRows = 0;
+    var q = connection.query('select 1+1 as qqq');
+    q.on('result', function(res) {
+        //console.log("result!");
+        //console.log(res);
+
+        res.on('row', function(r) {
+           //console.log(r);
+           numRows++;
+        });
+
+        res.on('end', function() {
+          if (numLeft > 1)
+            benchmarkSelect(numLeft-1, callback);
+          else
+            callback(numRows);
+        });
+      });
+}
+
+function benchmarkSelects(n, cb) {
+  var numSelects = 100;
+  var start = process.hrtime();
+  benchmarkSelect(numSelects, function(rowsPerQuery) {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(' rows: ' +  numSelects*1e9/diff + ' results/sec, ' +  rowsPerQuery*numSelects*1e9/diff + ' rows/sec');
+    if (n > 1)
+      benchmarkSelects(n - 1, cb);
+    else
+      cb();
+  });
+}
+
+module.exports = function(done) {
+  console.log('connected');
+  var testStart = process.hrtime();
+  benchmarkSelects(5, function() {
+    var testEnd = process.hrtime();
+    console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
+    connection.end();
+    if (done)
+      done();
+  });
+};
+
+connection.on('connect', module.exports);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server.js
new file mode 100644
index 0000000000000000000000000000000000000000..a4b5cb52a5be94c96ff1031bd511740fb6f137f4
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-fake-server.js
@@ -0,0 +1,60 @@
+var common     = require('../test/common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+// ==== simple pool ===
+var connections = new Array(10);
+for (var i=0; i < connections.length; ++i)
+  connections[i] = common.createConnection();
+var currConn = 0;
+function next() {
+  currConn++;
+  if (currConn == connections.length)
+    currConn = 0;
+  connection = connections[currConn];
+}
+// ======================
+
+function benchmarkSelect(numLeft, callback) {
+  //connection.query('query from fake server fixture', function(err, result) {
+
+  // comment if no pool:
+  next();
+
+  var rows = 0;
+  var q = connection.query('query from fake server fixture');
+  q.on('result', function() { rows++; });
+  q.on('end', function() {
+    if (numLeft > 1)
+      benchmarkSelect(numLeft-1, callback);
+    else
+      callback(rows);
+  });
+}
+
+function benchmarkSelects(n, cb) {
+  var numSelects = 100000;
+  var start = process.hrtime();
+  benchmarkSelect(numSelects, function(rowsPerQuery) {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(' rows: ' +  numSelects*1e9/diff + ' results/sec, ' +  rowsPerQuery*numSelects*1e9/diff + ' rows/sec');
+    if (n > 1)
+      benchmarkSelects(n - 1, cb);
+    else
+      cb();
+  });
+}
+
+module.exports = function(done) {
+  var testStart = process.hrtime();
+  benchmarkSelects(5, function() {
+    var testEnd = process.hrtime();
+    console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
+    connection.end();
+    if (done)
+      done();
+  });
+};
+
+  module.exports();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-parallel.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-parallel.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9a9d520df02e47ddf1f64adcf823e5854e36928
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-parallel.js
@@ -0,0 +1,80 @@
+var common     = require('../test/common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var table = 'insert_test';
+//var text = "本日は晴天なり";
+var text = "test abc xyz";
+connection.query('drop table ' + table).on('error', function() {});
+connection.query([
+  'CREATE TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255) NOT NULL,',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+function benchmarkInsert(numLeft, callback) {
+  connection.query('INSERT INTO ' + table + ' SET title="' + text + '"', function(err, result) {
+    if (err) throw err;
+    if (numLeft > 1)
+      benchmarkInsert(numLeft-1, callback);
+    else
+      callback();
+  });
+}
+
+function benchmarkInserts(n, cb) {
+  var numInsert = 50000;
+  var start = process.hrtime();
+  benchmarkInsert(numInsert, function() {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(numInsert*1e9/diff + ' inserts/sec');
+    if (n > 1)
+      benchmarkInserts(n - 1, cb);
+    else
+      cb();
+  });
+}
+
+function benchmarkParallelSelects(n, size, cb) {
+  var start = process.hrtime();
+  var numRunning = 0;
+
+  function commandDone() {
+    console.log(numRunning);
+    numRunning--;
+    if (numRunning > 0)
+      return;
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(size + ' rows: ' +  n*1e9/diff + ' results/sec, ' +  size*n*1e9/diff + ' rows/sec');
+    cb();
+  }
+
+  var connections = new Array(n);
+  for (var i=0; i < n; ++i)
+  {
+    numRunning++;
+    connections[i] = common.createConnection();
+    var cmd = connections[i].execute('select * from ' + table + ' limit ' + size, []);
+    cmd.on('end', commandDone);
+  }
+}
+
+module.exports = function(done) {
+  var testStart = process.hrtime();
+  benchmarkInserts(1, function() {
+    benchmarkParallelSelects(8, 50000, function() {
+      var testEnd = process.hrtime();
+      console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
+      if (done)
+        done();
+    });
+  });
+};
+
+if (require.main === module) {
+  module.exports();
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-prepared.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-prepared.js
new file mode 100644
index 0000000000000000000000000000000000000000..5715ec5f76d4a4bde47410dd28e9a13db845694b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select-prepared.js
@@ -0,0 +1,83 @@
+var common     = require('../test/common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var table = 'insert_test';
+//var text = "本日は晴天なり";
+var text = "test abc xyz";
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+function benchmarkInsert(numLeft, callback) {
+  connection.execute('INSERT INTO ' + table + ' SET title="' + text + '"', [], function(err, result) {
+    if (err) throw err;
+    if (numLeft > 1)
+      benchmarkInsert(numLeft-1, callback);
+    else
+      callback();
+  });
+}
+
+function benchmarkInserts(n, cb) {
+  var numInsert = 10000;
+  var start = process.hrtime();
+  benchmarkInsert(numInsert, function() {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(numInsert*1e9/diff + ' inserts/sec');
+    if (n > 1)
+      benchmarkInserts(n - 1, cb);
+    else
+      cb();
+  });
+}
+
+function benchmarkSelect(numLeft, numSelect, callback) {
+  connection.execute('select * from ' + table + ' limit ' + numSelect, [], function(err, result) {
+    if (err) throw err;
+    if (numLeft > 1)
+      benchmarkSelect(numLeft-1, numSelect, callback);
+    else
+      callback();
+  });
+}
+
+function benchmarkSelects(n, size, cb) {
+  var numSelects = 100;
+  var start = process.hrtime();
+  benchmarkSelect(numSelects, size, function() {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(size + ' rows: ' +  numSelects*1e9/diff + ' results/sec, ' +  size*numSelects*1e9/diff + ' rows/sec');
+    if (n > 1)
+      benchmarkSelects(n - 1, size, cb);
+    else
+      cb();
+  });
+}
+
+module.exports = function(done) {
+  var testStart = process.hrtime();
+  benchmarkInserts(1, function() {
+    benchmarkSelects(5, 100, function() {
+      benchmarkSelects(10, 1000, function() {
+        benchmarkSelects(2, 50000, function() {
+          var testEnd = process.hrtime();
+          console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
+          connection.end();
+          if (done)
+            done();
+        });
+      });
+    });
+  });
+};
+
+if (require.main === module) {
+  module.exports();
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1910e1e8e27b71b0bb3ba2aa08663d793c9f9f4
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/bench-insert-select.js
@@ -0,0 +1,82 @@
+var common     = require('../test/common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var table = 'insert_test';
+var text = "本日は晴天なり";
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+function benchmarkInsert(numLeft, callback) {
+  connection.query('INSERT INTO ' + table + ' SET title="' + text + '"', function(err, result) {
+    if (err) throw err;
+    if (numLeft > 1)
+      benchmarkInsert(numLeft-1, callback);
+    else
+      callback();
+  });
+}
+
+function benchmarkInserts(n, cb) {
+  var numInsert = 10000;
+  var start = process.hrtime();
+  benchmarkInsert(numInsert, function() {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(numInsert*1e9/diff + ' inserts/sec');
+    if (n > 1)
+      benchmarkInserts(n - 1, cb);
+    else
+      cb();
+  });
+}
+
+function benchmarkSelect(numLeft, numSelect, callback) {
+  connection.query('select * from ' + table + ' limit ' + numSelect, function(err, result) {
+    if (err) throw err;
+    if (numLeft > 1)
+      benchmarkSelect(numLeft-1, numSelect, callback);
+    else
+      callback();
+  });
+}
+
+function benchmarkSelects(n, size, cb) {
+  var numSelects = 100;
+  var start = process.hrtime();
+  benchmarkSelect(numSelects, size, function() {
+    var end = process.hrtime();
+    var diff = common.hrdiff(start, end);
+    console.log(size + ' rows: ' +  numSelects*1e9/diff + ' results/sec, ' +  size*numSelects*1e9/diff + ' rows/sec');
+    if (n > 1)
+      benchmarkSelects(n - 1, size, cb);
+    else
+      cb();
+  });
+}
+
+module.exports = function(done) {
+  var testStart = process.hrtime();
+  benchmarkInserts(5, function() {
+    benchmarkSelects(5, 10000, function() {
+      benchmarkSelects(10, 1000, function() {
+        benchmarkSelects(2, 50000, function() {
+          var testEnd = process.hrtime();
+          console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
+          connection.end();
+          if (done)
+            done();
+        });
+      });
+    });
+  });
+};
+
+if (require.main === module) {
+  module.exports();
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-query.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-query.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ce15f89adb848f096908aea51da15afbe01fcf4
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-query.js
@@ -0,0 +1,34 @@
+var assert = require('assert');
+var createConnection = require('../test/common').createConnection;
+
+var sql = process.argv[2];
+
+(function(cb) {
+    var db = createConnection();
+
+       var left = 10000;
+       var start = Date.now();
+       var prev1000 = start;
+       function bench()
+       {
+           db.query(sql).on('end', function(err, res) {
+               left--;
+               if (left % 1000 === 0)
+               {
+                   var curTime = Date.now();
+                   var last1000time = curTime - prev1000;
+                   prev1000 = curTime;
+                   console.error( (1000000/last1000time) + ' req/sec' );
+               }
+
+               if (left > 0)
+                   bench();
+               else {
+                   console.error( 10000000/(Date.now() - start) + ' req/sec (average 10000 reqs)');
+                   db.end();
+                   if (cb) cb();
+               }
+           });
+       }
+       bench();
+})();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-server.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-server.js
new file mode 100644
index 0000000000000000000000000000000000000000..d05b3b19f24bdeedda23e89b8124cd1294ff8689
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/benchmark-server.js
@@ -0,0 +1,72 @@
+var mysql = require('../index.js');
+var flags  = require('../lib/constants/client');
+var Packets      = require('../lib/packets/index.js');
+var Packet       = require('../lib/packets/packet');
+
+function prepareReply(columns, row, n) {
+  var length = 0;
+  var rsHeader = Packets.ResultSetHeader.toPacket(columns.length);
+  length += rsHeader.length();
+  var columnPackets = [];
+  columns.forEach(function(column) {
+    var packet = Packets.ColumnDefinition.toPacket(column);
+    length += packet.length();
+    columnPackets.push(packet);
+  });
+  var eof = Packets.EOF.toPacket();
+  length += 2*eof.length();
+  var rowPacket = Packets.TextRow.toPacket(row);
+  length += n*rowPacket.length();
+
+  var replyBuffer = new Buffer(length);
+  var offset = 0;
+  var id = 1;
+  function add(packet) {
+    packet.writeHeader(id);
+    id = id + 1;
+    packet.buffer.copy(replyBuffer, offset);
+    offset += packet.length();
+  }
+
+  var i;
+  add(rsHeader);
+  for (i=0; i < columns.length; ++i)
+    add(columnPackets[i]);
+  add(eof);
+  for (i=0; i < n; ++i)
+    add(rowPacket);
+  add(eof);
+
+  return replyBuffer;
+}
+
+var buff = prepareReply([{
+      catalog: 'def',
+      schema: 'test',
+      table: 'test_table',
+      orgTable: 'test_table',
+      name: 'beta',
+      orgName: 'beta',
+      characterSet: 33,
+      columnLength: 384,
+      columnType: 3, //253,
+      flags: 0,
+      decimals: 0
+    }], ['12345'], 1);
+
+var server = mysql.createServer();
+server.listen('/tmp/mybench3.sock');
+server.on('connection', function(conn) {
+  conn.serverHandshake({
+    protocolVersion: 10,
+    serverVersion: 'node.js rocks',
+    connectionId: 1234,
+    statusFlags: 2,
+    characterSet: 8,
+    capabilityFlags: 0xffffff
+  });
+  conn.on('query', function(query) {
+    //console.log(query);
+    conn.write(buff);
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/http-select-and-render.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/http-select-and-render.js
new file mode 100644
index 0000000000000000000000000000000000000000..bfb92525b00dd1d2ca6f2f77e3cc5f42a33f14d3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/http-select-and-render.js
@@ -0,0 +1,39 @@
+var http   = require('http');
+var fs     = require('fs');
+var common = require('../test/common');
+var url = require('url');
+
+var conn = common.createConnection();
+var render = common.createTemplate();
+var port = process.env.PORT;
+
+http.createServer(function(req, res) {
+  var q = url.parse(req.url, true);
+  if (q.pathname == '/render') {
+
+    var sql = q.query.q;
+    var n = q.query.n;
+    var rowsTotal = [];
+    var doQueries = function(number) {
+      if (number === 0) {
+        var body = render({ records: rowsTotal});
+        res.writeHead(200, {
+          'Content-Length': body.length,
+          'Content-Type': 'text/html' }
+        );
+        res.end(body);
+      } else {
+        conn.query(sql, function(err, rows) {
+          // TODO: handle error
+          rowsTotal = rowsTotal.concat(rows);
+          doQueries(number-1);
+        });
+      }
+    };
+    doQueries(n);
+
+  } else {
+    res.writeHead(404);
+    res.end();
+  }
+}).listen(port || 1234);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/httperf.sh b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/httperf.sh
new file mode 100644
index 0000000000000000000000000000000000000000..85630ef7d6052199a0bfe5050abc797fe80f169c
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/httperf.sh
@@ -0,0 +1 @@
+httperf --port=1234 --uri='/render?q=select%20*%20from%20foos%20limit%205,10000&n=2' --num-conns=10 --num-calls=2 rate=100
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-client.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-client.js
new file mode 100644
index 0000000000000000000000000000000000000000..64a6717b9699604adac7286a028f06148805522b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-client.js
@@ -0,0 +1,18 @@
+var net = require('net');
+var count = 0;
+var byte = new Buffer([0x33]);
+function pong()
+{
+  count++;
+  this.write(byte);
+}
+
+var c = net.connect(3334);
+c.setNoDelay(true);
+c.ondata = pong;
+pong.apply(c);
+
+setInterval(function() {
+  console.log(count);
+  count = 0;
+}, 1000);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-server.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-server.js
new file mode 100644
index 0000000000000000000000000000000000000000..7eb90713c6941a19ac088ee617270f2d9ee88499
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-server.js
@@ -0,0 +1,12 @@
+var net = require('net');
+
+var byte = new Buffer([0x33]);
+function pong()
+{
+  this.write(byte);
+}
+
+net.createServer(function(s) {
+  s.setNoDelay(true);
+  s.ondata = pong;
+}).listen(3334);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-uv.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-uv.js
new file mode 100644
index 0000000000000000000000000000000000000000..973284c1cb4ec21ef23c249786a512b18f1e8292
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ping-pong-uv.js
@@ -0,0 +1,30 @@
+var count = 0;
+var byte = new Buffer([0x33]);
+
+function ping(buffer, offset, length) {
+  count++;
+  pong(this);
+}
+
+function noop() {}
+function pong(sock)
+{
+  var writeReq = sock.writeBuffer(byte);
+  writeReq.oncomplete = noop;
+}
+
+var port = 3334;
+var TCP = process.binding('tcp_wrap').TCP;
+var client = new TCP();
+var req = client.connect('127.0.0.1', port);
+req.oncomplete = function() {
+  console.log('connected');
+  pong(client);
+};
+client.onread = ping;
+client.readStart();
+
+setInterval(function() {
+  console.log(count);
+  count = 0;
+}, 1000);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/bench.rb b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/bench.rb
new file mode 100644
index 0000000000000000000000000000000000000000..beb06821a1a5405664abfcb9d9d50c77fdceac1f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/bench.rb
@@ -0,0 +1,29 @@
+require 'rubygems'
+require 'benchmark'
+require 'mysql2'
+require 'haml'
+
+number_of = 1
+database = 'test'
+sql = "SELECT * FROM mysql2_test LIMIT 1"
+
+Benchmark.bmbm do |x|
+  mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
+  mysql2.query "USE #{database}"
+  x.report "Mysql2 (cast: true)" do
+    number_of.times do
+      mysql2_result = mysql2.query sql, :symbolize_keys => true, :cast => true
+      puts haml :index, :locals => { :rows => mysqql2_result }
+    end
+  end
+
+  x.report "Mysql2 (cast: false)" do
+    number_of.times do
+      mysql2_result = mysql2.query sql, :symbolize_keys => true, :cast => false
+      mysql2_result.each do |res|
+        # puts res.inspect
+      end
+    end
+  end
+
+end
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/benchmark-query.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/benchmark-query.js
new file mode 100644
index 0000000000000000000000000000000000000000..4e16cd549d1507dd98f2f605deca7ce47b72bbb4
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/benchmark-query.js
@@ -0,0 +1,56 @@
+var assert = require('assert');
+var createConnection = require('../../test/common').createConnection;
+
+var sql = process.argv[2];
+var starthr = process.hrtime();
+var haml = require('hamljs');
+var fs = require('fs');
+
+var render = haml.compile(fs.readFileSync('./views/index.haml'));
+
+l = 0;
+var rowsReceived = 0;
+var numRequests = 0;
+
+(function(cb) {
+    var db = createConnection();
+
+       var left = 1;
+
+       var start = Date.now();
+       var prev1000 = start;
+       function bench()
+       {
+           //db.query(sql).on('end', function(err, res) {
+           db.query(sql, function(err, res) {
+           //db.execute(sql, function(err, res) {
+
+               rowsReceived += res.length;
+               numRequests++;
+
+               l += render({results: res}).length;
+               console.log(render({results: res}));
+
+               left--;
+               if (left % 1000 === 0)
+               {
+                   var curTime = Date.now();
+                   var last1000time = curTime - prev1000;
+                   prev1000 = curTime;
+                   console.error( (1000000/last1000time) + ' req/sec' );
+               }
+
+               if (left > 0)
+                   bench();
+               else {
+                   console.error( numRequests *1000/(Date.now() - start) + ' req/sec (average 10000 reqs)');
+                   console.error( rowsReceived*1000/(Date.now() - start) + ' row/sec (average 10000 reqs)');
+                   db.end();
+                   if (cb) cb();
+                   console.log(process.hrtime(starthr));
+                   console.log(l);
+               }
+           });
+       }
+       bench();
+})();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/populate.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/populate.js
new file mode 100644
index 0000000000000000000000000000000000000000..64afb36fc414813ee8bb5cdf11f06c13c698c052
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/populate.js
@@ -0,0 +1,82 @@
+var common     = require('../../test/common');
+var connection = common.createConnection();
+var assert     = require('assert');
+var Faker      = require('charlatan');
+var fs = require('fs');
+
+var createSql = fs.readFileSync('./schema.sql').toString();
+
+// use seed to make it consistent between runs
+// copy-paste from http://stackoverflow.com/questions/521295/javascript-random-seeds
+
+var m_w = 123456789;
+var m_z = 987654321;
+var mask = 0xffffffff;
+
+// Takes any integer
+function seed(i) {
+    m_w = i;
+}
+
+// Returns number between 0 (inclusive) and 1.0 (exclusive),
+// just like Math.random().
+function rand()
+{
+    m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
+    m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
+    var result = ((m_z << 16) + m_w) & mask;
+    result /= 4294967296;
+    return result + 0.5;
+}
+
+seed(123);
+
+connection.query(createSql);
+connection.query("DELETE FROM mysql2_test");
+
+function insertRow(r) {
+  connection.query("INSERT INTO mysql2_test SET ? ", r);
+}
+
+var num_rows = 10000;
+
+var five_words, twenty5_paragraphs;
+for (var i = 0; i < num_rows; ++i)
+{
+  five_words = Faker.Lorem.words(1 + rand(4)).join(' ').slice(0, 10);
+  twenty5_paragraphs = Faker.Lorem.paragraphs(1 + rand(24)).join(' ');
+  insertRow({
+     bit_test: 1,
+     tiny_int_test: rand(128),
+     small_int_test: rand(32767),
+     medium_int_test: rand(8388607),
+     int_test: rand(2147483647),
+     big_int_test: rand(9223372036854775807),
+     float_test: rand(32767)/1.87,
+     float_zero_test: 0.0,
+     double_test: rand(8388607)/1.87,
+     decimal_test: rand(8388607)/1.87,
+     decimal_zero_test: 0,
+     date_test: '2010-4-4',
+     date_time_test: '2010-4-4 11:44:00',
+     timestamp_test: '2010-4-4 11:44:00',
+     time_test: '11:44:00',
+     year_test: 14,
+     char_test: five_words,
+     varchar_test: five_words,
+     binary_test: five_words,
+     varbinary_test: five_words,
+     tiny_blob_test: five_words,
+     tiny_text_test: Faker.Lorem.paragraph(rand(5)),
+     blob_test: twenty5_paragraphs,
+     text_test: twenty5_paragraphs,
+     medium_blob_test: twenty5_paragraphs,
+     medium_text_test: twenty5_paragraphs,
+     long_blob_test: twenty5_paragraphs,
+     long_text_test: twenty5_paragraphs,
+     enum_test: ['val1', 'val2'][rand(2)],
+     set_test: ['val1', 'val2', 'val1,val2'][rand(3)]
+  });
+}
+
+connection.end();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/schema.sql b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..541a122c5c2ab109a7a241f6e4c34f1fa5d6bb2b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/schema.sql
@@ -0,0 +1,33 @@
+  CREATE TABLE IF NOT EXISTS mysql2_test (
+    null_test VARCHAR(10),
+    bit_test BIT,
+    tiny_int_test TINYINT,
+    small_int_test SMALLINT,
+    medium_int_test MEDIUMINT,
+    int_test INT,
+    big_int_test BIGINT,
+    float_test FLOAT(10,3),
+    float_zero_test FLOAT(10,3),
+    double_test DOUBLE(10,3),
+    decimal_test DECIMAL(10,3),
+    decimal_zero_test DECIMAL(10,3),
+    date_test DATE,
+    date_time_test DATETIME,
+    timestamp_test TIMESTAMP,
+    time_test TIME,
+    year_test YEAR(4),
+    char_test CHAR(10),
+    varchar_test VARCHAR(10),
+    binary_test BINARY(10),
+    varbinary_test VARBINARY(10),
+    tiny_blob_test TINYBLOB,
+    tiny_text_test TINYTEXT,
+    blob_test BLOB,
+    text_test TEXT,
+    medium_blob_test MEDIUMBLOB,
+    medium_text_test MEDIUMTEXT,
+    long_blob_test LONGBLOB,
+    long_text_test LONGTEXT,
+    enum_test ENUM('val1', 'val2'),
+    set_test SET('val1', 'val2')
+  ) DEFAULT CHARSET=utf8
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/views/index.haml b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/views/index.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d958d894e78207c0c157a1c558d379f2d9a954b6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/ruby-mysql2/views/index.haml
@@ -0,0 +1,41 @@
+!!!
+%html
+  %head
+    %title table dump goes here
+  %body
+    %h1 data data 
+    %table
+      %tbody
+        - each row in results
+          %tr
+            %td= row.null_test
+            %td= row.bit_test
+            %td= row.tiny_int_test
+            %td= row.small_int_test
+            %td= row.medium_int_test
+            %td= row.int_test
+            %td= row.big_int_test
+            %td= row.float_test
+            %td= row.float_zero_test
+            %td= row.double_test
+            %td= row.decimal_test
+            %td= row.decimal_zero_test
+            %td= row.date_test
+            %td= row.date_time_test
+            %td= row.timestamp_test
+            %td= row.time_test
+            %td= row.year_test
+            %td= row.char_test
+            %td= row.varchar_test
+            %td= row.binary_test
+            %td= row.varbinary_test
+            %td= row.tiny_blob_test
+            %td= row.tiny_text_test
+            %td= row.blob_test
+            %td= row.text_test
+            %td= row.medium_blob_test
+            %td= row.medium_text_test
+            %td= row.long_blob_test
+            %td= row.long_text_test
+            %td= row.enum_test
+            %td= row.set_test
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/run-unit.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/run-unit.js
new file mode 100644
index 0000000000000000000000000000000000000000..326e56bf19506c6b24fdff956f887485935d7437
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/run-unit.js
@@ -0,0 +1,134 @@
+#!/usr/bin/env node
+var progress = require('progress');
+
+var fs = require('fs');
+var nWarmup = 2;
+var nRepeats = 32 + nWarmup;
+var path = require('path');
+
+var prevResults = {};
+try {
+  var r = require('./results.json');
+  r.forEach(function(rr) {
+    prevResults[rr.path] = rr
+  });
+} catch(e) {
+  // no prev results?
+}
+
+function stats(times) {
+  var avg = 0;
+  for(var i=0; i < times.length; ++i) {
+    avg += times[i]/times.length;
+  }
+  var v = 0;
+  for(var i=0; i < times.length; ++i) {
+    v += (times[i] - avg)*(times[i] - avg) / times.length;
+  }
+  var stdev = Math.sqrt(v);
+  return {
+    avg: avg,
+    stdev: stdev,
+    stdevrel: stdev/avg
+  };
+}
+
+function runFolder(name, done) {
+  fs.readdir(name, function(err, list) {
+    if (err)
+      return done(err);
+    runFileList(name, list, done);
+  });
+}
+
+function benchmarkModule(m, modulePath, done) {
+
+  var results = [];
+   var bar = new progress(m.comment + ' [:bar] ', {
+     total: nRepeats,
+     clear: true
+   });
+  function repeat(w, n) {
+    bar.tick();
+    if (n === 0) {
+      var result = {};
+      var s = stats(results);
+      var unsDigits = Math.floor(Math.floor(s.stdev).toString().length * 0.8);
+      var pow = Math.pow(10, unsDigits);
+      var avg = Math.round(s.avg / pow)*pow;
+      var uns = Math.round(s.stdev / pow)*pow;
+      console.log('%s: %s  ±%s', m.comment, avg, uns);
+      result.time = s.avg;
+      result.timeStdev = s.stdev;
+      result.comment = m.comment;
+      result.path = path.relative(__dirname, modulePath);
+      if (m.toSpeed) {
+        var speed = m.toSpeed(s.avg, s.stdev);
+        var speedDigits =  Math.floor(Math.floor(speed.error).toString().length * 0.8);
+        pow = Math.pow(10, speedDigits);
+        console.log('           = %s ±%s %s',
+          Math.round(speed.value / pow)*pow,
+          Math.round(speed.error / pow)*pow, speed.units);
+        var prev = prevResults[result.path];
+        if (prev) {
+          if (speed.value > prev.speed.value + prev.speed.error) {
+            console.log('Faster then prev result: %s ±%s %s', prev.speed.value, prev.speed.units)
+          } else if (speed.value < prev.speed.value - prev.speed.error) {
+            console.log('Slower then prev result: %s ±%s %s', prev.speed.value, prev.speed.units)
+          }
+        }
+        result.speed = speed;
+      }
+      return done(null, result);
+    }
+    var start = process.hrtime();
+    setImmediate(function() {
+      m(function() {
+        var end = process.hrtime(start);
+        if (w <= 0)
+          results.push(end[0]*1e9 + end[1]);
+        repeat(w-1, n-1);
+      });
+    });
+  }
+  repeat(nWarmup-1, nRepeats-1, done);
+}
+
+function runFileList(base, list, done) {
+  var index = -1;
+  var results;
+  function runOne(err, res) {
+    if (err) return done(err);
+    ++index;
+    if (res) {
+      if (!results)
+        results = [];
+      if (Array.isArray(res))
+        results = results.concat(res);
+      else
+        results.push(res);
+    }
+    if (index >= list.length) {
+      return done(null, results);
+    }
+    var fname = base + '/' + list[index];
+    fs.stat(fname, function(err, stat) {
+      if (err) return done(err);
+      if (stat.isDirectory())
+        return runFolder(fname, runOne);
+
+      else if (fname.slice(-3) == '.js') {
+        var m = require(fname);
+        return benchmarkModule(m, fname, runOne);
+      }
+      runOne();
+    });
+  }
+  runOne();
+}
+
+//var name = process.argv[2] || __dirname + '/unit';
+runFolder(__dirname + '/unit', function(err, results) {
+  //console.log(results);
+  fs.writeFileSync(__dirname + '/results.json', JSON.stringify(results));
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/test-benchmark-select-1.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/test-benchmark-select-1.js
new file mode 100644
index 0000000000000000000000000000000000000000..842771c9120b555946fb18ca218ccf538cd0af0c
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/test-benchmark-select-1.js
@@ -0,0 +1,32 @@
+var assert = require('assert');
+var createConnection = require('../common').createConnection;
+
+(function(cb) {
+    var db = createConnection();
+
+       var left = 10000;
+       var start = Date.now();
+       var prev1000 = start;
+       function bench()
+       {
+           db.query('select 1').on('end', function(err, res) {
+               left--;
+               if (left % 1000 === 0)
+               {
+                   var curTime = Date.now();
+                   var last1000time = curTime - prev1000;
+                   prev1000 = curTime;
+                   console.error( (1000000/last1000time) + ' req/sec' );
+               }
+
+               if (left > 0)
+                   bench();
+               else {
+                   console.error( 10000000/(Date.now() - start) + ' req/sec (average 10000 reqs)');
+                   db.end();
+                   if (cb) cb();
+               }
+           });
+       }
+       bench();
+})();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition0 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition0
new file mode 100644
index 0000000000000000000000000000000000000000..b4472919b4207dfc185b90678dcc3dd14dc4420d
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition0 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition1 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition1
new file mode 100644
index 0000000000000000000000000000000000000000..a96ad6c9c534db6bfd4ebb9c4951f646c1e5e2ae
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition1 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition10 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition10
new file mode 100644
index 0000000000000000000000000000000000000000..fb69d663cabc2ff4f55fd79faea60afbbd4c2b7e
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition10 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition11 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition11
new file mode 100644
index 0000000000000000000000000000000000000000..2c7b6e92540e744df6e8664bcd6ed54acbbb0e51
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition11 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition12 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition12
new file mode 100644
index 0000000000000000000000000000000000000000..c8a151e41cfc356c7ce184fed89a23acd62c1355
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition12 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition13 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition13
new file mode 100644
index 0000000000000000000000000000000000000000..8bb1bcc93004ebff62f69a652d1db4a398a6cb2f
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition13 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition14 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition14
new file mode 100644
index 0000000000000000000000000000000000000000..4f9223beda26e6a018f782551b94de24c2c694f8
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition14 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition15 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition15
new file mode 100644
index 0000000000000000000000000000000000000000..c5d29c0a4f3d2c26daa1625182b46a2ddd96ad06
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition15 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition16 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition16
new file mode 100644
index 0000000000000000000000000000000000000000..7154cc8c9efde028ce3d59a4bc2c5073bacb76d3
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition16 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition17 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition17
new file mode 100644
index 0000000000000000000000000000000000000000..3881ac3ac0ecef02921acd5b80e4f599984a54ca
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition17 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition18 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition18
new file mode 100644
index 0000000000000000000000000000000000000000..b85f7c82d1b866778891467ffc0dc4980e184b81
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition18 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition19 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition19
new file mode 100644
index 0000000000000000000000000000000000000000..d451ee9953e12a986a285b76476a9bb2312116b5
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition19 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition2 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition2
new file mode 100644
index 0000000000000000000000000000000000000000..0369fbe5896965bc9d8f98d51bb297b7a089f092
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition2 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition20 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition20
new file mode 100644
index 0000000000000000000000000000000000000000..54258216b96269438e118ba3da5d7f6e5e0a9bbd
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition20 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition21 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition21
new file mode 100644
index 0000000000000000000000000000000000000000..242f96e9df8cffddc9d6c1e9675e6986cde6e8be
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition21 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition22 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition22
new file mode 100644
index 0000000000000000000000000000000000000000..ce65a57b229f7cae74d27588363056d665766c78
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition22 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition23 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition23
new file mode 100644
index 0000000000000000000000000000000000000000..e40244b1f6cf1de9430ea368f4fa176ff6f1d8b7
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition23 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition24 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition24
new file mode 100644
index 0000000000000000000000000000000000000000..6dc797ba80a1d4a69903dc9e638272c0b04bc2c3
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition24 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition25 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition25
new file mode 100644
index 0000000000000000000000000000000000000000..06f8e4162ca8727b61a2ca20aebfd9c5e8e17801
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition25 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition26 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition26
new file mode 100644
index 0000000000000000000000000000000000000000..98ec79cdfc6136b740eafc6e736b04f2bef48379
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition26 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition27 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition27
new file mode 100644
index 0000000000000000000000000000000000000000..33ece3fd74e6e886e6c17fe0f7e86b0c53e258b0
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition27 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition28 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition28
new file mode 100644
index 0000000000000000000000000000000000000000..15bc68e42bfe93d2bb3076011a04f0f00d7fcfc4
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition28 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition29 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition29
new file mode 100644
index 0000000000000000000000000000000000000000..bc5b16a428e30f44f1230d630044dcba5f9d4078
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition29 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition3 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition3
new file mode 100644
index 0000000000000000000000000000000000000000..7a6596116a6e3e95d56dfc38b64d0e9b74e47897
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition3 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition30 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition30
new file mode 100644
index 0000000000000000000000000000000000000000..6ecf2df71df409b1ecb5192755896e0fb2ed0225
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition30 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition31 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition31
new file mode 100644
index 0000000000000000000000000000000000000000..ea4e238d6c235d1eebc982f1518e2931deb71587
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition31 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition32 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition32
new file mode 100644
index 0000000000000000000000000000000000000000..3e80ec9d5136d17a5f5d42c2841a072b76a06e27
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition32 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition33 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition33
new file mode 100644
index 0000000000000000000000000000000000000000..835877d2f50dedc2b26f499a2edbb8799c5ea884
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition33 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition34 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition34
new file mode 100644
index 0000000000000000000000000000000000000000..9a58bd917ccf64e4d8d46da45df4153ba1435c1e
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition34 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition35 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition35
new file mode 100644
index 0000000000000000000000000000000000000000..9287dea25164bf18e40a857a3fbcaf74bf3ac8fc
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition35 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition36 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition36
new file mode 100644
index 0000000000000000000000000000000000000000..117d8a5c122b75f0dfb45bfe6a3b4db63d92087b
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition36 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition37 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition37
new file mode 100644
index 0000000000000000000000000000000000000000..5d938453f0f795316faa073ee3be30a12a392739
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition37 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition38 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition38
new file mode 100644
index 0000000000000000000000000000000000000000..296d39073c75c6082bf9494e3062359f2f889989
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition38 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition39 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition39
new file mode 100644
index 0000000000000000000000000000000000000000..24e4ca8ce563c353f699ec11af7ee440175e130d
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition39 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition4 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition4
new file mode 100644
index 0000000000000000000000000000000000000000..24c9b85fe35a4027201fc750d157c742037d7f32
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition4 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition40 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition40
new file mode 100644
index 0000000000000000000000000000000000000000..5cc69b4be380f083c4c0f7262763517b30f0c0e2
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition40 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition41 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition41
new file mode 100644
index 0000000000000000000000000000000000000000..97474b73598908632f3b3c93287138bc5e378f4e
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition41 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition42 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition42
new file mode 100644
index 0000000000000000000000000000000000000000..65f5c41bf1196c768568fe1f9383b5157c041a12
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition42 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition5 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition5
new file mode 100644
index 0000000000000000000000000000000000000000..ae50e8edff6f2fe39791622acac6de26376bf1db
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition5 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition6 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition6
new file mode 100644
index 0000000000000000000000000000000000000000..8767eb78a3ae993ecf1ba44b597753cd7d12800b
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition6 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition7 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition7
new file mode 100644
index 0000000000000000000000000000000000000000..92bc5e7913f006c239ebcaeb0dc470d6a720855e
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition7 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition8 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition8
new file mode 100644
index 0000000000000000000000000000000000000000..b7400df3b25d371f045dc66ee226e52a3b804a64
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition8 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition9 b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition9
new file mode 100644
index 0000000000000000000000000000000000000000..f1cbde258fd4b5909c57a557857ef90f1de18b2b
Binary files /dev/null and b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/fixtures/column_definition9 differ
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packet_parser.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packet_parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..703d4e718e6664e72308fb3f35b3659bfb42c18d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packet_parser.js
@@ -0,0 +1,47 @@
+var p = new Buffer(65535*10);
+var offset = 0;
+var plen = 17;
+while(1) {
+  if (p.length - offset >= plen+4) {
+    p[offset] = plen;
+    p[offset+1] = 0;
+    p[offset+2] = 0;
+    p[offset+3] = 123; // packet id
+    offset += plen + 4;
+  } else {
+    p[offset] = p.length - offset - 4;
+    p[offset+1] = 0;
+    p[offset+2] = 0;
+    p[offset+3] = 123; // packet id
+    break;
+  }
+}
+
+var PP = require('../../lib/packet_parser.js');
+
+var count = 0;
+var cc = 0;
+
+function handler(packet) {
+  //console.log(packet.length(), packet.sequenceId);
+  cc += packet.sequenceId
+  count++;
+}
+
+var chunks = [];
+var csize = parseInt(process.argv[2]);
+for (var o=0; o + csize < p.length; o += csize) {
+  chunks.push(p.slice(o, o+csize));
+}
+
+var start = process.hrtime();
+for (var i=0; i < 50; ++i) {
+  var packetParser = new PP(handler);
+  for (var j=0; j < chunks.length; ++j) {
+    packetParser.execute(chunks[j]);
+  }
+}
+var end = process.hrtime(start);
+var dur = end[0]*1e9 + end[1];
+
+console.log(1e9*count/dur, count, cc);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packets/column_definition.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packets/column_definition.js
new file mode 100644
index 0000000000000000000000000000000000000000..24e144730023332b9664f25cb1108d3c6023ce08
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/packets/column_definition.js
@@ -0,0 +1,56 @@
+var fs = require('fs');
+var ColumnDefinition = require('../../../lib/packets/column_definition.js');
+var Packet = require('../../../lib/packets/packet.js');
+var fixtureFile = __dirname + '/../fixtures/column_definition';
+
+function prepareFixture() {
+  var Packets = require('../../../lib/packets/index.js');
+  var packetInd = 0;
+  Packets.ColumnDefinition = function(packet) {
+    fs.writeFileSync(fixtureFile + packetInd, packet.buffer.slice(packet.start, packet.end));
+    packetInd++;
+    var c = new ColumnDefinition(packet);
+    //console.log('packet', c);
+    return c;
+  };
+  var connection = require('../../../test/common.js').createConnection();
+  connection.query('select * from mysql.user', function() {});
+  connection.end();
+}
+
+//prepareFixture();
+//return;
+
+var npackets = 43;
+var packets = [];
+var packet;
+
+for (var i=0; i < npackets; ++i) {
+  var buf = fs.readFileSync(fixtureFile + i);
+  packet = new Packet(0, buf, 0, buf.length);
+  packets.push(packet);
+}
+
+var c;
+var repeats = 10000;
+
+function bench(done) {
+  for (var i=0; i < repeats; ++i) {
+    for (var j=0; j < npackets; ++j) {
+      packets[j].offset = 0;
+      c =new ColumnDefinition(packets[j]);
+    }
+  }
+  done();
+}
+
+module.exports = bench;
+module.exports.comment = "read " + npackets + " column definitions (select * from mysql.user) x " + repeats;
+module.exports.toSpeed = function(timeAvg, timeStdev) {
+  var value = 43*repeats*1e9 / timeAvg;
+  return {
+    value: value,
+    error: value*(timeStdev / timeAvg),
+    units: 'columns/second'
+  }
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/simple/buffer-to-string.js b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/simple/buffer-to-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..2a7ccc34ca423e21b167eeada877b0f184d362e1
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/benchmarks/unit/simple/buffer-to-string.js
@@ -0,0 +1,24 @@
+var a = new Buffer(10000);
+a.fill(120); // 'x'
+var l = 5;
+var s = '';
+var repeats = 10000;
+
+module.exports = function(next) {
+  for (var n=0; n < repeats; ++n) {
+    for (var i=0; i < a.length - l; ++i) {
+      s = s.toString('utf8', i, i+l);
+    }
+  }
+  next();
+};
+
+module.exports.comment = 'read ' + l + ' chars strings from ' + a.length + ' bytes buffer x ' + repeats;
+module.exports.toSpeed = function(time, timeError) {
+  var value = 1e9*a.length*l*repeats / time;
+  return {
+    value: value,
+    error: value*(timeError/time),
+    units: 'chars/second'
+  };
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/binlog-watcher.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/binlog-watcher.js
new file mode 100644
index 0000000000000000000000000000000000000000..dcb4b0841e3290efbcbd1a30ea14c99ee6eddbce
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/binlog-watcher.js
@@ -0,0 +1,16 @@
+var mysql = require('../test/common').createConnection();
+var through2 = require('through2');
+
+var binlogStream = mysql.createBinlogStream({
+  serverId: 123, // slave ID, first field in "show slave hosts" sql response
+  // you can also specify slave host, username, password and port
+  masterId: 0,
+  filename: 'mysql-bin.000007',
+  binlogPos: 120,
+  flags: 1, // 1 = "non-blocking mode"
+});
+
+binlogStream.pipe(through2.obj(function(obj, enc, next) {
+  console.log(obj);
+  next();
+}));
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/connect-over-socks.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/connect-over-socks.js
new file mode 100644
index 0000000000000000000000000000000000000000..66ae19b2110ee26631600a8e40796f9310b3f0e7
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/connect-over-socks.js
@@ -0,0 +1,33 @@
+var SocksConnection = require('socksjs');
+var mysql = require('../index.js');
+
+//var socksProxy = new SocksConnection({ port: 3306 });
+//var conn = mysql.createConnection({
+//  stream: socksProxy,
+//});
+
+//conn.query("select 1+1", function(err, rows, fields) {
+//  console.log(err, rows, fields);
+//});
+
+
+var conn1 = mysql.createPool({
+  debug: 1,
+  stream: function() {
+    return new SocksConnection({ port: 3306 });
+  }
+});
+
+
+conn1.execute("select sleep(1.1) as www", function(err, rows, fields) {
+  console.log(err, rows, fields);
+});
+
+
+conn1.execute("select sleep(1) as qqq", function(err, rows, fields) {
+  console.log(err, rows, fields);
+});
+
+conn1.execute("select sleep(1) as qqq", function(err, rows, fields) {
+  console.log(err, rows, fields);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/execute.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/execute.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc88892febfc5690bd0165aaa06cc7e4e9c04dc0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/execute.js
@@ -0,0 +1,12 @@
+var mysql = require('../test/common').createConnection();
+mysql.execute("select ?+1 as qqq, ? as rrr, ? as yyy", [1, null, 3], function(err, rows, fields) {
+//mysql.execute("select ?+?+? as qqq, ? as rrr", [1, 2, 5, "test"], function(err, rows, fields) {
+  console.log(err, rows, fields);
+  mysql.execute("select ?+1 as qqq, ? as rrr, ? as yyy", [3, null, 3], function(err, rows, fields) {
+    console.log(err, rows, fields);
+    mysql.unprepare("select ?+1 as qqq, ? as rrr, ? as yyy");
+    mysql.execute("select ?+1 as qqq, ? as rrr, ? as yyy", [3, null, 3], function(err, rows, fields) {
+      console.log(err, rows, fields);
+    });
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/mysqlproxy.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/mysqlproxy.js
new file mode 100644
index 0000000000000000000000000000000000000000..eeaa776f9e9788d23c7974c0c8597490a046658a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/mysqlproxy.js
@@ -0,0 +1,45 @@
+var mysql = require('../index.js');
+
+var server = mysql.createServer();
+server.listen(3307);
+server.on('connection', function(conn) {
+  console.log('connection');
+
+  conn.serverHandshake({
+    protocolVersion: 10,
+    serverVersion: 'node.js rocks',
+    connectionId: 1234,
+    statusFlags: 2,
+    characterSet: 8,
+    capabilityFlags: 0xffffff
+  });
+
+  conn.on('field_list', function(table, fields) {
+    console.log('field list:', table, fields);
+    conn.writeEof();
+  });
+
+  var remote = mysql.createConnection({user: 'root', database: 'dbname', host:'server.example.com', password: 'secret'});
+
+  conn.on('query', function(sql) {
+    console.log('proxying query:' + sql);
+    remote.query(sql, function(err) { // overloaded args, either (err, result :object) 
+                                      // or (err, rows :array, columns :array)
+      if (Array.isArray(arguments[1])) {
+        // response to a 'select', 'show' or similar
+        var rows = arguments[1], columns = arguments[2];
+        console.log('rows', rows);
+        console.log('columns', columns);
+        conn.writeTextResult(rows, columns);
+      } else {
+        // response to an 'insert', 'update' or 'delete' 
+        var result = arguments[1];
+        console.log('result', result);
+        conn.writeOk(result);
+      }
+    });
+  });
+
+  conn.on('end', remote.end.bind(remote));
+});
+
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/pass-sha.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/pass-sha.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee585ff7b90c2d7745630b9268bfee3aaded967a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/pass-sha.js
@@ -0,0 +1,8 @@
+var mysql = require('../index.js').createConnection({
+  user: 'testuser',
+  //password: 'testpassword'
+  passwordSha1: Buffer('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex')
+});
+mysql.execute("select ?+1 as qqq, ? as rrr, ? as yyy", [1, null, 3], function(err, rows, fields) {
+  console.log(err, rows, fields);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/pool-test.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/pool-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa13446e7281db0b9b6b1e7b8765fdbcd0359d91
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/pool-test.js
@@ -0,0 +1,12 @@
+var pool = require('../test/common').createPool();
+
+setInterval(function() {
+for (var i=0; i < 5; ++i) {
+  pool.getConnection(function(err, db) {
+    db.query("select sleep(0.5) as qqq", function(err, rows, fields) {
+      console.log(rows, fields);
+      db.end();
+    });
+  });
+}
+}, 1000);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/prepare.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/prepare.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f1f5bb3aeefe4fd2493570a9ee2a007b43d6156
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/prepare.js
@@ -0,0 +1,5 @@
+var mysql = require('../test/common').createConnection();
+
+mysql.prepare("SELECT * from mysql.user into outfile '/tmp/mysql.user.txt'", function(err, stmt) {
+    console.log(stmt);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/server.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/server.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa6425692cade0ab1aa3b5cc1ccdaa5648463a25
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/server.js
@@ -0,0 +1,57 @@
+var mysql = require('../index.js');
+var flags = require('../lib/constants/client.js');
+var auth  = require('../lib/auth_41.js');
+
+function authenticate(params, cb) {
+  console.log(params);
+  var doubleSha = auth.doubleSha1('pass123');
+  var isValid = auth.verifyToken(params.authPluginData1, params.authPluginData2, params.authToken, doubleSha);
+  if (isValid)
+    cb(null);
+  else
+    // for list of codes lib/constants/errors.js
+    cb(null, { message: 'wrong password dude', code: 1045});
+}
+
+var server = mysql.createServer();
+server.listen(3333);
+server.on('connection', function(conn) {
+
+  // we can deny connection here:
+  // conn.writeError({ message: 'secret', code: 123 });
+  // conn.close();
+  conn.serverHandshake({
+    protocolVersion: 10,
+    serverVersion: '5.6.10', //'node.js rocks',
+    connectionId: 1234,
+    statusFlags: 2,
+    characterSet: 8,
+    capabilityFlags: 0xffffff,
+    authCallback: authenticate
+  });
+
+  conn.on('field_list', function(table, fields) {
+    console.log('FIELD LIST:', table, fields);
+    conn.writeEof();
+  });
+
+  conn.on('query', function(query) {
+    conn.writeColumns([{
+      catalog: 'def',
+      schema: 'test',
+      table: 'test_table',
+      orgTable: 'test_table',
+      name: 'beta',
+      orgName: 'beta',
+      characterSet: 33,
+      columnLength: 384,
+      columnType: 253,
+      flags: 0,
+      decimals: 0
+    }]);
+    conn.writeTextRow(['test тест テスト փորձարկում পরীক্ষা kiểm tra ']);
+    conn.writeTextRow(['ტესტი પરીક્ષણ  מבחן פּרובירן اختبار परीक्षण']);
+    conn.writeEof();
+    conn.close();
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/simple-select.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/simple-select.js
new file mode 100644
index 0000000000000000000000000000000000000000..df47d385d4e9c590b521b8e1afe86a434473aa46
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/simple-select.js
@@ -0,0 +1,5 @@
+var mysql = require('../test/common').createConnection();
+
+mysql.query("select * from foos limit 10", function(err, rows, fields) {
+    console.log(rows, fields);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-cert.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..6e0a83b008c6ae05073cc4dfb763c7d80980c08e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIJALO3/a+fdsicMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTMwNDMwMDEzNTUwWhcNMTYwMTI1MDEzNTUwWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxFrsDfgxd5fb053eVqZ1a+iVVxoOkTl9f97BhIuUp3GE82UBMXQdL4Ec
+gc3oQ56dEokvz9ghYn60cUBaH5sVjzm3qO3HYsHhA/nYoVa7U9TrSGhv3hWyqo48
+wWKHBYea325tcO2h9QanLFsnc1aauv8qGeWoa91lrfsT9G3nFdpiw587Nk+7NkKR
+MhEbAf84qoTmcxo6hqOrqEZwhIozuiF0+oNNfj/Tmcd5517WJfWLAHjLPpBmc7Yw
+vJqYqk7OK/BkX6NVx8OxcxcejvuosoZRbVK3Tuk+5N2AddncxU5Eq2kGVr890xTg
+ZVwUFF4TRkenDKe3ez2DvlRDnuFzjQIDAQABo4GnMIGkMB0GA1UdDgQWBBQd7DqN
+xTmSuT3f82DP13asHrqHIjB1BgNVHSMEbjBsgBQd7DqNxTmSuT3f82DP13asHrqH
+IqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJALO3/a+fdsicMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAA9+kUPZ7PfvD0SkgMnGXqnL2EPUPsgo
+bRwciPx5E/SqoEczfYip+IcWAxRnifkFGXAzBq6w3GmGaJqG95vV5noj+md7KE2m
+t8dxwGlOYP2H0oEubfrz6AHOcMDF68N2hmA4K0zj+Ag9XCJxN41vzaPgLuvNmDqB
+O16Qh47CNoKtpEFZ4g6Yp3rErzhGVSLgLh2NmDzi6Vd78mmy454euLDTcbCnlKsA
+kXvt8KCYacYNNV0m8mLYqPylJUZNvtFE4mAo35Uzbw6NawkWd+Aqx8UJCsQDhWWw
+5T+24NcfiAs+Wqg3UvuzXlOZB721nmqgIYIcjyumMewGE/y1xLschIQ=
+-----END CERTIFICATE-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-key.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-key.pem
new file mode 100644
index 0000000000000000000000000000000000000000..76ba872fd585e03ebc0c3971f3b3a34ba5f2b4eb
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/ca-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAxFrsDfgxd5fb053eVqZ1a+iVVxoOkTl9f97BhIuUp3GE82UB
+MXQdL4Ecgc3oQ56dEokvz9ghYn60cUBaH5sVjzm3qO3HYsHhA/nYoVa7U9TrSGhv
+3hWyqo48wWKHBYea325tcO2h9QanLFsnc1aauv8qGeWoa91lrfsT9G3nFdpiw587
+Nk+7NkKRMhEbAf84qoTmcxo6hqOrqEZwhIozuiF0+oNNfj/Tmcd5517WJfWLAHjL
+PpBmc7YwvJqYqk7OK/BkX6NVx8OxcxcejvuosoZRbVK3Tuk+5N2AddncxU5Eq2kG
+Vr890xTgZVwUFF4TRkenDKe3ez2DvlRDnuFzjQIDAQABAoIBAQDDQW7PDWmTdU1C
+CBCatfi6D5TCAsVNoI+t4kMpnOt7/qSorF4dYUvMe2VvpuQ6qbWkQwtqcY/xM/IX
+VFjKaRttS4XY1GqbSBSMMZ08AtVRLb+yRzhG7ei3Na4w19tQomJdoJ/v1j5hO/Zt
+Y0+9n/dJ0Id7LSbn7Ec6VRyoyckrrjmikw/y91UU/Xi3u2/64rJY+vbH2h090Ztg
+MNt39v+VbengJ4vS/VbDk6qPv4CGUYWYfbz4ekRK0/xLWKW9vAu8KcN1iewmEyeH
+W16686qKrhwDlCXYpZcTBnHB+QCxNfPRFJpfXzXSTCTY9aId79skCnEzBlUshKrV
+6mYzlFcBAoGBAPIn62Gc7uRWCQkQaP05pjI4/v0I8ggvVfDwAyxY7QowLQXRT49O
+zohCLtJFYN5Zd01hAgdrNl6QdtBF+rQEoKFKMRY8BI8G+lz6KHX5K37mAip/VjIl
+a6sUUKu5lYOPqouDuAPoO1VRWulVPOx18/8s+vtk9OV3M+01vMBewXptAoGBAM+U
+rx5Plg7qBPtLGTXCTbUHcvKKY2HdUHlzJjj8zcV8e6012GWcRblL4XmaxZTpS177
+JIDBPuhXDKjUwYemV1VBQlvh94f1ArDgh9+MEdYypYPvRDAzOg+Q3EGBW11zfYF9
+EqiWFud4vSZ4zFQgeg3cfCRIsXXfc3CDpzeV+CmhAoGBAJGeM8ulRXsFybUrqxbr
+vedhouSipnkJjhKvIhle+FwyEED5V3CEIWqK8gD8O346KqXbeg7gB/fhw7EHA/WQ
++s9DADWwrcUcmx2iSQZ4ahGLWy4XGMxa+F4Of1xk42YT1KjE8rlWw6dQnuzFlzdS
+zwFaGStn0GTUw+MXd4Pu90YZAoGAWlPS2Be9roO64zbMo44HjmzNYilCEcXiTNcE
+nOu1BuiiUL8LiTu1Q2p3lRj6PVA/Ufdq7PQqUaP/iD/8bvC9NAYPwDfWJL1DDIDH
+30juQg0L5Rtqyqaf70IT9hU6ErI8vOoWAnI9SUBK3sDV+Q2gzwNQqeFQB4DSlPVV
+AGUr9cECgYARilqjaF8Ns3ilS3r3IEZ8I2wPAei/P9PCtkwkUsVpZ2+/SHxFAJkf
+CaPVXdHMHkRXQUf1a+fAEYWiDnFnTaWXg/HyCt1V+Rr7g5eXsN+GwoeQ5Rywzi7m
+K6atiYVINfvpNcN73dO7mB4jXgTNCh0K8ru9lf2nKgPzjd0muNDBww==
+-----END RSA PRIVATE KEY-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-cert.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..288be5cee777d8fb4b145a17638dd7ab0735e337
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-cert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
+ZDAeFw0xMzA0MzAwMTM1NTVaFw0xNjAxMjUwMTM1NTVaMEUxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
+IFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCa+f+OWaOI
+1W6HaBZ5Ch0fW9SKrv7Uz/mzAAGFer7+0KNF7JC0/WtK1lz0oBuYqt6wZQmIO0at
+6RP55Uxyj5Zf8C2jyHPU2iAUYcV/QTBXw0JNXCV0v+NeNjmh7/Tngj5l7nfdebLz
+4oooQ3OlN3wbbHSd4UNmMhCQKNVFGS3nOp1q7C3QXuJJuq5zOXE6T6DO43zLo3HG
+JEGjtkXA8oFWW2wIKrhxJlNLxaW70UrLMxBCLJ2hI0MITYsYSA5aPw+EZ0rrkGc9
+qaagpWYR7Yu//i78XOK1p8wgtZTlHY4akWMCRMUEkcKpiMLxrTyBijG/4jrYuxdJ
++ZnIYWKkjYevAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEl6Yw2X2tJhHV8Wut+1
+YWXYuuYV/JbPx1KJLWl78eFnnZfzdCkSzywv9ThW2xSehIH2anfb8HxrvypVa1/r
+EUcgy8kMzoa9ZcPXs0Ol/hCEsYYQZ/rXgXtPjaIb92kznKXhLckAKpChx8LxeSYc
+TZ6DVdhT+sWwSy/DetzavAq8QGFRyYL88bxibSgiBGRw7i5sWk5/T6dpx322MbtK
+FMPv3K5Mt0b3eBsegcjTvFqJAPBADB/WVLUsp+ESruFTcWGf8H91aoiWhZspEHjt
+j2XD/nlkC44t3RU8YNx2jAxj9HhG7QHfwsY9CDSwmnKtpUhvGUrGkp98Q/dUMbds
+NP0=
+-----END CERTIFICATE-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-key.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-key.pem
new file mode 100644
index 0000000000000000000000000000000000000000..d6134fd3f7662e8f7aa2866911bce6431c93eb9e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAmvn/jlmjiNVuh2gWeQodH1vUiq7+1M/5swABhXq+/tCjReyQ
+tP1rStZc9KAbmKresGUJiDtGrekT+eVMco+WX/Ato8hz1NogFGHFf0EwV8NCTVwl
+dL/jXjY5oe/054I+Ze533Xmy8+KKKENzpTd8G2x0neFDZjIQkCjVRRkt5zqdauwt
+0F7iSbquczlxOk+gzuN8y6NxxiRBo7ZFwPKBVltsCCq4cSZTS8Wlu9FKyzMQQiyd
+oSNDCE2LGEgOWj8PhGdK65BnPammoKVmEe2Lv/4u/FzitafMILWU5R2OGpFjAkTF
+BJHCqYjC8a08gYoxv+I62LsXSfmZyGFipI2HrwIDAQABAoIBAQCXqKrEHUiB8Yu2
+is/jJ1iUhYMbLGFI1TXgS9MxUotyRa5iET0TQSQsGlbhNYWMAzrlmBqZ7JggPIVF
++XS0b3uS6zFepB1mYQcfqwZgn+S1HenWVqR4+geA/MOti2s42yZBDfrTC/Np43mc
+KVYUipWzKJF+pyET805uJOeANUHMkvP6So066akZgi+bAdIpNu0hvvq04KUbPNfE
+c4XdT7CKZnNSHhgfXBLN+H10wfIKnL916qJtOaRERZmM/M/LQRJRrSZTTKZWwMHg
+5eBdYLI3+/eYeNriLlWVAEMXuUN7TueJFzePuTe5TRdVHkHbBvQTliIvr+udu4MV
+FGMTrfchAoGBAMjUuoF8X5dPtu3eHCrGsg787hPdSn9jDhOYoKKTAj8Ft7Rnl5X3
+twLfeTtBhrPpo0KYOYkO2bETb0xXp1hUAfOGTl/jy1LREqHUxKPnaEpO5CbJMzwq
+rhAIR4ZgQcqxHkBbUJd+lLptnWbw9LxiysEVrHwRyKH39ZdbJTM4KZU3AoGBAMWM
+mJRhYbPpiDLRiskFqEou9qU+zjq1RlbI6fWoz5+8K6A3zfBHE1J1ZvqF6tvOeoDx
+HLY5vIwlIKy8XwmTwUQvd9TTuRD+ZnY9gUoPgDhEK8fSJeSb2OqZyKBwATM7Q9Cn
+5pyTOsTkmlm4AKpczoAJ3WUmRmvYeT+uGfXU611JAoGAGEkJKKFWmeCM2WTTeSS/
+4WoajBJlcNQUnrAFNMOcMOzLEyi3vu3Olq1ZZp384QKuuF3aD0XZcz1LZyruVJMM
+DVu/XH8aVjBsFV+6S6uvA9VYZ4xLAsqSc+PcalZ3fkA+zT99lmQ7LfQVZZ5bqfA0
+Xnb1fadU4KkwbJYcAH6ZIK8CgYAVVp14kZhDHbuXeajbE+BcuvvrV4BhOQlzAFq9
+LVHX+DRiJwT4qkS9CG9qKiL3QTNcUC8Aw/XI0Y3Y+rPtTed3XQU9mO0Jl+ErbnNT
+s57u9PYhrGJpcigZFyljoxWOGh22IRy41vJnKCZAAK8Zt9KaY/ZlIaBDr+tQ5JZr
+Rmdx+QKBgAI/n9g6Gf32skdVsM8ydyZbmUmU2EarGPLKtwv6rDljZekrX+ZQouJU
+Wh0Wl7BZGoWScJGlcuNoeewalGY/GrAavaN0YvoyhCkIbeD/B53/bzsMTUvnDHk4
+sxT7ieigYTYabCbpr+g1687ydpEoU7GopE6u3xlmuhj3+HoR825c
+-----END RSA PRIVATE KEY-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-req.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-req.pem
new file mode 100644
index 0000000000000000000000000000000000000000..9229af320aed28215b146044b4a49f6591001b18
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/client-req.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
+ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAJr5/45Zo4jVbodoFnkKHR9b1Iqu/tTP+bMAAYV6
+vv7Qo0XskLT9a0rWXPSgG5iq3rBlCYg7Rq3pE/nlTHKPll/wLaPIc9TaIBRhxX9B
+MFfDQk1cJXS/4142OaHv9OeCPmXud915svPiiihDc6U3fBtsdJ3hQ2YyEJAo1UUZ
+Lec6nWrsLdBe4km6rnM5cTpPoM7jfMujccYkQaO2RcDygVZbbAgquHEmU0vFpbvR
+SsszEEIsnaEjQwhNixhIDlo/D4RnSuuQZz2ppqClZhHti7/+Lvxc4rWnzCC1lOUd
+jhqRYwJExQSRwqmIwvGtPIGKMb/iOti7F0n5mchhYqSNh68CAwEAAaAAMA0GCSqG
+SIb3DQEBBQUAA4IBAQATmAC1QQqi5DWnhtHhKCFORpclZLwNqQJR+wpMZ00Ajt3r
++jSJo/1j9Ecys1niia79y6iyiTqTJDVEmkP+9Wmgols1bMMYZIcbnb09m1G4kCuJ
+Axg6ktJ/Dt5R5Gp3JiejBdimAwUJq1gZ7ywcXeV0LnZVpPBz1J1cfWkfP3vMcbqv
+qufWq1JOQK0VxfhQqay0CZK4+LCoMaEgWPJCZoC7Eqw5KQKEBERhwETGYHF7wlgG
+lqEgWL+aym5su+EW8nFRLJ8pdr9CW+pTaYZw28w34oIx8PYUNgwJ5uIawqZA7IuZ
+dST/6A4nD04kJcs7KnPbLCRpRyvdqHiy+7xBd9SJ
+-----END CERTIFICATE REQUEST-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/mkcerts.sh b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/mkcerts.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7e2d9fc7bedebe6caa96794e3d6c27c86eaf7ccf
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/mkcerts.sh
@@ -0,0 +1,6 @@
+openssl genrsa 2048 > ca-key.pem
+openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem
+openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem > server-req.pem
+openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
+openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem > client-req.pem
+openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-cert.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..94b495b487153c259a345ae1143b49bdc362b77d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-cert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
+ZDAeFw0xMzA0MzAwMTM1NTJaFw0xNjAxMjUwMTM1NTJaMEUxCzAJBgNVBAYTAkFV
+MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
+IFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqqHgScXj4
+koJQeURbPss1yAqiByb4Ub/ggNP4+ZQXdoXX+kBKoCXstPHvNwBQlg+m8a4g/x9g
+Vj0gKL2nEo+CcIyNHjea728n1xTBHlpSesWqDsbdSMD6sgDl07hCVS4QAjt8a521
+pf4kKbv44Wa9ntpGPmLX7BFxLyN8LBsfTa+noYKxlQK9WJAbP7oL5bza4Uf84Iwg
+BEXkku7RRyw48S9RFIEMjIIyUvhS1YIJW57F9rcqaMerdd5BQYcgzpfESbtayWkJ
+Es89TgbvoD5njii7EFGgCB5DQfCbgOImJPRHNPHYj4iqGXitFKZO6uxUCyceodxV
+KOM/LKZvJKFNAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBALSFOwPrNEyQg1Wp/WkW
+BJACqNsnWJKnackSfjS6N4GwH8MOQgAgRwXx3RgpOHUgTnt6KiEQMI40tuHXU8A9
+JNC9XdX7x/EEqny+ZCpVd4P5CzXAJEiZ63WtmEUnjBRQiFxBsgh88cUnXFfIAGEa
+jgudFMmVS/tz+UQgciu2FAWkfcCPH1z3fUmxBjrcX9iOCuJXohk2G7qmawfpCkaW
+RFo6dBl3u8sEo5+/KeFtl0EmLRD9yMOx1XPoT9oVcpis/XxTkvPxS7hAHHc5ZIBq
+w8f5NX/7jTiHJI4k1/mfyrDJMCwJPMzRlTppKSdwEylII5b8SmAaGjGvOiNi/7EX
+v90=
+-----END CERTIFICATE-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-key.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-key.pem
new file mode 100644
index 0000000000000000000000000000000000000000..c24f872708fbe88de8be6a497f7e6a07ab9e133b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAqqh4EnF4+JKCUHlEWz7LNcgKogcm+FG/4IDT+PmUF3aF1/pA
+SqAl7LTx7zcAUJYPpvGuIP8fYFY9ICi9pxKPgnCMjR43mu9vJ9cUwR5aUnrFqg7G
+3UjA+rIA5dO4QlUuEAI7fGudtaX+JCm7+OFmvZ7aRj5i1+wRcS8jfCwbH02vp6GC
+sZUCvViQGz+6C+W82uFH/OCMIARF5JLu0UcsOPEvURSBDIyCMlL4UtWCCVuexfa3
+KmjHq3XeQUGHIM6XxEm7WslpCRLPPU4G76A+Z44ouxBRoAgeQ0Hwm4DiJiT0RzTx
+2I+Iqhl4rRSmTursVAsnHqHcVSjjPyymbyShTQIDAQABAoIBAHMqu9UedJezL3Ql
+UicNik9iDyLnFrpvWMClz+bubq0i1BI7lJWH2/AQ8FAR2wmHK0rrQCqOYNs/d4Kz
+W8Fa+jP5xjAZm0bYnDfTovLsi+Grbqdjz3pX9bt40rhGl8tT9oDhMMm3SjfirE41
+R+AeJJqEkCLlSQkUC3VJbXYHwcnuJhkVVxsRtNeIE9d5DSOoXuPjAnQjmS5zUBLz
+JlA2a5bTLeENfcUL8Jr7WhxWIyIAFBY4ewpg7sbVmMnir3VD315OeowYMQpk/AaC
+AiwDA1kJCYoKUCAuizSAS3I5WNFeqZfbhWskdct6MphcMrMsLWvqLtXvLImU+lgX
+Z9rJHDUCgYEA1R3+p8WQ/YKppJb/klRMtWLnXHLlTan2YfDxmcLGC9zHro24uAL3
+SpuXivKzSKX8BGA+9lzSnWndX7PK5fi2UMnMAxNNE6Cxu0S+yjras92B+DMjiPRf
+lk7trtyXhYjoxPQE8cCxfbKkl6uLYCKyi9JQwygyOPhEUDkZRcyNVusCgYEAzP9W
+zqALi7ay0Dizu5ZXRsehQKw4ElMuvHHjt4r16aW7pe8ydqkmsm3Qk8VwfblqZFyU
+ndSzWU+SguuD2pUz5re6wLKrZFIicirNS6m88AmCjTUQ5W+FBHpvkQCQWsN5ykfy
+KAdfEJlZoInLYdU9Z1GueUk/4EBpToNFz7kzSqcCgYEAlrebvPLP0zlw1+Gh5M6R
+YUYM8SigWgh1IlbPxjok7Ya6AQxhMmGGmdDnn3B8skgQrteSL5D9si2ITYJNX85A
+wWm1SgeAXv0qNJIti7+Lo+BnZixkWRrZ7ubq2NtQnTNxyrf4NzBbVdXc6RZ8fwSK
+2K9oRlxLCFcrmMCIywAahPkCgYEAwK0mTCNFdtYLj4Yb+K6/7Xjo6T51nVOt09U/
+8V2c8TSjAL2oMrud8YshxiKHLsQ9aYNS9F3dDI6r6H2wepxOIgaCc2f7i9lfIutz
+9i/ds8dce5hq/xsobSMfBa0AAS9Fo4in5FO5WIKqKSgajyO8CQZO9RSSAxbHY9Ii
+pbEusnUCgYBzVXEFSload51C82XgvwjwcayrKrGBq+5/K/N5xMGBxuObu2vWA3ks
+MSTU2tXUiwpApY51v+88JGBHwI6+3EGRGEow09S0MlsHxjAG+MCz5Fj+nhoIJk78
+I/E+FGjJW+otrrz8rLi8bz+t3QTtB7rTiKMMpmIIIwG8OacUQPr82g==
+-----END RSA PRIVATE KEY-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-req.pem b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-req.pem
new file mode 100644
index 0000000000000000000000000000000000000000..5d44838f5315fb35e4f7be9ec6b47cfacac90210
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/certs/server-req.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
+ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKqoeBJxePiSglB5RFs+yzXICqIHJvhRv+CA0/j5
+lBd2hdf6QEqgJey08e83AFCWD6bxriD/H2BWPSAovacSj4JwjI0eN5rvbyfXFMEe
+WlJ6xaoOxt1IwPqyAOXTuEJVLhACO3xrnbWl/iQpu/jhZr2e2kY+YtfsEXEvI3ws
+Gx9Nr6ehgrGVAr1YkBs/ugvlvNrhR/zgjCAEReSS7tFHLDjxL1EUgQyMgjJS+FLV
+gglbnsX2typox6t13kFBhyDOl8RJu1rJaQkSzz1OBu+gPmeOKLsQUaAIHkNB8JuA
+4iYk9Ec08diPiKoZeK0Upk7q7FQLJx6h3FUo4z8spm8koU0CAwEAAaAAMA0GCSqG
+SIb3DQEBBQUAA4IBAQCDtIfTr/LmuFYkuxt1bPj79AOmbONQrwOFP6szeBL44jJf
+jaIH4gDWy70zhaZ4FmnskV4TbdEK5ENoW2Rif87JGex2yL+vzdKigRX0TzUYFA0x
+IqzR/sx0iMV3EsW3qYPRq/QJErvD5rL1KA6J+nHMeZiRFRF34XaoVHk4zaFDM+J5
+rjMy8GnRS7lqBe31zuqLfU2I9Bwq2InpYMw1Pf+boarZiIwmfMtiHbb5Aap1lMh0
+u1WKfiuB6CqXtyXFJR5PJTwO581yuINByzKlZZyXUpP4MbargPc5f1thf3tKndgB
+3GG1gmMsl/cUQ7XBdBH2WXCuipt0mflWj8qKylUA
+-----END CERTIFICATE REQUEST-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/client-flags.sh b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/client-flags.sh
new file mode 100644
index 0000000000000000000000000000000000000000..04e1cf231e8e77c59546abe49f615ac3acf4567a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/client-flags.sh
@@ -0,0 +1 @@
+mysql --ssl-key=certs/client-key.pem --ssl-cert=certs/client-cert.pem -h 127.0.0.1 -P 3307
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/rds-ssl.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/rds-ssl.js
new file mode 100644
index 0000000000000000000000000000000000000000..4454d3d48f4c4e07aff48db496cc1ab6da102638
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/rds-ssl.js
@@ -0,0 +1,16 @@
+var fs = require('fs');
+var mysql = require('../../index.js');
+
+var conn = mysql.createConnection({
+   user: process.env.USER,
+   password: process.env.PASSWORD,
+   database: process.env.DB,
+   host: process.env.HOST,
+   port: 3306,
+   ssl: 'Amazon RDS'
+});
+
+conn.query('show status like \'Ssl_cipher\'', function(err, res) {
+  console.log(err, res);
+  conn.end();
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/select-over-ssl.js b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/select-over-ssl.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0a1e99ae3f928d1bab3bc16bbe0a43fdd24ee65
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/examples/ssl/select-over-ssl.js
@@ -0,0 +1,21 @@
+var fs = require('fs');
+var mysql = require('../../index.js');
+var conn = mysql.createConnection({
+   user: 'root',
+   password: '',
+   database: 'test',
+   host: '127.0.0.1',
+   port: '3306',
+   ssl: {
+     //key: fs.readFileSync('./certs/client-key.pem'),
+     //cert: fs.readFileSync('./certs/client-cert.pem')
+     ca: fs.readFileSync('./certs/ca-cert.pem')
+   }
+});
+
+conn.query('select 1+1 as test', function(err, res) {
+  console.log(res);
+  conn.query('select repeat("a", 100) as test', function(err, res) {
+    console.log(res);
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/fixtures/mysql-ssl-ca-cert.pem b/node_modules/mysql2-promise/node_modules/mysql2/fixtures/mysql-ssl-ca-cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..8b54fd29447e63ac6b95e9c31e2c146a37828f30
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/fixtures/mysql-ssl-ca-cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAqygAwIBAgIJAOd1tlfiGoEoMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRMw
+EQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNSRFMxHDAaBgNVBAMTE2F3cy5h
+bWF6b24uY29tL3Jkcy8wHhcNMTAwNDA1MjI0NDMxWhcNMTUwNDA0MjI0NDMxWjB1
+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh
+dHRsZTETMBEGA1UEChMKQW1hem9uLmNvbTEMMAoGA1UECxMDUkRTMRwwGgYDVQQD
+ExNhd3MuYW1hem9uLmNvbS9yZHMvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQDKhXGU7tizxUR5WaFoMTFcxNxa05PEjZaIOEN5ctkWrqYSRov0/nOMoZjqk8bC
+med9vPFoQGD0OTakPs0jVe3wwmR735hyVwmKIPPsGlaBYj1O6llIpZeQVyupNx56
+UzqtiLaDzh1KcmfqP3qP2dInzBfJQKjiRudo1FWnpPt33QIDAQABo4HaMIHXMB0G
+A1UdDgQWBBT/H3x+cqSkR/ePSIinPtc4yWKe3DCBpwYDVR0jBIGfMIGcgBT/H3x+
+cqSkR/ePSIinPtc4yWKe3KF5pHcwdTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
+c2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxEzARBgNVBAoTCkFtYXpvbi5jb20x
+DDAKBgNVBAsTA1JEUzEcMBoGA1UEAxMTYXdzLmFtYXpvbi5jb20vcmRzL4IJAOd1
+tlfiGoEoMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAvguZy/BDT66x
+GfgnJlyQwnFSeVLQm9u/FIvz4huGjbq9dqnD6h/Gm56QPFdyMEyDiZWaqY6V08lY
+LTBNb4kcIc9/6pc0/ojKciP5QJRm6OiZ4vgG05nF4fYjhU7WClUx7cxq1fKjNc2J
+UCmmYqgiVkAGWRETVo+byOSDZ4swb10=
+-----END CERTIFICATE-----
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/index.js b/node_modules/mysql2-promise/node_modules/mysql2/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6509cde879fb016cb4a3ab5814512d28d590210c
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/index.js
@@ -0,0 +1,32 @@
+var Connection       = require('./lib/connection.js');
+var ConnectionConfig = require('./lib/connection_config.js');
+var SqlString        = require('./lib/sql_string.js');
+
+module.exports.createConnection = function(opts) {
+  return new Connection({config: new ConnectionConfig(opts)});
+};
+
+module.exports.connect = module.exports.createConnection;
+
+module.exports.Connection = Connection;
+module.exports.Types      = require('./lib/constants/types.js');
+
+module.exports.createPool = function(config) {
+  var PoolConfig = require('./lib/pool_config.js');
+  var Pool       = require('./lib/pool.js');
+  return new Pool({config: new PoolConfig(config)});
+};
+
+exports.createPoolCluster = function(config) {
+  var PoolCluster = require('./lib/pool_cluster.js');
+  return new PoolCluster(config);
+};
+
+module.exports.createServer = function() {
+  var Server = require('./lib/server.js');
+  return new Server();
+};
+
+exports.escape   = SqlString.escape;
+exports.escapeId = SqlString.escapeId;
+exports.format   = SqlString.format;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/auth_41.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/auth_41.js
new file mode 100644
index 0000000000000000000000000000000000000000..f55df869c5e45ca7f8008460305bb1ccd7e7c287
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/auth_41.js
@@ -0,0 +1,75 @@
+/*
+4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
+
+  SERVER:  public_seed=create_random_string()
+           send(public_seed)
+
+  CLIENT:  recv(public_seed)
+           hash_stage1=sha1("password")
+           hash_stage2=sha1(hash_stage1)
+           reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
+
+           // this three steps are done in scramble()
+
+           send(reply)
+
+
+  SERVER:  recv(reply)
+           hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
+           candidate_hash2=sha1(hash_stage1)
+           check(candidate_hash2==hash_stage2)
+
+server stores sha1(sha1(password)) ( hash_stag2)
+*/
+
+var crypto = require('crypto');
+
+function sha1(msg, msg1, msg2) {
+  var hash = crypto.createHash('sha1');
+  hash.update(msg);
+  if (msg1)
+    hash.update(msg1);
+  if (msg2)
+    hash.update(msg2);
+  return hash.digest();
+}
+
+function xor(a, b) {
+  if (!Buffer.isBuffer(a))
+    a = new Buffer(a, 'binary');
+  if (!Buffer.isBuffer(b))
+    b = new Buffer(b, 'binary');
+  var result = new Buffer(a.length);
+  for (var i = 0; i < a.length; i++) {
+    result[i] = (a[i] ^ b[i]);
+  }
+  return result;
+}
+
+function token(password, scramble1, scramble2) {
+  // TODO: use buffers (not sure why strings here)
+  if (!password) {
+    return new Buffer(0);
+  }
+  var stage1 = sha1(password);
+  return module.exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
+}
+
+module.exports.calculateTokenFromPasswordSha = function(passwordSha, scramble1, scramble2) {
+  var stage2 = sha1(passwordSha);
+  var stage3 = sha1(scramble1, scramble2, stage2);
+  return xor(stage3, passwordSha);
+};
+
+module.exports.calculateToken = token;
+
+module.exports.verifyToken = function(publicSeed1, publicSeed2, token, doubleSha) {
+  var hashStage1 =xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
+  var candidateHash2 = sha1(hashStage1);
+  // TODO better way to compare buffers?
+  return candidateHash2.toString('hex') == doubleSha.toString('hex');
+}
+
+module.exports.doubleSha1 = function(password) {
+  return sha1(sha1(password));
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/binlog_dump.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/binlog_dump.js
new file mode 100644
index 0000000000000000000000000000000000000000..6812c2b0158aac6494e38a3125672b0ac1a828d9
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/binlog_dump.js
@@ -0,0 +1,104 @@
+var Command  = require('./command');
+var util    = require('util');
+var CommandCode = require('../constants/commands');
+var Packets = require('../packets');
+
+function BinlogDump(opts)
+{
+  Command.call(this);
+  //this.onResult = callback;
+  this.opts = opts;
+}
+util.inherits(BinlogDump, Command);
+
+BinlogDump.prototype.start = function(packet, connection) {
+  var packet = new Packets.BinlogDump(this.opts);
+  connection.writePacket(packet.toPacket(1));
+  return BinlogDump.prototype.binlogData;
+};
+
+function BinlogEventHeader(packet) {
+  this.timestamp = packet.readInt32();
+  this.eventType = packet.readInt8();
+  this.serverId  = packet.readInt32();
+  this.eventSize = packet.readInt32();
+  this.logPos    = packet.readInt32();
+  this.flags     = packet.readInt16();
+}
+
+function RotateEvent(packet) {
+  this.pposition = packet.readInt32();
+  // TODO: read uint64 here
+  var positionDword2 = packet.readInt32();
+  this.nextBinlog = packet.readString();
+  this.name = 'RotateEvent';
+}
+
+function FormatDescriptionEvent(packet) {
+  this.binlogVersion = packet.readInt16();
+  this.serverVersion = packet.readString(50).replace(/\u0000.*/, '');
+  this.createTimestamp = packet.readInt32();
+  this.eventHeaderLength = packet.readInt8(); // should be 19
+  this.eventsLength  = packet.readBuffer();
+  this.name = 'FormatDescriptionEvent';
+}
+
+function QueryEvent(packet) {
+  
+  var parseStatusVars = require('../packets/binlog_query_statusvars.js');
+
+  this.slaveProxyId  = packet.readInt32();
+  this.executionTime = packet.readInt32();
+  var schemaLength  = packet.readInt8();
+  this.errorCode     = packet.readInt16();
+  var statusVarsLength = packet.readInt16();
+  var statusVars = packet.readBuffer(statusVarsLength);
+  
+  this.schema = packet.readString(schemaLength);
+  packet.readInt8(); // should be zero
+  this.statusVars = parseStatusVars(statusVars);
+  
+  this.query = packet.readString();
+  this.name = 'QueryEvent';
+}
+
+function XidEvent(packet) {
+  this.binlogVersion = packet.readInt16();
+  this.xid = packet.readInt64();
+  this.name = 'XidEvent';
+}
+
+var eventParsers = [];
+
+eventParsers[2]  = QueryEvent;
+eventParsers[4]  = RotateEvent;
+eventParsers[15] = FormatDescriptionEvent;
+eventParsers[16] = XidEvent;
+
+BinlogDump.prototype.binlogData = function(packet) {
+  // ok - continue consuming events
+  // error - error
+  // eof - end of binlog
+  if (packet.isEOF()) {
+    this.emit('eof');
+    return null;
+  }
+  
+  // binlog event header
+  var ok = packet.readInt8();
+  var header = new BinlogEventHeader(packet);
+  var EventParser = eventParsers[header.eventType];
+  var event;
+  if (EventParser)
+    event = new EventParser(packet);
+  else {
+    event = {
+      name: 'UNKNOWN'
+    }
+  }
+  event.header = header;
+  this.emit('event', event);
+  return BinlogDump.prototype.binlogData;
+};
+
+module.exports = BinlogDump;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/change_user.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/change_user.js
new file mode 100644
index 0000000000000000000000000000000000000000..901c8b2fec938679637a36dac1caf27277d2d911
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/change_user.js
@@ -0,0 +1,45 @@
+var util     = require('util');
+
+var Command  = require('./command.js');
+var Packets  = require('../packets/index.js');
+var ClientConstants = require('../constants/client.js');
+
+function ChangeUser(options, callback)
+{
+  this.onResult      = callback;
+  this._user          = options.user;
+  this._password      = options.password;
+  this._database      = options.database;
+  this._passwordSha1  = options.passwordSha1;
+  this._charsetNumber = options.charsetNumber;
+  this._currentConfig = options.currentConfig;
+  Command.call(this);
+}
+util.inherits(ChangeUser, Command);
+
+ChangeUser.prototype.start = function(packet, connection) {
+  var packet = new Packets.ChangeUser({
+    user            : this._user,
+    database        : this._database,
+    charsetNumber   : this._charsetNumber,
+    password        : this._password,
+    passwordSha1    : this._passwordSha1,
+    authPluginData1 : connection._handshakePacket.authPluginData1,
+    authPluginData2 : connection._handshakePacket.authPluginData2
+  });
+  this._currentConfig.user          = this._user;
+  this._currentConfig.password      = this._password;
+  this._currentConfig.database      = this._database;
+  this._currentConfig.charsetNumber = this._charsetNumber;
+  // reset prepared statements cache as all statements become invalid after changeUser
+  connection._statements = {};
+  connection.writePacket(packet.toPacket());
+  return ChangeUser.prototype.changeOk;
+};
+
+ChangeUser.prototype.changeOk = function(okPacket, connection) {
+  if (this.onResult)
+    this.onResult(null);
+  return null;
+};
+module.exports = ChangeUser;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/client_handshake.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/client_handshake.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc1f86a83b25f214c11ed599c79686ebb55b3507
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/client_handshake.js
@@ -0,0 +1,100 @@
+var util     = require('util');
+
+var Command  = require('./command.js');
+var Packets  = require('../packets/index.js');
+var ClientConstants = require('../constants/client.js');
+
+function ClientHandshake(clientFlags)
+{
+  this.handshake = null;
+  this.clientFlags = clientFlags;
+  Command.call(this);
+}
+util.inherits(ClientHandshake, Command);
+
+ClientHandshake.prototype.start = function() {
+  return ClientHandshake.prototype.handshakeInit;
+};
+
+ClientHandshake.prototype.sendSSLRequest = function(connection) {
+  var sslRequest = new Packets.SSLRequest(this.clientFlags);
+  connection.writePacket(sslRequest.toPacket());
+};
+
+function flagNames(flags) {
+  var res = [];
+  for (var c in ClientConstants) {
+    if (flags & ClientConstants[c])
+     res.push(c.replace(/_/g, ' ').toLowerCase());
+  }
+  return res;
+}
+
+ClientHandshake.prototype.sendCredentials = function(connection) {
+  if (connection.config.debug) {
+    console.log('Sending handshake packet: flags:%d=(%s)', this.clientFlags,
+      flagNames(this.clientFlags).join(', '));
+  }
+  var handshakeResponse = new Packets.HandshakeResponse({
+    flags   : this.clientFlags,
+    user    : connection.config.user,
+    database: connection.config.database,
+    password: connection.config.password,
+    passwordSha1   : connection.config.passwordSha1,
+    charsetNumber  : connection.config.charsetNumber,
+    authPluginData1: this.handshake.authPluginData1,
+    authPluginData2: this.handshake.authPluginData2,
+    compress: connection.config.compress
+  });
+  connection.writePacket(handshakeResponse.toPacket());
+};
+
+ClientHandshake.prototype.handshakeInit = function(helloPacket, connection) {
+  var command = this;
+
+  this.on('connect', function(connArgs) {
+    connection.emit('connect', connArgs);
+  });
+  this.on('error', function(err) {
+    connection._protocolError = err;
+    connection.emit('error', err);
+  });
+  this.handshake = Packets.Handshake.fromPacket(helloPacket);
+  if (connection.config.debug) {
+    console.log('Server hello packet: capability flags:%d=(%s)', this.handshake.capabilityFlags,
+      flagNames(this.handshake.capabilityFlags).join(', '));
+  }
+  connection.serverCapabilityFlags = this.handshake.capabilityFlags;
+  connection.connectionId = this.handshake.connectionId;
+  var serverSSLSupport = this.handshake.capabilityFlags & ClientConstants.SSL;
+
+  // use compression only if requested by client and supported by server
+  connection.config.compress = connection.config.compress && (this.handshake.capabilityFlags & ClientConstants.COMPRESS);
+  this.clientFlags = this.clientFlags | connection.config.compress;
+
+  if (connection.config.ssl) {
+    if (!serverSSLSupport)
+      command.emit('error', new Error('Server does not support secure connnection'));
+    // send ssl upgrade request and immediately upgrade connection to secure
+    this.clientFlags |= ClientConstants.SSL;
+    this.sendSSLRequest(connection);
+    connection.startTLS(function() {
+      // after connection is secure
+      command.sendCredentials(connection);
+    });
+  } else {
+    this.sendCredentials(connection);
+  }
+  return ClientHandshake.prototype.handshakeResult;
+};
+
+ClientHandshake.prototype.handshakeResult = function(okPacket, connection) {
+  // error is already checked in base class. Done auth.
+  connection.authorized = true;
+  if (connection.config.compress)
+    connection.packetParser.onPacket = connection.handleCompressedPacket.bind(connection);
+  // TODO any useful information in ok packet to pass as argument?
+  connection.emit('connect', true);
+  return null;
+};
+module.exports = ClientHandshake;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/close_statement.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/close_statement.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ec988a910b4b3230cf54fd1fd0fd42f97424c38
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/close_statement.js
@@ -0,0 +1,18 @@
+var util    = require('util');
+
+var Command  = require('./command');
+var Packets  = require('../packets/index.js');
+
+function CloseStatement(id)
+{
+  Command.call(this);
+  this.id = id;
+}
+util.inherits(CloseStatement, Command);
+
+CloseStatement.prototype.start = function(packet, connection) {
+  connection.writePacket(new Packets.CloseStatement(this.id).toPacket(1));
+  return null;
+};
+
+module.exports = CloseStatement;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/command.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/command.js
new file mode 100644
index 0000000000000000000000000000000000000000..62dd0bc199989e46a2e58bc8b151b61b7bdc5796
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/command.js
@@ -0,0 +1,43 @@
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
+
+function Command() {
+  EventEmitter.call(this);
+  this.next = null;
+}
+util.inherits(Command, EventEmitter);
+
+// slow. debug only
+Command.prototype.stateName = function() {
+  var state = this.next;
+  for (i in this)
+    if (this[i] == state && i != 'next')
+      return i;
+};
+
+Command.prototype.execute = function(packet, connection) {
+  // TODO: hack
+  if (!this.next) {
+    this.next = this.start;
+  }
+
+  if (packet && packet.isError()) {
+    var err = packet.asError();
+    if (this.onResult)
+      this.onResult(err);
+    else
+      this.emit('error', err);
+    return true;
+  }
+
+  // TODO: don't return anything from execute, it's ugly and error-prone. Listen for 'end' event in connection
+  this.next = this.next(packet, connection);
+  if (this.next) {
+    return false;
+  } else {
+    this.emit('end');
+    return true;
+  }
+};
+
+module.exports = Command;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/execute.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/execute.js
new file mode 100644
index 0000000000000000000000000000000000000000..14071dc4a508ab5e497a990cc48ded291914ed74
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/execute.js
@@ -0,0 +1,86 @@
+var util    = require('util');
+
+var Command  = require('./command.js');
+var Query    = require('./query.js');
+var Packets  = require('../packets/index.js');
+
+var compileParser = require('../compile_binary_parser.js');
+
+function Execute(options, callback)
+{
+  Command.call(this);
+  this.statement = options.statement;
+  this.sql      = options.sql;
+  this.values   = options.values;
+  this.onResult = callback;
+  this.parameters = options.values;
+
+  this.insertId = 0;
+
+  this._rows   = [];
+  this._fields = [];
+  this._result = [];
+  this._fieldCount = 0;
+  this._rowParser  = null;
+  this.options = options;
+  this._resultIndex = 0;
+  this._localStream = null;
+  this._streamFactory = options.infileStreamFactory;
+}
+util.inherits(Execute, Command);
+
+Execute.prototype.buildParserFromFields = function(fields, connection) {
+  var parserKey = connection.keyFromFields(fields, this.options);
+  var parser = connection.binaryProtocolParsers[parserKey];
+  if (!parser) {
+    parser = compileParser(fields, this.options, connection.config);
+    connection.binaryProtocolParsers[parserKey] = parser;
+  }
+  return parser;
+}
+
+Execute.prototype.start = function(packet, connection) {
+  var executePacket = new Packets.Execute(this.statement.id, this.parameters);
+  connection.writePacket(executePacket.toPacket(1));
+  return Execute.prototype.resultsetHeader;
+};
+
+Execute.prototype.done = Query.prototype.done;
+Execute.prototype.doneInsert = Query.prototype.doneInsert;
+Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
+Execute.prototype._findOrCreateReadStream = Query.prototype._findOrCreateReadStream
+Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
+Execute.prototype.row = Query.prototype.row;
+Execute.prototype.stream = Query.prototype.stream;
+
+Execute.prototype.readField = function(packet, connection) {
+  var def, fields;
+
+  // disabling for now, but would be great to find reliable way to parse fields only once
+  // fields reported by prepare can be empty at all or just incorrect - see #169
+  //
+  // perfomance optimisation: if we already have this field parsed in statement header, use one from header
+  //var field = this.statement.columns.length == this._fieldCount ?
+  //  this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
+
+  var field = new Packets.ColumnDefinition(packet);
+
+  this._receivedFieldsCount++;
+  this._fields[this._resultIndex].push(field);
+  if (this._receivedFieldsCount == this._fieldCount) {
+    fields = this._fields[this._resultIndex];
+    this.emit('fields', fields, this._resultIndex);
+    return Execute.prototype.fieldsEOF;
+  }
+  return Execute.prototype.readField;
+};
+
+Execute.prototype.fieldsEOF = function(packet, connection) {
+  // check EOF
+  if (!packet.isEOF())
+    return connection.protocolError("Expected EOF packet");
+  this._rowParser = this.buildParserFromFields(this._fields[this._resultIndex], connection)
+  return Execute.prototype.row;
+};
+
+module.exports = Execute;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/index.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..12ac9cf22a2b72f3986210ef3bc399ac30fee0ca
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/index.js
@@ -0,0 +1,4 @@
+"client_handshake server_handshake query prepare close_statement execute ping register_slave binlog_dump change_user quit".split(' ').forEach(function(name) {
+  var ctor = require('./' + name + '.js');
+  module.exports[ctor.name] = ctor;
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/ping.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/ping.js
new file mode 100644
index 0000000000000000000000000000000000000000..531c227312fe33fdedcdbbd4f38711283f22254d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/ping.js
@@ -0,0 +1,30 @@
+var Command  = require('./command');
+var util    = require('util');
+var CommandCode = require('../constants/commands');
+var Packet = require('../packets/packet');
+
+// TODO: time statistics?
+// usefull for queue size and network latency monitoring
+// store created,sent,reply timestamps
+
+function Ping(callback)
+{
+  Command.call(this);
+  this.onResult = callback;
+}
+util.inherits(Ping, Command);
+
+Ping.prototype.start = function(packet, connection) {
+  var ping = new Packet(0, new Buffer([0, 0, 0, 0, CommandCode.PING]));
+  connection.writePacket(ping);
+  return Ping.prototype.pingResponse;
+};
+
+Ping.prototype.pingResponse = function(packet) {
+  // TODO: check it's OK packet. error check already done in caller
+  if (this.onResult)
+    process.nextTick(this.onResult.bind(this));
+  return null;
+};
+
+module.exports = Ping;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/prepare.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/prepare.js
new file mode 100644
index 0000000000000000000000000000000000000000..982428a9afb4405bced60bcee3205218fc4aa341
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/prepare.js
@@ -0,0 +1,112 @@
+var util    = require('util');
+
+var Packets        = require('../packets/index.js');
+var Command        = require('./command.js');
+var CloseStatement = require('./close_statement.js')
+var Execute        = require('./execute.js')
+
+function Prepare(options, callback)
+{
+  Command.call(this);
+  this.query = options.sql;
+  this.onResult = callback;
+
+  this.id = 0;
+  this.fieldCount = 0;
+  this.parameterCount = 0;
+  this.fields = [];
+  this.parameterDefinitions = [];
+  this.options = options;
+}
+util.inherits(Prepare, Command);
+
+Prepare.prototype.start = function(packet, connection) {
+  connection.writePacket(new Packets.PrepareStatement(this.query).toPacket(1));
+  return Prepare.prototype.prepareHeader;
+};
+
+function PreparedStatementInfo(query, id, columns, parameters, connection) {
+  this.query      = query;
+  this.id         = id;
+  this.columns    = columns;
+  this.parameters = parameters;
+  this.rowParser  = null;
+  this._connection = connection
+}
+
+PreparedStatementInfo.prototype.close = function() {
+  return this._connection.addCommand(new CloseStatement(this.id));
+};
+
+PreparedStatementInfo.prototype.execute = function(parameters, callback) {
+  if (typeof parameters == 'function') {
+    callback = parameters;
+    parameters = [];
+  }
+  return this._connection.addCommand(new Execute({ statement: this, values: parameters}, callback));
+};
+
+Prepare.prototype.prepareHeader = function(packet, connection) {
+  var header = new Packets.PreparedStatementHeader(packet);
+  this.id             = header.id;
+  this.fieldCount     = header.fieldCount;
+  this.parameterCount = header.parameterCount;
+  if (this.parameterCount > 0)
+    return Prepare.prototype.readParameter;
+  else if (this.fieldCount > 0)
+    return Prepare.prototype.readField;
+  else
+    return this.prepareDone(connection);
+};
+
+Prepare.prototype.readParameter = function(packet) {
+  var def = new Packets.ColumnDefinition(packet);
+  this.parameterDefinitions.push(def);
+  if (this.parameterDefinitions.length == this.parameterCount)
+    return Prepare.prototype.parametersEOF;
+  return this.readParameter;
+};
+
+Prepare.prototype.readField = function(packet, connection) {
+  var def = new Packets.ColumnDefinition(packet);
+  this.fields.push(def);
+  if (this.fields.length == this.fieldCount)
+    return Prepare.prototype.fieldsEOF;
+  return Prepare.prototype.readField;
+};
+
+Prepare.prototype.parametersEOF = function(packet, connection) {
+  if (!packet.isEOF())
+    return connection.protocolError("Expected EOF packet after parameters");
+  if (this.fieldCount > 0)
+    return Prepare.prototype.readField;
+  else
+    return this.prepareDone(connection);
+};
+
+Prepare.prototype.fieldsEOF = function(packet, connection) {
+  if (!packet.isEOF())
+    return connection.protocolError("Expected EOF packet after fields");
+  return this.prepareDone(connection);
+};
+
+Prepare.prototype.prepareDone = function(connection)
+{
+  var self = this;
+  if (this.onResult)
+    process.nextTick(function() {
+      self.onResult(
+        null,
+        new PreparedStatementInfo(
+          self.query,
+          self.id,
+          self.fields,
+          self.parameterDefinitions,
+          connection
+        )
+      );
+    });
+  return null;
+};
+
+module.exports = Prepare;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/query.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/query.js
new file mode 100644
index 0000000000000000000000000000000000000000..08c722731841dd0998aad68559449464aca53895
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/query.js
@@ -0,0 +1,243 @@
+var fs           = require('fs');
+var util         = require('util');
+
+var Readable     = require('readable-stream');
+
+var Command  = require('./command.js');
+var Packets  = require('../packets/index.js');
+var compileParser = require('../compile_text_parser.js');
+var ServerStatus = require('../constants/server_status.js');
+
+var EmptyPacket = new Packets.Packet(0, new Buffer(4), 0, 4);
+
+function Query(sql, options, callback)
+{
+  Command.call(this);
+  this.query = sql;
+  // node-mysql compatibility: query.sql as alias to query.query #121
+  this.sql = this.query;
+  this.options = options;
+  this.onResult = callback;
+  this._fieldCount = 0;
+  this._rowParser  = null;
+  this._fields     = [];
+  this._rows       = [];
+  this._receivedFieldsCount = 0;
+  this._resultIndex = 0;
+  this._localStream = null;
+  this._streamFactory = options.infileStreamFactory;
+  this._connection = null;
+}
+util.inherits(Query, Command);
+
+Query.prototype.start = function(packet, connection) {
+  if (connection.config.debug) {
+    console.log('        Sending query command: %s', this.query);
+  }
+  this._connection = connection;
+  var cmdPacket = new Packets.Query(this.query);
+  connection.writePacket(cmdPacket.toPacket(1));
+  return Query.prototype.resultsetHeader;
+};
+
+Query.prototype.done = function() {
+  var self = this;
+  if (this.onResult) {
+    var rows, fields;
+    if (this._resultIndex === 0) {
+      rows = this._rows[0];
+      fields = this._fields[0];
+    } else {
+      rows = this._rows;
+      fields = this._fields;
+    }
+    if (fields) {
+      process.nextTick(function() {
+        self.onResult(null, rows, fields, self._resultIndex + 1);
+      });
+    } else {
+      process.nextTick(function() {
+        self.onResult(null, rows, void(0), self._resultIndex + 1);
+      });
+    }
+  }
+  return null;
+};
+
+Query.prototype.doneInsert = function(rs) {
+  if (this._localStreamError) {
+    if (this.onResult) {
+      this.onResult(this._localStreamError, rs);
+    } else {
+      this.emit('error', this._localStreamError);
+    }
+    return null;
+  }
+  this._rows.push(rs);
+  this._fields.push(void(0));
+  this.emit('result', rs, this._resultIndex);
+  this.emit('fields', void(0), this._resultIndex);
+  if (rs.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
+    this._resultIndex++;
+    return this.resultsetHeader;
+  }
+  return this.done();
+};
+
+Query.prototype.resultsetHeader = function(packet, connection) {
+  var rs = new Packets.ResultSetHeader(packet, connection.config.bigNumberStrings);
+  this._fieldCount = rs.fieldCount;
+  if (connection.config.debug) {
+    console.log('        Resultset header received, expecting ' + rs.fieldCount + ' column definition packets');
+  }
+  if (this._fieldCount === 0) {
+    return this.doneInsert(rs);
+  }
+  if (this._fieldCount === null) {
+    this._localStream = this._findOrCreateReadStream(rs.infileName);
+    // start streaming, after last packet expect OK
+    this._streamLocalInfile(connection);
+    return this.infileOk;
+  }
+
+  this._receivedFieldsCount = 0;
+  this._rows.push([]);
+  this._fields.push([]);
+  return this.readField;
+};
+
+// some code taken from https://github.com/felixge/node-mysql/pull/668
+Query.prototype._findOrCreateReadStream = function(path) {
+  if (this._streamFactory)
+    return this._streamFactory(path);
+  return fs.createReadStream(path, {
+    'flag': 'r',
+    'encoding': null,
+    'autoClose': true
+  });
+};
+
+Query.prototype._streamLocalInfile = function(connection) {
+  var command = this;
+  connection.stream.on('pause', function() {
+    command._localStream.pause();
+  });
+  connection.stream.on('drain', function() {
+    command._localStream.resume();
+  });
+  this._localStream.on('data', function (data) {
+    var dataWithHeader = new Buffer(data.length + 4);
+    data.copy(dataWithHeader, 4);
+    connection.writePacket(new Packets.Packet(0, dataWithHeader, 0, dataWithHeader.length));
+  });
+  this._localStream.on('end', function (data) {
+    connection.writePacket(EmptyPacket);
+  });
+  this._localStream.on('error', function(err) {
+    command._localStreamError = err;
+    command._localStream.emit('end');
+  });
+}
+
+Query.prototype.readField = function(packet, connection) {
+
+  this._receivedFieldsCount++;
+
+  // Often there is much more data in the column definition than in the row itself
+  // If you set manually _fields[0] to array of ColumnDefinition's (from previous call)
+  // you can 'cache' result of parsing. Field packets still received, but ignored in that case
+  // this is the reason _receivedFieldsCount exist (otherwise we could just use current length of fields array)
+
+  if (this._fields[this._resultIndex].length != this._fieldCount) {
+    var field = new Packets.ColumnDefinition(packet);
+    this._fields[this._resultIndex].push(field);
+    if (connection.config.debug) {
+      console.log('        Column definition:');
+      console.log('          name: ' + field.name);
+      console.log('          type: ' + field.columnType);
+      console.log('         flags: ' + field.flags);
+    }
+  }
+
+  // last field received
+  if (this._receivedFieldsCount == this._fieldCount) {
+    var fields = this._fields[this._resultIndex];
+    this.emit('fields', fields, this._resultIndex);
+    var parserKey = connection.keyFromFields(fields, this.options);
+    this._rowParser = connection.textProtocolParsers[parserKey];
+    if (!this._rowParser) {
+      this._rowParser = compileParser(fields, this.options, connection.config);
+      connection.textProtocolParsers[parserKey] = this.rowParser;
+    }
+    return Query.prototype.fieldsEOF;
+  }
+  return Query.prototype.readField;
+};
+
+Query.prototype.fieldsEOF = function(packet, connection) {
+  // check EOF
+  if (!packet.isEOF())
+    return connection.protocolError("Expected EOF packet");
+  return this.row;
+};
+
+Query.prototype.row = function(packet)
+{
+  if (packet.isEOF()) {
+    var status = packet.eofStatusFlags();
+    var moreResults = status & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
+    if (moreResults) {
+      this._resultIndex++;
+      return Query.prototype.resultsetHeader;
+    }
+    return this.done();
+  }
+
+  var row = new this._rowParser(packet);
+  if (this.onResult)
+    this._rows[this._resultIndex].push(row);
+  else
+    this.emit('result', row, this._resultIndex);
+
+  return Query.prototype.row;
+};
+
+Query.prototype.infileOk = function(packet, connection) {
+  var rs = new Packets.ResultSetHeader(packet, connection.config.bigNumberStrings);
+  return this.doneInsert(rs);
+};
+
+Query.prototype.stream = function(options) {
+  var self = this,
+      stream;
+
+  options = options || {};
+  options.objectMode = true;
+  stream = new Readable(options);
+
+  stream._read = function() {
+    self._connection && self._connection.resume();
+  };
+
+  this.on('result',function(row,i) {
+    if (!stream.push(row)) self._connection.pause();
+    stream.emit('result',row,i);  // replicate old emitter
+  });
+
+  this.on('error',function(err) {
+    stream.emit('error',err);  // Pass on any errors
+  });
+
+  this.on('end', function() {
+    stream.emit('close');  // notify readers that query has completed
+    stream.push(null);  // pushing null, indicating EOF
+  });
+
+  this.on('fields',function(fields,i) {
+    stream.emit('fields',fields,i);  // replicate old emitter
+  });
+
+  return stream;
+};
+
+module.exports = Query;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/quit.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/quit.js
new file mode 100644
index 0000000000000000000000000000000000000000..d21846c7c20b34b99c6373e710074b6995b7cb9a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/quit.js
@@ -0,0 +1,22 @@
+var util        = require('util');
+var Command     = require('./command.js');
+var CommandCode = require('../constants/commands.js');
+var Packet      = require('../packets/packet.js');
+
+function Quit(callback)
+{
+  this.done = callback;
+  Command.call(this);
+}
+util.inherits(Quit, Command);
+
+Quit.prototype.start = function(packet, connection) {
+  connection._closing = true;
+  var quit = new Packet(0, new Buffer([0, 0, 0, 0, CommandCode.QUIT]));
+  if (this.done)
+    this.done();
+  connection.writePacket(quit);
+  return null;
+};
+
+module.exports = Quit;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/register_slave.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/register_slave.js
new file mode 100644
index 0000000000000000000000000000000000000000..19304f678af5a3638fb964d86af2297c1eed0a3f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/register_slave.js
@@ -0,0 +1,26 @@
+var Command  = require('./command');
+var util    = require('util');
+var CommandCode = require('../constants/commands');
+var Packets = require('../packets');
+
+function RegisterSlave(opts, callback)
+{
+  Command.call(this);
+  this.onResult = callback;
+  this.opts = opts;
+}
+util.inherits(RegisterSlave, Command);
+
+RegisterSlave.prototype.start = function(packet, connection) {
+  var packet = new Packets.RegisterSlave(this.opts);
+  connection.writePacket(packet.toPacket(1));
+  return RegisterSlave.prototype.registerResponse;
+};
+
+RegisterSlave.prototype.registerResponse = function(packet) {
+  if (this.onResult)
+    process.nextTick(this.onResult.bind(this));
+  return null;
+};
+
+module.exports = RegisterSlave;
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/server_handshake.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/server_handshake.js
new file mode 100644
index 0000000000000000000000000000000000000000..3eebba968a03af6c4faf3ca0d05b2ffc99253702
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/commands/server_handshake.js
@@ -0,0 +1,132 @@
+var util     = require('util');
+
+var ClientConstants = require('../constants/client.js');
+var CommandCode     = require('../constants/commands.js');
+
+var Command  = require('./command.js');
+var Packets  = require('../packets/index.js');
+var auth41   = require('../auth_41.js');
+
+function ServerHandshake(args)
+{
+  Command.call(this);
+  this.args = args;
+  /*
+  this.protocolVersion = args.protocolVersion || 10;
+  this.serverVersion   = args.serverVersion;
+  this.connectionId    = args.connectionId,
+  this.statusFlags     = args.statusFlags,
+  this.characterSet    = args.characterSet,
+  this.capabilityFlags = args.capabilityFlags || 512;
+  */
+}
+util.inherits(ServerHandshake, Command);
+
+ServerHandshake.prototype.start = function(packet, connection) {
+  var serverHelloPacket = new Packets.Handshake(this.args);
+  this.serverHello = serverHelloPacket;
+  serverHelloPacket.setScrambleData(function(err) {
+    if (err)
+      return connection.emit('error', new Error('Error generating random bytes'));
+    connection.writePacket(serverHelloPacket.toPacket(0));
+  });
+  return ServerHandshake.prototype.readClientReply;
+};
+
+ServerHandshake.prototype.readClientReply = function(packet, connection) {
+  // check auth here
+  var clientHelloReply = new Packets.HandshakeResponse.fromPacket(packet);
+  if (this.args.authCallback) {
+    try {
+      this.args.authCallback({
+        user: clientHelloReply.user,
+        database: clientHelloReply.database,
+        address: connection.stream.remoteAddress,
+        authPluginData1: this.serverHello.authPluginData1,
+        authPluginData2: this.serverHello.authPluginData2,
+        authToken: clientHelloReply.authToken,
+      }, function(err, mysqlError) {
+        //if (err)
+        if (!mysqlError)
+          connection.writeOk();
+        else {
+          // TODO create constants / errorToCode
+          // 1045 = ER_ACCESS_DENIED_ERROR
+          connection.writeError({ message: mysqlError.message || '',  code: mysqlError.code || 1045 });
+          connection.close();
+        }
+      });
+    } catch(err) {
+      throw err;
+      // TODO
+      // connection.writeError(err)
+    }
+  } else {
+    connection.writeOk();
+  }
+  return ServerHandshake.prototype.dispatchCommands;
+};
+
+ServerHandshake.prototype.dispatchCommands = function(packet, connection) {
+  // command from client to server
+  var commandCode = packet.readInt8();
+  switch (commandCode) {
+  case CommandCode.QUIT:
+    connection.emit('quit');
+    // connection.stream.end();
+    break;
+  case CommandCode.INIT_DB:
+    var schemaName = packet.readString();
+    connection.emit('init_db', schemaName);
+    connection.writeOk();
+    break;
+  case CommandCode.PING:
+    // allow custom ping response (delayed/incorrect/etc)
+    // if no listeners, respond with OK
+    if (connection.listeners('ping').length === 0) {
+      connection.writeOk();
+    } else {
+      connection.emit('ping');
+    }
+    break;
+  case CommandCode.QUERY:
+    var query = packet.readString();
+    connection.emit('query', query);
+    break;
+  case CommandCode.FIELD_LIST:
+    var table = packet.readNullTerminatedString();
+    var fields = packet.readString();
+    connection.emit('field_list', table, fields);
+    break;
+  default:
+    console.log('Unknown command:', commandCode);
+  }
+  return ServerHandshake.prototype.dispatchCommands;
+};
+
+module.exports = ServerHandshake;
+
+// TODO: implement server-side 4.1 authentication
+/*
+4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
+
+  SERVER:  public_seed=create_random_string()
+           send(public_seed)
+
+  CLIENT:  recv(public_seed)
+           hash_stage1=sha1("password")
+           hash_stage2=sha1(hash_stage1)
+           reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
+
+           // this three steps are done in scramble()
+
+           send(reply)
+
+
+  SERVER:  recv(reply)
+           hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
+           candidate_hash2=sha1(hash_stage1)
+           check(candidate_hash2==hash_stage2)
+
+server stores sha1(sha1(password)) ( hash_stag2)
+*/
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_binary_parser.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_binary_parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..9e972394244daf7d1c1deefdb2723a7977f8c1a4
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_binary_parser.js
@@ -0,0 +1,137 @@
+var vm = require('vm');
+
+var FieldFlags = require('./constants/field_flags.js');
+var Charsets   = require('./constants/charsets.js');
+var Types      = require('./constants/types.js');
+var srcEscape  = require('./helpers').srcEscape;
+
+var typeNames = [];
+for (var t in Types) {
+  typeNames[Types[t]] = t;
+}
+
+function compile(fields, options, config) {
+  var result = [];
+  var i=0;
+  var nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
+  result.push('(function(){ return function BinaryRow(packet) {');
+
+  if (options.rowsAsArray)
+    result.push('  var result = new Array(' + fields.length + ');');
+
+  var resultTables = {};
+  var resultTablesArray = [];
+
+  if (options.nestTables === true) {
+    for (i = 0; i < fields.length; i++) {
+      resultTables[fields[i].table] = 1;
+    }
+    resultTablesArray = Object.keys(resultTables);
+    for (i = 0; i < resultTablesArray.length; i++) {
+      result.push('  this[' + srcEscape(resultTablesArray[i]) + '] = {};');
+    }
+  }
+
+  result.push('  var statusByte = packet.readInt8();');
+  for (i=0; i < nullBitmapLength; ++i)
+    result.push('  var nullBitmaskByte' + i + ' = packet.readInt8();');
+
+  var lvalue = '';
+  var currentFieldNullBit = 4;
+  var nullByteIndex = 0;
+  var fieldName = '';
+  var tableName = '';
+
+  for (i = 0; i < fields.length; i++) {
+    fieldName = srcEscape(fields[i].name);
+    result.push('  // ' + fieldName + ': '+ typeNames[fields[i].columnType]);
+
+    if (typeof options.nestTables == 'string') {
+      tableName = srcEscape(fields[i].table);
+      lvalue = ['  this[', srcEscape(fields[i].table + options.nestTables + fields[i].name), ']'].join('');
+    } else if (options.nestTables === true) {
+      tableName = srcEscape(fields[i].table);
+      lvalue = ['  this[', tableName, '][', fieldName, ']'].join('');
+    } else if (options.rowsAsArray) {
+      lvalue = '  result[' + i.toString(10) + ']';
+    } else
+      lvalue = '  this[' + srcEscape(fields[i].name) + ']';
+
+    // TODO: this used to be an optimisation ( if column marked as NOT_NULL don't include code to check null
+    // bitmap at all, but it seems that we can't rely on this flag, see #178
+    // TODO: benchmark performance difference
+    //
+    //if (fields[i].flags & FieldFlags.NOT_NULL) { // don't need to check null bitmap if field can't be null.
+    //  result.push(lvalue + ' = ' + readCodeFor(fields[i], config));
+    //} else if (fields[i].columnType == Types.NULL) {
+    //  result.push(lvalue + ' = null;');
+    //} else {
+      result.push('  if (nullBitmaskByte' + nullByteIndex  + ' & ' + currentFieldNullBit + ')');
+      result.push('  ' + lvalue + ' = null;');
+      result.push('  else');
+      result.push('  ' + lvalue + ' = ' + readCodeFor(fields[i], config));
+    //}
+    currentFieldNullBit *= 2;
+    if (currentFieldNullBit == 0x100)
+    {
+      currentFieldNullBit = 1;
+      nullByteIndex++;
+    }
+  }
+
+  if (options.rowsAsArray)
+    result.push('  return result;');
+
+  result.push('}; })()');
+  var src = result.join('\n');
+  if (config.debug) {
+    console.log('Compiled binary protocol row parser:');
+    var cardinal = require('cardinal');
+    console.log(cardinal.highlight(src));
+  }
+  return vm.runInThisContext(src);
+}
+
+function readCodeFor(field, config) {
+  var unsigned = field.flags & FieldFlags.UNSIGNED;
+  switch(field.columnType) {
+  case Types.TINY:
+    return unsigned ? "packet.readInt8();" : "packet.readSInt8();";
+  case Types.SHORT:
+    return unsigned ? "packet.readInt16();" : "packet.readSInt16();";
+  case Types.LONG:
+  case Types.INT24: // in binary protocol int24 is encoded in 4 bytes int32
+    return unsigned ? "packet.readInt32();" : "packet.readSInt32();";
+  case Types.YEAR:
+    return "packet.readInt16()";
+  case Types.FLOAT:
+    return "packet.readFloat();";
+  case Types.DOUBLE:
+    return "packet.readDouble();";
+  case Types.NULL:
+    return "null;";
+  case Types.DATE:
+  case Types.DATETIME:
+  case Types.TIMESTAMP:
+  case Types.NEWDATE:
+    if (config.dateStrings)
+      return "packet.readDateTimeString();";
+    return "packet.readDateTime();";
+  case Types.TIME:
+    return "packet.readTimeString()";
+  case Types.DECIMAL:
+  case Types.NEWDECIMAL:
+    return "packet.readLengthCodedString();";
+  case Types.GEOMETRY:
+    return "packet.parseGeometryValue();";
+  case Types.LONGLONG: // TODO: 8 bytes. Implement as two 4 bytes read for now (it's out of JavaScript int precision!)
+    return unsigned ? "packet.readInt64();" : "packet.readSInt64();";
+  default:
+    if (field.characterSet == Charsets.BINARY)
+      return "packet.readLengthCodedBuffer();";
+    else
+      return "packet.readLengthCodedString();";
+  }
+}
+
+module.exports = compile;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_text_parser.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_text_parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2fbfcf09be77a1e7995520419f7236b811223ae
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/compile_text_parser.js
@@ -0,0 +1,108 @@
+var Types = require('./constants/types');
+var Charsets = require('./constants/charsets');
+var vm = require('vm');
+var srcEscape = require('./helpers').srcEscape;
+
+var typeNames = [];
+for (var t in Types) {
+  typeNames[Types[t]] = t;
+}
+
+function compile(fields, options, config) {
+
+  var result = [];
+  var i=0;
+  var lvalue = '';
+
+  result.push('(function() { return function TextRow(packet) {');
+  if (options.rowsAsArray)
+    result.push('  var result = new Array(' + fields.length + ')');
+
+  var resultTables = {};
+  var resultTablesArray = [];
+
+  if (options.nestTables === true) {
+    for (i = 0; i < fields.length; i++) {
+      resultTables[fields[i].table] = 1;
+    }
+    resultTablesArray = Object.keys(resultTables);
+    for (i = 0; i < resultTablesArray.length; i++) {
+      result.push('  this[' + srcEscape(resultTablesArray[i]) + '] = {};');
+    }
+  }
+
+  var fieldName = '';
+  var tableName = '';
+  for (i = 0; i < fields.length; i++) {
+    fieldName = srcEscape(fields[i].name);
+    result.push('  // ' + fieldName + ': '+ typeNames[fields[i].columnType]);
+    if (typeof options.nestTables == 'string') {
+      tableName = srcEscape(fields[i].table);
+      lvalue = ['  this[', srcEscape(fields[i].table + options.nestTables + fields[i].name), ']'].join('');
+    } else if (options.nestTables === true) {
+      tableName = srcEscape(fields[i].table);
+      lvalue = ['  this[', tableName, '][', fieldName, ']'].join('');
+    } else if (options.rowsAsArray) {
+      lvalue = '  result[' + i.toString(10) + ']';
+    } else
+      lvalue = '  this[' + srcEscape(fields[i].name) + ']';
+    result.push(lvalue + ' = ' + readCodeFor(fields[i].columnType, fields[i].characterSet, config));
+  }
+
+  if (options.rowsAsArray)
+    result.push('  return result;');
+
+  result.push('};})()');
+  var src = result.join('\n');
+  if (config.debug) {
+    console.log('        Compiled text protocol row parser:\n\n');
+    var cardinal = require('cardinal');
+    console.log(cardinal.highlight(src) + '\n\n');
+  }
+  return vm.runInThisContext(src);
+}
+
+function readCodeFor(type, charset, config) {
+  switch(type) {
+  case Types.TINY:
+  case Types.SHORT:
+  case Types.LONG:
+  case Types.INT24:
+  case Types.YEAR:
+  case Types.LONG:
+    return "packet.parseLengthCodedInt();";
+  case Types.LONGLONG:
+    if (config.supportBigNumbers && config.bigNumberStrings) {
+      return "packet.parseLengthCodedIntString();";
+    }
+    return "packet.parseLengthCodedInt();";
+  case Types.FLOAT:
+  case Types.DOUBLE:
+    return "packet.parseLengthCodedFloat();";
+  case Types.NULL:
+    return "null; packet.skip(1);";
+  case Types.DECIMAL:
+  case Types.NEWDECIMAL:
+    return "packet.readLengthCodedString(); //" + type + ' ' + charset;
+  case Types.DATE:
+    if (config.dateStrings)
+      return "packet.readLengthCodedString()";
+    return "packet.parseDate();";
+  case Types.DATETIME:
+  case Types.TIMESTAMP:
+    if (config.dateStrings)
+      return "packet.readLengthCodedString()";
+    return "packet.parseDateTime();";
+  case Types.TIME:
+    return "packet.readLengthCodedString()";
+  case Types.GEOMETRY:
+    return "packet.parseGeometryValue();";
+  default:
+    if (charset == Charsets.BINARY)
+      return "packet.readLengthCodedBuffer();";
+    else
+      return "packet.readLengthCodedString(); //" + type + ' ' + charset;
+  }
+}
+
+module.exports = compile;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/connection.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/connection.js
new file mode 100644
index 0000000000000000000000000000000000000000..4697945db56a435379c1afe1a8460299ebb6d05b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/connection.js
@@ -0,0 +1,672 @@
+var net          = require('net');
+var util         = require('util');
+var EventEmitter = require('events').EventEmitter;
+var Queue        = require('double-ended-queue');
+
+var PacketParser = require('./packet_parser.js');
+var Packet       = require('./packets/packet.js');
+var Packets      = require('./packets/index.js');
+var Commands     = require('./commands/index.js');
+var SqlString    = require('./sql_string.js');
+var ConnectionConfig = require('./connection_config.js');
+
+var _connectionId = 0;
+var noop = function() {};
+
+function Connection(opts)
+{
+  EventEmitter.call(this);
+  this.config = opts.config;
+
+  // TODO: fill defaults
+  // if no params, connect to /var/lib/mysql/mysql.sock ( /tmp/mysql.sock on OSX )
+  // if host is given, connect to host:3306
+
+  // TODO: use `/usr/local/mysql/bin/mysql_config --socket` output? as default socketPath
+  // if there is no host/port and no socketPath parameters?
+
+  if (!opts.config.stream) {
+    if (opts.config.socketPath)
+      this.stream = net.connect(opts.config.socketPath);
+    else
+      this.stream = net.connect(opts.config.port, opts.config.host);
+  } else {
+    // if stream is a function, treat it as "stream agent / factory"
+    if (typeof opts.config.stream == 'function')
+      this.stream = opts.config.stream(opts);
+    else
+      this.stream = opts.config.stream;
+  }
+  this._internalId = _connectionId++;
+
+  this._commands = new Queue();
+  this._command = null;
+
+  this._paused = false;
+  this._paused_packets = new Queue();
+
+  this._statements = {};
+
+  // TODO: make it lru cache
+  // https://github.com/mercadolibre/node-simple-lru-cache
+  // or https://github.com/rsms/js-lru
+  // or https://github.com/monsur/jscache
+  // or https://github.com/isaacs/node-lru-cache
+  //
+  // key is field.name + ':' + field.columnType + ':' field.flags + '/'
+  this.textProtocolParsers = {};
+
+  // TODO: not sure if cache should be separate (same key as with textProtocolParsers)
+  // or part of prepared statements cache (key is sql query)
+  this.binaryProtocolParsers = {};
+
+  this.serverCapabilityFlags = 0;
+  this.authorized = false;
+
+  var connection = this;
+  this.sequenceId = 0;
+
+  this.threadId = null;
+  this._handshakePacket = null;
+
+  this.stream.on('error', function(err) {
+    connection.emit('error', err);
+  });
+
+  // big TODO: benchmark if it all worth using 'ondata' and onPacket callbacks directly
+  // compositing streams would be much more easier.
+  // also, look for existing length-prefixed streams to reuse instead of packet_parser
+  //  https://github.com/squaremo/node-spb - currently only fixed 4 byte prefix
+  //  ...?
+
+  // see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
+  this.packetParser = new PacketParser(function(p) { connection.handlePacket(p); });
+
+  // TODO: this code used to be an optimized version of handler
+  // DOES NOT WORK IN NODE 11
+  // TODO: measure if we actually get something here
+  // if yes, re-enable for node 10
+  //if (this.stream instanceof net.Stream) {
+  //  this.stream.ondata = function(data, start, end) {
+  //    connection.packetParser.execute(data, start, end);
+  //  };
+  //} else {
+    this.stream.on('data', function(data) {
+      connection.packetParser.execute(data);
+    });
+  //}
+  this._protocolError = null;
+  this.stream.on('end', function() {
+    // we need to set this flag everywhere where we want connection to close
+    if (connection._closing)
+      return;
+
+    // TODO: move to protocolError()
+    if (!connection._protocolError) // no particular error message before disconnect
+      connection._protocolError = 'PROTOCOL_CONNECTION_LOST';
+    var err = new Error('Connection lost: The server closed the connection.');
+    err.fatal = true;
+    err.code = connection._protocolError;
+
+    var command;
+    if (connection._command && connection._command.onResult)
+      connection._command.onResult(err);
+    while (command = connection._commands.shift()) {
+      if (command.onResult)
+         command.onResult(err);
+    }
+
+    connection.emit('error', err);
+
+  });
+  var handshakeCommand;
+  if (!this.config.isServer) {
+    handshakeCommand = new Commands.ClientHandshake(this.config.clientFlags);
+    handshakeCommand.on('error', function(e) { connection.emit('error', e); });
+    handshakeCommand.on('end', function() {
+      connection._handshakePacket = handshakeCommand.handshake;
+      connection.threadId = handshakeCommand.handshake.connectionId;
+    });
+    this.addCommand(handshakeCommand);
+  }
+}
+util.inherits(Connection, EventEmitter);
+
+Connection.prototype.write = function(buffer) {
+  this.stream.write(buffer);
+};
+
+// TODO: replace function in runtime instead of having if() here
+// Needs benchmark.
+Connection.prototype.writePacket = function(packet) {
+  packet.writeHeader(this.sequenceId);
+  if (this.config.debug) {
+    console.log(this._internalId + ' ' + this.connectionId + ' <== ' + this._command._commandName + '#' + this._command.stateName() + '(' + [this.sequenceId, packet._name, packet.length()].join(',') + ')');
+  }
+  this.sequenceId++;
+  if (this.sequenceId == 256)
+    this.sequenceId = 0
+  if (!this.config.compress || !this.authorized) {
+    this.write(packet.buffer);
+  } else {
+    var packetLen = packet.length();
+    var compressHeader = new Buffer(7);
+
+    // TODO: currently all outgoing packets are sent uncompressed (header + deflated length=0 as uncompressed flag)
+    // Need to implement deflation of outgoing packet. Also need to decide when not to compress small packets
+    // http://dev.mysql.com/doc/internals/en/compression.html#uncompressed-payload suggest not to compress packets less than 50 bytes
+
+    // Write uncompressed packet
+    compressHeader.fill(0);
+    compressHeader.writeUInt8(packetLen & 0xff, 0);
+    compressHeader.writeUInt16LE(packetLen >> 8, 1);
+    this.write(compressHeader);
+    this.write(packet.buffer);
+  }
+};
+
+Connection.prototype.startTLS = function(onSecure) {
+  if (this.config.debug) {
+    console.log('Upgrading connection to TLS');
+  }
+  var connection = this;
+  var crypto = require('crypto');
+  var tls = require('tls');
+  var config = this.config;
+  var stream = this.stream;
+
+  var credentials = crypto.createCredentials({
+    key: config.ssl.key,
+    cert: config.ssl.cert,
+    passphrase: config.ssl.passphrase,
+    ca: config.ssl.ca
+  });
+  var securePair = tls.createSecurePair(credentials, false);
+  if (stream.ondata)
+    stream.ondata = null;
+  stream.removeAllListeners('data');
+  stream.pipe(securePair.encrypted);
+  securePair.encrypted.pipe(stream);
+  securePair.cleartext.on('data', function(data) {
+    connection.packetParser.execute(data);
+  });
+  connection.write = function(buffer) {
+    securePair.cleartext.write(buffer);
+  };
+  securePair.on('secure', onSecure);
+};
+
+// TODO: this does not work if uncompressed packet is split by compressed
+// packet boundary.
+// My assumption about compressedPacket to contain one or more complete
+// compressed packets was wrong. It can wrap any chunk of data.
+// This will be rmoved in favor of connection.startInflate
+// currently Handshake command overwrites connection.handlePacket with handleCompressedPacket
+// before expecting first compressed packet
+var zlib = require('zlib');
+Connection.prototype.handleCompressedPacket = function(packet) {
+  var connection = this;
+  var inflatedLength = packet.readInt24();
+  if (inflatedLength !== 0) {
+    var compressedBody = packet.readBuffer(packet.length() - 3);
+    zlib.inflate(compressedBody, function(err, packets) {
+      if (err)
+        return connection.emit('error', err);
+      var offset = packets.offset;
+      var end = offset + packets.length;
+      var buffer = packets.parent;
+      var len = 0;
+      var id = 0;
+      // single compressed packet can contain multiple uncompressed
+      while (offset < end) {
+        len = buffer.readUInt16LE(offset) + (buffer[offset+2] << 16);
+        id  = buffer[offset+3];
+        connection.handlePacket(new Packet(id, buffer, offset + 4, offset + 4 + len));
+        offset += 4 + len;
+      }
+    });
+  } else {
+    inflatedLength = packet.readInt24();
+    var sequenceId = packet.readInt8();
+    connection.handlePacket(new Packet(sequenceId, packet.buffer, packet.offset, packet.offset + inflatedLength));
+  }
+};
+
+// TODO: consider using @creationix simple-streams
+// https://gist.github.com/creationix/5498108
+// https://github.com/creationix/min-stream-uv
+// https://github.com/creationix/min-stream-helpers
+
+
+// TODO: try with Stream2 streams
+//
+// changes stream -> packetParser to
+// stream -> compressedPacketParser -> inflateStream -> packetParser
+// note that in the caseof ssl this should become
+// stream -> securePair.encrypted -> securePair.cleartext -> compressedPacketParser -> inflateStream -> packetParser
+Connection.prototype.startInflate = function() {
+  var connection = this;
+  var zlib = require('zlib');
+  var inflateStream = zlib.createInflate();
+  var uncompressedPacketParser = connection.packetParser;
+  connection.packetParser = new PacketParser(function(packet) {
+    var inflatedLength = packet.readInt24();
+    if (inflatedLength !== 0) {
+      inflateStream.write(packet.readBuffer(packet.length() - 3));
+    } else {
+      uncompressedPacketParser.execute(packet.buffer, packet.offset, packet.end);
+    }
+  });
+  inflateStream.on('data', function(buff) {
+    uncompressedPacketParser.execute(buff.parent, buff.offset, buff.offset + buff.length);
+  });
+  if (this.stream.ondata)
+    this.stream.ondata = null;
+  this.stream.removeAllListeners('data');
+  this.pipe();
+};
+
+Connection.prototype.pipe = function() {
+  var connection = this;
+  if (this.stream instanceof net.Stream) {
+    this.stream.ondata = function(data, start, end) {
+      connection.packetParser.execute(data, start, end);
+    };
+  } else {
+    this.stream.on('data', function(data) {
+      connection.packetParser.execute(data.parent, data.offset, data.offset + data.length);
+    });
+  }
+};
+
+Connection.prototype.protocolError = function(message, code) {
+  var err = new Error(message);
+  err.fatal = true;
+  err.code = code || 'PROTOCOL_ERROR';
+  this.emit('error', err);
+}
+
+Connection.prototype.handlePacket = function(packet) {
+
+  if (this._paused)
+  {
+    this._paused_packets.push(packet);
+    return;
+  }
+
+  // TODO: check packet sequenceId here
+  if (packet)
+    this.sequenceId = packet.sequenceId + 1;
+  if (this.config.debug) {
+    if (packet) {
+      console.log(this._internalId + ' ' + this.connectionId + ' ==> ' + this._command._commandName + '#' + this._command.stateName() + '(' + [packet.sequenceId, packet.type(), packet.length()].join(',') + ')');
+      console.log(' raw: ' + packet.buffer.slice(packet.offset, packet.offset + packet.length()).toString('hex'));
+    }
+  }
+  if (!this._command) {
+    this.protocolError('Unexpected packet while no commands in the queue', 'PROTOCOL_UNEXPECTED_PACKET');
+    return this.close();
+  }
+  var done = this._command.execute(packet, this);
+  if (done) {
+    this.sequenceId = 0;
+    this._command = this._commands.shift();
+    if (this._command)
+      this.handlePacket();
+  }
+};
+
+Connection.prototype.addCommand = function(cmd) {
+  if (this.config.debug) {
+    console.log('Add command: ' + arguments.callee.caller.name);
+    cmd._commandName = arguments.callee.caller.name;
+  }
+  if (!this._command) {
+    this._command = cmd;
+    this.handlePacket();
+  } else {
+    this._commands.push(cmd);
+  }
+  return cmd;
+};
+
+Connection.prototype.format = function(sql, values) {
+  if (typeof this.config.queryFormat == "function") {
+    return this.config.queryFormat.call(this, sql, values, this.config.timezone);
+  }
+  var opts = {
+    sql: sql,
+    values: values
+  };
+  this._resolveNamedPlaceholders(opts);
+  return SqlString.format(opts.sql, opts.values, this.config.stringifyObjects, this.config.timezone);
+};
+
+Connection.prototype.escape = function(value) {
+  return SqlString.escape(value, false, this.config.timezone);
+};
+
+Connection.prototype.escapeId = function escapeId(value) {
+  return SqlString.escapeId(value, false);
+};
+
+function _domainify(callback) {
+  var domain = process.domain;
+  if (domain && callback)
+    return process.domain.bind(callback);
+  else
+    return callback;
+}
+
+var convertNamedPlaceholders = null;
+Connection.prototype._resolveNamedPlaceholders = function(options) {
+  var unnamed;
+  if (this.config.namedPlaceholders || options.namedPlaceholders) {
+    if (convertNamedPlaceholders === null)
+      convertNamedPlaceholders = require('named-placeholders')();
+    unnamed = convertNamedPlaceholders(options.sql, options.values);
+    options.sql = unnamed[0];
+    options.values = unnamed[1];
+  }
+};
+
+Connection.prototype.query = function query(sql, values, cb) {
+  // copy-paste from node-mysql/lib/Connection.js:createQuery
+  var options = {};
+  if (typeof sql === 'object') {
+    // query(options, cb)
+    options = sql;
+    if (typeof values === 'function') {
+      cb = values;
+    } else {
+      options.values = values;
+    }
+  } else if (typeof values === 'function') {
+    // query(sql, cb)
+    cb             = values;
+    options.sql    = sql;
+    options.values = undefined;
+  } else {
+    // query(sql, values, cb)
+    options.sql    = sql;
+    options.values = values;
+  }
+
+  this._resolveNamedPlaceholders(options);
+  var rawSql = this.format(options.sql, options.values || []);
+  return this.addCommand(new Commands.Query(rawSql, options, _domainify(cb)));
+};
+
+Connection.prototype.pause = function pause() {
+  this._paused = true;
+  this.stream.pause();
+};
+
+Connection.prototype.resume= function resume() {
+  var packet;
+  this._paused = false;
+  while( packet = this._paused_packets.shift() ) {
+    this.handlePacket(packet);
+    // don't resume if packet hander paused connection
+    if (this._paused)
+      return;
+  }
+  this.stream.resume();
+};
+
+Connection.prototype.keyFromFields = function keyFromFields(fields, options) {
+  var res = (typeof options.nestTables) + '/' + options.nestTables + '/' + options.rowsAsHash;
+  for (var i=0; i < fields.length; ++i)
+    res += '/' + fields[i].name + ':' + fields[i].columnType + ':' + fields[i].flags;
+  return res;
+}
+
+function statementKey(options) {
+  return (typeof options.nestTables) +
+    '/' + options.nestTables + '/' + options.rowsAsHash + options.sql;
+}
+
+// TODO: named placeholders support
+Connection.prototype.prepare = function prepare(options, cb) {
+  if (typeof options == 'string')
+    options = { sql: options };
+  return this.addCommand(new Commands.Prepare(options, _domainify(cb)));
+};
+
+Connection.prototype.unprepare = function execute(sql) {
+  var options = {};
+  if (typeof sql === 'object') {
+    options = sql;
+  } else
+    options.sql    = sql;
+  var key  = statementKey(options);
+  var stmt = this._statements[key];
+  if (stmt) {
+    this._statements[key] = null;
+    stmt.close();
+  }
+  return stmt;
+};
+
+Connection.prototype.execute = function execute(sql, values, cb) {
+  var options = {};
+  if (typeof sql === 'object') {
+    // execute(options, cb)
+    options = sql;
+    if (typeof values === 'function') {
+      cb = values;
+    } else {
+      options.values = values;
+    }
+  } else if (typeof values === 'function') {
+    // execute(sql, cb)
+    cb             = values;
+    options.sql    = sql;
+    options.values = undefined;
+  } else {
+    // execute(sql, values, cb)
+    options.sql    = sql;
+    options.values = values;
+  }
+  cb = _domainify(cb);
+  this._resolveNamedPlaceholders(options);
+
+  var connection = this;
+  var key = statementKey(options);
+  var statement = connection._statements[key];
+
+  options.statement = statement;
+  var executeCommand = new Commands.Execute(options, cb);
+
+  if (!statement) {
+    connection.prepare(options, function executeStatement(err, stmt) {
+      if (err) {
+        if (cb)
+          cb(err);
+        else
+          executeCommand.emit('error', err);
+        return;
+      }
+      executeCommand.statement = stmt;
+      connection._statements[key] = stmt;
+      connection.addCommand(executeCommand);
+    });
+  } else {
+    connection.addCommand(executeCommand);
+  }
+  return executeCommand;
+};
+
+Connection.prototype.changeUser = function changeUser(options, callback) {
+  if (!callback && typeof options === 'function') {
+    callback = options;
+    options = {};
+  }
+
+  var charsetNumber = (options.charset) ? ConnectionConfig.getCharsetNumber(options.charset) : this.config.charsetNumber;
+
+  return this.addCommand(new Commands.ChangeUser({
+    user          : options.user || this.config.user,
+    password      : options.password || this.config.password,
+    passwordSha1  : options.passwordSha1 || this.config.passwordSha1,
+    database      : options.database || this.config.database,
+    timeout       : options.timeout,
+    charsetNumber : charsetNumber,
+    currentConfig : this.config
+  }, _domainify(function(err) {
+    if (err)
+      err.fatal = true;
+    if (callback) callback(err);
+  })));
+};
+
+// transaction helpers
+Connection.prototype.beginTransaction = function(cb) {
+  return this.query('START TRANSACTION', cb);
+};
+
+Connection.prototype.commit = function(cb) {
+  return this.query('COMMIT', cb);
+};
+
+Connection.prototype.rollback = function(cb) {
+  return this.query('ROLLBACK', cb);
+};
+
+Connection.prototype.ping = function ping(cb) {
+  return this.addCommand(new Commands.Ping(_domainify(cb)));
+};
+
+Connection.prototype._registerSlave = function registerSlave(opts, cb) {
+  return this.addCommand(new Commands.RegisterSlave(opts, _domainify(cb)));
+};
+
+Connection.prototype._binlogDump = function binlogDump(opts, cb) {
+  return this.addCommand(new Commands.BinlogDump(opts, _domainify(cb)));
+};
+
+// currently just alias to close
+Connection.prototype.destroy = function() {
+  this.close();
+};
+
+Connection.prototype.close = function() {
+  this._closing = true;
+  this.stream.end();
+};
+
+Connection.prototype.createBinlogStream = function(opts) {
+  // TODO: create proper stream class
+  // TODO: use through2
+  var test = 1;
+  var Readable = require('stream').Readable;
+  var stream = new Readable({objectMode: true});
+  stream._read = function() {
+    return {
+      data: test++
+    };
+  };
+  var connection = this;
+  connection._registerSlave(opts, function(err) {
+    var dumpCmd = connection._binlogDump(opts);
+    dumpCmd.on('event', function(ev) {
+      stream.push(ev);
+    });
+    dumpCmd.on('eof', function() {
+      stream.push(null);
+      // if non-blocking, then close stream to prevent errors
+      if (opts.flags && (opts.flags & 0x01)) {
+        connection.close();
+      }
+    });
+    // TODO: pipe errors as well
+  });
+  return stream;
+};
+
+Connection.prototype.connect = function(cb) {
+  if (!cb) return;
+  var connectCalled = 0;
+
+  // TODO domainify this callback as well. Note that domain has to be captured
+  // at the top of function due to nested callback
+  function callbackOnce(isErrorHandler) {
+    return function(param) {
+      if (!connectCalled) {
+        if (isErrorHandler)
+          cb(param);
+        else
+          cb(null, param);
+      }
+      connectCalled = 1;
+    };
+  }
+  this.once('error',   callbackOnce(true) );
+  this.once('connect', callbackOnce(false));
+};
+
+// ===================================
+// outgoing server connection methods
+// ===================================
+
+Connection.prototype.writeColumns = function(columns) {
+  var connection = this;
+  this.writePacket(Packets.ResultSetHeader.toPacket(columns.length));
+  columns.forEach(function(column) {
+    connection.writePacket(Packets.ColumnDefinition.toPacket(column));
+  });
+  this.writeEof();
+};
+
+// row is array of columns, not hash
+Connection.prototype.writeTextRow = function(column) {
+  this.writePacket(Packets.TextRow.toPacket(column));
+};
+
+Connection.prototype.writeTextResult = function(rows, columns) {
+  var connection = this;
+  connection.writeColumns(columns);
+  rows.forEach(function(row) {
+    var arrayRow = new Array(columns.length);
+    columns.forEach(function(column) {
+      arrayRow.push(row[column.name]);
+    });
+    connection.writeTextRow(arrayRow);
+  });
+  connection.writeEof();
+};
+
+Connection.prototype.writeEof = function(warnings, statusFlags) {
+  this.writePacket(Packets.EOF.toPacket(warnings, statusFlags));
+};
+
+Connection.prototype.writeOk = function(args) {
+  if (!args)
+    args = { affectedRows: 0 };
+  this.writePacket(Packets.OK.toPacket(args));
+};
+
+Connection.prototype.writeError = function(args) {
+  this.writePacket(Packets.Error.toPacket(args));
+};
+
+Connection.prototype.serverHandshake = function serverHandshake(args) {
+  return this.addCommand(new Commands.ServerHandshake(args));
+};
+
+// ===============================================================
+
+// TODO: domainify
+Connection.prototype.end = function(callback) {
+  var connection = this;
+  // trigger error if more commands enqueued after end command
+  var quitCmd =  this.addCommand(new Commands.Quit(callback));
+  connection.addCommand = function() {
+    if (connection._closing) {
+      this.emit(new Error('addCommand() called on closing connection'));
+    }
+  };
+  return quitCmd;
+};
+
+module.exports = Connection;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/connection_config.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/connection_config.js
new file mode 100644
index 0000000000000000000000000000000000000000..e09e4b8666d49062395b14854e27b0809df09996
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/connection_config.js
@@ -0,0 +1,156 @@
+var urlParse        = require('url').parse;
+var ClientConstants = require('./constants/client');
+var Charsets        = require('./constants/charsets');
+var SSLProfiles     = null;
+
+module.exports = ConnectionConfig;
+function ConnectionConfig(options) {
+  if (typeof options === 'string') {
+    options = ConnectionConfig.parseUrl(options);
+  }
+
+  this.isServer           = options.isServer;
+  this.stream             = options.stream;
+
+  this.host               = options.host || 'localhost';
+  this.port               = options.port || 3306;
+  this.localAddress       = options.localAddress;
+  this.socketPath         = options.socketPath;
+  this.user               = options.user || undefined;
+  this.password           = options.password || undefined;
+  this.passwordSha1       = options.passwordSha1 || undefined;
+  this.database           = options.database;
+  this.connectTimeout     = (options.connectTimeout === undefined)
+    ? (10 * 1000)
+    : options.connectTimeout;
+  this.insecureAuth       = options.insecureAuth || false;
+  this.supportBigNumbers  = options.supportBigNumbers || false;
+  this.bigNumberStrings   = options.bigNumberStrings || false;
+  this.dateStrings        = options.dateStrings || false;
+  this.debug              = options.debug;
+  this.trace              = options.trace !== false;
+  this.stringifyObjects   = options.stringifyObjects || false;
+  this.timezone           = options.timezone || 'local';
+  this.flags              = options.flags || '';
+  this.queryFormat        = options.queryFormat;
+  this.pool               = options.pool || undefined;
+  this.ssl                = (typeof options.ssl === 'string')
+    ? ConnectionConfig.getSSLProfile(options.ssl)
+    : (options.ssl || false);
+  this.multipleStatements = options.multipleStatements || false;
+  this.namedPlaceholders  = options.namedPlaceholders || false;
+  this.typeCast           = (options.typeCast === undefined)
+    ? true
+    : options.typeCast;
+
+  if (this.timezone[0] == " ") {
+    // "+" is a url encoded char for space so it
+    // gets translated to space when giving a
+    // connection string..
+    this.timezone = "+" + this.timezone.substr(1);
+  }
+
+  if (this.ssl) {
+    // Default rejectUnauthorized to true
+    this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
+  }
+
+  this.maxPacketSize = 0;
+  this.charsetNumber = (options.charset)
+    ? ConnectionConfig.getCharsetNumber(options.charset)
+    : options.charsetNumber||Charsets.UTF8_GENERAL_CI;
+
+  this.clientFlags = ConnectionConfig.mergeFlags(ConnectionConfig.getDefaultFlags(options),
+                                                 options.flags || '');
+}
+
+ConnectionConfig.mergeFlags = function(default_flags, user_flags) {
+  var flags = 0x0, i;
+
+  user_flags = (user_flags || '').toUpperCase().split(/\s*,+\s*/);
+
+  // add default flags unless "blacklisted"
+  for (i in default_flags) {
+    if (user_flags.indexOf("-" + default_flags[i]) >= 0) continue;
+
+    flags |= ClientConstants[default_flags[i]] || 0x0;
+  }
+  // add user flags unless already already added
+  for (i in user_flags) {
+    if (user_flags[i][0] == "-") continue;
+    if (default_flags.indexOf(user_flags[i]) >= 0) continue;
+
+    flags |= ClientConstants[user_flags[i]] || 0x0;
+  }
+
+  return flags;
+};
+
+ConnectionConfig.getDefaultFlags = function(options) {
+  var defaultFlags = [ "LONG_PASSWORD", "FOUND_ROWS", "LONG_FLAG",
+                        "CONNECT_WITH_DB", "ODBC", "LOCAL_FILES",
+                        "IGNORE_SPACE", "PROTOCOL_41", "IGNORE_SIGPIPE",
+                        "TRANSACTIONS", "RESERVED", "SECURE_CONNECTION",
+                        "MULTI_RESULTS" ];
+  if (options && options.multipleStatements) {
+    defaultFlags.push("MULTI_STATEMENTS");
+  }
+
+  return defaultFlags;
+};
+
+ConnectionConfig.getCharsetNumber = function getCharsetNumber(charset) {
+  var num = Charsets[charset.toUpperCase()];
+
+  if (num === undefined) {
+    throw new TypeError('Unknown charset \'' + charset + '\'');
+  }
+
+  return num;
+};
+
+ConnectionConfig.getSSLProfile = function getSSLProfile(name) {
+  if (!SSLProfiles) {
+    SSLProfiles = require('./constants/ssl_profiles.js');
+  }
+
+  var ssl = SSLProfiles[name];
+
+  if (ssl === undefined) {
+    throw new TypeError('Unknown SSL profile \'' + name + '\'');
+  }
+
+  return ssl;
+};
+
+ConnectionConfig.parseUrl = function(url) {
+  url = urlParse(url, true);
+
+  var options = {
+    host     : url.hostname,
+    port     : url.port,
+    database : url.pathname.substr(1),
+  };
+
+  if (url.auth) {
+    var auth = url.auth.split(':');
+    options.user     = auth[0];
+    options.password = auth[1];
+  }
+
+  if (url.query) {
+    for (var key in url.query) {
+      var value = url.query[key];
+
+      try {
+        // Try to parse this as a JSON expression first
+        options[key] = JSON.parse(value);
+      } catch (err) {
+        // Otherwise assume it is a plain string
+        options[key] = value;
+      }
+    }
+  }
+
+  return options;
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/charsets.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/charsets.js
new file mode 100644
index 0000000000000000000000000000000000000000..5883964e2d1a1b4b866ee138581114efed0d9298
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/charsets.js
@@ -0,0 +1,195 @@
+exports.BIG5_CHINESE_CI        = 1;
+exports.LATIN2_CZECH_CS        = 2;
+exports.DEC8_SWEDISH_CI        = 3;
+exports.CP850_GENERAL_CI       = 4;
+exports.LATIN1_GERMAN1_CI      = 5;
+exports.HP8_ENGLISH_CI         = 6;
+exports.KOI8R_GENERAL_CI       = 7;
+exports.LATIN1_SWEDISH_CI      = 8;
+exports.LATIN2_GENERAL_CI      = 9;
+exports.SWE7_SWEDISH_CI        = 10;
+exports.ASCII_GENERAL_CI       = 11;
+exports.UJIS_JAPANESE_CI       = 12;
+exports.SJIS_JAPANESE_CI       = 13;
+exports.CP1251_BULGARIAN_CI    = 14;
+exports.LATIN1_DANISH_CI       = 15;
+exports.HEBREW_GENERAL_CI      = 16;
+exports.TIS620_THAI_CI         = 18;
+exports.EUCKR_KOREAN_CI        = 19;
+exports.LATIN7_ESTONIAN_CS     = 20;
+exports.LATIN2_HUNGARIAN_CI    = 21;
+exports.KOI8U_GENERAL_CI       = 22;
+exports.CP1251_UKRAINIAN_CI    = 23;
+exports.GB2312_CHINESE_CI      = 24;
+exports.GREEK_GENERAL_CI       = 25;
+exports.CP1250_GENERAL_CI      = 26;
+exports.LATIN2_CROATIAN_CI     = 27;
+exports.GBK_CHINESE_CI         = 28;
+exports.CP1257_LITHUANIAN_CI   = 29;
+exports.LATIN5_TURKISH_CI      = 30;
+exports.LATIN1_GERMAN2_CI      = 31;
+exports.ARMSCII8_GENERAL_CI    = 32;
+exports.UTF8_GENERAL_CI        = 33;
+exports.CP1250_CZECH_CS        = 34;
+exports.UCS2_GENERAL_CI        = 35;
+exports.CP866_GENERAL_CI       = 36;
+exports.KEYBCS2_GENERAL_CI     = 37;
+exports.MACCE_GENERAL_CI       = 38;
+exports.MACROMAN_GENERAL_CI    = 39;
+exports.CP852_GENERAL_CI       = 40;
+exports.LATIN7_GENERAL_CI      = 41;
+exports.LATIN7_GENERAL_CS      = 42;
+exports.MACCE_BIN              = 43;
+exports.CP1250_CROATIAN_CI     = 44;
+exports.UTF8MB4_GENERAL_CI     = 45;
+exports.UTF8MB4_BIN            = 46;
+exports.LATIN1_BIN             = 47;
+exports.LATIN1_GENERAL_CI      = 48;
+exports.LATIN1_GENERAL_CS      = 49;
+exports.CP1251_BIN             = 50;
+exports.CP1251_GENERAL_CI      = 51;
+exports.CP1251_GENERAL_CS      = 52;
+exports.MACROMAN_BIN           = 53;
+exports.UTF16_GENERAL_CI       = 54;
+exports.UTF16_BIN              = 55;
+exports.CP1256_GENERAL_CI      = 57;
+exports.CP1257_BIN             = 58;
+exports.CP1257_GENERAL_CI      = 59;
+exports.UTF32_GENERAL_CI       = 60;
+exports.UTF32_BIN              = 61;
+exports.BINARY                 = 63;
+exports.ARMSCII8_BIN           = 64;
+exports.ASCII_BIN              = 65;
+exports.CP1250_BIN             = 66;
+exports.CP1256_BIN             = 67;
+exports.CP866_BIN              = 68;
+exports.DEC8_BIN               = 69;
+exports.GREEK_BIN              = 70;
+exports.HEBREW_BIN             = 71;
+exports.HP8_BIN                = 72;
+exports.KEYBCS2_BIN            = 73;
+exports.KOI8R_BIN              = 74;
+exports.KOI8U_BIN              = 75;
+exports.LATIN2_BIN             = 77;
+exports.LATIN5_BIN             = 78;
+exports.LATIN7_BIN             = 79;
+exports.CP850_BIN              = 80;
+exports.CP852_BIN              = 81;
+exports.SWE7_BIN               = 82;
+exports.UTF8_BIN               = 83;
+exports.BIG5_BIN               = 84;
+exports.EUCKR_BIN              = 85;
+exports.GB2312_BIN             = 86;
+exports.GBK_BIN                = 87;
+exports.SJIS_BIN               = 88;
+exports.TIS620_BIN             = 89;
+exports.UCS2_BIN               = 90;
+exports.UJIS_BIN               = 91;
+exports.GEOSTD8_GENERAL_CI     = 92;
+exports.GEOSTD8_BIN            = 93;
+exports.LATIN1_SPANISH_CI      = 94;
+exports.CP932_JAPANESE_CI      = 95;
+exports.CP932_BIN              = 96;
+exports.EUCJPMS_JAPANESE_CI    = 97;
+exports.EUCJPMS_BIN            = 98;
+exports.CP1250_POLISH_CI       = 99;
+exports.UTF16_UNICODE_CI       = 101;
+exports.UTF16_ICELANDIC_CI     = 102;
+exports.UTF16_LATVIAN_CI       = 103;
+exports.UTF16_ROMANIAN_CI      = 104;
+exports.UTF16_SLOVENIAN_CI     = 105;
+exports.UTF16_POLISH_CI        = 106;
+exports.UTF16_ESTONIAN_CI      = 107;
+exports.UTF16_SPANISH_CI       = 108;
+exports.UTF16_SWEDISH_CI       = 109;
+exports.UTF16_TURKISH_CI       = 110;
+exports.UTF16_CZECH_CI         = 111;
+exports.UTF16_DANISH_CI        = 112;
+exports.UTF16_LITHUANIAN_CI    = 113;
+exports.UTF16_SLOVAK_CI        = 114;
+exports.UTF16_SPANISH2_CI      = 115;
+exports.UTF16_ROMAN_CI         = 116;
+exports.UTF16_PERSIAN_CI       = 117;
+exports.UTF16_ESPERANTO_CI     = 118;
+exports.UTF16_HUNGARIAN_CI     = 119;
+exports.UTF16_SINHALA_CI       = 120;
+exports.UCS2_UNICODE_CI        = 128;
+exports.UCS2_ICELANDIC_CI      = 129;
+exports.UCS2_LATVIAN_CI        = 130;
+exports.UCS2_ROMANIAN_CI       = 131;
+exports.UCS2_SLOVENIAN_CI      = 132;
+exports.UCS2_POLISH_CI         = 133;
+exports.UCS2_ESTONIAN_CI       = 134;
+exports.UCS2_SPANISH_CI        = 135;
+exports.UCS2_SWEDISH_CI        = 136;
+exports.UCS2_TURKISH_CI        = 137;
+exports.UCS2_CZECH_CI          = 138;
+exports.UCS2_DANISH_CI         = 139;
+exports.UCS2_LITHUANIAN_CI     = 140;
+exports.UCS2_SLOVAK_CI         = 141;
+exports.UCS2_SPANISH2_CI       = 142;
+exports.UCS2_ROMAN_CI          = 143;
+exports.UCS2_PERSIAN_CI        = 144;
+exports.UCS2_ESPERANTO_CI      = 145;
+exports.UCS2_HUNGARIAN_CI      = 146;
+exports.UCS2_SINHALA_CI        = 147;
+exports.UTF32_UNICODE_CI       = 160;
+exports.UTF32_ICELANDIC_CI     = 161;
+exports.UTF32_LATVIAN_CI       = 162;
+exports.UTF32_ROMANIAN_CI      = 163;
+exports.UTF32_SLOVENIAN_CI     = 164;
+exports.UTF32_POLISH_CI        = 165;
+exports.UTF32_ESTONIAN_CI      = 166;
+exports.UTF32_SPANISH_CI       = 167;
+exports.UTF32_SWEDISH_CI       = 168;
+exports.UTF32_TURKISH_CI       = 169;
+exports.UTF32_CZECH_CI         = 170;
+exports.UTF32_DANISH_CI        = 171;
+exports.UTF32_LITHUANIAN_CI    = 172;
+exports.UTF32_SLOVAK_CI        = 173;
+exports.UTF32_SPANISH2_CI      = 174;
+exports.UTF32_ROMAN_CI         = 175;
+exports.UTF32_PERSIAN_CI       = 176;
+exports.UTF32_ESPERANTO_CI     = 177;
+exports.UTF32_HUNGARIAN_CI     = 178;
+exports.UTF32_SINHALA_CI       = 179;
+exports.UTF8_UNICODE_CI        = 192;
+exports.UTF8_ICELANDIC_CI      = 193;
+exports.UTF8_LATVIAN_CI        = 194;
+exports.UTF8_ROMANIAN_CI       = 195;
+exports.UTF8_SLOVENIAN_CI      = 196;
+exports.UTF8_POLISH_CI         = 197;
+exports.UTF8_ESTONIAN_CI       = 198;
+exports.UTF8_SPANISH_CI        = 199;
+exports.UTF8_SWEDISH_CI        = 200;
+exports.UTF8_TURKISH_CI        = 201;
+exports.UTF8_CZECH_CI          = 202;
+exports.UTF8_DANISH_CI         = 203;
+exports.UTF8_LITHUANIAN_CI     = 204;
+exports.UTF8_SLOVAK_CI         = 205;
+exports.UTF8_SPANISH2_CI       = 206;
+exports.UTF8_ROMAN_CI          = 207;
+exports.UTF8_PERSIAN_CI        = 208;
+exports.UTF8_ESPERANTO_CI      = 209;
+exports.UTF8_HUNGARIAN_CI      = 210;
+exports.UTF8_SINHALA_CI        = 211;
+exports.UTF8MB4_UNICODE_CI     = 224;
+exports.UTF8MB4_ICELANDIC_CI   = 225;
+exports.UTF8MB4_LATVIAN_CI     = 226;
+exports.UTF8MB4_ROMANIAN_CI    = 227;
+exports.UTF8MB4_SLOVENIAN_CI   = 228;
+exports.UTF8MB4_POLISH_CI      = 229;
+exports.UTF8MB4_ESTONIAN_CI    = 230;
+exports.UTF8MB4_SPANISH_CI     = 231;
+exports.UTF8MB4_SWEDISH_CI     = 232;
+exports.UTF8MB4_TURKISH_CI     = 233;
+exports.UTF8MB4_CZECH_CI       = 234;
+exports.UTF8MB4_DANISH_CI      = 235;
+exports.UTF8MB4_LITHUANIAN_CI  = 236;
+exports.UTF8MB4_SLOVAK_CI      = 237;
+exports.UTF8MB4_SPANISH2_CI    = 238;
+exports.UTF8MB4_ROMAN_CI       = 239;
+exports.UTF8MB4_PERSIAN_CI     = 240;
+exports.UTF8MB4_ESPERANTO_CI   = 241;
+exports.UTF8MB4_HUNGARIAN_CI   = 242;
+exports.UTF8MB4_SINHALA_CI     = 243;
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/client.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/client.js
new file mode 100644
index 0000000000000000000000000000000000000000..119488eb1a411c5eaf94871e42a8f7a7cdc60445
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/client.js
@@ -0,0 +1,26 @@
+// Manually extracted from mysql-5.5.23/include/mysql_com.h
+exports.LONG_PASSWORD     = 1; /* new more secure passwords */
+exports.FOUND_ROWS        = 2; /* Found instead of affected rows */
+exports.LONG_FLAG         = 4; /* Get all column flags */
+exports.CONNECT_WITH_DB   = 8; /* One can specify db on connect */
+exports.NO_SCHEMA         = 16; /* Don't allow database.table.column */
+exports.COMPRESS          = 32; /* Can use compression protocol */
+exports.ODBC              = 64; /* Odbc client */
+exports.LOCAL_FILES       = 128; /* Can use LOAD DATA LOCAL */
+exports.IGNORE_SPACE      = 256; /* Ignore spaces before '(' */
+exports.PROTOCOL_41       = 512; /* New 4.1 protocol */
+exports.INTERACTIVE       = 1024; /* This is an interactive client */
+exports.SSL               = 2048; /* Switch to SSL after handshake */
+exports.IGNORE_SIGPIPE    = 4096;    /* IGNORE sigpipes */
+exports.TRANSACTIONS      = 8192; /* Client knows about transactions */
+exports.RESERVED          = 16384;   /* Old flag for 4.1 protocol  */
+exports.SECURE_CONNECTION = 32768;  /* New 4.1 authentication */
+
+exports.MULTI_STATEMENTS = 65536; /* Enable/disable multi-stmt support */
+exports.MULTI_RESULTS    = 131072; /* Enable/disable multi-results */
+exports.PS_MULTI_RESULTS = 262144; /* Multi-results in PS-protocol */
+
+exports.PLUGIN_AUTH = 524288; /* Client supports plugin authentication */
+
+exports.SSL_VERIFY_SERVER_CERT = 1073741824;
+exports.REMEMBER_OPTIONS       = 2147483648;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/commands.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/commands.js
new file mode 100644
index 0000000000000000000000000000000000000000..adf0c1e5721ef76cfb09f518ac8eeae38f967f07
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/commands.js
@@ -0,0 +1,34 @@
+module.exports = {
+  SLEEP              : 0x00,  // deprecated
+  QUIT               : 0x01,
+  INIT_DB            : 0x02,
+  QUERY              : 0x03,
+  FIELD_LIST         : 0x04,
+  CREATE_DB          : 0x05,
+  DROP_DB            : 0x06,
+  REFRESH            : 0x07,
+  SHUTDOWN           : 0x08,
+  STATISTICS         : 0x09,
+  PROCESS_INFO       : 0x0a,  // deprecated
+  CONNECT            : 0x0b,  // deprecated
+  PROCESS_KILL       : 0x0c,
+  DEBUG              : 0x0d,
+  PING               : 0x0e,
+  TIME               : 0x0f,  // deprecated
+  DELAYED_INSERT     : 0x10,  // deprecated
+  CHANGE_USER        : 0x11,
+  BINLOG_DUMP        : 0x12,
+  TABLE_DUMP         : 0x13,
+  CONNECT_OUT        : 0x14,
+  REGISTER_SLAVE     : 0x15,
+  STMT_PREPARE       : 0x16,
+  STMT_EXECUTE       : 0x17,
+  STMT_SEND_LONG_DATA: 0x18,
+  STMT_CLOSE         : 0x19,
+  STMT_RESET         : 0x1a,
+  SET_OPTION         : 0x1b,
+  STMT_FETCH         : 0x1c,
+  DAEMON             : 0x1d,  // deprecated
+  BINLOG_DUMP_GTID   : 0x1e,
+  UNKNOWN            : 0xff   // bad!
+};
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/cursor.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/cursor.js
new file mode 100644
index 0000000000000000000000000000000000000000..97e3d3ef282ca401123ebac44c38dad20eaa7b2e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/cursor.js
@@ -0,0 +1,6 @@
+module.exports = {
+  NO_CURSOR: 0,
+  READ_ONLY: 1,
+  FOR_UPDATE: 2,
+  SCROLLABLE: 3
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/errors.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/errors.js
new file mode 100644
index 0000000000000000000000000000000000000000..5fcd72bb31b7590f5a9feb1fb677e28468e24915
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/errors.js
@@ -0,0 +1,726 @@
+// Generated by generate-error-constants.js, do not modify by hand
+module.exports.codeToName  = [];
+module.exports.codeToName[1000] = 'ER_HASHCHK';
+module.exports.codeToName[1001] = 'ER_NISAMCHK';
+module.exports.codeToName[1002] = 'ER_NO';
+module.exports.codeToName[1003] = 'ER_YES';
+module.exports.codeToName[1004] = 'ER_CANT_CREATE_FILE';
+module.exports.codeToName[1005] = 'ER_CANT_CREATE_TABLE';
+module.exports.codeToName[1006] = 'ER_CANT_CREATE_DB';
+module.exports.codeToName[1007] = 'ER_DB_CREATE_EXISTS';
+module.exports.codeToName[1008] = 'ER_DB_DROP_EXISTS';
+module.exports.codeToName[1009] = 'ER_DB_DROP_DELETE';
+module.exports.codeToName[1010] = 'ER_DB_DROP_RMDIR';
+module.exports.codeToName[1011] = 'ER_CANT_DELETE_FILE';
+module.exports.codeToName[1012] = 'ER_CANT_FIND_SYSTEM_REC';
+module.exports.codeToName[1013] = 'ER_CANT_GET_STAT';
+module.exports.codeToName[1014] = 'ER_CANT_GET_WD';
+module.exports.codeToName[1015] = 'ER_CANT_LOCK';
+module.exports.codeToName[1016] = 'ER_CANT_OPEN_FILE';
+module.exports.codeToName[1017] = 'ER_FILE_NOT_FOUND';
+module.exports.codeToName[1018] = 'ER_CANT_READ_DIR';
+module.exports.codeToName[1019] = 'ER_CANT_SET_WD';
+module.exports.codeToName[1020] = 'ER_CHECKREAD';
+module.exports.codeToName[1021] = 'ER_DISK_FULL';
+module.exports.codeToName[1022] = 'ER_DUP_KEY';
+module.exports.codeToName[1023] = 'ER_ERROR_ON_CLOSE';
+module.exports.codeToName[1024] = 'ER_ERROR_ON_READ';
+module.exports.codeToName[1025] = 'ER_ERROR_ON_RENAME';
+module.exports.codeToName[1026] = 'ER_ERROR_ON_WRITE';
+module.exports.codeToName[1027] = 'ER_FILE_USED';
+module.exports.codeToName[1028] = 'ER_FILSORT_ABORT';
+module.exports.codeToName[1029] = 'ER_FORM_NOT_FOUND';
+module.exports.codeToName[1030] = 'ER_GET_ERRNO';
+module.exports.codeToName[1031] = 'ER_ILLEGAL_HA';
+module.exports.codeToName[1032] = 'ER_KEY_NOT_FOUND';
+module.exports.codeToName[1033] = 'ER_NOT_FORM_FILE';
+module.exports.codeToName[1034] = 'ER_NOT_KEYFILE';
+module.exports.codeToName[1035] = 'ER_OLD_KEYFILE';
+module.exports.codeToName[1036] = 'ER_OPEN_AS_READONLY';
+module.exports.codeToName[1037] = 'ER_OUTOFMEMORY';
+module.exports.codeToName[1038] = 'ER_OUT_OF_SORTMEMORY';
+module.exports.codeToName[1039] = 'ER_UNEXPECTED_EOF';
+module.exports.codeToName[1040] = 'ER_CON_COUNT_ERROR';
+module.exports.codeToName[1041] = 'ER_OUT_OF_RESOURCES';
+module.exports.codeToName[1042] = 'ER_BAD_HOST_ERROR';
+module.exports.codeToName[1043] = 'ER_HANDSHAKE_ERROR';
+module.exports.codeToName[1044] = 'ER_DBACCESS_DENIED_ERROR';
+module.exports.codeToName[1045] = 'ER_ACCESS_DENIED_ERROR';
+module.exports.codeToName[1046] = 'ER_NO_DB_ERROR';
+module.exports.codeToName[1047] = 'ER_UNKNOWN_COM_ERROR';
+module.exports.codeToName[1048] = 'ER_BAD_NULL_ERROR';
+module.exports.codeToName[1049] = 'ER_BAD_DB_ERROR';
+module.exports.codeToName[1050] = 'ER_TABLE_EXISTS_ERROR';
+module.exports.codeToName[1051] = 'ER_BAD_TABLE_ERROR';
+module.exports.codeToName[1052] = 'ER_NON_UNIQ_ERROR';
+module.exports.codeToName[1053] = 'ER_SERVER_SHUTDOWN';
+module.exports.codeToName[1054] = 'ER_BAD_FIELD_ERROR';
+module.exports.codeToName[1055] = 'ER_WRONG_FIELD_WITH_GROUP';
+module.exports.codeToName[1056] = 'ER_WRONG_GROUP_FIELD';
+module.exports.codeToName[1057] = 'ER_WRONG_SUM_SELECT';
+module.exports.codeToName[1058] = 'ER_WRONG_VALUE_COUNT';
+module.exports.codeToName[1059] = 'ER_TOO_LONG_IDENT';
+module.exports.codeToName[1060] = 'ER_DUP_FIELDNAME';
+module.exports.codeToName[1061] = 'ER_DUP_KEYNAME';
+module.exports.codeToName[1062] = 'ER_DUP_ENTRY';
+module.exports.codeToName[1063] = 'ER_WRONG_FIELD_SPEC';
+module.exports.codeToName[1064] = 'ER_PARSE_ERROR';
+module.exports.codeToName[1065] = 'ER_EMPTY_QUERY';
+module.exports.codeToName[1066] = 'ER_NONUNIQ_TABLE';
+module.exports.codeToName[1067] = 'ER_INVALID_DEFAULT';
+module.exports.codeToName[1068] = 'ER_MULTIPLE_PRI_KEY';
+module.exports.codeToName[1069] = 'ER_TOO_MANY_KEYS';
+module.exports.codeToName[1070] = 'ER_TOO_MANY_KEY_PARTS';
+module.exports.codeToName[1071] = 'ER_TOO_LONG_KEY';
+module.exports.codeToName[1072] = 'ER_KEY_COLUMN_DOES_NOT_EXITS';
+module.exports.codeToName[1073] = 'ER_BLOB_USED_AS_KEY';
+module.exports.codeToName[1074] = 'ER_TOO_BIG_FIELDLENGTH';
+module.exports.codeToName[1075] = 'ER_WRONG_AUTO_KEY';
+module.exports.codeToName[1076] = 'ER_READY';
+module.exports.codeToName[1077] = 'ER_NORMAL_SHUTDOWN';
+module.exports.codeToName[1078] = 'ER_GOT_SIGNAL';
+module.exports.codeToName[1079] = 'ER_SHUTDOWN_COMPLETE';
+module.exports.codeToName[1080] = 'ER_FORCING_CLOSE';
+module.exports.codeToName[1081] = 'ER_IPSOCK_ERROR';
+module.exports.codeToName[1082] = 'ER_NO_SUCH_INDEX';
+module.exports.codeToName[1083] = 'ER_WRONG_FIELD_TERMINATORS';
+module.exports.codeToName[1084] = 'ER_BLOBS_AND_NO_TERMINATED';
+module.exports.codeToName[1085] = 'ER_TEXTFILE_NOT_READABLE';
+module.exports.codeToName[1086] = 'ER_FILE_EXISTS_ERROR';
+module.exports.codeToName[1087] = 'ER_LOAD_INFO';
+module.exports.codeToName[1088] = 'ER_ALTER_INFO';
+module.exports.codeToName[1089] = 'ER_WRONG_SUB_KEY';
+module.exports.codeToName[1090] = 'ER_CANT_REMOVE_ALL_FIELDS';
+module.exports.codeToName[1091] = 'ER_CANT_DROP_FIELD_OR_KEY';
+module.exports.codeToName[1092] = 'ER_INSERT_INFO';
+module.exports.codeToName[1093] = 'ER_UPDATE_TABLE_USED';
+module.exports.codeToName[1094] = 'ER_NO_SUCH_THREAD';
+module.exports.codeToName[1095] = 'ER_KILL_DENIED_ERROR';
+module.exports.codeToName[1096] = 'ER_NO_TABLES_USED';
+module.exports.codeToName[1097] = 'ER_TOO_BIG_SET';
+module.exports.codeToName[1098] = 'ER_NO_UNIQUE_LOGFILE';
+module.exports.codeToName[1099] = 'ER_TABLE_NOT_LOCKED_FOR_WRITE';
+module.exports.codeToName[1100] = 'ER_TABLE_NOT_LOCKED';
+module.exports.codeToName[1101] = 'ER_BLOB_CANT_HAVE_DEFAULT';
+module.exports.codeToName[1102] = 'ER_WRONG_DB_NAME';
+module.exports.codeToName[1103] = 'ER_WRONG_TABLE_NAME';
+module.exports.codeToName[1104] = 'ER_TOO_BIG_SELECT';
+module.exports.codeToName[1105] = 'ER_UNKNOWN_ERROR';
+module.exports.codeToName[1106] = 'ER_UNKNOWN_PROCEDURE';
+module.exports.codeToName[1107] = 'ER_WRONG_PARAMCOUNT_TO_PROCEDURE';
+module.exports.codeToName[1108] = 'ER_WRONG_PARAMETERS_TO_PROCEDURE';
+module.exports.codeToName[1109] = 'ER_UNKNOWN_TABLE';
+module.exports.codeToName[1110] = 'ER_FIELD_SPECIFIED_TWICE';
+module.exports.codeToName[1111] = 'ER_INVALID_GROUP_FUNC_USE';
+module.exports.codeToName[1112] = 'ER_UNSUPPORTED_EXTENSION';
+module.exports.codeToName[1113] = 'ER_TABLE_MUST_HAVE_COLUMNS';
+module.exports.codeToName[1114] = 'ER_RECORD_FILE_FULL';
+module.exports.codeToName[1115] = 'ER_UNKNOWN_CHARACTER_SET';
+module.exports.codeToName[1116] = 'ER_TOO_MANY_TABLES';
+module.exports.codeToName[1117] = 'ER_TOO_MANY_FIELDS';
+module.exports.codeToName[1118] = 'ER_TOO_BIG_ROWSIZE';
+module.exports.codeToName[1119] = 'ER_STACK_OVERRUN';
+module.exports.codeToName[1120] = 'ER_WRONG_OUTER_JOIN';
+module.exports.codeToName[1121] = 'ER_NULL_COLUMN_IN_INDEX';
+module.exports.codeToName[1122] = 'ER_CANT_FIND_UDF';
+module.exports.codeToName[1123] = 'ER_CANT_INITIALIZE_UDF';
+module.exports.codeToName[1124] = 'ER_UDF_NO_PATHS';
+module.exports.codeToName[1125] = 'ER_UDF_EXISTS';
+module.exports.codeToName[1126] = 'ER_CANT_OPEN_LIBRARY';
+module.exports.codeToName[1127] = 'ER_CANT_FIND_DL_ENTRY';
+module.exports.codeToName[1128] = 'ER_FUNCTION_NOT_DEFINED';
+module.exports.codeToName[1129] = 'ER_HOST_IS_BLOCKED';
+module.exports.codeToName[1130] = 'ER_HOST_NOT_PRIVILEGED';
+module.exports.codeToName[1131] = 'ER_PASSWORD_ANONYMOUS_USER';
+module.exports.codeToName[1132] = 'ER_PASSWORD_NOT_ALLOWED';
+module.exports.codeToName[1133] = 'ER_PASSWORD_NO_MATCH';
+module.exports.codeToName[1134] = 'ER_UPDATE_INFO';
+module.exports.codeToName[1135] = 'ER_CANT_CREATE_THREAD';
+module.exports.codeToName[1136] = 'ER_WRONG_VALUE_COUNT_ON_ROW';
+module.exports.codeToName[1137] = 'ER_CANT_REOPEN_TABLE';
+module.exports.codeToName[1138] = 'ER_INVALID_USE_OF_NULL';
+module.exports.codeToName[1139] = 'ER_REGEXP_ERROR';
+module.exports.codeToName[1140] = 'ER_MIX_OF_GROUP_FUNC_AND_FIELDS';
+module.exports.codeToName[1141] = 'ER_NONEXISTING_GRANT';
+module.exports.codeToName[1142] = 'ER_TABLEACCESS_DENIED_ERROR';
+module.exports.codeToName[1143] = 'ER_COLUMNACCESS_DENIED_ERROR';
+module.exports.codeToName[1144] = 'ER_ILLEGAL_GRANT_FOR_TABLE';
+module.exports.codeToName[1145] = 'ER_GRANT_WRONG_HOST_OR_USER';
+module.exports.codeToName[1146] = 'ER_NO_SUCH_TABLE';
+module.exports.codeToName[1147] = 'ER_NONEXISTING_TABLE_GRANT';
+module.exports.codeToName[1148] = 'ER_NOT_ALLOWED_COMMAND';
+module.exports.codeToName[1149] = 'ER_SYNTAX_ERROR';
+module.exports.codeToName[1150] = 'ER_DELAYED_CANT_CHANGE_LOCK';
+module.exports.codeToName[1151] = 'ER_TOO_MANY_DELAYED_THREADS';
+module.exports.codeToName[1152] = 'ER_ABORTING_CONNECTION';
+module.exports.codeToName[1153] = 'ER_NET_PACKET_TOO_LARGE';
+module.exports.codeToName[1154] = 'ER_NET_READ_ERROR_FROM_PIPE';
+module.exports.codeToName[1155] = 'ER_NET_FCNTL_ERROR';
+module.exports.codeToName[1156] = 'ER_NET_PACKETS_OUT_OF_ORDER';
+module.exports.codeToName[1157] = 'ER_NET_UNCOMPRESS_ERROR';
+module.exports.codeToName[1158] = 'ER_NET_READ_ERROR';
+module.exports.codeToName[1159] = 'ER_NET_READ_INTERRUPTED';
+module.exports.codeToName[1160] = 'ER_NET_ERROR_ON_WRITE';
+module.exports.codeToName[1161] = 'ER_NET_WRITE_INTERRUPTED';
+module.exports.codeToName[1162] = 'ER_TOO_LONG_STRING';
+module.exports.codeToName[1163] = 'ER_TABLE_CANT_HANDLE_BLOB';
+module.exports.codeToName[1164] = 'ER_TABLE_CANT_HANDLE_AUTO_INCREMENT';
+module.exports.codeToName[1165] = 'ER_DELAYED_INSERT_TABLE_LOCKED';
+module.exports.codeToName[1166] = 'ER_WRONG_COLUMN_NAME';
+module.exports.codeToName[1167] = 'ER_WRONG_KEY_COLUMN';
+module.exports.codeToName[1168] = 'ER_WRONG_MRG_TABLE';
+module.exports.codeToName[1169] = 'ER_DUP_UNIQUE';
+module.exports.codeToName[1170] = 'ER_BLOB_KEY_WITHOUT_LENGTH';
+module.exports.codeToName[1171] = 'ER_PRIMARY_CANT_HAVE_NULL';
+module.exports.codeToName[1172] = 'ER_TOO_MANY_ROWS';
+module.exports.codeToName[1173] = 'ER_REQUIRES_PRIMARY_KEY';
+module.exports.codeToName[1174] = 'ER_NO_RAID_COMPILED';
+module.exports.codeToName[1175] = 'ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE';
+module.exports.codeToName[1176] = 'ER_KEY_DOES_NOT_EXITS';
+module.exports.codeToName[1177] = 'ER_CHECK_NO_SUCH_TABLE';
+module.exports.codeToName[1178] = 'ER_CHECK_NOT_IMPLEMENTED';
+module.exports.codeToName[1179] = 'ER_CANT_DO_THIS_DURING_AN_TRANSACTION';
+module.exports.codeToName[1180] = 'ER_ERROR_DURING_COMMIT';
+module.exports.codeToName[1181] = 'ER_ERROR_DURING_ROLLBACK';
+module.exports.codeToName[1182] = 'ER_ERROR_DURING_FLUSH_LOGS';
+module.exports.codeToName[1183] = 'ER_ERROR_DURING_CHECKPOINT';
+module.exports.codeToName[1184] = 'ER_NEW_ABORTING_CONNECTION';
+module.exports.codeToName[1185] = 'ER_DUMP_NOT_IMPLEMENTED';
+module.exports.codeToName[1186] = 'ER_FLUSH_MASTER_BINLOG_CLOSED';
+module.exports.codeToName[1187] = 'ER_INDEX_REBUILD';
+module.exports.codeToName[1188] = 'ER_MASTER';
+module.exports.codeToName[1189] = 'ER_MASTER_NET_READ';
+module.exports.codeToName[1190] = 'ER_MASTER_NET_WRITE';
+module.exports.codeToName[1191] = 'ER_FT_MATCHING_KEY_NOT_FOUND';
+module.exports.codeToName[1192] = 'ER_LOCK_OR_ACTIVE_TRANSACTION';
+module.exports.codeToName[1193] = 'ER_UNKNOWN_SYSTEM_VARIABLE';
+module.exports.codeToName[1194] = 'ER_CRASHED_ON_USAGE';
+module.exports.codeToName[1195] = 'ER_CRASHED_ON_REPAIR';
+module.exports.codeToName[1196] = 'ER_WARNING_NOT_COMPLETE_ROLLBACK';
+module.exports.codeToName[1197] = 'ER_TRANS_CACHE_FULL';
+module.exports.codeToName[1198] = 'ER_SLAVE_MUST_STOP';
+module.exports.codeToName[1199] = 'ER_SLAVE_NOT_RUNNING';
+module.exports.codeToName[1200] = 'ER_BAD_SLAVE';
+module.exports.codeToName[1201] = 'ER_MASTER_INFO';
+module.exports.codeToName[1202] = 'ER_SLAVE_THREAD';
+module.exports.codeToName[1203] = 'ER_TOO_MANY_USER_CONNECTIONS';
+module.exports.codeToName[1204] = 'ER_SET_CONSTANTS_ONLY';
+module.exports.codeToName[1205] = 'ER_LOCK_WAIT_TIMEOUT';
+module.exports.codeToName[1206] = 'ER_LOCK_TABLE_FULL';
+module.exports.codeToName[1207] = 'ER_READ_ONLY_TRANSACTION';
+module.exports.codeToName[1208] = 'ER_DROP_DB_WITH_READ_LOCK';
+module.exports.codeToName[1209] = 'ER_CREATE_DB_WITH_READ_LOCK';
+module.exports.codeToName[1210] = 'ER_WRONG_ARGUMENTS';
+module.exports.codeToName[1211] = 'ER_NO_PERMISSION_TO_CREATE_USER';
+module.exports.codeToName[1212] = 'ER_UNION_TABLES_IN_DIFFERENT_DIR';
+module.exports.codeToName[1213] = 'ER_LOCK_DEADLOCK';
+module.exports.codeToName[1214] = 'ER_TABLE_CANT_HANDLE_FT';
+module.exports.codeToName[1215] = 'ER_CANNOT_ADD_FOREIGN';
+module.exports.codeToName[1216] = 'ER_NO_REFERENCED_ROW';
+module.exports.codeToName[1217] = 'ER_ROW_IS_REFERENCED';
+module.exports.codeToName[1218] = 'ER_CONNECT_TO_MASTER';
+module.exports.codeToName[1219] = 'ER_QUERY_ON_MASTER';
+module.exports.codeToName[1220] = 'ER_ERROR_WHEN_EXECUTING_COMMAND';
+module.exports.codeToName[1221] = 'ER_WRONG_USAGE';
+module.exports.codeToName[1222] = 'ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT';
+module.exports.codeToName[1223] = 'ER_CANT_UPDATE_WITH_READLOCK';
+module.exports.codeToName[1224] = 'ER_MIXING_NOT_ALLOWED';
+module.exports.codeToName[1225] = 'ER_DUP_ARGUMENT';
+module.exports.codeToName[1226] = 'ER_USER_LIMIT_REACHED';
+module.exports.codeToName[1227] = 'ER_SPECIFIC_ACCESS_DENIED_ERROR';
+module.exports.codeToName[1228] = 'ER_LOCAL_VARIABLE';
+module.exports.codeToName[1229] = 'ER_GLOBAL_VARIABLE';
+module.exports.codeToName[1230] = 'ER_NO_DEFAULT';
+module.exports.codeToName[1231] = 'ER_WRONG_VALUE_FOR_VAR';
+module.exports.codeToName[1232] = 'ER_WRONG_TYPE_FOR_VAR';
+module.exports.codeToName[1233] = 'ER_VAR_CANT_BE_READ';
+module.exports.codeToName[1234] = 'ER_CANT_USE_OPTION_HERE';
+module.exports.codeToName[1235] = 'ER_NOT_SUPPORTED_YET';
+module.exports.codeToName[1236] = 'ER_MASTER_FATAL_ERROR_READING_BINLOG';
+module.exports.codeToName[1237] = 'ER_SLAVE_IGNORED_TABLE';
+module.exports.codeToName[1238] = 'ER_INCORRECT_GLOBAL_LOCAL_VAR';
+module.exports.codeToName[1239] = 'ER_WRONG_FK_DEF';
+module.exports.codeToName[1240] = 'ER_KEY_REF_DO_NOT_MATCH_TABLE_REF';
+module.exports.codeToName[1241] = 'ER_OPERAND_COLUMNS';
+module.exports.codeToName[1242] = 'ER_SUBQUERY_NO_';
+module.exports.codeToName[1243] = 'ER_UNKNOWN_STMT_HANDLER';
+module.exports.codeToName[1244] = 'ER_CORRUPT_HELP_DB';
+module.exports.codeToName[1245] = 'ER_CYCLIC_REFERENCE';
+module.exports.codeToName[1246] = 'ER_AUTO_CONVERT';
+module.exports.codeToName[1247] = 'ER_ILLEGAL_REFERENCE';
+module.exports.codeToName[1248] = 'ER_DERIVED_MUST_HAVE_ALIAS';
+module.exports.codeToName[1249] = 'ER_SELECT_REDUCED';
+module.exports.codeToName[1250] = 'ER_TABLENAME_NOT_ALLOWED_HERE';
+module.exports.codeToName[1251] = 'ER_NOT_SUPPORTED_AUTH_MODE';
+module.exports.codeToName[1252] = 'ER_SPATIAL_CANT_HAVE_NULL';
+module.exports.codeToName[1253] = 'ER_COLLATION_CHARSET_MISMATCH';
+module.exports.codeToName[1254] = 'ER_SLAVE_WAS_RUNNING';
+module.exports.codeToName[1255] = 'ER_SLAVE_WAS_NOT_RUNNING';
+module.exports.codeToName[1256] = 'ER_TOO_BIG_FOR_UNCOMPRESS';
+module.exports.codeToName[1257] = 'ER_ZLIB_Z_MEM_ERROR';
+module.exports.codeToName[1258] = 'ER_ZLIB_Z_BUF_ERROR';
+module.exports.codeToName[1259] = 'ER_ZLIB_Z_DATA_ERROR';
+module.exports.codeToName[1260] = 'ER_CUT_VALUE_GROUP_CONCAT';
+module.exports.codeToName[1261] = 'ER_WARN_TOO_FEW_RECORDS';
+module.exports.codeToName[1262] = 'ER_WARN_TOO_MANY_RECORDS';
+module.exports.codeToName[1263] = 'ER_WARN_NULL_TO_NOTNULL';
+module.exports.codeToName[1264] = 'ER_WARN_DATA_OUT_OF_RANGE';
+module.exports.codeToName[1265] = 'WARN_DATA_TRUNCATED';
+module.exports.codeToName[1266] = 'ER_WARN_USING_OTHER_HANDLER';
+module.exports.codeToName[1267] = 'ER_CANT_AGGREGATE_';
+module.exports.codeToName[1268] = 'ER_DROP_USER';
+module.exports.codeToName[1269] = 'ER_REVOKE_GRANTS';
+module.exports.codeToName[1270] = 'ER_CANT_AGGREGATE_';
+module.exports.codeToName[1271] = 'ER_CANT_AGGREGATE_NCOLLATIONS';
+module.exports.codeToName[1272] = 'ER_VARIABLE_IS_NOT_STRUCT';
+module.exports.codeToName[1273] = 'ER_UNKNOWN_COLLATION';
+module.exports.codeToName[1274] = 'ER_SLAVE_IGNORED_SSL_PARAMS';
+module.exports.codeToName[1275] = 'ER_SERVER_IS_IN_SECURE_AUTH_MODE';
+module.exports.codeToName[1276] = 'ER_WARN_FIELD_RESOLVED';
+module.exports.codeToName[1277] = 'ER_BAD_SLAVE_UNTIL_COND';
+module.exports.codeToName[1278] = 'ER_MISSING_SKIP_SLAVE';
+module.exports.codeToName[1279] = 'ER_UNTIL_COND_IGNORED';
+module.exports.codeToName[1280] = 'ER_WRONG_NAME_FOR_INDEX';
+module.exports.codeToName[1281] = 'ER_WRONG_NAME_FOR_CATALOG';
+module.exports.codeToName[1282] = 'ER_WARN_QC_RESIZE';
+module.exports.codeToName[1283] = 'ER_BAD_FT_COLUMN';
+module.exports.codeToName[1284] = 'ER_UNKNOWN_KEY_CACHE';
+module.exports.codeToName[1285] = 'ER_WARN_HOSTNAME_WONT_WORK';
+module.exports.codeToName[1286] = 'ER_UNKNOWN_STORAGE_ENGINE';
+module.exports.codeToName[1287] = 'ER_WARN_DEPRECATED_SYNTAX';
+module.exports.codeToName[1288] = 'ER_NON_UPDATABLE_TABLE';
+module.exports.codeToName[1289] = 'ER_FEATURE_DISABLED';
+module.exports.codeToName[1290] = 'ER_OPTION_PREVENTS_STATEMENT';
+module.exports.codeToName[1291] = 'ER_DUPLICATED_VALUE_IN_TYPE';
+module.exports.codeToName[1292] = 'ER_TRUNCATED_WRONG_VALUE';
+module.exports.codeToName[1293] = 'ER_TOO_MUCH_AUTO_TIMESTAMP_COLS';
+module.exports.codeToName[1294] = 'ER_INVALID_ON_UPDATE';
+module.exports.codeToName[1295] = 'ER_UNSUPPORTED_PS';
+module.exports.codeToName[1296] = 'ER_GET_ERRMSG';
+module.exports.codeToName[1297] = 'ER_GET_TEMPORARY_ERRMSG';
+module.exports.codeToName[1298] = 'ER_UNKNOWN_TIME_ZONE';
+module.exports.codeToName[1299] = 'ER_WARN_INVALID_TIMESTAMP';
+module.exports.codeToName[1300] = 'ER_INVALID_CHARACTER_STRING';
+module.exports.codeToName[1301] = 'ER_WARN_ALLOWED_PACKET_OVERFLOWED';
+module.exports.codeToName[1302] = 'ER_CONFLICTING_DECLARATIONS';
+module.exports.codeToName[1303] = 'ER_SP_NO_RECURSIVE_CREATE';
+module.exports.codeToName[1304] = 'ER_SP_ALREADY_EXISTS';
+module.exports.codeToName[1305] = 'ER_SP_DOES_NOT_EXIST';
+module.exports.codeToName[1306] = 'ER_SP_DROP_FAILED';
+module.exports.codeToName[1307] = 'ER_SP_STORE_FAILED';
+module.exports.codeToName[1308] = 'ER_SP_LILABEL_MISMATCH';
+module.exports.codeToName[1309] = 'ER_SP_LABEL_REDEFINE';
+module.exports.codeToName[1310] = 'ER_SP_LABEL_MISMATCH';
+module.exports.codeToName[1311] = 'ER_SP_UNINIT_VAR';
+module.exports.codeToName[1312] = 'ER_SP_BADSELECT';
+module.exports.codeToName[1313] = 'ER_SP_BADRETURN';
+module.exports.codeToName[1314] = 'ER_SP_BADSTATEMENT';
+module.exports.codeToName[1315] = 'ER_UPDATE_LOG_DEPRECATED_IGNORED';
+module.exports.codeToName[1316] = 'ER_UPDATE_LOG_DEPRECATED_TRANSLATED';
+module.exports.codeToName[1317] = 'ER_QUERY_INTERRUPTED';
+module.exports.codeToName[1318] = 'ER_SP_WRONG_NO_OF_ARGS';
+module.exports.codeToName[1319] = 'ER_SP_COND_MISMATCH';
+module.exports.codeToName[1320] = 'ER_SP_NORETURN';
+module.exports.codeToName[1321] = 'ER_SP_NORETURNEND';
+module.exports.codeToName[1322] = 'ER_SP_BAD_CURSOR_QUERY';
+module.exports.codeToName[1323] = 'ER_SP_BAD_CURSOR_SELECT';
+module.exports.codeToName[1324] = 'ER_SP_CURSOR_MISMATCH';
+module.exports.codeToName[1325] = 'ER_SP_CURSOR_ALREADY_OPEN';
+module.exports.codeToName[1326] = 'ER_SP_CURSOR_NOT_OPEN';
+module.exports.codeToName[1327] = 'ER_SP_UNDECLARED_VAR';
+module.exports.codeToName[1328] = 'ER_SP_WRONG_NO_OF_FETCH_ARGS';
+module.exports.codeToName[1329] = 'ER_SP_FETCH_NO_DATA';
+module.exports.codeToName[1330] = 'ER_SP_DUP_PARAM';
+module.exports.codeToName[1331] = 'ER_SP_DUP_VAR';
+module.exports.codeToName[1332] = 'ER_SP_DUP_COND';
+module.exports.codeToName[1333] = 'ER_SP_DUP_CURS';
+module.exports.codeToName[1334] = 'ER_SP_CANT_ALTER';
+module.exports.codeToName[1335] = 'ER_SP_SUBSELECT_NYI';
+module.exports.codeToName[1336] = 'ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG';
+module.exports.codeToName[1337] = 'ER_SP_VARCOND_AFTER_CURSHNDLR';
+module.exports.codeToName[1338] = 'ER_SP_CURSOR_AFTER_HANDLER';
+module.exports.codeToName[1339] = 'ER_SP_CASE_NOT_FOUND';
+module.exports.codeToName[1340] = 'ER_FPARSER_TOO_BIG_FILE';
+module.exports.codeToName[1341] = 'ER_FPARSER_BAD_HEADER';
+module.exports.codeToName[1342] = 'ER_FPARSER_EOF_IN_COMMENT';
+module.exports.codeToName[1343] = 'ER_FPARSER_ERROR_IN_PARAMETER';
+module.exports.codeToName[1344] = 'ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER';
+module.exports.codeToName[1345] = 'ER_VIEW_NO_EXPLAIN';
+module.exports.codeToName[1346] = 'ER_FRM_UNKNOWN_TYPE';
+module.exports.codeToName[1347] = 'ER_WRONG_OBJECT';
+module.exports.codeToName[1348] = 'ER_NONUPDATEABLE_COLUMN';
+module.exports.codeToName[1349] = 'ER_VIEW_SELECT_DERIVED';
+module.exports.codeToName[1350] = 'ER_VIEW_SELECT_CLAUSE';
+module.exports.codeToName[1351] = 'ER_VIEW_SELECT_VARIABLE';
+module.exports.codeToName[1352] = 'ER_VIEW_SELECT_TMPTABLE';
+module.exports.codeToName[1353] = 'ER_VIEW_WRONG_LIST';
+module.exports.codeToName[1354] = 'ER_WARN_VIEW_MERGE';
+module.exports.codeToName[1355] = 'ER_WARN_VIEW_WITHOUT_KEY';
+module.exports.codeToName[1356] = 'ER_VIEW_INVALID';
+module.exports.codeToName[1357] = 'ER_SP_NO_DROP_SP';
+module.exports.codeToName[1358] = 'ER_SP_GOTO_IN_HNDLR';
+module.exports.codeToName[1359] = 'ER_TRG_ALREADY_EXISTS';
+module.exports.codeToName[1360] = 'ER_TRG_DOES_NOT_EXIST';
+module.exports.codeToName[1361] = 'ER_TRG_ON_VIEW_OR_TEMP_TABLE';
+module.exports.codeToName[1362] = 'ER_TRG_CANT_CHANGE_ROW';
+module.exports.codeToName[1363] = 'ER_TRG_NO_SUCH_ROW_IN_TRG';
+module.exports.codeToName[1364] = 'ER_NO_DEFAULT_FOR_FIELD';
+module.exports.codeToName[1365] = 'ER_DIVISION_BY_ZERO';
+module.exports.codeToName[1366] = 'ER_TRUNCATED_WRONG_VALUE_FOR_FIELD';
+module.exports.codeToName[1367] = 'ER_ILLEGAL_VALUE_FOR_TYPE';
+module.exports.codeToName[1368] = 'ER_VIEW_NONUPD_CHECK';
+module.exports.codeToName[1369] = 'ER_VIEW_CHECK_FAILED';
+module.exports.codeToName[1370] = 'ER_PROCACCESS_DENIED_ERROR';
+module.exports.codeToName[1371] = 'ER_RELAY_LOG_FAIL';
+module.exports.codeToName[1372] = 'ER_PASSWD_LENGTH';
+module.exports.codeToName[1373] = 'ER_UNKNOWN_TARGET_BINLOG';
+module.exports.codeToName[1374] = 'ER_IO_ERR_LOG_INDEX_READ';
+module.exports.codeToName[1375] = 'ER_BINLOG_PURGE_PROHIBITED';
+module.exports.codeToName[1376] = 'ER_FSEEK_FAIL';
+module.exports.codeToName[1377] = 'ER_BINLOG_PURGE_FATAL_ERR';
+module.exports.codeToName[1378] = 'ER_LOG_IN_USE';
+module.exports.codeToName[1379] = 'ER_LOG_PURGE_UNKNOWN_ERR';
+module.exports.codeToName[1380] = 'ER_RELAY_LOG_INIT';
+module.exports.codeToName[1381] = 'ER_NO_BINARY_LOGGING';
+module.exports.codeToName[1382] = 'ER_RESERVED_SYNTAX';
+module.exports.codeToName[1383] = 'ER_WSAS_FAILED';
+module.exports.codeToName[1384] = 'ER_DIFF_GROUPS_PROC';
+module.exports.codeToName[1385] = 'ER_NO_GROUP_FOR_PROC';
+module.exports.codeToName[1386] = 'ER_ORDER_WITH_PROC';
+module.exports.codeToName[1387] = 'ER_LOGGING_PROHIBIT_CHANGING_OF';
+module.exports.codeToName[1388] = 'ER_NO_FILE_MAPPING';
+module.exports.codeToName[1389] = 'ER_WRONG_MAGIC';
+module.exports.codeToName[1390] = 'ER_PS_MANY_PARAM';
+module.exports.codeToName[1391] = 'ER_KEY_PART_';
+module.exports.codeToName[1392] = 'ER_VIEW_CHECKSUM';
+module.exports.codeToName[1393] = 'ER_VIEW_MULTIUPDATE';
+module.exports.codeToName[1394] = 'ER_VIEW_NO_INSERT_FIELD_LIST';
+module.exports.codeToName[1395] = 'ER_VIEW_DELETE_MERGE_VIEW';
+module.exports.codeToName[1396] = 'ER_CANNOT_USER';
+module.exports.codeToName[1397] = 'ER_XAER_NOTA';
+module.exports.codeToName[1398] = 'ER_XAER_INVAL';
+module.exports.codeToName[1399] = 'ER_XAER_RMFAIL';
+module.exports.codeToName[1400] = 'ER_XAER_OUTSIDE';
+module.exports.codeToName[1401] = 'ER_XAER_RMERR';
+module.exports.codeToName[1402] = 'ER_XA_RBROLLBACK';
+module.exports.codeToName[1403] = 'ER_NONEXISTING_PROC_GRANT';
+module.exports.codeToName[1404] = 'ER_PROC_AUTO_GRANT_FAIL';
+module.exports.codeToName[1405] = 'ER_PROC_AUTO_REVOKE_FAIL';
+module.exports.codeToName[1406] = 'ER_DATA_TOO_LONG';
+module.exports.codeToName[1407] = 'ER_SP_BAD_SQLSTATE';
+module.exports.codeToName[1408] = 'ER_STARTUP';
+module.exports.codeToName[1409] = 'ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR';
+module.exports.codeToName[1410] = 'ER_CANT_CREATE_USER_WITH_GRANT';
+module.exports.codeToName[1411] = 'ER_WRONG_VALUE_FOR_TYPE';
+module.exports.codeToName[1412] = 'ER_TABLE_DEF_CHANGED';
+module.exports.codeToName[1413] = 'ER_SP_DUP_HANDLER';
+module.exports.codeToName[1414] = 'ER_SP_NOT_VAR_ARG';
+module.exports.codeToName[1415] = 'ER_SP_NO_RETSET';
+module.exports.codeToName[1416] = 'ER_CANT_CREATE_GEOMETRY_OBJECT';
+module.exports.codeToName[1417] = 'ER_FAILED_ROUTINE_BREAK_BINLOG';
+module.exports.codeToName[1418] = 'ER_BINLOG_UNSAFE_ROUTINE';
+module.exports.codeToName[1419] = 'ER_BINLOG_CREATE_ROUTINE_NEED_SUPER';
+module.exports.codeToName[1420] = 'ER_EXEC_STMT_WITH_OPEN_CURSOR';
+module.exports.codeToName[1421] = 'ER_STMT_HAS_NO_OPEN_CURSOR';
+module.exports.codeToName[1422] = 'ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG';
+module.exports.codeToName[1423] = 'ER_NO_DEFAULT_FOR_VIEW_FIELD';
+module.exports.codeToName[1424] = 'ER_SP_NO_RECURSION';
+module.exports.codeToName[1425] = 'ER_TOO_BIG_SCALE';
+module.exports.codeToName[1426] = 'ER_TOO_BIG_PRECISION';
+module.exports.codeToName[1427] = 'ER_M_BIGGER_THAN_D';
+module.exports.codeToName[1428] = 'ER_WRONG_LOCK_OF_SYSTEM_TABLE';
+module.exports.codeToName[1429] = 'ER_CONNECT_TO_FOREIGN_DATA_SOURCE';
+module.exports.codeToName[1430] = 'ER_QUERY_ON_FOREIGN_DATA_SOURCE';
+module.exports.codeToName[1431] = 'ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST';
+module.exports.codeToName[1432] = 'ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE';
+module.exports.codeToName[1433] = 'ER_FOREIGN_DATA_STRING_INVALID';
+module.exports.codeToName[1434] = 'ER_CANT_CREATE_FEDERATED_TABLE';
+module.exports.codeToName[1435] = 'ER_TRG_IN_WRONG_SCHEMA';
+module.exports.codeToName[1436] = 'ER_STACK_OVERRUN_NEED_MORE';
+module.exports.codeToName[1437] = 'ER_TOO_LONG_BODY';
+module.exports.codeToName[1438] = 'ER_WARN_CANT_DROP_DEFAULT_KEYCACHE';
+module.exports.codeToName[1439] = 'ER_TOO_BIG_DISPLAYWIDTH';
+module.exports.codeToName[1440] = 'ER_XAER_DUPID';
+module.exports.codeToName[1441] = 'ER_DATETIME_FUNCTION_OVERFLOW';
+module.exports.codeToName[1442] = 'ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG';
+module.exports.codeToName[1443] = 'ER_VIEW_PREVENT_UPDATE';
+module.exports.codeToName[1444] = 'ER_PS_NO_RECURSION';
+module.exports.codeToName[1445] = 'ER_SP_CANT_SET_AUTOCOMMIT';
+module.exports.codeToName[1446] = 'ER_MALFORMED_DEFINER';
+module.exports.codeToName[1447] = 'ER_VIEW_FRM_NO_USER';
+module.exports.codeToName[1448] = 'ER_VIEW_OTHER_USER';
+module.exports.codeToName[1449] = 'ER_NO_SUCH_USER';
+module.exports.codeToName[1450] = 'ER_FORBID_SCHEMA_CHANGE';
+module.exports.codeToName[1451] = 'ER_ROW_IS_REFERENCED_';
+module.exports.codeToName[1452] = 'ER_NO_REFERENCED_ROW_';
+module.exports.codeToName[1453] = 'ER_SP_BAD_VAR_SHADOW';
+module.exports.codeToName[1454] = 'ER_TRG_NO_DEFINER';
+module.exports.codeToName[1455] = 'ER_OLD_FILE_FORMAT';
+module.exports.codeToName[1456] = 'ER_SP_RECURSION_LIMIT';
+module.exports.codeToName[1457] = 'ER_SP_PROC_TABLE_CORRUPT';
+module.exports.codeToName[1458] = 'ER_SP_WRONG_NAME';
+module.exports.codeToName[1459] = 'ER_TABLE_NEEDS_UPGRADE';
+module.exports.codeToName[1460] = 'ER_SP_NO_AGGREGATE';
+module.exports.codeToName[1461] = 'ER_MAX_PREPARED_STMT_COUNT_REACHED';
+module.exports.codeToName[1462] = 'ER_VIEW_RECURSIVE';
+module.exports.codeToName[1463] = 'ER_NON_GROUPING_FIELD_USED';
+module.exports.codeToName[1464] = 'ER_TABLE_CANT_HANDLE_SPKEYS';
+module.exports.codeToName[1465] = 'ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA';
+module.exports.codeToName[1466] = 'ER_REMOVED_SPACES';
+module.exports.codeToName[1467] = 'ER_AUTOINC_READ_FAILED';
+module.exports.codeToName[1468] = 'ER_USERNAME';
+module.exports.codeToName[1469] = 'ER_HOSTNAME';
+module.exports.codeToName[1470] = 'ER_WRONG_STRING_LENGTH';
+module.exports.codeToName[1471] = 'ER_NON_INSERTABLE_TABLE';
+module.exports.codeToName[1472] = 'ER_ADMIN_WRONG_MRG_TABLE';
+module.exports.codeToName[1473] = 'ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT';
+module.exports.codeToName[1474] = 'ER_NAME_BECOMES_EMPTY';
+module.exports.codeToName[1475] = 'ER_AMBIGUOUS_FIELD_TERM';
+module.exports.codeToName[1476] = 'ER_FOREIGN_SERVER_EXISTS';
+module.exports.codeToName[1477] = 'ER_FOREIGN_SERVER_DOESNT_EXIST';
+module.exports.codeToName[1478] = 'ER_ILLEGAL_HA_CREATE_OPTION';
+module.exports.codeToName[1479] = 'ER_PARTITION_REQUIRES_VALUES_ERROR';
+module.exports.codeToName[1480] = 'ER_PARTITION_WRONG_VALUES_ERROR';
+module.exports.codeToName[1481] = 'ER_PARTITION_MAXVALUE_ERROR';
+module.exports.codeToName[1482] = 'ER_PARTITION_SUBPARTITION_ERROR';
+module.exports.codeToName[1483] = 'ER_PARTITION_SUBPART_MIX_ERROR';
+module.exports.codeToName[1484] = 'ER_PARTITION_WRONG_NO_PART_ERROR';
+module.exports.codeToName[1485] = 'ER_PARTITION_WRONG_NO_SUBPART_ERROR';
+module.exports.codeToName[1486] = 'ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR';
+module.exports.codeToName[1487] = 'ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR';
+module.exports.codeToName[1488] = 'ER_FIELD_NOT_FOUND_PART_ERROR';
+module.exports.codeToName[1489] = 'ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR';
+module.exports.codeToName[1490] = 'ER_INCONSISTENT_PARTITION_INFO_ERROR';
+module.exports.codeToName[1491] = 'ER_PARTITION_FUNC_NOT_ALLOWED_ERROR';
+module.exports.codeToName[1492] = 'ER_PARTITIONS_MUST_BE_DEFINED_ERROR';
+module.exports.codeToName[1493] = 'ER_RANGE_NOT_INCREASING_ERROR';
+module.exports.codeToName[1494] = 'ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR';
+module.exports.codeToName[1495] = 'ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR';
+module.exports.codeToName[1496] = 'ER_PARTITION_ENTRY_ERROR';
+module.exports.codeToName[1497] = 'ER_MIX_HANDLER_ERROR';
+module.exports.codeToName[1498] = 'ER_PARTITION_NOT_DEFINED_ERROR';
+module.exports.codeToName[1499] = 'ER_TOO_MANY_PARTITIONS_ERROR';
+module.exports.codeToName[1500] = 'ER_SUBPARTITION_ERROR';
+module.exports.codeToName[1501] = 'ER_CANT_CREATE_HANDLER_FILE';
+module.exports.codeToName[1502] = 'ER_BLOB_FIELD_IN_PART_FUNC_ERROR';
+module.exports.codeToName[1503] = 'ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF';
+module.exports.codeToName[1504] = 'ER_NO_PARTS_ERROR';
+module.exports.codeToName[1505] = 'ER_PARTITION_MGMT_ON_NONPARTITIONED';
+module.exports.codeToName[1506] = 'ER_FOREIGN_KEY_ON_PARTITIONED';
+module.exports.codeToName[1507] = 'ER_DROP_PARTITION_NON_EXISTENT';
+module.exports.codeToName[1508] = 'ER_DROP_LAST_PARTITION';
+module.exports.codeToName[1509] = 'ER_COALESCE_ONLY_ON_HASH_PARTITION';
+module.exports.codeToName[1510] = 'ER_REORG_HASH_ONLY_ON_SAME_NO';
+module.exports.codeToName[1511] = 'ER_REORG_NO_PARAM_ERROR';
+module.exports.codeToName[1512] = 'ER_ONLY_ON_RANGE_LIST_PARTITION';
+module.exports.codeToName[1513] = 'ER_ADD_PARTITION_SUBPART_ERROR';
+module.exports.codeToName[1514] = 'ER_ADD_PARTITION_NO_NEW_PARTITION';
+module.exports.codeToName[1515] = 'ER_COALESCE_PARTITION_NO_PARTITION';
+module.exports.codeToName[1516] = 'ER_REORG_PARTITION_NOT_EXIST';
+module.exports.codeToName[1517] = 'ER_SAME_NAME_PARTITION';
+module.exports.codeToName[1518] = 'ER_NO_BINLOG_ERROR';
+module.exports.codeToName[1519] = 'ER_CONSECUTIVE_REORG_PARTITIONS';
+module.exports.codeToName[1520] = 'ER_REORG_OUTSIDE_RANGE';
+module.exports.codeToName[1521] = 'ER_PARTITION_FUNCTION_FAILURE';
+module.exports.codeToName[1522] = 'ER_PART_STATE_ERROR';
+module.exports.codeToName[1523] = 'ER_LIMITED_PART_RANGE';
+module.exports.codeToName[1524] = 'ER_PLUGIN_IS_NOT_LOADED';
+module.exports.codeToName[1525] = 'ER_WRONG_VALUE';
+module.exports.codeToName[1526] = 'ER_NO_PARTITION_FOR_GIVEN_VALUE';
+module.exports.codeToName[1527] = 'ER_FILEGROUP_OPTION_ONLY_ONCE';
+module.exports.codeToName[1528] = 'ER_CREATE_FILEGROUP_FAILED';
+module.exports.codeToName[1529] = 'ER_DROP_FILEGROUP_FAILED';
+module.exports.codeToName[1530] = 'ER_TABLESPACE_AUTO_EXTEND_ERROR';
+module.exports.codeToName[1531] = 'ER_WRONG_SIZE_NUMBER';
+module.exports.codeToName[1532] = 'ER_SIZE_OVERFLOW_ERROR';
+module.exports.codeToName[1533] = 'ER_ALTER_FILEGROUP_FAILED';
+module.exports.codeToName[1534] = 'ER_BINLOG_ROW_LOGGING_FAILED';
+module.exports.codeToName[1535] = 'ER_BINLOG_ROW_WRONG_TABLE_DEF';
+module.exports.codeToName[1536] = 'ER_BINLOG_ROW_RBR_TO_SBR';
+module.exports.codeToName[1537] = 'ER_EVENT_ALREADY_EXISTS';
+module.exports.codeToName[1538] = 'ER_EVENT_STORE_FAILED';
+module.exports.codeToName[1539] = 'ER_EVENT_DOES_NOT_EXIST';
+module.exports.codeToName[1540] = 'ER_EVENT_CANT_ALTER';
+module.exports.codeToName[1541] = 'ER_EVENT_DROP_FAILED';
+module.exports.codeToName[1542] = 'ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG';
+module.exports.codeToName[1543] = 'ER_EVENT_ENDS_BEFORE_STARTS';
+module.exports.codeToName[1544] = 'ER_EVENT_EXEC_TIME_IN_THE_PAST';
+module.exports.codeToName[1545] = 'ER_EVENT_OPEN_TABLE_FAILED';
+module.exports.codeToName[1546] = 'ER_EVENT_NEITHER_M_EXPR_NOR_M_AT';
+module.exports.codeToName[1547] = 'ER_COL_COUNT_DOESNT_MATCH_CORRUPTED';
+module.exports.codeToName[1548] = 'ER_CANNOT_LOAD_FROM_TABLE';
+module.exports.codeToName[1549] = 'ER_EVENT_CANNOT_DELETE';
+module.exports.codeToName[1550] = 'ER_EVENT_COMPILE_ERROR';
+module.exports.codeToName[1551] = 'ER_EVENT_SAME_NAME';
+module.exports.codeToName[1552] = 'ER_EVENT_DATA_TOO_LONG';
+module.exports.codeToName[1553] = 'ER_DROP_INDEX_FK';
+module.exports.codeToName[1554] = 'ER_WARN_DEPRECATED_SYNTAX_WITH_VER';
+module.exports.codeToName[1555] = 'ER_CANT_WRITE_LOCK_LOG_TABLE';
+module.exports.codeToName[1556] = 'ER_CANT_LOCK_LOG_TABLE';
+module.exports.codeToName[1557] = 'ER_FOREIGN_DUPLICATE_KEY';
+module.exports.codeToName[1558] = 'ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE';
+module.exports.codeToName[1559] = 'ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR';
+module.exports.codeToName[1560] = 'ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT';
+module.exports.codeToName[1561] = 'ER_NDB_CANT_SWITCH_BINLOG_FORMAT';
+module.exports.codeToName[1562] = 'ER_PARTITION_NO_TEMPORARY';
+module.exports.codeToName[1563] = 'ER_PARTITION_CONST_DOMAIN_ERROR';
+module.exports.codeToName[1564] = 'ER_PARTITION_FUNCTION_IS_NOT_ALLOWED';
+module.exports.codeToName[1565] = 'ER_DDL_LOG_ERROR';
+module.exports.codeToName[1566] = 'ER_NULL_IN_VALUES_LESS_THAN';
+module.exports.codeToName[1567] = 'ER_WRONG_PARTITION_NAME';
+module.exports.codeToName[1568] = 'ER_CANT_CHANGE_TX_ISOLATION';
+module.exports.codeToName[1569] = 'ER_DUP_ENTRY_AUTOINCREMENT_CASE';
+module.exports.codeToName[1570] = 'ER_EVENT_MODIFY_QUEUE_ERROR';
+module.exports.codeToName[1571] = 'ER_EVENT_SET_VAR_ERROR';
+module.exports.codeToName[1572] = 'ER_PARTITION_MERGE_ERROR';
+module.exports.codeToName[1573] = 'ER_CANT_ACTIVATE_LOG';
+module.exports.codeToName[1574] = 'ER_RBR_NOT_AVAILABLE';
+module.exports.codeToName[1575] = 'ER_BASE';
+module.exports.codeToName[1576] = 'ER_EVENT_RECURSION_FORBIDDEN';
+module.exports.codeToName[1577] = 'ER_EVENTS_DB_ERROR';
+module.exports.codeToName[1578] = 'ER_ONLY_INTEGERS_ALLOWED';
+module.exports.codeToName[1579] = 'ER_UNSUPORTED_LOG_ENGINE';
+module.exports.codeToName[1580] = 'ER_BAD_LOG_STATEMENT';
+module.exports.codeToName[1581] = 'ER_CANT_RENAME_LOG_TABLE';
+module.exports.codeToName[1582] = 'ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT';
+module.exports.codeToName[1583] = 'ER_WRONG_PARAMETERS_TO_NATIVE_FCT';
+module.exports.codeToName[1584] = 'ER_WRONG_PARAMETERS_TO_STORED_FCT';
+module.exports.codeToName[1585] = 'ER_NATIVE_FCT_NAME_COLLISION';
+module.exports.codeToName[1586] = 'ER_DUP_ENTRY_WITH_KEY_NAME';
+module.exports.codeToName[1587] = 'ER_BINLOG_PURGE_EMFILE';
+module.exports.codeToName[1588] = 'ER_EVENT_CANNOT_CREATE_IN_THE_PAST';
+module.exports.codeToName[1589] = 'ER_EVENT_CANNOT_ALTER_IN_THE_PAST';
+module.exports.codeToName[1590] = 'ER_SLAVE_INCIDENT';
+module.exports.codeToName[1591] = 'ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT';
+module.exports.codeToName[1592] = 'ER_BINLOG_UNSAFE_STATEMENT';
+module.exports.codeToName[1593] = 'ER_SLAVE_FATAL_ERROR';
+module.exports.codeToName[1594] = 'ER_SLAVE_RELAY_LOG_READ_FAILURE';
+module.exports.codeToName[1595] = 'ER_SLAVE_RELAY_LOG_WRITE_FAILURE';
+module.exports.codeToName[1596] = 'ER_SLAVE_CREATE_EVENT_FAILURE';
+module.exports.codeToName[1597] = 'ER_SLAVE_MASTER_COM_FAILURE';
+module.exports.codeToName[1598] = 'ER_BINLOG_LOGGING_IMPOSSIBLE';
+module.exports.codeToName[1599] = 'ER_VIEW_NO_CREATION_CTX';
+module.exports.codeToName[1600] = 'ER_VIEW_INVALID_CREATION_CTX';
+module.exports.codeToName[1601] = 'ER_SR_INVALID_CREATION_CTX';
+module.exports.codeToName[1602] = 'ER_TRG_CORRUPTED_FILE';
+module.exports.codeToName[1603] = 'ER_TRG_NO_CREATION_CTX';
+module.exports.codeToName[1604] = 'ER_TRG_INVALID_CREATION_CTX';
+module.exports.codeToName[1605] = 'ER_EVENT_INVALID_CREATION_CTX';
+module.exports.codeToName[1606] = 'ER_TRG_CANT_OPEN_TABLE';
+module.exports.codeToName[1607] = 'ER_CANT_CREATE_SROUTINE';
+module.exports.codeToName[1608] = 'ER_NEVER_USED';
+module.exports.codeToName[1609] = 'ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT';
+module.exports.codeToName[1610] = 'ER_SLAVE_CORRUPT_EVENT';
+module.exports.codeToName[1611] = 'ER_LOAD_DATA_INVALID_COLUMN';
+module.exports.codeToName[1612] = 'ER_LOG_PURGE_NO_FILE';
+module.exports.codeToName[1613] = 'ER_XA_RBTIMEOUT';
+module.exports.codeToName[1614] = 'ER_XA_RBDEADLOCK';
+module.exports.codeToName[1615] = 'ER_NEED_REPREPARE';
+module.exports.codeToName[1616] = 'ER_DELAYED_NOT_SUPPORTED';
+module.exports.codeToName[1617] = 'WARN_NO_MASTER_INFO';
+module.exports.codeToName[1618] = 'WARN_OPTION_IGNORED';
+module.exports.codeToName[1619] = 'WARN_PLUGIN_DELETE_BUILTIN';
+module.exports.codeToName[1620] = 'WARN_PLUGIN_BUSY';
+module.exports.codeToName[1621] = 'ER_VARIABLE_IS_READONLY';
+module.exports.codeToName[1622] = 'ER_WARN_ENGINE_TRANSACTION_ROLLBACK';
+module.exports.codeToName[1623] = 'ER_SLAVE_HEARTBEAT_FAILURE';
+module.exports.codeToName[1624] = 'ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE';
+module.exports.codeToName[1625] = 'ER_NDB_REPLICATION_SCHEMA_ERROR';
+module.exports.codeToName[1626] = 'ER_CONFLICT_FN_PARSE_ERROR';
+module.exports.codeToName[1627] = 'ER_EXCEPTIONS_WRITE_ERROR';
+module.exports.codeToName[1628] = 'ER_TOO_LONG_TABLE_COMMENT';
+module.exports.codeToName[1629] = 'ER_TOO_LONG_FIELD_COMMENT';
+module.exports.codeToName[1630] = 'ER_FUNC_INEXISTENT_NAME_COLLISION';
+module.exports.codeToName[1631] = 'ER_DATABASE_NAME';
+module.exports.codeToName[1632] = 'ER_TABLE_NAME';
+module.exports.codeToName[1633] = 'ER_PARTITION_NAME';
+module.exports.codeToName[1634] = 'ER_SUBPARTITION_NAME';
+module.exports.codeToName[1635] = 'ER_TEMPORARY_NAME';
+module.exports.codeToName[1636] = 'ER_RENAMED_NAME';
+module.exports.codeToName[1637] = 'ER_TOO_MANY_CONCURRENT_TRXS';
+module.exports.codeToName[1638] = 'WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED';
+module.exports.codeToName[1639] = 'ER_DEBUG_SYNC_TIMEOUT';
+module.exports.codeToName[1640] = 'ER_DEBUG_SYNC_HIT_LIMIT';
+module.exports.codeToName[1641] = 'ER_DUP_SIGNAL_SET';
+module.exports.codeToName[1642] = 'ER_SIGNAL_WARN';
+module.exports.codeToName[1643] = 'ER_SIGNAL_NOT_FOUND';
+module.exports.codeToName[1644] = 'ER_SIGNAL_EXCEPTION';
+module.exports.codeToName[1645] = 'ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER';
+module.exports.codeToName[1646] = 'ER_SIGNAL_BAD_CONDITION_TYPE';
+module.exports.codeToName[1647] = 'WARN_COND_ITEM_TRUNCATED';
+module.exports.codeToName[1648] = 'ER_COND_ITEM_TOO_LONG';
+module.exports.codeToName[1649] = 'ER_UNKNOWN_LOCALE';
+module.exports.codeToName[1650] = 'ER_SLAVE_IGNORE_SERVER_IDS';
+module.exports.codeToName[1651] = 'ER_QUERY_CACHE_DISABLED';
+module.exports.codeToName[1652] = 'ER_SAME_NAME_PARTITION_FIELD';
+module.exports.codeToName[1653] = 'ER_PARTITION_COLUMN_LIST_ERROR';
+module.exports.codeToName[1654] = 'ER_WRONG_TYPE_COLUMN_VALUE_ERROR';
+module.exports.codeToName[1655] = 'ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR';
+module.exports.codeToName[1656] = 'ER_MAXVALUE_IN_VALUES_IN';
+module.exports.codeToName[1657] = 'ER_TOO_MANY_VALUES_ERROR';
+module.exports.codeToName[1658] = 'ER_ROW_SINGLE_PARTITION_FIELD_ERROR';
+module.exports.codeToName[1659] = 'ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD';
+module.exports.codeToName[1660] = 'ER_PARTITION_FIELDS_TOO_LONG';
+module.exports.codeToName[1661] = 'ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE';
+module.exports.codeToName[1662] = 'ER_BINLOG_ROW_MODE_AND_STMT_ENGINE';
+module.exports.codeToName[1663] = 'ER_BINLOG_UNSAFE_AND_STMT_ENGINE';
+module.exports.codeToName[1664] = 'ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE';
+module.exports.codeToName[1665] = 'ER_BINLOG_STMT_MODE_AND_ROW_ENGINE';
+module.exports.codeToName[1666] = 'ER_BINLOG_ROW_INJECTION_AND_STMT_MODE';
+module.exports.codeToName[1667] = 'ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE';
+module.exports.codeToName[1668] = 'ER_BINLOG_UNSAFE_LIMIT';
+module.exports.codeToName[1669] = 'ER_BINLOG_UNSAFE_INSERT_DELAYED';
+module.exports.codeToName[1670] = 'ER_BINLOG_UNSAFE_SYSTEM_TABLE';
+module.exports.codeToName[1671] = 'ER_BINLOG_UNSAFE_AUTOINC_COLUMNS';
+module.exports.codeToName[1672] = 'ER_BINLOG_UNSAFE_UDF';
+module.exports.codeToName[1673] = 'ER_BINLOG_UNSAFE_SYSTEM_VARIABLE';
+module.exports.codeToName[1674] = 'ER_BINLOG_UNSAFE_SYSTEM_FUNCTION';
+module.exports.codeToName[1675] = 'ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS';
+module.exports.codeToName[1676] = 'ER_MESSAGE_AND_STATEMENT';
+module.exports.codeToName[1677] = 'ER_SLAVE_CONVERSION_FAILED';
+module.exports.codeToName[1678] = 'ER_SLAVE_CANT_CREATE_CONVERSION';
+module.exports.codeToName[1679] = 'ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT';
+module.exports.codeToName[1680] = 'ER_PATH_LENGTH';
+module.exports.codeToName[1681] = 'ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT';
+module.exports.codeToName[1682] = 'ER_WRONG_NATIVE_TABLE_STRUCTURE';
+module.exports.codeToName[1683] = 'ER_WRONG_PERFSCHEMA_USAGE';
+module.exports.codeToName[1684] = 'ER_WARN_I_S_SKIPPED_TABLE';
+module.exports.codeToName[1685] = 'ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT';
+module.exports.codeToName[1686] = 'ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT';
+module.exports.codeToName[1687] = 'ER_SPATIAL_MUST_HAVE_GEOM_COL';
+module.exports.codeToName[1688] = 'ER_TOO_LONG_INDEX_COMMENT';
+module.exports.codeToName[1689] = 'ER_LOCK_ABORTED';
+module.exports.codeToName[1690] = 'ER_DATA_OUT_OF_RANGE';
+module.exports.codeToName[1691] = 'ER_WRONG_SPVAR_TYPE_IN_LIMIT';
+module.exports.codeToName[1692] = 'ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE';
+module.exports.codeToName[1693] = 'ER_BINLOG_UNSAFE_MIXED_STATEMENT';
+module.exports.codeToName[1694] = 'ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN';
+module.exports.codeToName[1695] = 'ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN';
+module.exports.codeToName[1696] = 'ER_FAILED_READ_FROM_PAR_FILE';
+module.exports.codeToName[1697] = 'ER_VALUES_IS_NOT_INT_TYPE_ERROR';
+module.exports.codeToName[1698] = 'ER_ACCESS_DENIED_NO_PASSWORD_ERROR';
+module.exports.codeToName[1699] = 'ER_SET_PASSWORD_AUTH_PLUGIN';
+module.exports.codeToName[1700] = 'ER_GRANT_PLUGIN_USER_EXISTS';
+module.exports.codeToName[1701] = 'ER_TRUNCATE_ILLEGAL_FK';
+module.exports.codeToName[1702] = 'ER_PLUGIN_IS_PERMANENT';
+module.exports.codeToName[1703] = 'ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN';
+module.exports.codeToName[1704] = 'ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX';
+module.exports.codeToName[1705] = 'ER_STMT_CACHE_FULL';
+module.exports.codeToName[1706] = 'ER_MULTI_UPDATE_KEY_CONFLICT';
+module.exports.codeToName[1707] = 'ER_TABLE_NEEDS_REBUILD';
+module.exports.codeToName[1708] = 'WARN_OPTION_BELOW_LIMIT';
+module.exports.codeToName[1709] = 'ER_INDEX_COLUMN_TOO_LONG';
+module.exports.codeToName[1710] = 'ER_ERROR_IN_TRIGGER_BODY';
+module.exports.codeToName[1711] = 'ER_ERROR_IN_UNKNOWN_TRIGGER_BODY';
+module.exports.codeToName[1712] = 'ER_INDEX_CORRUPT';
+module.exports.codeToName[1713] = 'ER_UNDO_RECORD_TOO_BIG';
+module.exports.codeToName[1714] = 'ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT';
+module.exports.codeToName[1715] = 'ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE';
+module.exports.codeToName[1716] = 'ER_BINLOG_UNSAFE_REPLACE_SELECT';
+module.exports.codeToName[1717] = 'ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT';
+module.exports.codeToName[1718] = 'ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT';
+module.exports.codeToName[1719] = 'ER_BINLOG_UNSAFE_UPDATE_IGNORE';
+module.exports.codeToName[1720] = 'ER_PLUGIN_NO_UNINSTALL';
+module.exports.codeToName[1721] = 'ER_PLUGIN_NO_INSTALL';
+module.exports.codeToName[1722] = 'ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT';
+module.exports.codeToName[1723] = 'ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC';
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/field_flags.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/field_flags.js
new file mode 100644
index 0000000000000000000000000000000000000000..3fe05c39242f805ef8cfcd4c581ae672347c1614
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/field_flags.js
@@ -0,0 +1,18 @@
+// Manually extracted from mysql-5.5.23/include/mysql_com.h
+exports.NOT_NULL     = 1; /* Field can't be NULL */
+exports.PRI_KEY      = 2; /* Field is part of a primary key */
+exports.UNIQUE_KEY   = 4; /* Field is part of a unique key */
+exports.MULTIPLE_KEY = 8; /* Field is part of a key */
+exports.BLOB         = 16; /* Field is a blob */
+exports.UNSIGNED     = 32; /* Field is unsigned */
+exports.ZEROFILL     = 64; /* Field is zerofill */
+exports.BINARY       = 128; /* Field is binary   */
+
+/* The following are only sent to new clients */
+exports.ENUM             = 256; /* field is an enum */
+exports.AUTO_INCREMENT   = 512; /* field is a autoincrement field */
+exports.TIMESTAMP        = 1024; /* Field is a timestamp */
+exports.SET              = 2048; /* field is a set */
+exports.NO_DEFAULT_VALUE = 4096; /* Field doesn't have default value */
+exports.ON_UPDATE_NOW    = 8192; /* Field is set to NOW on UPDATE */
+exports.NUM              = 32768; /* Field is num (for clients) */
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/server_status.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/server_status.js
new file mode 100644
index 0000000000000000000000000000000000000000..5537ee5b47905738edcb2718d946a7dc1b225522
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/server_status.js
@@ -0,0 +1,39 @@
+// Manually extracted from mysql-5.5.23/include/mysql_com.h
+
+/**
+  Is raised when a multi-statement transaction
+  has been started, either explicitly, by means
+  of BEGIN or COMMIT AND CHAIN, or
+  implicitly, by the first transactional
+  statement, when autocommit=off.
+*/
+exports.SERVER_STATUS_IN_TRANS          = 1;
+exports.SERVER_STATUS_AUTOCOMMIT        = 2;  /* Server in auto_commit mode */
+exports.SERVER_MORE_RESULTS_EXISTS      = 8;    /* Multi query - next query exists */
+exports.SERVER_QUERY_NO_GOOD_INDEX_USED = 16;
+exports.SERVER_QUERY_NO_INDEX_USED      = 32;
+/**
+  The server was able to fulfill the clients request and opened a
+  read-only non-scrollable cursor for a query. This flag comes
+  in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
+*/
+exports.SERVER_STATUS_CURSOR_EXISTS = 64;
+/**
+  This flag is sent when a read-only cursor is exhausted, in reply to
+  COM_STMT_FETCH command.
+*/
+exports.SERVER_STATUS_LAST_ROW_SENT        = 128;
+exports.SERVER_STATUS_DB_DROPPED           = 256; /* A database was dropped */
+exports.SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512;
+/**
+  Sent to the client if after a prepared statement reprepare
+  we discovered that the new statement returns a different 
+  number of result set columns.
+*/
+exports.SERVER_STATUS_METADATA_CHANGED = 1024;
+exports.SERVER_QUERY_WAS_SLOW          = 2048;
+
+/**
+  To mark ResultSet containing output parameter values.
+*/
+exports.SERVER_PS_OUT_PARAMS = 4096;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/ssl_profiles.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/ssl_profiles.js
new file mode 100644
index 0000000000000000000000000000000000000000..51a704f0f9ad23c1af015c7f8850fc5a02e6c8c8
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/ssl_profiles.js
@@ -0,0 +1,265 @@
+// Certificate for Amazon RDS (Updated for 2015)
+exports['Amazon RDS'] = {
+    ca: [
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIIDQzCCAqygAwIBAgIJAOd1tlfiGoEoMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV\n'
+        + 'BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRMw\n'
+        + 'EQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNSRFMxHDAaBgNVBAMTE2F3cy5h\n'
+        + 'bWF6b24uY29tL3Jkcy8wHhcNMTAwNDA1MjI0NDMxWhcNMTUwNDA0MjI0NDMxWjB1\n'
+        + 'MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh\n'
+        + 'dHRsZTETMBEGA1UEChMKQW1hem9uLmNvbTEMMAoGA1UECxMDUkRTMRwwGgYDVQQD\n'
+        + 'ExNhd3MuYW1hem9uLmNvbS9yZHMvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n'
+        + 'gQDKhXGU7tizxUR5WaFoMTFcxNxa05PEjZaIOEN5ctkWrqYSRov0/nOMoZjqk8bC\n'
+        + 'med9vPFoQGD0OTakPs0jVe3wwmR735hyVwmKIPPsGlaBYj1O6llIpZeQVyupNx56\n'
+        + 'UzqtiLaDzh1KcmfqP3qP2dInzBfJQKjiRudo1FWnpPt33QIDAQABo4HaMIHXMB0G\n'
+        + 'A1UdDgQWBBT/H3x+cqSkR/ePSIinPtc4yWKe3DCBpwYDVR0jBIGfMIGcgBT/H3x+\n'
+        + 'cqSkR/ePSIinPtc4yWKe3KF5pHcwdTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh\n'
+        + 'c2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxEzARBgNVBAoTCkFtYXpvbi5jb20x\n'
+        + 'DDAKBgNVBAsTA1JEUzEcMBoGA1UEAxMTYXdzLmFtYXpvbi5jb20vcmRzL4IJAOd1\n'
+        + 'tlfiGoEoMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAvguZy/BDT66x\n'
+        + 'GfgnJlyQwnFSeVLQm9u/FIvz4huGjbq9dqnD6h/Gm56QPFdyMEyDiZWaqY6V08lY\n'
+        + 'LTBNb4kcIc9/6pc0/ojKciP5QJRm6OiZ4vgG05nF4fYjhU7WClUx7cxq1fKjNc2J\n'
+        + 'UCmmYqgiVkAGWRETVo+byOSDZ4swb10=\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID9DCCAtygAwIBAgIBQjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUwOTExMzFaFw0y\n'
+        + 'MDAzMDUwOTExMzFaMIGKMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEbMBkGA1UEAwwSQW1hem9uIFJE\n'
+        + 'UyBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuD8nrZ8V\n'
+        + 'u+VA8yVlUipCZIKPTDcOILYpUe8Tct0YeQQr0uyl018StdBsa3CjBgvwpDRq1HgF\n'
+        + 'Ji2N3+39+shCNspQeE6aYU+BHXhKhIIStt3r7gl/4NqYiDDMWKHxHq0nsGDFfArf\n'
+        + 'AOcjZdJagOMqb3fF46flc8k2E7THTm9Sz4L7RY1WdABMuurpICLFE3oHcGdapOb9\n'
+        + 'T53pQR+xpHW9atkcf3pf7gbO0rlKVSIoUenBlZipUlp1VZl/OD/E+TtRhDDNdI2J\n'
+        + 'P/DSMM3aEsq6ZQkfbz/Ilml+Lx3tJYXUDmp+ZjzMPLk/+3beT8EhrwtcG3VPpvwp\n'
+        + 'BIOqsqVVTvw/CwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw\n'
+        + 'AwEB/zAdBgNVHQ4EFgQUTgLurD72FchM7Sz1BcGPnIQISYMwHwYDVR0jBBgwFoAU\n'
+        + 'TgLurD72FchM7Sz1BcGPnIQISYMwDQYJKoZIhvcNAQEFBQADggEBAHZcgIio8pAm\n'
+        + 'MjHD5cl6wKjXxScXKtXygWH2BoDMYBJF9yfyKO2jEFxYKbHePpnXB1R04zJSWAw5\n'
+        + '2EUuDI1pSBh9BA82/5PkuNlNeSTB3dXDD2PEPdzVWbSKvUB8ZdooV+2vngL0Zm4r\n'
+        + '47QPyd18yPHrRIbtBtHR/6CwKevLZ394zgExqhnekYKIqqEX41xsUV0Gm6x4vpjf\n'
+        + '2u6O/+YE2U+qyyxHE5Wd5oqde0oo9UUpFETJPVb6Q2cEeQib8PBAyi0i6KnF+kIV\n'
+        + 'A9dY7IHSubtCK/i8wxMVqfd5GtbA8mmpeJFwnDvm9rBEsHybl08qlax9syEwsUYr\n'
+        + '/40NawZfTUU=\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIIEATCCAumgAwIBAgIBRDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMDZaFw0y\n'
+        + 'MDAzMDUyMjAzMDZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'
+        + 'UyBhcC1ub3J0aGVhc3QtMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'
+        + 'ggEBAMmM2B4PfTXCZjbZMWiDPyxvk/eeNwIRJAhfzesiGUiLozX6CRy3rwC1ZOPV\n'
+        + 'AcQf0LB+O8wY88C/cV+d4Q2nBDmnk+Vx7o2MyMh343r5rR3Na+4izd89tkQVt0WW\n'
+        + 'vO21KRH5i8EuBjinboOwAwu6IJ+HyiQiM0VjgjrmEr/YzFPL8MgHD/YUHehqjACn\n'
+        + 'C0+B7/gu7W4qJzBL2DOf7ub2qszGtwPE+qQzkCRDwE1A4AJmVE++/FLH2Zx78Egg\n'
+        + 'fV1sUxPtYgjGH76VyyO6GNKM6rAUMD/q5mnPASQVIXgKbupr618bnH+SWHFjBqZq\n'
+        + 'HvDGPMtiiWII41EmGUypyt5AbysCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'
+        + 'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFIiKM0Q6n1K4EmLxs3ZXxINbwEwR\n'
+        + 'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'
+        + 'A4IBAQBezGbE9Rw/k2e25iGjj5n8r+M3dlye8ORfCE/dijHtxqAKasXHgKX8I9Tw\n'
+        + 'JkBiGWiuzqn7gO5MJ0nMMro1+gq29qjZnYX1pDHPgsRjUX8R+juRhgJ3JSHijRbf\n'
+        + '4qNJrnwga7pj94MhcLq9u0f6dxH6dXbyMv21T4TZMTmcFduf1KgaiVx1PEyJjC6r\n'
+        + 'M+Ru+A0eM+jJ7uCjUoZKcpX8xkj4nmSnz9NMPog3wdOSB9cAW7XIc5mHa656wr7I\n'
+        + 'WJxVcYNHTXIjCcng2zMKd1aCcl2KSFfy56sRfT7J5Wp69QSr+jq8KM55gw8uqAwi\n'
+        + 'VPrXn2899T1rcTtFYFP16WXjGuc0\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIIEATCCAumgAwIBAgIBRTANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMTlaFw0y\n'
+        + 'MDAzMDUyMjAzMTlaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'
+        + 'UyBhcC1zb3V0aGVhc3QtMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'
+        + 'ggEBANaXElmSEYt/UtxHFsARFhSUahTf1KNJzR0Dmay6hqOXQuRVbKRwPd19u5vx\n'
+        + 'DdF1sLT7D69IK3VDnUiQScaCv2Dpu9foZt+rLx+cpx1qiQd1UHrvqq8xPzQOqCdC\n'
+        + 'RFStq6yVYZ69yfpfoI67AjclMOjl2Vph3ftVnqP0IgVKZdzeC7fd+umGgR9xY0Qr\n'
+        + 'Ubhd/lWdsbNvzK3f1TPWcfIKQnpvSt85PIEDJir6/nuJUKMtmJRwTymJf0i+JZ4x\n'
+        + '7dJa341p2kHKcHMgOPW7nJQklGBA70ytjUV6/qebS3yIugr/28mwReflg3TJzVDl\n'
+        + 'EOvi6pqbqNbkMuEwGDCmEQIVqgkCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'
+        + 'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAu93/4k5xbWOsgdCdn+/KdiRuit\n'
+        + 'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'
+        + 'A4IBAQBlcjSyscpPjf5+MgzMuAsCxByqUt+WFspwcMCpwdaBeHOPSQrXNqX2Sk6P\n'
+        + 'kth6oCivA64trWo8tFMvPYlUA1FYVD5WpN0kCK+P5pD4KHlaDsXhuhClJzp/OP8t\n'
+        + 'pOyUr5109RHLxqoKB5J5m1XA7rgcFjnMxwBSWFe3/4uMk/+4T53YfCVXuc6QV3i7\n'
+        + 'I/2LAJwFf//pTtt6fZenYfCsahnr2nvrNRNyAxcfvGZ/4Opn/mJtR6R/AjvQZHiR\n'
+        + 'bkRNKF2GW0ueK5W4FkZVZVhhX9xh1Aj2Ollb+lbOqADaVj+AT3PoJPZ3MPQHKCXm\n'
+        + 'xwG0LOLlRr/TfD6li1AfOVTAJXv9\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIIEATCCAumgAwIBAgIBRjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMjRaFw0y\n'
+        + 'MDAzMDUyMjAzMjRaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'
+        + 'UyBhcC1zb3V0aGVhc3QtMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'
+        + 'ggEBAJqBAJutz69hFOh3BtLHZTbwE8eejGGKayn9hu98YMDPzWzGXWCmW+ZYWELA\n'
+        + 'cY3cNWNF8K4FqKXFr2ssorBYim1UtYFX8yhydT2hMD5zgQ2sCGUpuidijuPA6zaq\n'
+        + 'Z3tdhVR94f0q8mpwpv2zqR9PcqaGDx2VR1x773FupRPRo7mEW1vC3IptHCQlP/zE\n'
+        + '7jQiLl28bDIH2567xg7e7E9WnZToRnhlYdTaDaJsHTzi5mwILi4cihSok7Shv/ME\n'
+        + 'hnukvxeSPUpaVtFaBhfBqq055ePq9I+Ns4KGreTKMhU0O9fkkaBaBmPaFgmeX/XO\n'
+        + 'n2AX7gMouo3mtv34iDTZ0h6YCGkCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'
+        + 'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFIlQnY0KHYWn1jYumSdJYfwj/Nfw\n'
+        + 'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'
+        + 'A4IBAQA0wVU6/l41cTzHc4azc4CDYY2Wd90DFWiH9C/mw0SgToYfCJ/5Cfi0NT/Y\n'
+        + 'PRnk3GchychCJgoPA/k9d0//IhYEAIiIDjyFVgjbTkKV3sh4RbdldKVOUB9kumz/\n'
+        + 'ZpShplsGt3z4QQiVnKfrAgqxWDjR0I0pQKkxXa6Sjkicos9LQxVtJ0XA4ieG1E7z\n'
+        + 'zJr+6t80wmzxvkInSaWP3xNJK9azVRTrgQZQlvkbpDbExl4mNTG66VD3bAp6t3Wa\n'
+        + 'B49//uDdfZmPkqqbX+hsxp160OH0rxJppwO3Bh869PkDnaPEd/Pxw7PawC+li0gi\n'
+        + 'NRV8iCEx85aFxcyOhqn0WZOasxee\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/zCCAuegAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMzFaFw0y\n'
+        + 'MDAzMDUyMjAzMzFaMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEjMCEGA1UEAwwaQW1hem9uIFJE\n'
+        + 'UyBldS1jZW50cmFsLTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n'
+        + 'AQDFtP2dhSLuaPOI4ZrrPWsK4OY9ocQBp3yApH1KJYmI9wpQKZG/KCH2E6Oo7JAw\n'
+        + 'QORU519r033T+FO2Z7pFPlmz1yrxGXyHpJs8ySx3Yo5S8ncDCdZJCLmtPiq/hahg\n'
+        + '5/0ffexMFUCQaYicFZsrJ/cStdxUV+tSw2JQLD7UxS9J97LQWUPyyG+ZrjYVTVq+\n'
+        + 'zudnFmNSe4QoecXMhAFTGJFQXxP7nhSL9Ao5FGgdXy7/JWeWdQIAj8ku6cBDKPa6\n'
+        + 'Y6kP+ak+In+Lye8z9qsCD/afUozfWjPR2aA4JoIZVF8dNRShIMo8l0XfgfM2q0+n\n'
+        + 'ApZWZ+BjhIO5XuoUgHS3D2YFAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNV\n'
+        + 'HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRm4GsWIA/M6q+tK8WGHWDGh2gcyTAf\n'
+        + 'BgNVHSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOC\n'
+        + 'AQEAHpMmeVQNqcxgfQdbDIi5UIy+E7zZykmtAygN1XQrvga9nXTis4kOTN6g5/+g\n'
+        + 'HCx7jIXeNJzAbvg8XFqBN84Quqgpl/tQkbpco9Jh1HDs558D5NnZQxNqH5qXQ3Mm\n'
+        + 'uPgCw0pYcPOa7bhs07i+MdVwPBsX27CFDtsgAIru8HvKxY1oTZrWnyIRo93tt/pk\n'
+        + 'WuItVMVHjaQZVfTCow0aDUbte6Vlw82KjUFq+n2NMSCJDiDKsDDHT6BJc4AJHIq3\n'
+        + '/4Z52MSC9KMr0yAaaoWfW/yMEj9LliQauAgwVjArF4q78rxpfKTG9Rfd8U1BZANP\n'
+        + '7FrFMN0ThjfA1IvmOYcgskY5bQ==\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/DCCAuSgAwIBAgIBSDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMzVaFw0y\n'
+        + 'MDAzMDUyMjAzMzVaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'
+        + 'UyBldS13ZXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx\n'
+        + 'PdbqQ0HKRj79Pmocxvjc+P6i4Ux24kgFIl+ckiir1vzkmesc3a58gjrMlCksEObt\n'
+        + 'Yihs5IhzEq1ePT0gbfS9GYFp34Uj/MtPwlrfCBWG4d2TcrsKRHr1/EXUYhWqmdrb\n'
+        + 'RhX8XqoRhVkbF/auzFSBhTzcGGvZpQ2KIaxRcQfcXlMVhj/pxxAjh8U4F350Fb0h\n'
+        + 'nX1jw4/KvEreBL0Xb2lnlGTkwVxaKGSgXEnOgIyOFdOQc61vdome0+eeZsP4jqeR\n'
+        + 'TGYJA9izJsRbe2YJxHuazD+548hsPlM3vFzKKEVURCha466rAaYAHy3rKur3HYQx\n'
+        + 'Yt+SoKcEz9PXuSGj96ejAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'
+        + 'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTebg//h2oeXbZjQ4uuoiuLYzuiPDAfBgNV\n'
+        + 'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'
+        + 'TikPaGeZasTPw+4RBemlsyPAjtFFQLo7ddaFdORLgdEysVf8aBqndvbA6MT/v4lj\n'
+        + 'GtEtUdF59ZcbWOrVm+fBZ2h/jYJ59dYF/xzb09nyRbdMSzB9+mkSsnOMqluq5y8o\n'
+        + 'DY/PfP2vGhEg/2ZncRC7nlQU1Dm8F4lFWEiQ2fi7O1cW852Vmbq61RIfcYsH/9Ma\n'
+        + 'kpgk10VZ75b8m3UhmpZ/2uRY+JEHImH5WpcTJ7wNiPNJsciZMznGtrgOnPzYco8L\n'
+        + 'cDleOASIZifNMQi9PKOJKvi0ITz0B/imr8KBsW0YjZVJ54HMa7W1lwugSM7aMAs+\n'
+        + 'E3Sd5lS+SHwWaOCHwhOEVA==\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/DCCAuSgAwIBAgIBSTANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNDBaFw0y\n'
+        + 'MDAzMDUyMjAzNDBaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'
+        + 'UyBzYS1lYXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCU\n'
+        + 'X4OBnQ5xA6TLJAiFEI6l7bUWjoVJBa/VbMdCCSs2i2dOKmqUaXu2ix2zcPILj3lZ\n'
+        + 'GMk3d/2zvTK/cKhcFrewHUBamTeVHdEmynhMQamqNmkM4ptYzFcvEUw1TGxHT4pV\n'
+        + 'Q6gSN7+/AJewQvyHexHo8D0+LDN0/Wa9mRm4ixCYH2CyYYJNKaZt9+EZfNu+PPS4\n'
+        + '8iB0TWH0DgQkbWMBfCRgolLLitAZklZ4dvdlEBS7evN1/7ttBxUK6SvkeeSx3zBl\n'
+        + 'ww3BlXqc3bvTQL0A+RRysaVyFbvtp9domFaDKZCpMmDFAN/ntx215xmQdrSt+K3F\n'
+        + 'cXdGQYHx5q410CAclGnbAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'
+        + 'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBT6iVWnm/uakS+tEX2mzIfw+8JL0zAfBgNV\n'
+        + 'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'
+        + 'FmDD+QuDklXn2EgShwQxV13+txPRuVdOSrutHhoCgMwFWCMtPPtBAKs6KPY7Guvw\n'
+        + 'DpJoZSehDiOfsgMirjOWjvfkeWSNvKfjWTVneX7pZD9W5WPnsDBvTbCGezm+v87z\n'
+        + 'b+ZM2ZMo98m/wkMcIEAgdSKilR2fuw8rLkAjhYFfs0A7tDgZ9noKwgHvoE4dsrI0\n'
+        + 'KZYco6DlP/brASfHTPa2puBLN9McK3v+h0JaSqqm5Ro2Bh56tZkQh8AWy/miuDuK\n'
+        + '3+hNEVdxosxlkM1TPa1DGj0EzzK0yoeerXuH2HX7LlCrrxf6/wdKnjR12PMrLQ4A\n'
+        + 'pCqkcWw894z6bV9MAvKe6A==\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/DCCAuSgAwIBAgIBQzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMTU0MDRaFw0y\n'
+        + 'MDAzMDUyMTU0MDRaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'
+        + 'UyB1cy1lYXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDI\n'
+        + 'UIuwh8NusKHk1SqPXcP7OqxY3S/M2ZyQWD3w7Bfihpyyy/fc1w0/suIpX3kbMhAV\n'
+        + '2ESwged2/2zSx4pVnjp/493r4luhSqQYzru78TuPt9bhJIJ51WXunZW2SWkisSaf\n'
+        + 'USYUzVN9ezR/bjXTumSUQaLIouJt3OHLX49s+3NAbUyOI8EdvgBQWD68H1epsC0n\n'
+        + 'CI5s+pIktyOZ59c4DCDLQcXErQ+tNbDC++oct1ANd/q8p9URonYwGCGOBy7sbCYq\n'
+        + '9eVHh1Iy2M+SNXddVOGw5EuruvHoCIQyOz5Lz4zSuZA9dRbrfztNOpezCNYu6NKM\n'
+        + 'n+hzcvdiyxv77uNm8EaxAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'
+        + 'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBQSQG3TmMe6Sa3KufaPBa72v4QFDzAfBgNV\n'
+        + 'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'
+        + 'L/mOZfB3187xTmjOHMqN2G2oSKHBKiQLM9uv8+97qT+XR+TVsBT6b3yoPpMAGhHA\n'
+        + 'Pc7nxAF5gPpuzatx0OTLPcmYucFmfqT/1qA5WlgCnMNtczyNMH97lKFTNV7Njtek\n'
+        + 'jWEzAEQSyEWrkNpNlC4j6kMYyPzVXQeXUeZTgJ9FNnVZqmvfjip2N22tawMjrCn5\n'
+        + '7KN/zN65EwY2oO9XsaTwwWmBu3NrDdMbzJnbxoWcFWj4RBwanR1XjQOVNhDwmCOl\n'
+        + '/1Et13b8CPyj69PC8BOVU6cfTSx8WUVy0qvYOKHNY9Bqa5BDnIL3IVmUkeTlM1mt\n'
+        + 'enRpyBj+Bk9rh/ICdiRKmA==\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/DCCAuSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNDVaFw0y\n'
+        + 'MDAzMDUyMjAzNDVaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'
+        + 'UyB1cy13ZXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE\n'
+        + 'Dhw+uw/ycaiIhhyu2pXFRimq0DlB8cNtIe8hdqndH8TV/TFrljNgR8QdzOgZtZ9C\n'
+        + 'zzQ2GRpInN/qJF6slEd6wO+6TaDBQkPY+07TXNt52POFUhdVkhJXHpE2BS7Xn6J7\n'
+        + '7RFAOeG1IZmc2DDt+sR1BgXzUqHslQGfFYNS0/MBO4P+ya6W7IhruB1qfa4HiYQS\n'
+        + 'dbe4MvGWnv0UzwAqdR7OF8+8/5c58YXZIXCO9riYF2ql6KNSL5cyDPcYK5VK0+Q9\n'
+        + 'VI6vuJHSMYcF7wLePw8jtBktqAFE/wbdZiIHhZvNyiNWPPNTGUmQbaJ+TzQEHDs5\n'
+        + '8en+/W7JKnPyBOkxxENbAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'
+        + 'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBS0nw/tFR9bCjgqWTPJkyy4oOD8bzAfBgNV\n'
+        + 'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'
+        + 'CXGAY3feAak6lHdqj6+YWjy6yyUnLK37bRxZDsyDVXrPRQaXRzPTzx79jvDwEb/H\n'
+        + 'Q/bdQ7zQRWqJcbivQlwhuPJ4kWPUZgSt3JUUuqkMsDzsvj/bwIjlrEFDOdHGh0mi\n'
+        + 'eVIngFEjUXjMh+5aHPEF9BlQnB8LfVtKj18e15UDTXFa+xJPFxUR7wDzCfo4WI1m\n'
+        + 'sUMG4q1FkGAZgsoyFPZfF8IVvgCuGdR8z30VWKklFxttlK0eGLlPAyIO0CQxPQlo\n'
+        + 'saNJrHf4tLOgZIWk+LpDhNd9Et5EzvJ3aURUsKY4pISPPF5WdvM9OE59bERwUErd\n'
+        + 'nuOuQWQeeadMceZnauRzJQ==\n'
+        + '-----END CERTIFICATE-----\n',
+        '-----BEGIN CERTIFICATE-----\n'
+        + 'MIID/DCCAuSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'
+        + 'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'
+        + 'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'
+        + 'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNTBaFw0y\n'
+        + 'MDAzMDUyMjAzNTBaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'
+        + 'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'
+        + 'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'
+        + 'UyB1cy13ZXN0LTIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM\n'
+        + 'H58SR48U6jyERC1vYTnub34smf5EQVXyzaTmspWGWGzT31NLNZGSDFaa7yef9kdO\n'
+        + 'mzJsgebR5tXq6LdwlIoWkKYQ7ycUaadtVKVYdI40QcI3cHn0qLFlg2iBXmWp/B+i\n'
+        + 'Z34VuVlCh31Uj5WmhaBoz8t/GRqh1V/aCsf3Wc6jCezH3QfuCjBpzxdOOHN6Ie2v\n'
+        + 'xX09O5qmZTvMoRBAvPkxdaPg/Mi7fxueWTbEVk78kuFbF1jHYw8U1BLILIAhcqlq\n'
+        + 'x4u8nl73t3O3l/soNUcIwUDK0/S+Kfqhwn9yQyPlhb4Wy3pfnZLJdkyHldktnQav\n'
+        + '9TB9u7KH5Lk0aAYslMLxAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'
+        + 'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBT8roM4lRnlFHWMPWRz0zkwFZog1jAfBgNV\n'
+        + 'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'
+        + 'JwrxwgwmPtcdaU7O7WDdYa4hprpOMamI49NDzmE0s10oGrqmLwZygcWU0jT+fJ+Y\n'
+        + 'pJe1w0CVfKaeLYNsOBVW3X4ZPmffYfWBheZiaiEflq/P6t7/Eg81gaKYnZ/x1Dfa\n'
+        + 'sUYkzPvCkXe9wEz5zdUTOCptDt89rBR9CstL9vE7WYUgiVVmBJffWbHQLtfjv6OF\n'
+        + 'NMb0QME981kGRzc2WhgP71YS2hHd1kXtsoYP1yTu4vThSKsoN4bkiHsaC1cRkLoy\n'
+        + '0fFA4wpB3WloMEvCDaUvvH1LZlBXTNlwi9KtcwD4tDxkkBt4tQczKLGpQ/nF/W9n\n'
+        + '8YDWk3IIc1sd0bkZqoau2Q==\n'
+        + '-----END CERTIFICATE-----\n'
+    ]
+}
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/types.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/types.js
new file mode 100644
index 0000000000000000000000000000000000000000..21c40005e4838c94043ea2483f5b6c3c4c8f4793
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/constants/types.js
@@ -0,0 +1,29 @@
+// Manually extracted from mysql-5.5.23/include/mysql_com.h
+// some more info here: http://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-statement-type-codes.html
+exports.DECIMAL     = 0x00; // aka DECIMAL (http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html)
+exports.TINY        = 0x01; // aka TINYINT, 1 byte
+exports.SHORT       = 0x02; // aka SMALLINT, 2 bytes
+exports.LONG        = 0x03; // aka INT, 4 bytes
+exports.FLOAT       = 0x04; // aka FLOAT, 4-8 bytes
+exports.DOUBLE      = 0x05; // aka DOUBLE, 8 bytes
+exports.NULL        = 0x06; // NULL (used for prepared statements, I think)
+exports.TIMESTAMP   = 0x07; // aka TIMESTAMP
+exports.LONGLONG    = 0x08; // aka BIGINT, 8 bytes
+exports.INT24       = 0x09; // aka MEDIUMINT, 3 bytes
+exports.DATE        = 0x0a; // aka DATE
+exports.TIME        = 0x0b; // aka TIME
+exports.DATETIME    = 0x0c; // aka DATETIME
+exports.YEAR        = 0x0d; // aka YEAR, 1 byte (don't ask)
+exports.NEWDATE     = 0x0e; // aka ?
+exports.VARCHAR     = 0x0f; // aka VARCHAR (?)
+exports.BIT         = 0x10; // aka BIT, 1-8 byte
+exports.NEWDECIMAL  = 0xf6; // aka DECIMAL
+exports.ENUM        = 0xf7; // aka ENUM
+exports.SET         = 0xf8; // aka SET
+exports.TINY_BLOB   = 0xf9; // aka TINYBLOB, TINYTEXT
+exports.MEDIUM_BLOB = 0xfa; // aka MEDIUMBLOB, MEDIUMTEXT
+exports.LONG_BLOB   = 0xfb; // aka LONGBLOG, LONGTEXT
+exports.BLOB        = 0xfc; // aka BLOB, TEXT
+exports.VAR_STRING  = 0xfd; // aka VARCHAR, VARBINARY
+exports.STRING      = 0xfe; // aka CHAR, BINARY
+exports.GEOMETRY    = 0xff; // aka GEOMETRY
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/helpers.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/helpers.js
new file mode 100644
index 0000000000000000000000000000000000000000..255490581f129bd35474e90a62022c2c15578f2e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/helpers.js
@@ -0,0 +1,21 @@
+  /*
+
+  this seems to be not only shorter, but faster than
+  string.replace(/\\/g, '\\\\').
+            replace(/\u0008/g, '\\b').
+            replace(/\t/g, '\\t').
+            replace(/\n/g, '\\n').
+            replace(/\f/g, '\\f').
+            replace(/\r/g, '\\r').
+            replace(/'/g, '\\\'').
+            replace(/"/g, '\\"');
+  or string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
+  see http://jsperf.com/string-escape-regexp-vs-json-stringify
+  */
+  function srcEscape(str) {
+    var a = {};
+    a[str] = 1;
+    return JSON.stringify(a).slice(1,-3);
+  }
+
+module.exports.srcEscape = srcEscape;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packet_parser.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packet_parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e4a3910209e863c50dc6977fc637254c347014b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packet_parser.js
@@ -0,0 +1,103 @@
+var Packet   = require('./packets/packet.js');
+
+function PacketParser(onPacket)
+{
+  // array of last payload chunks
+  // only used when corrent payload is not complete
+  this.buffer = [];
+  // total length of chunks on buffer
+  this.bufferLength = 0;
+
+  // incomplete header state: number of header bytes received
+  this.headerLen = 0;
+
+  // expected payload length
+  this.length     = 0;
+
+  this.onPacket = onPacket;
+  this.execute  = PacketParser.prototype.executeStart;
+}
+
+function readPacketLength(b,off) {
+  var b0 = b[off];
+  var b1 = b[off+1];
+  var b2 = b[off+2];
+  if (b1 + b2 === 0)
+    return b0;
+  return b0 + (b1<<8) + (b2<<16);
+}
+
+//
+PacketParser.prototype.executeStart = function executeStart(chunk) {
+  var start = 0;
+  var end = chunk.length;
+  // if (start-end === 0) return;
+
+  while (end - start >= 3) {
+    this.length = readPacketLength(chunk, start);
+    if (end - start >= this.length + 4) { // at least one more full packet
+      this.onPacket(new Packet(chunk[start+3], chunk, start + 4, start + 4 + this.length));
+      start += 4 + this.length;
+    } else { // payload is incomplete
+      this.buffer = [chunk.slice(start + 3, end)];
+      this.bufferLength = end - start - 3;
+      this.execute = PacketParser.prototype.executePayload;
+      return;
+    }
+  }
+  if (end - start > 0) { // there is start of length header, but it's not full 3 bytes
+    this.headerLen = end - start; // 1 or 2 bytes
+    this.length = chunk[start];
+    if (this.headerLen == 2) {
+      this.length = chunk[start] + (chunk[start+1] << 8);
+      this.execute = PacketParser.prototype.executeHeader3;
+    } else {
+      this.execute = PacketParser.prototype.executeHeader2;
+    }
+  }
+}
+
+PacketParser.prototype.executePayload = function executePayload(chunk) {
+  var start = 0;
+  var end = chunk.length;
+  var remainingPayload = this.length - this.bufferLength + 1;
+
+  if (end - start >= remainingPayload) { // last chunk for payload
+    var payload = new Buffer(this.length + 1);
+    var offset = 0;
+    for (var i=0; i < this.buffer.length; ++i) {
+      this.buffer[i].copy(payload, offset);
+      offset += this.buffer[i].length;
+    }
+    chunk.copy(payload, offset, start, start + remainingPayload);
+    this.onPacket(new Packet(payload[0], payload, 1, this.length + 1));
+    this.buffer = [];
+    this.bufferLength = 0;
+    this.execute = PacketParser.prototype.executeStart;
+    start += remainingPayload;
+    if (end - start > 0)
+      return this.execute(chunk.slice(start, end));
+  } else {
+    this.buffer.push(chunk);
+    this.bufferLength += chunk.length;
+  }
+}
+
+PacketParser.prototype.executeHeader2 = function executeHeader2(chunk) {
+  this.length += chunk[0] << 8;
+  if (chunk.length > 1) {
+    this.length += chunk[1] << 16;
+    this.execute = PacketParser.prototype.executePayload;
+    return this.executePayload(chunk.slice(2));
+  } else {
+    this.execute = PacketParser.prototype.executeHeader3;
+  }
+}
+
+PacketParser.prototype.executeHeader3 = function executeHeader3(chunk) {
+  this.length += chunk[0] << 16;
+  this.execute = PacketParser.prototype.executePayload;
+  return this.executePayload(chunk.slice(1));
+}
+
+module.exports = PacketParser;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binary_row.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binary_row.js
new file mode 100644
index 0000000000000000000000000000000000000000..695e7f2e34c88677cad86eab004af5b35400cd63
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binary_row.js
@@ -0,0 +1,44 @@
+var Types = require('../constants/types');
+var Packet = require('../packets/packet');
+
+function BinaryRow(columns)
+{
+  this.columns = columns || [];
+}
+
+  var binaryReader = new Array(256);
+
+  // TODO: replace with constants.MYSQL_TYPE_*
+  binaryReader[Types.DECIMAL] = Packet.prototype.readLengthCodedString;
+  binaryReader[1] = Packet.prototype.readInt8;   // tiny
+  binaryReader[2] = Packet.prototype.readInt16;  // short
+  binaryReader[3] = Packet.prototype.readInt32;  // long
+  binaryReader[4] = Packet.prototype.readFloat;  // float
+  binaryReader[5] = Packet.prototype.readDouble; // double
+  binaryReader[6] = Packet.prototype.assertInvalid; // null, should be skipped vie null bitmap
+  binaryReader[7] = Packet.prototype.readTimestamp; // timestamp, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIMESTAMP
+  binaryReader[8] = Packet.prototype.readInt64;  // long long
+  binaryReader[9] = Packet.prototype.readInt32;  // int24
+  binaryReader[10] = Packet.prototype.readTimestamp; // date
+  binaryReader[11] = Packet.prototype.readTime;  // time, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIME
+  binaryReader[12] = Packet.prototype.readDateTime;  // datetime, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_DATETIME
+  binaryReader[13] = Packet.prototype.readInt16;  // year
+  binaryReader[Types.VAR_STRING] = Packet.prototype.readLengthCodedString;  // var string
+  // TODO: complete list of types...
+
+BinaryRow.fromPacket = function(fields, packet) {
+  var columns = new Array(fields.length);
+  var ok = packet.readInt8(); // TODO check it's 0
+  var nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
+  // TODO: read and interpret null bitmap
+  packet.skip(nullBitmapLength);
+  for (var i = 0; i < columns.length; ++i)
+     columns[i] = binaryReader[fields[i].columnType].apply(packet);
+  return new BinaryRow(columns);
+};
+
+BinaryRow.prototype.toPacket = function(sequenceId) {
+  throw "Not implemented";
+};
+
+module.exports = BinaryRow;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_dump.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_dump.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ca14f9dbf92d6192d41c4b2dddd8419ede9a348
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_dump.js
@@ -0,0 +1,33 @@
+// http://dev.mysql.com/doc/internals/en/com-binlog-dump.html#packet-COM_BINLOG_DUMP
+
+var Packet = require('../packets/packet');
+var CommandCodes = require('../constants/commands');
+
+// TODO: add flag to constants
+// 0x01 - BINLOG_DUMP_NON_BLOCK
+// send EOF instead of blocking
+
+function BinlogDump(opts)
+{
+  this.binlogPos       = opts.binlogPos || 0;
+  this.serverId        = opts.serverId  || 0;
+  this.flags           = opts.flags || 0;
+  this.filename        = opts.filename || '';
+}
+
+BinlogDump.prototype.toPacket = function()
+{
+  var length =  15 + // TODO: should be ascii?
+    Buffer.byteLength(this.filename, 'utf8');
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(CommandCodes.BINLOG_DUMP);
+  packet.writeInt32(this.binlogPos);
+  packet.writeInt16(this.flags);
+  packet.writeInt32(this.serverId);
+  packet.writeString(this.filename);
+  return packet;
+};
+
+module.exports = BinlogDump;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_query_statusvars.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_query_statusvars.js
new file mode 100644
index 0000000000000000000000000000000000000000..d880288f133b2279bcfc801c0b1c741e312cc53f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/binlog_query_statusvars.js
@@ -0,0 +1,99 @@
+// http://dev.mysql.com/doc/internals/en/query-event.html
+
+var keys = {
+  FLAGS2: 0,
+  SQL_MODE: 1,
+  CATALOG: 2,
+  AUTO_INCREMENT: 3,
+  CHARSET: 4,
+  TIME_ZONE: 5,
+  CATALOG_NZ: 6,
+  LC_TIME_NAMES: 7,
+  CHARSET_DATABASE: 8,
+  TABLE_MAP_FOR_UPDATE: 9,
+  MASTER_DATA_WRITTEN: 10,
+  INVOKERS: 11,
+  UPDATED_DB_NAMES: 12,
+  MICROSECONDS: 3
+};
+
+module.exports = function parseStatusVars(buffer) {
+  var result = {};
+  var offset = 0;
+  var key, length, username, hostname, prevOffset;
+  while(offset < buffer.length) {
+    key = buffer[offset++];
+    val = [key];
+    switch(key) {
+    case keys.FLAGS2:
+      result.flags = buffer.readUInt32LE(offset);
+      offset += 4; break;
+    case keys.SQL_MODE:
+      // value is 8 bytes, but all dcumented flags are in first 4 bytes
+      result.sqlMode = buffer.readUInt32LE(offset);
+      offset += 8; 
+      break;
+    case keys.CATALOG:
+      length = buffer[offset++];
+      result.catalog = buffer.toString('utf8', offset, offset + length);
+      offset += length + 1; // null byte after string
+      break;
+    case keys.CHARSET:
+      result.clientCharset = buffer.readUInt16LE(offset);
+      result.connectionCollation = buffer.readUInt16LE(offset + 2);
+      result.serverCharset = buffer.readUInt16LE(offset + 4);
+      offset += 6;
+      break;
+    case keys.TIME_ZONE:
+      length = buffer[offset++];
+      result.timeZone = buffer.toString('utf8', offset, offset + length);
+      offset += length; // no null byte
+      break;
+    case keys.CATALOG_NZ:
+      length = buffer[offset++];
+      result.catalogNz = buffer.toString('utf8', offset, offset + length);
+      offset += length ; // no null byte
+      break;
+    case keys.LC_TIME_NAMES:
+      result.lcTimeNames = buffer.readUInt16LE(offset); 
+      offset += 2; 
+      break;
+    case keys.CHARSET_DATABASE:
+      result.schemaCharset = buffer.readUInt16LE(offset);
+      offset += 2;
+      break;
+    case keys.TABLE_MAP_FOR_UPDATE:
+      result.mapForUpdate1 = buffer.readUInt32LE(offset);
+      result.mapForUpdate2 = buffer.readUInt32LE(offset + 4);
+      offset += 8; 
+      break;
+    case keys.MASTER_DATA_WRITTEN:
+      result.masterDataWritten = buffer.readUInt32LE(offset);
+      offset += 4;
+      break;
+    case keys.INVOKERS:
+      length = buffer[offset++];
+      result.invokerUsername = buffer.toString('utf8', offset, offset + length);
+      offset += length;
+      length = buffer[offset++];
+      result.invokerHostname = buffer.toString('utf8', offset, offset + length);
+      offset += length;
+      break;
+    case keys.UPDATED_DB_NAMES:
+      length = buffer[offset++];
+      // length - number of null-terminated strings
+      result.updatedDBs = []; // we'll store them as array here
+      for (; length; --length) {
+        prevOffset = offset;
+        // fast forward to null terminating byte
+        while(buffer[offset++] && offset < buffer.length) {}
+        result.updatedDBs.push(buffer.toString('utf8', prevOffset, offset-1));
+      }
+      break;
+    case keys.MICROSECONDS:
+      result.microseconds = buffer.readInt16LE(offset) + (buffsre[offset+2] << 16);
+      offset += 3;
+    }
+  }
+  return result;
+}
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/change_user.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/change_user.js
new file mode 100644
index 0000000000000000000000000000000000000000..d5888aaac44b5426a239e3e1a35abe8b197d1038
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/change_user.js
@@ -0,0 +1,50 @@
+var CommandCode     = require('../constants/commands.js');
+var Packet          = require('../packets/packet.js');
+
+var auth41 = require('../auth_41.js');
+
+function ChangeUser(opts)
+{
+  this.user            = opts.user || '';
+  this.database        = opts.database || '';
+  this.password        = opts.password || '';
+  this.passwordSha1    = opts.passwordSha1;
+  this.authPluginData1 = opts.authPluginData1;
+  this.authPluginData2 = opts.authPluginData2;
+  var authToken;
+  if (this.passwordSha1) {
+    authToken = auth41.calculateTokenFromPasswordSha(this.passwordSha1, this.authPluginData1, this.authPluginData2);
+  } else {
+    authToken = auth41.calculateToken(this.password, this.authPluginData1, this.authPluginData2);
+  }
+  this.authToken       = authToken;
+  this.charsetNumber   = opts.charsetNumber;
+}
+
+// TODO
+//ChangeUser.fromPacket = function(packet)
+//};
+
+ChangeUser.prototype.toPacket = function()
+{
+  if (typeof this.user != 'string')
+    throw new Error('"user" connection config prperty must be a string');
+  if (typeof this.database != 'string')
+    throw new Error('"database" connection config prperty must be a string');
+
+  var length = 4 + 1 + (1 + this.authToken.length) + (2 + this.user.length + this.database.length) + 2;
+
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+
+  packet.writeInt8(CommandCode.CHANGE_USER);
+  packet.writeNullTerminatedString(this.user);
+  packet.writeInt8(this.authToken.length);
+  packet.writeBuffer(this.authToken);
+  packet.writeNullTerminatedString(this.database);
+  packet.writeInt16(this.charsetNumber);
+  return packet;
+};
+
+module.exports = ChangeUser;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/close_statement.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/close_statement.js
new file mode 100644
index 0000000000000000000000000000000000000000..5a51449a6e9c5a623414d50dbfc5aac3d30f7f26
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/close_statement.js
@@ -0,0 +1,19 @@
+var Packet = require('../packets/packet');
+var CommandCodes = require('../constants/commands');
+
+function CloseStatement(id)
+{
+  this.id = id;
+}
+
+// note: no response sent back
+CloseStatement.prototype.toPacket = function()
+{
+  var packet = new Packet(0, new Buffer(9));
+  packet.offset = 4;
+  packet.writeInt8(CommandCodes.STMT_CLOSE);
+  packet.writeInt32(this.id);
+  return packet;
+};
+
+module.exports = CloseStatement;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/column_definition.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/column_definition.js
new file mode 100644
index 0000000000000000000000000000000000000000..84be5217619956fe0232191e8fd39871c78cd2de
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/column_definition.js
@@ -0,0 +1,110 @@
+var Packet = require('../packets/packet');
+
+// creating JS string is relatively expencive (compared to
+// reading few bytes from buffer) because all string properties
+// except for name are unlikely to be used we postpone
+// string conversion until property access
+//
+// TODO: watch for integration benchmarks (one with real network buffer)
+// there could be bad side effect as keeping reference to a buffer makes it
+// sit in the memory longer (usually until final .query() callback)
+// Latest v8 perform much better in regard to bufferer -> string convertion,
+// at some point of time this optimisation might become unnecessary
+// see https://github.com/sidorares/node-mysql2/pull/137
+//
+function ColumnDefinition(packet)
+{
+  this._buf     = packet.buffer;
+
+  this._catalogLength = packet.readLengthCodedNumber();
+  this._catalogStart  = packet.offset;
+  packet.offset += this._catalogLength;
+
+  this._schemaLength = packet.readLengthCodedNumber();
+  this._schemaStart  = packet.offset;
+  packet.offset += this._schemaLength;
+
+  this._tableLength = packet.readLengthCodedNumber();
+  this._tableStart  = packet.offset;
+  packet.offset += this._tableLength;
+
+  this._orgTableLength = packet.readLengthCodedNumber();
+  this._orgTableStart  = packet.offset;
+  packet.offset += this._orgTableLength;
+
+  // name is always used, don't make it lazy
+  this.name     = packet.readLengthCodedString();
+
+  this._orgNameLength = packet.readLengthCodedNumber();
+  this._orgNameStart  = packet.offset;
+  packet.offset += this._orgNameLength;
+
+  packet.skip(1); //  length of the following fields (always 0x0c)
+  this.characterSet = packet.readInt16();
+  this.columnLength = packet.readInt32();
+  this.columnType   = packet.readInt8();
+  this.flags        = packet.readInt16();
+  this.decimals     = packet.readInt8();
+}
+
+var addString = function(name) {
+  Object.defineProperty(ColumnDefinition.prototype, name, { get: function() {
+    var start = this['_' + name + 'Start'];
+    var end = start + this['_' + name + 'Length'];
+    return this._buf.utf8Slice(start, end);
+  }});
+};
+
+addString('catalog');
+addString('schema');
+addString('table');
+addString('orgTable');
+addString('orgName');
+
+ColumnDefinition.prototype.inspect = function() {
+  return {
+    catalog      : this.catalog,
+    schema      : this.schema,
+    name        : this.name,
+    orgName     : this.orgName,
+    table       : this.table,
+    orgTable    : this.orgTable,
+    characterSet: this.characterSet,
+    columnLength: this.columnLength,
+    columnType  : this.columnType,
+    flags       : this.flags,
+    decimals    : this.decimals
+  };
+};
+
+ColumnDefinition.toPacket = function(column, sequenceId)
+{
+  var length = 0;
+  var fields = 'catalog schema table orgTable name orgName'.split(' ');
+  function addFieldLength(name) {
+    var str = column[name];
+    length +=Packet.lengthCodedNumberLength(str);
+    length += str.length;
+  }
+  fields.forEach(addFieldLength);
+  length += 13;
+  var buffer = new Buffer(length);
+  for (var i=0; i < length; ++i)
+    buffer[i] = 0;
+
+  function writeField(name) {
+    packet.writeLengthCodedString(column[name]);
+  }
+  var packet = new Packet(sequenceId, buffer, 0, length);
+  packet.offset = 4;
+  fields.forEach(writeField);
+  packet.writeInt8 (0x0c);
+  packet.writeInt16(column.characterSet);
+  packet.writeInt32(column.columnLength);
+  packet.writeInt8 (column.columnType);
+  packet.writeInt16(column.flags);
+  packet.writeInt8 (column.decimals);
+  return packet;
+};
+
+module.exports = ColumnDefinition;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/execute.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/execute.js
new file mode 100644
index 0000000000000000000000000000000000000000..b21f326bc7798dbd6971dfab6088c74dac4e6f26
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/execute.js
@@ -0,0 +1,103 @@
+var CursorType   = require('../constants/cursor');
+var CommandCodes = require('../constants/commands');
+var Types        = require('../constants/types');
+var Packet       = require('../packets/packet');
+
+function Execute(id, parameters)
+{
+  this.id = id;
+  this.parameters = parameters;
+}
+
+Execute.prototype.toPacket = function()
+{
+
+  // TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
+  // and copy + reallocate if not enough
+
+  var i;
+  // 0 + 4 - length, seqId
+  // 4 + 1 - COM_EXECUTE
+  // 5 + 4 - stmtId
+  // 9 + 1 - flags
+  // 10 + 4 - iteration-count (always 1)
+  var length = 14;
+  if (this.parameters && this.parameters.length > 0)
+  {
+    length += Math.floor((this.parameters.length + 7) / 8);
+    length += 1; // new-params-bound-flag
+    length += 2*this.parameters.length;  // type byte for each parameter if new-params-bound-flag is set
+    for (i=0; i < this.parameters.length; i++)
+    {
+      if (this.parameters[i] !== null) {
+        if (Object.prototype.toString.call(this.parameters[i]) == '[object Date]') {
+          var d = this.parameters[i];
+          // TODO: move to asMysqlDateTime()
+          this.parameters[i] = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-') +
+            ' ' + [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
+        }
+        if (Buffer.isBuffer(this.parameters[i])) {
+          length += Packet.lengthCodedNumberLength(this.parameters[i].length);
+          length += this.parameters[i].length;
+        }
+        else {
+          var str = this.parameters[i].toString();
+          var byteLen = Buffer.byteLength(str, 'utf8');
+          length += Packet.lengthCodedNumberLength(byteLen);
+          length += byteLen;
+        }
+      }
+    }
+  }
+
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(CommandCodes.STMT_EXECUTE);
+  packet.writeInt32(this.id);
+  packet.writeInt8(CursorType.NO_CURSOR);  // flags
+  packet.writeInt32(1); // iteration-count, always 1
+  if (this.parameters && this.parameters.length > 0) {
+
+    var bitmap = 0;
+    var bitValue = 1;
+    for (i=0; i < this.parameters.length; i++)
+    {
+      if (this.parameters[i] === null)
+        bitmap += bitValue;
+      bitValue *= 2;
+      if (bitValue == 256) {
+        packet.writeInt8(bitmap);
+        bitmap = 0;
+        bitValue = 1;
+      }
+    }
+    if (bitValue != 1)
+      packet.writeInt8(bitmap);
+
+    // TODO: explain meaning of the flag
+    // afaik, if set n*2 bytes with type of parameter are sent before parameters
+    // if not, previous execution types are used (TODO prooflink)
+    packet.writeInt8(1); // new-params-bound-flag
+
+    // TODO: don't typecast always to sting, use parameters type
+    for (i=0; i < this.parameters.length; i++)
+    {
+      if (this.parameters[i] !== null)
+        packet.writeInt16(Types.VAR_STRING);
+      else
+        packet.writeInt16(Types.NULL);
+    }
+    for (i=0; i < this.parameters.length; i++)
+    {
+      if (this.parameters[i] !== null)
+        if (Buffer.isBuffer(this.parameters[i]))
+          packet.writeLengthCodedBuffer(this.parameters[i]);
+        else
+          packet.writeLengthCodedString(this.parameters[i].toString());
+    }
+  }
+  return packet;
+};
+
+module.exports = Execute;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake.js
new file mode 100644
index 0000000000000000000000000000000000000000..337338c13eff806774011cb01c9840b8e33cfe93
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake.js
@@ -0,0 +1,73 @@
+var Packet = require('../packets/packet');
+
+function Handshake(args) {
+  this.protocolVersion = args.protocolVersion;
+  this.serverVersion   = args.serverVersion;
+  this.capabilityFlags = args.capabilityFlags;
+  this.connectionId    = args.connectionId;
+  this.authPluginData1 = args.authPluginData1;
+  this.authPluginData2 = args.authPluginData2;
+  this.characterSet    = args.characterSet;
+  this.statusFlags     = args.statusFlags;
+}
+
+Handshake.fromPacket = function(packet)
+{
+  var args = {};
+  args.protocolVersion = packet.readInt8();
+  args.serverVersion   = packet.readNullTerminatedString();
+  args.connectionId    = packet.readInt32();
+  args.authPluginData1 = packet.readBuffer(8);
+  packet.skip(1);
+  args.capabilityFlags = packet.readInt16();
+  if (packet.haveMoreData()) {
+    args.characterSet = packet.readInt8();
+    args.statusFlags  = packet.readInt16();
+    // upper 2 bytes
+    args.capabilityFlags += packet.readInt16() << 16;
+    args.authPluginDataLength = packet.readInt8();
+    packet.skip(10);
+  }
+  //var len = Math.max(12, args.authPluginDataLength - 8);
+  args.authPluginData2 = packet.readBuffer(12);
+  return new Handshake(args);
+};
+
+Handshake.prototype.setScrambleData = function(cb) {
+  var self = this;
+  require('crypto').randomBytes(20, function(err, data) {
+    if (err) return cb(err);
+    self.authPluginData1 = data.slice(0, 8);
+    self.authPluginData2 = data.slice(8,20);
+    cb();
+  });
+};
+
+Handshake.prototype.toPacket = function(sequenceId) {
+  var buffer, packet;
+  var length = 68 + Buffer.byteLength(this.serverVersion, 'utf8');
+  buffer = new Buffer(length + 4);
+  packet  = new Packet(sequenceId, buffer, 0, length + 4);
+  packet.offset = 4;
+  packet.writeInt8(this.protocolVersion);
+  packet.writeString(this.serverVersion);
+  packet.writeInt8(0);
+  packet.writeInt32(this.connectionId);
+  packet.writeBuffer(this.authPluginData1);
+  packet.writeInt8(0);
+  packet.writeInt16(this.capabilityFlags & 0xffff);
+  packet.writeInt8(this.characterSet);
+  packet.writeInt16(this.statusFlags);
+  packet.writeInt16(this.capabilityFlags >> 16);
+  packet.writeInt8(21); // authPluginDataLength
+  var filler = new Buffer(10);
+  filler.fill(0);
+  packet.writeBuffer(filler);
+  packet.writeBuffer(this.authPluginData2);
+  packet.writeInt8(0);
+  packet.writeString('mysql_native_password');
+  packet.writeInt8(0);
+  return packet;
+};
+
+module.exports = Handshake;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake_response.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake_response.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfc9359a38be74c12b8933632b20789e24fbbbe3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/handshake_response.js
@@ -0,0 +1,68 @@
+var ClientConstants = require('../constants/client.js');
+var Charsets        = require('../constants/charsets.js');
+var Packet          = require('../packets/packet.js');
+
+var auth41 = require('../auth_41.js');
+
+function HandshakeResponse(handshake)
+{
+  this.user            = handshake.user || '';
+  this.database        = handshake.database || '';
+  this.password        = handshake.password || '';
+  this.passwordSha1    = handshake.passwordSha1;
+  this.authPluginData1 = handshake.authPluginData1;
+  this.authPluginData2 = handshake.authPluginData2;
+  this.compress        = handshake.compress;
+  this.clientFlags     = handshake.flags;
+  // TODO: pre-4.1 auth support
+  var authToken;
+  if (this.passwordSha1)
+    authToken = auth41.calculateTokenFromPasswordSha(this.passwordSha1, this.authPluginData1, this.authPluginData2);
+  else
+    authToken = auth41.calculateToken(this.password, this.authPluginData1, this.authPluginData2);
+  this.authToken       = authToken;
+  this.charsetNumber   = handshake.charsetNumber;
+}
+
+HandshakeResponse.fromPacket = function(packet)
+{
+  var args = {};
+  //packet.skip(4);
+  args.clientFlags   = packet.readInt32();
+  args.maxPacketSize = packet.readInt32();
+  args.charsetNumber = packet.readInt8();
+  packet.skip(23);
+  args.user = packet.readNullTerminatedString();
+  var authTokenLength = packet.readInt8();
+  args.authToken = packet.readBuffer(authTokenLength);
+  args.database  = packet.readNullTerminatedString();
+  //return new HandshakeResponse(args);
+  return args;
+};
+
+HandshakeResponse.prototype.toPacket = function()
+{
+  if (typeof this.user != 'string')
+    throw new Error('"user" connection config prperty must be a string');
+  if (typeof this.database != 'string')
+    throw new Error('"database" connection config prperty must be a string');
+
+  var length = 36 + 23 + this.user.length + this.database.length;
+
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  buffer.fill(0);
+  packet.offset = 4;
+
+  packet.writeInt32(this.clientFlags);
+  packet.writeInt32(0); // max packet size. todo: move to config
+  packet.writeInt8(this.charsetNumber);
+  packet.skip(23);
+  packet.writeNullTerminatedString(this.user);
+  packet.writeInt8(this.authToken.length);
+  packet.writeBuffer(this.authToken);
+  packet.writeNullTerminatedString(this.database);
+  return packet;
+};
+
+module.exports = HandshakeResponse;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/index.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..05b0fde37a2b733967fe68c4e8c5692049ae784b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/index.js
@@ -0,0 +1,79 @@
+'binlog_dump register_slave ssl_request handshake handshake_response query resultset_header column_definition text_row binary_row prepare_statement close_statement prepared_statement_header execute change_user'.split(' ').forEach(function(name) {
+  var ctor = require('./' + name + '.js');
+  module.exports[ctor.name] = ctor;
+  // monkey-patch it to include name if debug is on
+  if (process.env.NODE_DEBUG) {
+    if (ctor.prototype.toPacket) {
+      var old = ctor.prototype.toPacket;
+      ctor.prototype.toPacket = function() {
+        var p = old.call(this);
+        p._name = ctor.name;
+        return p;
+      }
+    }
+  }
+});
+
+// simple packets:
+var Packet = require('./packet');
+module.exports.Packet = Packet;
+
+module.exports.OK = function OK() {
+};
+
+module.exports.OK.toPacket = function(args) {
+  args = args || {};
+  var affectedRows = args.affectedRows || 0;
+  var insertId     = args.insertId || 0;
+  var serverStatus = args.serverStatus || 0;
+  var warningCount = args.warningCount || 0;
+  var message      = args.message || "";
+
+  var length = 9 + Packet.lengthCodedNumberLength(affectedRows);
+  length += Packet.lengthCodedNumberLength(insertId);
+
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(0);
+  packet.writeLengthCodedNumber(affectedRows);
+  packet.writeLengthCodedNumber(insertId);
+  packet.writeInt16(serverStatus);
+  packet.writeInt16(warningCount);
+  packet.writeString(message);
+  packet._name = "OK";
+  return packet;
+};
+
+// warnings, statusFlags
+module.exports.EOF = function EOF() {
+};
+
+module.exports.EOF.toPacket = function(warnings, statusFlags) {
+  if (typeof warnings == 'undefined')
+    warnings = 0;
+  if (typeof statusFlags == 'undefined')
+    statusFlags = 0;
+  var packet = new Packet(0, new Buffer(9), 0, 9);
+  packet.offset = 4;
+  packet.writeInt8(0xfe);
+  packet.writeInt16(warnings);
+  packet.writeInt16(statusFlags);
+  packet._name = "EOF";
+  return packet;
+};
+
+module.exports.Error = function Error() {
+};
+
+module.exports.Error.toPacket = function(args) {
+  var length = 13 + Buffer.byteLength(args.message, 'utf8');
+  var packet = new Packet(0, new Buffer(length), 0, length);
+  packet.offset = 4;
+  packet.writeInt8(0xff);
+  packet.writeInt16(args.code);
+  packet.writeString('#_____');
+  packet.writeString(args.message);
+  packet._name = "Error";
+  return packet;
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/packet.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/packet.js
new file mode 100644
index 0000000000000000000000000000000000000000..4ee57d8673bf8e4fe77be1e1552bb72748cedfc0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/packet.js
@@ -0,0 +1,613 @@
+//var BigNumber = require("bignumber.js");
+var ErrorCodeToName = require('../constants/errors.js').codeToName;
+
+var bn = require('bn.js');
+
+function Packet(id, buffer, start, end)
+{
+  this.sequenceId = id;
+  this.buffer = buffer;
+  this.start  = start;
+  this.offset = start;
+  this.end    = end;
+}
+
+// ==============================
+// readers
+// ==============================
+
+Packet.prototype.reset = function() {
+  this.offset = this.start;
+};
+
+Packet.prototype.length = function() {
+  return this.end - this.start;
+};
+
+Packet.prototype.slice = function() {
+  return this.buffer.slice(this.start, this.end);
+};
+
+Packet.prototype.dump = function() {
+  console.log([this.buffer.asciiSlice(this.start, this.end)], this.buffer.slice(this.start, this.end), this.length(), this.sequenceId);
+};
+
+Packet.prototype.haveMoreData = function() {
+  return this.end > this.offset;
+};
+
+Packet.prototype.skip = function(num) {
+  this.offset += num;
+};
+
+Packet.prototype.readInt8 = function()
+{
+  return this.buffer[this.offset++];
+};
+
+Packet.prototype.readInt16 = function()
+{
+  this.offset += 2;
+  return this.buffer.readUInt16LE(this.offset - 2, true);
+};
+
+Packet.prototype.readInt24 = function() {
+  return this.readInt16() + (this.readInt8() << 16);
+};
+
+Packet.prototype.readInt32 = function()
+{
+  this.offset += 4;
+  return this.buffer.readUInt32LE(this.offset - 4, true);
+};
+
+Packet.prototype.readSInt8 = function()
+{
+  return this.buffer.readInt8(this.offset++, true);
+};
+
+Packet.prototype.readSInt16 = function()
+{
+  this.offset += 2;
+  return this.buffer.readInt16LE(this.offset - 2, true);
+};
+
+Packet.prototype.readSInt32 = function()
+{
+  this.offset += 4;
+  return this.buffer.readInt32LE(this.offset - 4, true);
+};
+
+Packet.prototype.readInt64 = function() {
+  return this.readInt32() + 0x100000000*this.readInt32();
+};
+
+Packet.prototype.readSInt64 = function() {
+  var word0 = this.readInt32();
+  var word1 = this.readInt32();
+  if (!(word1 & 0x80000000))
+    return word0 + 0x100000000*word1;
+  return -((((~word1)>>>0) * 0x100000000) + ((~word0)>>>0) + 1);
+};
+
+Packet.prototype.isEOF = function() {
+  return this.buffer[this.offset] == 0xfe && this.length() < 9;
+};
+
+Packet.prototype.eofStatusFlags = function() {
+  return this.buffer.readInt16LE(this.offset + 3);
+};
+
+Packet.prototype.eofWarningCount = function() {
+  return this.buffer.readInt16LE(this.offset + 1);
+};
+
+Packet.prototype.readLengthCodedNumber = function(bigNumberStrings) {
+  var byte1 = this.buffer[this.offset++];
+  if (byte1 < 251)
+    return byte1;
+  return this.readLengthCodedNumberExt(byte1, bigNumberStrings);
+}
+
+Packet.prototype.readLengthCodedNumberExt = function(tag, bigNumberStrings) {
+   var word0, word1;
+   var res;
+   if (tag == 0xfb)
+     return null;
+   if (tag == 0xfc) {
+     return this.readInt8() + (this.readInt8() << 8);
+   }
+   if (tag == 0xfd) {
+     return this.readInt8() + (this.readInt8() << 8) + (this.readInt8() << 16);
+   }
+   if (tag == 0xfe) {
+     // TODO: check version
+     // Up to MySQL 3.22, 0xfe was followed by a 4-byte integer.
+     word0 = this.readInt32();
+     word1 = this.readInt32();
+     if (word1 === 0)
+       return word0; // don't convert to float if possible
+     if (word1 < 2097152) // max exact float point int, 2^52 / 2^32
+       return  word1*0x100000000 + word0;
+
+     res = (new bn(word1)).ishln(32).iaddn(word0);
+     return bigNumberStrings ? res.toString() : res;
+   }
+
+   console.trace();
+   throw "Should not reach here: " + byte1;
+};
+
+Packet.prototype.readFloat = function() {
+  var res = this.buffer.readFloatLE(this.offset);
+  this.offset += 4;
+  return res;
+};
+
+Packet.prototype.readDouble = function() {
+  var res = this.buffer.readDoubleLE(this.offset);
+  this.offset += 8;
+  return res;
+};
+
+Packet.prototype.readBuffer = function(len) {
+  if (typeof len == 'undefined')
+    len = this.end - this.offset;
+  this.offset += len;
+  return this.buffer.slice(this.offset - len, this.offset);
+};
+
+var INVALID_DATE = new Date(NaN);
+// DATE, DATETIME and TIMESTAMP
+Packet.prototype.readDateTime = function() {
+  var length = this.readInt8();
+  var y = 0;
+  var m = 0;
+  var d = 0;
+  var H = 0;
+  var M = 0;
+  var S = 0;
+  var ms = 0;
+  if (length > 3) {
+    y = this.readInt16();
+    m = this.readInt8();
+    d = this.readInt8();
+
+  }
+  if (length > 6) {
+    H = this.readInt8();
+    M = this.readInt8();
+    S = this.readInt8();
+  }
+  if (length > 11)
+    ms = this.readInt32();
+  if ((y + m + d + H + M + S + ms) === 0) {
+    return INVALID_DATE;
+  }
+  return new Date(y, m-1, d, H, M, S, ms);
+};
+
+// this is nearly duplicate of previous function so generated code is not slower
+// due to "if (dateStrings)" branching
+var pad = "000000000000";
+function leftPad(num, value) {
+  var s = value.toString();
+  // if we don't need to pad
+  if (s.length >= num)
+    return s;
+  return (pad + s).slice(-num);
+}
+
+Packet.prototype.readDateTimeString = function() {
+  var length = this.readInt8();
+  var y = 0;
+  var m = 0;
+  var d = 0;
+  var H = 0;
+  var M = 0;
+  var S = 0;
+  var ms = 0;
+  var str;
+  if (length > 3) {
+    y = this.readInt16();
+    m = this.readInt8();
+    d = this.readInt8();
+    str =  [leftPad(4, y), leftPad(2, m), leftPad(2, d)].join('-');
+  }
+  if (length > 6) {
+    H = this.readInt8();
+    M = this.readInt8();
+    S = this.readInt8();
+    str += ' ' + [leftPad(2, H), leftPad(2, M), leftPad(2, S)].join(':');
+  }
+  /* in text protocol you don't see microseconds as DATETIME/TIMESTAMP result.
+     instead you need to use MICROSECOND() function
+  if (length > 11) {
+    ms = this.readInt32();
+  }
+  */
+  return str;
+};
+
+// TIME - value as a string, Can be negative
+Packet.prototype.readTimeString = function(convertTtoMs) {
+  var length = this.readInt8();
+  if (length === 0)
+    return 0;
+
+  var result = 0;
+  var sign = this.readInt8() ? -1 : 1; // 'isNegative' flag byte
+  var d = 0;
+  var H = 0;
+  var M = 0;
+  var S = 0;
+  var ms = 0;
+  if (length > 7) {
+    d = this.readInt32();
+    H = this.readInt8();
+    M = this.readInt8();
+    S = this.readInt8();
+  }
+  if (length > 11)
+    ms = this.readInt32();
+
+  if (convertTtoMs) {
+    H += d * 24;
+    M += H * 60;
+    S += M * 60;
+    ms += S * 1000;
+    ms *= sign;
+    return ms;
+  }
+  return ( sign === -1 ? '-' : '' ) + [( d ? (d*24) + H : H ), leftPad(2, M), leftPad(2, S)].join(':') + ( ms ? '.'+ ms : '' );
+};
+
+Packet.prototype.readLengthCodedString = function() {
+  var len = this.readLengthCodedNumber();
+  // TODO: check manually first byte here to avoid polymorphic return type?
+  if (len === null)
+    return null;
+  this.offset += len;
+  return this.buffer.utf8Slice(this.offset - len, this.offset);
+};
+
+Packet.prototype.readLengthCodedBuffer = function() {
+  var len = this.readLengthCodedNumber();
+  return this.readBuffer(len);
+};
+
+Packet.prototype.readNullTerminatedString = function() {
+  var start = this.offset;
+  var end = this.offset;
+  while (this.buffer[end])
+    end = end + 1; // TODO: handle OOB check
+  this.offset = end + 1;
+  return this.buffer.utf8Slice(start, end);
+};
+
+// TODO reuse?
+Packet.prototype.readString = function(len) {
+  if (typeof len == 'undefined')
+    len = this.end - this.offset;
+  this.offset += len;
+  return this.buffer.utf8Slice(this.offset - len, this.offset);
+};
+
+var minus = '-'.charCodeAt(0);
+var plus = '+'.charCodeAt(0);
+// TODO: faster versions of parseInt for smaller types?
+// discard overflow checks if we know from type definition it's safe so
+Packet.prototype.parseInt = function(len) {
+
+  if (len === null)
+    return null;
+
+  var result = 0;
+  var end = this.offset + len;
+  var sign = 1;
+  if (len === 0)
+    return 0; // TODO: assert? exception?
+  if (this.buffer[this.offset] == minus) {
+    this.offset++;
+    sign = -1;
+  }
+
+  // max precise int is 9007199254740992
+  // note that we are here after handling optional +/-
+  // treat everything above 9000000000000000 as potential overflow
+  var str;
+  var numDigits = end - this.offset;
+  if (numDigits == 16 && (this.buffer[this.offset] - 48) > 8) {
+    str = this.readString(end - this.offset);
+    result = parseInt(str, 10);
+    if (result.toString() == str)
+      return sign*result;
+    else
+      return sign == -1 ? "-" + str : str;
+  } else if (numDigits > 16) {
+    str = this.readString(end - this.offset);
+    return sign == -1 ? "-" + str : str;
+  }
+
+  if (this.buffer[this.offset] == plus) {
+    this.offset++; // just ignore
+  }
+  while(this.offset < end) {
+    result *= 10;
+    result += this.buffer[this.offset] - 48;
+    this.offset++;
+  }
+  return result*sign;
+};
+
+// copy-paste from https://github.com/felixge/node-mysql/blob/master/lib/protocol/Parser.js
+Packet.prototype.parseGeometryValue = function() {
+  var buffer = this.readLengthCodedBuffer();
+  var offset = 4;
+
+  if (buffer === null || !buffer.length) {
+    return null;
+  }
+
+  function parseGeometry() {
+    var x, y, i, j, numPoints, line;
+    var result = null;
+    var byteOrder = buffer.readUInt8(offset); offset += 1;
+    var wkbType = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
+    switch(wkbType) {
+      case 1: // WKBPoint
+        x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+        y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+        result = {x: x, y: y};
+        break;
+      case 2: // WKBLineString
+        numPoints = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
+        result = [];
+        for(i=numPoints;i>0;i--) {
+          x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+          y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+          result.push({x: x, y: y});
+        }
+        break;
+      case 3: // WKBPolygon
+        var numRings = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
+        result = [];
+        for(i=numRings;i>0;i--) {
+          numPoints = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
+          line = [];
+          for(j=numPoints;j>0;j--) {
+            x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+            y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
+            line.push({x: x, y: y});
+          }
+          result.push(line);
+        }
+        break;
+      case 4: // WKBMultiPoint
+      case 5: // WKBMultiLineString
+      case 6: // WKBMultiPolygon
+      case 7: // WKBGeometryCollection
+        var num = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
+        result = [];
+        for(i=num;i>0;i--) {
+          result.push(parseGeometry());
+        }
+        break;
+    }
+    return result;
+  }
+  return parseGeometry();
+};
+
+Packet.prototype.parseDate = function() {
+  var strLen = this.readLengthCodedNumber();
+  if (strLen === null)
+    return null;
+  if (strLen != 10) {
+    // we expect only YYYY-MM-DD here.
+    // if for some reason it's not the case return invalid date
+    return new Date(NaN);
+  }
+  var y = this.parseInt(4);
+  this.offset++; // -
+  var m = this.parseInt(2);
+  this.offset++; // -
+  var d = this.parseInt(2);
+  return new Date(y, m-1, d);
+};
+
+Packet.prototype.parseDateTime = function() {
+  var str = this.readLengthCodedString();
+  if (str === null)
+    return null;
+  return new Date(str);
+};
+
+
+// TODO: handle E notation
+var dot = '.'.charCodeAt(0);
+var exponent = 'e'.charCodeAt(0);
+var exponentCapital = 'E'.charCodeAt(0);
+Packet.prototype.parseFloat = function(len) {
+
+  if (len === null)
+    return null;
+
+  var result = 0;
+  var end = this.offset + len;
+  var factor = 1;
+  var pastDot = false;
+  var charCode = 0;
+  if (len === 0)
+    return 0; // TODO: assert? exception?
+
+  if (this.buffer[this.offset] == minus) {
+    this.offset++;
+    factor = -1;
+  }
+  if (this.buffer[this.offset] == plus) {
+    this.offset++; // just ignore
+  }
+  while(this.offset < end) {
+    charCode = this.buffer[this.offset];
+    if (charCode == dot)
+    {
+      pastDot = true;
+      this.offset++;
+    } else if (charCode == exponent || charCode == exponentCapital) {
+      this.offset++;
+      var exponentValue = this.parseInt(end - this.offset);
+      return (result/factor)*Math.pow(10, exponentValue);
+    } else {
+      result *= 10;
+      result += this.buffer[this.offset] - 48;
+      this.offset++;
+      if (pastDot)
+        factor = factor*10;
+    }
+  }
+  return result/factor;
+};
+
+Packet.prototype.parseLengthCodedInt = function() {
+  return this.parseInt(this.readLengthCodedNumber());
+};
+
+Packet.prototype.parseLengthCodedIntString = function() {
+  return this.readString(this.readLengthCodedNumber());
+};
+
+Packet.prototype.parseLengthCodedFloat = function() {
+  return this.parseFloat(this.readLengthCodedNumber());
+};
+
+Packet.prototype.isError = function() {
+  return this.buffer[this.offset] == 0xff;
+};
+
+Packet.prototype.asError = function() {
+  this.reset();
+
+  var fieldCount = this.readInt8();
+  var errorCode = this.readInt16();
+  var sqlState  = '';
+  if (this.buffer[this.offset] == 0x23)
+    sqlState = this.readBuffer(6).toString();
+  var message = this.readString();
+  var err = new Error(message);
+  err.code     = ErrorCodeToName[errorCode];
+  err.errno    = errorCode;
+  err.sqlState = sqlState;
+  return err;
+};
+
+
+Packet.lengthCodedNumberLength = function(n) {
+   if (n < 0xfb)
+     return 1;
+   if (n < 0xffff)
+     return 3;
+   if (n < 0xffffff)
+     return 5;
+   else
+     return 9;
+};
+
+Packet.prototype.writeInt32 = function(n) {
+  this.buffer.writeUInt32LE(n, this.offset);
+  this.offset += 4;
+};
+
+Packet.prototype.writeInt24 = function(n) {
+  this.writeInt8(n & 0xff);
+  this.writeInt16(n >> 8);
+};
+
+Packet.prototype.writeInt16 = function(n) {
+  this.buffer.writeUInt16LE(n, this.offset);
+  this.offset += 2;
+};
+
+Packet.prototype.writeInt8 = function(n) {
+  this.buffer.writeUInt8(n, this.offset);
+  this.offset++;
+};
+
+Packet.prototype.writeBuffer = function(b) {
+  b.copy(this.buffer, this.offset);
+  this.offset += b.length;
+};
+
+Packet.prototype.writeNull = function() {
+  this.buffer[this.offset] = 0xfb;
+  this.offset++;
+};
+
+// TODO: refactor following three?
+Packet.prototype.writeNullTerminatedString = function(s) {
+  this.buffer.write(s, this.offset);
+  this.offset += s.length;
+  this.writeInt8(0);
+};
+
+Packet.prototype.writeString = function(s) {
+  var bytes = Buffer.byteLength(s, 'utf8');
+  this.buffer.write(s, this.offset, bytes, 'utf8');
+  this.offset += bytes;
+};
+
+Packet.prototype.writeLengthCodedString = function(s) {
+  var bytes = Buffer.byteLength(s, 'utf8');
+  this.writeLengthCodedNumber(bytes);
+  this.buffer.write(s, this.offset, bytes, 'utf8');
+  this.offset += bytes;
+};
+
+Packet.prototype.writeLengthCodedBuffer = function(b) {
+  this.writeLengthCodedNumber(b.length);
+  b.copy(this.buffer, this.offset);
+  this.offset += b.length;
+};
+
+Packet.prototype.writeLengthCodedNumber = function(n) {
+  // TODO: null - http://dev.mysql.com/doc/internals/en/overview.html#length-encoded-integer
+  if (n < 0xfb)
+    return this.writeInt8(n);
+  if (n < 0xffff) {
+    this.writeInt8(0xfc);
+    return this.writeInt16(n);
+  }
+  if (n < 0xffffff) {
+    this.writeInt8(0xfd);
+    return this.writeInt24(n);
+  }
+  console.log(n);
+  console.trace();
+  throw "No bignumbers yet";
+};
+
+Packet.prototype.writeHeader = function(sequenceId)
+{
+  var offset = this.offset;
+  this.offset = 0;
+  this.writeInt24(this.buffer.length - 4);
+  this.writeInt8(sequenceId);
+  this.offset = offset;
+};
+
+Packet.prototype.clone = function() {
+  var buffer = this.buffer.slice(this.start, this.end);
+  var other = new Packet(this.sequenceId, this.buffer, 0, this.buffer.length);
+  return other;
+};
+
+Packet.prototype.type = function() {
+  if (this.isEOF())
+    return 'EOF';
+  if (this.isError())
+    return 'Error';
+  if (this.buffer[this.offset] == 0)
+    return 'maybeOK'; // could be other packet types as well
+  return '';
+};
+module.exports = Packet;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepare_statement.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepare_statement.js
new file mode 100644
index 0000000000000000000000000000000000000000..009303b8cd9e1de563151e39a387897e0725a442
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepare_statement.js
@@ -0,0 +1,20 @@
+var Packet = require('../packets/packet');
+var CommandCodes = require('../constants/commands');
+
+function PrepareStatement(sql)
+{
+  this.query = sql;
+}
+
+PrepareStatement.prototype.toPacket = function()
+{
+  var length = 5 + Buffer.byteLength(this.query, 'utf8');
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(CommandCodes.STMT_PREPARE);
+  packet.writeString(this.query);
+  return packet;
+};
+
+module.exports = PrepareStatement;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepared_statement_header.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepared_statement_header.js
new file mode 100644
index 0000000000000000000000000000000000000000..de8f0479acead7852f4a2ad5faa883682ddcf7e7
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/prepared_statement_header.js
@@ -0,0 +1,15 @@
+var Packet = require('../packets/packet');
+
+function PreparedStatementHeader(packet)
+{
+  packet.skip(1);     // should be 0
+  this.id = packet.readInt32();
+  this.fieldCount      = packet.readInt16();
+  this.parameterCount  = packet.readInt16();
+  packet.skip(1);     // should be 0
+  this.warningCount = packet.readInt16();
+}
+
+// TODO: toPacket
+
+module.exports = PreparedStatementHeader;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/query.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/query.js
new file mode 100644
index 0000000000000000000000000000000000000000..9bb45b90f18f7f49cd6cb886fce39e385ca0a1e6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/query.js
@@ -0,0 +1,20 @@
+var Packet      = require('../packets/packet.js');
+var CommandCode = require('../constants/commands.js');
+
+function Query(sql)
+{
+  this.query = sql;
+}
+
+Query.prototype.toPacket = function()
+{
+  var length = 5 + Buffer.byteLength(this.query, 'utf8');
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(CommandCode.QUERY);
+  packet.writeString(this.query);
+  return packet;
+};
+
+module.exports = Query;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/register_slave.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/register_slave.js
new file mode 100644
index 0000000000000000000000000000000000000000..bd16f40e4b921b017796bd33eb19dd3889b7800f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/register_slave.js
@@ -0,0 +1,41 @@
+// http://dev.mysql.com/doc/internals/en/com-register-slave.html
+// note that documentation is incorrect, for example command code is actually 0x15 but documented as 0x14
+
+var Packet = require('../packets/packet');
+var CommandCodes = require('../constants/commands');
+
+function RegisterSlave(opts)
+{
+  this.serverId        = opts.serverId || 0;
+  this.slaveHostname   = opts.slaveHostname || '';
+  this.slaveUser       = opts.slaveUser || '';
+  this.slavePassword   = opts.slavePassword || '';
+  this.slavePort       = opts.slavePort || 0;
+  this.replicationRank = opts.replicationRank || 0;
+  this.masterId        = opts.masterId || 0;
+}
+
+RegisterSlave.prototype.toPacket = function()
+{
+  var length =  15 + // TODO: should be ascii?
+    Buffer.byteLength(this.slaveHostname, 'utf8') +
+    Buffer.byteLength(this.slaveUser, 'utf8') +
+    Buffer.byteLength(this.slavePassword, 'utf8') + 3 + 4;
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeInt8(CommandCodes.REGISTER_SLAVE);
+  packet.writeInt32(this.serverId);
+  packet.writeInt8(Buffer.byteLength(this.slaveHostname, 'utf8'));
+  packet.writeString(this.slaveHostname);
+  packet.writeInt8(Buffer.byteLength(this.slaveUser, 'utf8'));
+  packet.writeString(this.slaveUser);
+  packet.writeInt8(Buffer.byteLength(this.slavePassword, 'utf8'));
+  packet.writeString(this.slavePassword);
+  packet.writeInt16(this.slavePort);
+  packet.writeInt32(this.replicationRank);
+  packet.writeInt32(this.masterId);
+  return packet;
+};
+
+module.exports = RegisterSlave;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/resultset_header.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/resultset_header.js
new file mode 100644
index 0000000000000000000000000000000000000000..5715ff6a1b1cdba2c9abdeed4ba5fa011d965a61
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/resultset_header.js
@@ -0,0 +1,43 @@
+// TODO: rename to OK packet
+
+var Packet = require('../packets/packet');
+
+function ResultSetHeader(packet, bigNumberStrings)
+{
+  if (packet.buffer[packet.offset] !== 0) {
+    this.fieldCount = packet.readLengthCodedNumber();
+  } else {
+    this.fieldCount   = packet.readInt8(); // skip OK byte
+    this.affectedRows = packet.readLengthCodedNumber(bigNumberStrings);
+    this.insertId     = packet.readLengthCodedNumber(bigNumberStrings);
+    this.serverStatus  = packet.readInt16();
+    this.warningStatus = packet.readInt16();
+  }
+  if (this.fieldCount === null) {
+    this.infileName = packet.readString();
+  }
+
+  // snippet from mysql-native:
+  // res.affected_rows = this.lcnum();
+  // res.insert_id = this.lcnum();
+  // res.server_status = this.num(2);
+  // res.warning_count = this.num(2);
+
+  // TODO: extra
+}
+
+// TODO: should be consistent instance member, but it's just easier here to have just function
+ResultSetHeader.toPacket = function(fieldCount, insertId, sequenceId) {
+  var length = 4 + Packet.lengthCodedNumberLength(fieldCount);
+  if (typeof(insertId) != 'undefined')
+    length += Packet.lengthCodedNumberLength(insertId);
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  packet.offset = 4;
+  packet.writeLengthCodedNumber(fieldCount);
+  if (typeof(insertId) != 'undefined')
+    packet.writeLengthCodedNumber(insertId);
+  return packet;
+};
+
+module.exports = ResultSetHeader;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/ssl_request.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/ssl_request.js
new file mode 100644
index 0000000000000000000000000000000000000000..f65a90f140f5e0ff3ca301f8375f53b219e604c6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/ssl_request.js
@@ -0,0 +1,24 @@
+var ClientConstants = require('../constants/client');
+var Packet = require('../packets/packet');
+var Charsets = require('../constants/charsets');
+
+function SSLRequest(flags)
+{
+  this.clientFlags = flags | ClientConstants.SSL;
+}
+
+SSLRequest.prototype.toPacket = function()
+{
+  var length = 36;
+  var buffer = new Buffer(length);
+  var packet = new Packet(0, buffer, 0, length);
+  buffer.fill(0);
+  packet.offset = 4;
+
+  packet.writeInt32(this.clientFlags);
+  packet.writeInt32(0); // max packet size. todo: move to config
+  packet.writeInt8(Charsets.UTF8_GENERAL_CI);
+  return packet;
+};
+
+module.exports = SSLRequest;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/text_row.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/text_row.js
new file mode 100644
index 0000000000000000000000000000000000000000..f6185efd935ff07ea10805e0374d9e524f09ee43
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/packets/text_row.js
@@ -0,0 +1,38 @@
+var Packet = require('../packets/packet');
+
+function TextRow(columns)
+{
+  this.columns = columns || [];
+}
+
+TextRow.fromPacket = function(packet) {
+  //packet.reset(); // set offset to starting point?
+  var columns = [];
+  while(packet.haveMoreData()) {
+    columns.push(packet.readLengthCodedString());
+  }
+  return new TextRow(columns);
+};
+
+TextRow.toPacket = function(column) {
+  var sequenceId = 0; // TODO remove, this is calculated now in connecton
+  var buffer, packet;
+  var length = 0;
+  column.forEach(function(val) {
+	if (val === null || typeof(val) == 'undefined') return ++length;
+    var str = val.toString(10);
+    length += Packet.lengthCodedNumberLength(str);
+    length += str.length;
+  });
+  buffer = new Buffer(length+4);
+  packet = new Packet(sequenceId, buffer, 0, length+4);
+  packet.offset = 4;
+  column.forEach(function(val) {
+    if (val === null) return packet.writeNull();
+    if (typeof val == 'undefined') return packet.writeInt8(0);
+    packet.writeLengthCodedString(val.toString(10));
+  });
+  return packet;
+};
+
+module.exports = TextRow;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/pool.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool.js
new file mode 100644
index 0000000000000000000000000000000000000000..e0f814ed70fb2c2f94de94fe7d873e2f8a5431e7
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool.js
@@ -0,0 +1,180 @@
+var mysql        = require('../index.js');
+
+var EventEmitter = require('events').EventEmitter;
+var Util         = require('util');
+var PoolConnection = require('./pool_connection.js');
+
+module.exports = Pool;
+
+Util.inherits(Pool, EventEmitter);
+function Pool(options) {
+  EventEmitter.call(this);
+  this.config = options.config;
+  this.config.connectionConfig.pool = this;
+
+  this._allConnections   = [];
+  this._freeConnections  = [];
+  this._connectionQueue  = [];
+  this._closed           = false;
+}
+
+Pool.prototype.getConnection = function (cb) {
+  if (this._closed) {
+    return process.nextTick(function(){
+      return cb(new Error('Pool is closed.'));
+    });
+  }
+
+  var connection;
+
+  if (this._freeConnections.length > 0) {
+    connection = this._freeConnections.shift();
+
+    return process.nextTick(function(){
+      return cb(null, connection);
+    });
+  }
+
+  if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) {
+    connection = new PoolConnection(this, { config: this.config.connectionConfig });
+
+    this._allConnections.push(connection);
+
+    return connection.connect(function(err) {
+      if (this._closed) {
+        return cb(new Error('Pool is closed.'));
+      }
+      if (err) {
+        return cb(err);
+      }
+
+      this.emit('connection', connection);
+      return cb(null, connection);
+    }.bind(this));
+  }
+
+  if (!this.config.waitForConnections) {
+    return process.nextTick(function(){
+      return cb(new Error('No connections available.'));
+    });
+  }
+
+  if (this.config.queueLimit && this._connectionQueue.length >= this.config.queueLimit) {
+    return cb(new Error('Queue limit reached.'));
+  }
+
+  this._connectionQueue.push(cb);
+};
+
+Pool.prototype.releaseConnection = function (connection) {
+  var cb;
+
+  if (!connection._pool) {
+    // The connection has been removed from the pool and is no longer good.
+    if (this._connectionQueue.length) {
+      cb = this._connectionQueue.shift();
+
+      process.nextTick(this.getConnection.bind(this, cb));
+    }
+  } else if (this._connectionQueue.length) {
+    cb = this._connectionQueue.shift();
+
+    process.nextTick(cb.bind(null, null, connection));
+  } else {
+    this._freeConnections.push(connection);
+  }
+};
+
+Pool.prototype.end = function (cb) {
+  this._closed = true;
+
+  if (typeof cb != "function") {
+    cb = function (err) {
+      if (err) throw err;
+    };
+  }
+
+  var calledBack        = false;
+  var closedConnections = 0;
+  var connection;
+
+  var endCB = function(err) {
+    if (calledBack) {
+      return;
+    }
+
+    if (err || ++closedConnections >= this._allConnections.length) {
+      calledBack = true;
+      return cb(err);
+    }
+  }.bind(this);
+
+  if (this._allConnections.length === 0) {
+    return endCB();
+  }
+
+  for (var i = 0; i < this._allConnections.length; i++) {
+    connection = this._allConnections[i];
+    connection._realEnd(endCB);
+  }
+};
+
+Pool.prototype.query = function (sql, values, cb) {
+  if (typeof values === 'function') {
+    cb = values;
+    values = null;
+  }
+
+  this.getConnection(function (err, conn) {
+    if (err) return cb(err);
+
+    conn.query(sql, values, function () {
+      conn.release();
+      cb.apply(this, arguments);
+    });
+  });
+};
+
+Pool.prototype.execute = function (sql, values, cb) {
+  if (typeof values === 'function') {
+    cb = values;
+    values = null;
+  }
+
+  this.getConnection(function (err, conn) {
+    if (err) return cb(err);
+
+    conn.execute(sql, values, function () {
+      conn.release();
+      cb.apply(this, arguments);
+    });
+  });
+};
+
+Pool.prototype._removeConnection = function(connection) {
+  var i;
+
+  for (i = 0; i < this._allConnections.length; i++) {
+    if (this._allConnections[i] === connection) {
+      this._allConnections.splice(i, 1);
+      break;
+    }
+  }
+
+  for (i = 0; i < this._freeConnections.length; i++) {
+    if (this._freeConnections[i] === connection) {
+      this._freeConnections.splice(i, 1);
+      break;
+    }
+  }
+
+  this.releaseConnection(connection);
+};
+
+Pool.prototype.escape = function(value) {
+  return mysql.escape(value, this.config.connectionConfig.stringifyObjects, this.config.connectionConfig.timezone);
+};
+
+Pool.prototype.escapeId = function escapeId(value) {
+  return mysql.escapeId(value, false);
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_cluster.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_cluster.js
new file mode 100644
index 0000000000000000000000000000000000000000..88cbe5301b970af789c99794ec2cd0208597a82d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_cluster.js
@@ -0,0 +1,242 @@
+var Pool         = require('./pool.js');
+var PoolConfig   = require('./pool_config.js');
+var Util         = require('util');
+var EventEmitter = require('events').EventEmitter;
+
+module.exports = PoolCluster;
+
+/**
+ * PoolCluster
+ */
+function PoolCluster(config) {
+  EventEmitter.call(this);
+
+  config = config || {};
+  this._canRetry = typeof config.canRetry === 'undefined' ? true : config.canRetry;
+  this._removeNodeErrorCount = config.removeNodeErrorCount || 5;
+  this._defaultSelector = config.defaultSelector || 'RR';
+
+  this._closed = false;
+  this._lastId = 0;
+  this._nodes = {};
+  this._serviceableNodeIds = [];
+  this._namespaces = {};
+  this._findCaches = {};
+}
+
+Util.inherits(PoolCluster, EventEmitter);
+
+PoolCluster.prototype.of = function(pattern, selector) {
+  pattern = pattern || '*';
+  
+  selector = selector || this._defaultSelector;
+  selector = selector.toUpperCase();
+  if (typeof Selector[selector] === 'undefined') {
+    selector = this._defaultSelector;
+  }
+  
+  var key = pattern + selector;
+
+  if (typeof this._namespaces[key] === 'undefined') {
+    this._namespaces[key] = new PoolNamespace(this, pattern, selector);
+  }
+
+  return this._namespaces[key];
+};
+
+PoolCluster.prototype.add = function(id, config) {
+  if (typeof id === 'object') {
+    config = id;
+    id = 'CLUSTER::' + (++this._lastId);
+  }
+
+  if (typeof this._nodes[id] === 'undefined') {
+    this._nodes[id] = {
+      id: id,
+      errorCount: 0,
+      pool: new Pool({config: new PoolConfig(config)})
+    };
+
+    this._serviceableNodeIds.push(id);
+    
+    this._clearFindCaches();
+  }
+};
+
+PoolCluster.prototype.getConnection = function(pattern, selector, cb) {
+  var namespace;
+  if (typeof pattern === 'function') {
+    cb = pattern;
+    namespace = this.of();
+  } else {
+    if (typeof selector === 'function') {
+      cb = selector;
+      selector = this._defaultSelector;
+    }
+
+    namespace = this.of(pattern, selector);
+  }
+
+  namespace.getConnection(cb);
+};
+
+PoolCluster.prototype.end = function() {
+  if (this._closed) {
+    return;
+  }
+
+  this._closed = true;
+
+  for (var id in this._nodes) {
+    this._nodes[id].pool.end();
+  }
+};
+
+PoolCluster.prototype._findNodeIds = function(pattern) {
+  if (typeof this._findCaches[pattern] !== 'undefined') {
+    return this._findCaches[pattern];
+  }
+  
+  var foundNodeIds;
+
+  if (pattern === '*') { // all
+    foundNodeIds = this._serviceableNodeIds;
+  } else  if (this._serviceableNodeIds.indexOf(pattern) != -1) { // one
+    foundNodeIds = [pattern];
+  } else { // wild matching
+    var keyword = pattern.substring(pattern.length - 1, 0);
+
+    foundNodeIds = this._serviceableNodeIds.filter(function (id) {
+      return id.indexOf(keyword) === 0;
+    });
+  }
+
+  this._findCaches[pattern] = foundNodeIds;
+  
+  return foundNodeIds;
+};
+
+PoolCluster.prototype._getNode = function(id) {
+  return this._nodes[id] || null;
+};
+
+PoolCluster.prototype._increaseErrorCount = function(node) {
+  if (++node.errorCount >= this._removeNodeErrorCount) {
+    var index = this._serviceableNodeIds.indexOf(node.id);
+    if (index !== -1) {
+      this._serviceableNodeIds.splice(index, 1);
+      delete this._nodes[node.id];
+      
+      this._clearFindCaches();
+      
+      node.pool.end();
+
+      this.emit('remove', node.id);
+    }
+  }
+};
+
+PoolCluster.prototype._decreaseErrorCount = function(node) {
+  if (node.errorCount > 0) {
+    --node.errorCount;
+  }
+};
+
+PoolCluster.prototype._getConnection = function(node, cb) {
+  var self = this;
+
+  node.pool.getConnection(function (err, connection) {
+    if (err) {      
+      self._increaseErrorCount(node);
+      
+      if (self._canRetry) {
+        console.warn('[Error] PoolCluster : ' + err);        
+        return cb(null, 'retry');
+      } else {
+        return cb(err);
+      }
+    } else {
+      self._decreaseErrorCount(node);
+    }
+
+    connection._clusterId = node.id;
+
+    cb(null, connection);
+  });
+};
+
+PoolCluster.prototype._clearFindCaches = function() {  
+  this._findCaches = {};
+};
+
+/**
+ * PoolNamespace
+ */
+function PoolNamespace(cluster, pattern, selector) {
+  this._cluster = cluster;
+  this._pattern = pattern;
+  this._selector = new Selector[selector]();
+}
+
+PoolNamespace.prototype.getConnection = function(cb) {
+  var clusterNode = this._getClusterNode();
+
+  if (clusterNode === null) {
+    return cb(new Error('Pool does Not exists.'));
+  }
+
+  this._cluster._getConnection(clusterNode, function(err, connection) {
+    if (err) {
+      return cb(err);
+    }
+
+    if (connection === 'retry') {
+      return this.getConnection(cb);
+    }
+
+    cb(null, connection);
+  }.bind(this));
+};
+
+PoolNamespace.prototype._getClusterNode = function() {
+  var foundNodeIds = this._cluster._findNodeIds(this._pattern);
+
+  if (foundNodeIds.length === 0) {
+      return null;
+  }
+
+  var nodeId = (foundNodeIds.length === 1) ? foundNodeIds[0] : this._selector(foundNodeIds);
+
+  return this._cluster._getNode(nodeId);
+};
+
+/**
+ * Selector
+ */
+var Selector = {};
+
+Selector.RR = function () {
+  var index = 0;
+
+  return function(clusterIds) {
+    if (index >= clusterIds.length) {
+      index = 0;
+    }
+
+    var clusterId = clusterIds[index++];
+
+    return clusterId;
+  };
+};
+
+Selector.RANDOM = function () {
+  return function(clusterIds) {
+    return clusterIds[Math.floor(Math.random() * clusterIds.length)];
+  };
+};
+
+Selector.ORDER = function () {
+  return function(clusterIds) {
+    return clusterIds[0];
+  };
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_config.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_config.js
new file mode 100644
index 0000000000000000000000000000000000000000..c75601e5e0ee1b6ec1bdd82fabec1e01bcbaa0ca
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_config.js
@@ -0,0 +1,15 @@
+var ConnectionConfig = require('./connection_config.js');
+
+module.exports = PoolConfig;
+function PoolConfig(options) {
+  this.connectionConfig   = new ConnectionConfig(options);
+  this.waitForConnections = (options.waitForConnections === undefined)
+    ? true
+    : Boolean(options.waitForConnections);
+  this.connectionLimit    = (options.connectionLimit === undefined)
+    ? 10
+    : Number(options.connectionLimit);
+  this.queueLimit         = (options.queueLimit === undefined)
+    ? 0
+    : Number(options.queueLimit);
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_connection.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_connection.js
new file mode 100644
index 0000000000000000000000000000000000000000..ccd2a4efe6c48409ed8d274bbbb1440d76ef49f0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/pool_connection.js
@@ -0,0 +1,54 @@
+var mysql        = require('../index.js');
+var Connection   = mysql.Connection;
+
+var inherits = require('util').inherits;
+
+module.exports = PoolConnection;
+inherits(PoolConnection, Connection);
+
+function PoolConnection(pool, options) {
+  Connection.call(this, options);
+  this._pool = pool;
+
+  // When a fatal error occurs the connection's protocol ends, which will cause
+  // the connection to end as well, thus we only need to watch for the end event
+  // and we will be notified of disconnects.
+  this.on('end', this._removeFromPool);
+  this.on('error', this._removeFromPool);
+}
+
+PoolConnection.prototype.release = function () {
+  if (!this._pool || this._pool._closed) {
+    return;
+  }
+
+  return this._pool.releaseConnection(this);
+};
+
+// TODO: Remove this when we are removing PoolConnection#end
+PoolConnection.prototype._realEnd = Connection.prototype.end;
+
+PoolConnection.prototype.end = function () {
+  console.warn( 'Calling conn.end() to release a pooled connection is '
+              + 'deprecated. In next version calling conn.end() will be '
+              + 'restored to default conn.end() behavior. Use '
+              + 'conn.release() instead.'
+              );
+  this.release();
+};
+
+PoolConnection.prototype.destroy = function () {
+  this._removeFromPool(this);
+  return Connection.prototype.destroy.apply(this, arguments);
+};
+
+PoolConnection.prototype._removeFromPool = function(connection) {
+  if (!this._pool || this._pool._closed) {
+    return;
+  }
+
+  var pool = this._pool;
+  this._pool = null;
+
+  pool._removeConnection(this);
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/results_stream.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/results_stream.js
new file mode 100644
index 0000000000000000000000000000000000000000..de214fcba42c840b27037cfce8effa9714ef1536
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/results_stream.js
@@ -0,0 +1,35 @@
+var Readable  = require('stream').Readable;
+
+// copy-paste from https://github.com/felixge/node-mysql/blob/master/lib/protocol/sequences/Query.js
+module.exports = function (command, connectionStream) {
+  command.stream = function(options) {
+    var stream;
+
+    options = options || {};
+    options.objectMode = true;
+    stream = new Readable(options),
+
+    stream._read = function() {
+      connectionStream.resume();
+    };
+
+    this.on("result",function(row,i) {
+      if (!stream.push(row)) connectionStream.pause();
+      stream.emit("result",row,i);  // replicate old emitter
+    });
+
+    this.on("error",function(err) {
+      stream.emit("error",err);  // Pass on any errors
+    });
+
+    this.on("end", function() {
+      stream.push(null);  // pushing null, indicating EOF
+    });
+
+    this.on("fields",function(fields,i) {
+      stream.emit("fields",fields,i);  // replicate old emitter
+    });
+
+    return stream;
+  };
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/server.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/server.js
new file mode 100644
index 0000000000000000000000000000000000000000..0db454f8f633218400b525108b37912fb716e6d0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/server.js
@@ -0,0 +1,33 @@
+var net          = require('net');
+var util         = require('util');
+var EventEmitter = require('events').EventEmitter;
+
+var Connection   = require('./connection');
+var ConnectionConfig = require('./connection_config');
+
+// TODO: inherit Server from net.Server
+function Server()
+{
+  EventEmitter.call(this);
+  this.connections = [];
+  this._server = net.createServer(this._handleConnection.bind(this));
+}
+util.inherits(Server, EventEmitter);
+
+Server.prototype._handleConnection = function(socket) {
+  var connectionConfig = new ConnectionConfig({ stream: socket, isServer: true});
+  var connection = new Connection({ config: connectionConfig});
+  this.emit('connection', connection);
+  this.connections.push(connection);
+};
+
+Server.prototype.listen = function(port, host, backlog, callback) {
+  this._server.listen.apply(this._server, arguments);
+  return this;
+};
+
+Server.prototype.close = function(cb) {
+  this._server.close(cb);
+};
+
+module.exports = Server;
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/lib/sql_string.js b/node_modules/mysql2-promise/node_modules/mysql2/lib/sql_string.js
new file mode 100644
index 0000000000000000000000000000000000000000..c9883daa30721ea27f384b5453360247b33d1c2d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/lib/sql_string.js
@@ -0,0 +1,140 @@
+var SqlString = exports;
+
+SqlString.escapeId = function (val, forbidQualified) {
+  if (Array.isArray(val)) {
+    return val.map(function(v) {
+      return SqlString.escapeId(v, forbidQualified);
+    }).join(', ');
+  }
+
+  if (forbidQualified) {
+    return '`' + val.replace(/`/g, '``') + '`';
+  }
+  return '`' + val.replace(/`/g, '``').replace(/\./g, '`.`') + '`';
+};
+
+SqlString.escape = function(val, stringifyObjects, timeZone) {
+  if (val === undefined || val === null) {
+    return 'NULL';
+  }
+
+  switch (typeof val) {
+    case 'boolean': return (val) ? 'true' : 'false';
+    case 'number': return val+'';
+  }
+
+  if (val instanceof Date) {
+    val = SqlString.dateToString(val, timeZone || 'local');
+  }
+
+  if (Buffer.isBuffer(val)) {
+    return SqlString.bufferToString(val);
+  }
+
+  if (Array.isArray(val)) {
+    return SqlString.arrayToList(val, timeZone);
+  }
+
+  if (typeof val === 'object') {
+    if (stringifyObjects) {
+      val = val.toString();
+    } else {
+      return SqlString.objectToValues(val, timeZone);
+    }
+  }
+
+  val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
+    switch(s) {
+      case "\0": return "\\0";
+      case "\n": return "\\n";
+      case "\r": return "\\r";
+      case "\b": return "\\b";
+      case "\t": return "\\t";
+      case "\x1a": return "\\Z";
+      default: return "\\"+s;
+    }
+  });
+  return "'"+val+"'";
+};
+
+SqlString.arrayToList = function(array, timeZone) {
+  return array.map(function(v) {
+    if (Array.isArray(v)) return '(' + SqlString.arrayToList(v, timeZone) + ')';
+    return SqlString.escape(v, true, timeZone);
+  }).join(', ');
+};
+
+SqlString.format = function(sql, values, stringifyObjects, timeZone) {
+  values = values == null ? [] : [].concat(values);
+
+  return sql.replace(/\?\??/g, function(match) {
+    if (!values.length) {
+      return match;
+    }
+
+    if (match == "??") {
+      return SqlString.escapeId(values.shift());
+    }
+    return SqlString.escape(values.shift(), stringifyObjects, timeZone);
+  });
+};
+
+SqlString.dateToString = function(date, timeZone) {
+  var dt = new Date(date);
+
+  if (timeZone != 'local') {
+    var tz = convertTimezone(timeZone);
+
+    dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000));
+    if (tz !== false) {
+      dt.setTime(dt.getTime() + (tz * 60000));
+    }
+  }
+
+  var year   = dt.getFullYear();
+  var month  = zeroPad(dt.getMonth() + 1, 2);
+  var day    = zeroPad(dt.getDate(), 2);
+  var hour   = zeroPad(dt.getHours(), 2);
+  var minute = zeroPad(dt.getMinutes(), 2);
+  var second = zeroPad(dt.getSeconds(), 2);
+  var millisecond = zeroPad(dt.getMilliseconds(), 3);
+
+  return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '.' + millisecond;
+};
+
+SqlString.bufferToString = function bufferToString(buffer) {
+  return "X'" + buffer.toString('hex') + "'";
+};
+
+SqlString.objectToValues = function(object, timeZone) {
+  var values = [];
+  for (var key in object) {
+    var value = object[key];
+    if(typeof value === 'function') {
+      continue;
+    }
+
+    values.push(this.escapeId(key) + ' = ' + SqlString.escape(value, true, timeZone));
+  }
+
+  return values.join(', ');
+};
+
+function zeroPad(number, length) {
+  number = number.toString();
+  while (number.length < length) {
+    number = '0' + number;
+  }
+
+  return number;
+}
+
+function convertTimezone(tz) {
+  if (tz == "Z") return 0;
+
+  var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/);
+  if (m) {
+    return (m[1] == '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60;
+  }
+  return false;
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/package.json b/node_modules/mysql2-promise/node_modules/mysql2/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..9d5f99f4c7cbb5ff3592288d3eec61b35932fed0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/package.json
@@ -0,0 +1,40 @@
+{
+  "name": "mysql2",
+  "version": "0.15.8",
+  "description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS",
+  "main": "index.js",
+  "directories": {
+    "example": "examples"
+  },
+  "scripts": {
+    "test": "node ./test/run.js",
+    "benchmark": "./benchmarks/run-unit.js",
+    "benchmarks": "./benchmarks/run-unit.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sidorares/node-mysql2"
+  },
+  "keywords": [
+    "mysql",
+    "client",
+    "server"
+  ],
+  "engines": {
+    "node": ">= 0.8"
+  },
+  "author": "Andrey Sidorov <sidorares@yandex.ru>",
+  "license": "MIT",
+  "dependencies": {
+    "bn.js": "2.0.0",
+    "cardinal": "0.4.4",
+    "double-ended-queue": "2.0.0-0",
+    "named-placeholders": "0.1.3",
+    "readable-stream": "1.0.33"
+  },
+  "devDependencies": {
+    "progress": "1.1.8",
+    "urun": "0.0.8",
+    "utest": "0.0.8"
+  }
+}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/common.js b/node_modules/mysql2-promise/node_modules/mysql2/test/common.js
new file mode 100644
index 0000000000000000000000000000000000000000..21da88e4694f390bc6f5a74b79a34076686a5910
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/common.js
@@ -0,0 +1,105 @@
+var config = {
+  host: process.env.MYSQL_HOST || '127.0.0.1',
+  user: process.env.MYSQL_USER || 'root',
+  password: process.env.CI ? process.env.MYSQL_PASSWORD : '',
+  database: process.env.MYSQL_DATABASE || 'test',
+  port: process.env.MYSQL_PORT || 3306
+};
+
+module.exports.SqlString = require('../lib/sql_string.js');
+
+module.exports.createConnection = function(args, callback) {
+  // hrtime polyfill for old node versions:
+  if (!process.hrtime)
+    process.hrtime = function(start) {
+      start = [0, 0] || start;
+      var timestamp = Date.now();
+      var seconds = Math.ceil(timestamp/1000);
+      return [seconds - start[0], (timestamp-seconds*1000)*1000 - start[1]];
+    };
+
+  if (process.env.BENCHMARK_MARIA) {
+    var Client = require('mariasql');
+    var c = new Client();
+    c.connect({
+      host: config.host,
+      user: config.user,
+      password: config.password,
+      db: config.database
+    });
+    //c.on('connect', function() {
+    //
+    //});
+    setTimeout( function() {
+    console.log('altering client...');
+    c.oldQuery = c.query;
+    c.query = function(sql, callback) {
+      var rows = [];
+      var q = c.oldQuery(sql);
+      q.on('result', function(res) {
+        res.on('row', function(row) { rows.push(row); });
+        res.on('end', function() {
+          callback(null, rows);
+        });
+      });
+    };
+    }, 1000);
+    return c;
+  }
+
+  var driver = require('../index.js');
+  if (process.env.BENCHMARK_MYSQL1)
+    driver = require('mysql');
+
+  return driver.createConnection({
+    host: config.host,
+    user: (args && args.user) || config.user,
+    password: (args && args.password) || config.password,
+    database: (args && args.database) || config.database,
+    multipleStatements: args ? args.multipleStatements : false,
+    port: (args && args.port) || config.port,
+    debug: process.env.DEBUG,
+    supportBigNumbers: args && args.supportBigNumbers,
+    bigNumberStrings: args && args.bigNumberStrings,
+    dateStrings: args && args.dateStrings
+  });
+};
+
+module.exports.createPool = function(callback) {
+  var driver = require('../index.js');
+  if (process.env.BENCHMARK_MYSQL1)
+    driver = require('mysql');
+
+  return driver.createPool(config);
+};
+
+module.exports.createTemplate = function() {
+  var jade = require('jade');
+  var template = require('fs').readFileSync(__dirname + '/template.jade', 'ascii');
+  return jade.compile(template);
+};
+
+module.exports.createServer = function(onListening, handler) {
+  var server = require('../index.js').createServer();
+  server.on('connection', function(conn) {
+    conn.on('error', function() {
+      // we are here when client drops connection
+    });
+    conn.serverHandshake({
+      protocolVersion: 10,
+      serverVersion: 'node.js rocks',
+      connectionId: 1234,
+      statusFlags: 2,
+      characterSet: 8,
+      capabilityFlags: 0xffffff
+    });
+    if (handler)
+      handler(conn);
+  });
+  server.listen(3307, onListening);
+  return server;
+};
+
+module.exports.useTestDb = function(cb) {
+  // no-op in my setup, need it for compatibility with node-mysql tests
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-ints-doubles-table.sql b/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-ints-doubles-table.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ee4bcc77ce1ee93aa3cdda6bd80e4a85306ad8d3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-ints-doubles-table.sql
@@ -0,0 +1,32 @@
+-- from http://sixarm.com/about/mysql-create-random-data-text-strings.html
+
+drop table if exists ints;
+drop procedure if exists randomize_nums;
+
+CREATE TABLE ints (
+    id int(11) NOT NULL AUTO_INCREMENT,
+    val1 int(11),
+    val2 double,
+    PRIMARY KEY (id)
+  );
+
+delimiter $$
+create procedure randomize_nums()
+    begin
+      declare i int Default 0 ;
+      declare random int(20);
+      declare random1 double;
+      myloop: loop
+      set random=floor(rand() * 99999);
+      set random1=rand() * 99999 ;
+      insert into ints VALUES (i+1,random, random1) ;
+      set i=i+1;
+      if i=500000 then
+        leave myloop;
+  end if;
+    end loop myloop;
+  end $$
+delimiter ;
+
+call randomize_nums;
+
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-rows-table.sql b/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-rows-table.sql
new file mode 100644
index 0000000000000000000000000000000000000000..2f6a419cbf9d606a21fc670e2fa4467ef2fbac11
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/create-500k-random-rows-table.sql
@@ -0,0 +1,29 @@
+-- from http://sixarm.com/about/mysql-create-random-data-text-strings.html
+
+drop table if exists foos;
+drop procedure if exists randomizer;
+
+CREATE TABLE foos (
+    id int(11) NOT NULL AUTO_INCREMENT,
+    name char(20),
+    PRIMARY KEY (id)
+  );
+
+delimiter $$
+create procedure randomizer()
+    begin
+      declare i int Default 0 ;
+      declare random char(20);
+      myloop: loop
+      set random=conv(floor(rand() * 99999999999999), 20, 36) ;
+      insert into `foos` (`id`, `name`) VALUES (i+1,random) ;
+      set i=i+1;
+      if i=500000 then
+        leave myloop;
+  end if;
+    end loop myloop;
+  end $$
+delimiter ;
+
+call randomizer;
+
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-charset-string.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-charset-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..fe32707c4b8aed07f60658dad375748d55e451b0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-charset-string.js
@@ -0,0 +1,75 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var fields = undefined;
+var rows1 = undefined;
+var fields1 = undefined;
+var rows2 = undefined;
+var fields2 = undefined;
+var rows3 = undefined;
+var fields3 = undefined;
+
+var rows4 = undefined;
+var fields4 = undefined;
+var rows5 = undefined;
+var fields5 = undefined;
+
+var query = "SELECT x'010203'";
+var query1 = "SELECT '010203'";
+
+connection.query(query, function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+});
+
+connection.query(query, function(err, _rows, _fields) {
+  if (err) throw err;
+  rows5 = _rows;
+  fields5 = _fields;
+});
+
+connection.query(query1, function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+  fields1 = _fields;
+});
+
+connection.execute(query, [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows2 = _rows;
+  fields2 = _fields;
+});
+
+// repeat same query - test cached fields and parser
+connection.execute(query, [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows4 = _rows;
+  fields4 = _fields;
+});
+
+connection.execute(query1, [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows3 = _rows;
+  fields3 = _fields;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{"x'010203'": Buffer([1, 2, 3])}]);
+  assert.equal(fields[0].name, "x'010203'");
+  assert.deepEqual(rows1, [{'010203': '010203'}]);
+  assert.equal(fields1[0].name, "010203");
+  assert.deepEqual(rows2, [{"x'010203'": Buffer([1, 2, 3])}]);
+  assert.equal(fields2[0].name, "x'010203'");
+  assert.deepEqual(rows3, [{'010203': '010203'}]);
+  assert.equal(fields3[0].name, "010203");
+
+  assert.deepEqual(rows4, [{"x'010203'": Buffer([1, 2, 3])}]);
+  assert.equal(fields4[0].name, "x'010203'");
+  assert.deepEqual(rows5, [{"x'010203'": Buffer([1, 2, 3])}]);
+  assert.equal(fields5[0].name, "x'010203'");
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-multiple-results.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-multiple-results.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1efd51457bad894ec0fe2e63258ddc6dc222282
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-multiple-results.js
@@ -0,0 +1,160 @@
+var mysql = require('../../common.js').createConnection({multipleStatements: true});
+var assert = require('assert');
+mysql.query('CREATE TEMPORARY TABLE no_rows (test int)');
+mysql.query('CREATE TEMPORARY TABLE some_rows (test int)');
+mysql.query('INSERT INTO some_rows values(0)');
+mysql.query('INSERT INTO some_rows values(42)');
+mysql.query('INSERT INTO some_rows values(314149)');
+
+var clone = function(obj) { return JSON.parse(JSON.stringify(obj)); };
+
+var rs1 = {
+  affectedRows: 0,
+  fieldCount: 0,
+  insertId: 0,
+  serverStatus: 10,
+  warningStatus: 0
+};
+var rs2 = clone(rs1);
+rs2.serverStatus = 2;
+var rs3 = clone(rs1);
+rs3.serverStatus = 34;
+
+var twoInsertResult = [[rs1, rs2], [undefined, undefined], 2];
+var select1 = [{"1":"1"}];
+var select2 = [{"2":"2"}];
+var fields1 = [{
+  catalog: "def",
+  characterSet: 63,
+  columnLength: 1,
+  columnType: 8,
+  decimals: 0,
+  flags: 129,
+  name: "1",
+  orgName: "",
+  orgTable: "",
+  schema: "",
+  table: ""
+}];
+var nr_fields = [{
+  catalog: "def",
+  characterSet: 63,
+  columnLength: 11,
+  columnType: 3,
+  decimals: 0,
+  flags: 0,
+  name: "test",
+  orgName: "test",
+  orgTable: "no_rows",
+  schema: mysql.config.database,
+  table: "no_rows"
+}];
+
+var sr_fields = clone(nr_fields);
+sr_fields[0].orgTable = "some_rows";
+sr_fields[0].table = "some_rows";
+var select3 = [{"test":0},{"test":42},{"test":314149}];
+
+var fields2 = clone(fields1);
+fields2[0].name = "2";
+
+var tests = [
+  ["select * from some_rows", [[select3,rs3],[sr_fields,undefined],2]], //  select 3 rows
+  ["SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT; SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS", [rs2, undefined, 1]],
+  ["set @a = 1", [rs2, undefined, 1]],
+  ["set @a = 1; set @b = 2", [rs2, undefined, 1]],
+  ["select 1; select 2", [[select1,select2,rs2],[fields1,fields2,undefined], 3]],
+  ["set @a = 1; select 1", [[select1,rs2], [fields1,undefined], 2]],
+  ["select 1; set @a = 1", [[select1, rs2], [fields1, undefined], 2]],
+  ["select * from no_rows", [[[], rs3], [nr_fields, undefined], 2]],    // select 0 rows"
+  ["set @a = 1; select * from no_rows", [[[], rs3], [nr_fields, undefined], 2]], // insert + select 0 rows
+  ["select * from no_rows; set @a = 1", [[[], rs3], [nr_fields, undefined], 2]], //  select 0 rows + insert
+  ["set @a = 1; select * from some_rows", [[select3, rs3],[sr_fields,undefined],2]], // insert + select 3 rows
+  ["select * from some_rows; set @a = 1", [[select3, rs3],[sr_fields,undefined],2]] //  select 3 rows + insert
+];
+
+function procedurise(sql) {
+  return [
+    'DROP PROCEDURE IF EXISTS _as_sp_call;',
+    'CREATE PROCEDURE _as_sp_call()',
+    'BEGIN',
+     sql + ';',
+    'END',
+  ].join('\n');
+}
+
+function do_test(testIndex) {
+  var next = function() {
+    if (testIndex + 1 < tests.length)
+      do_test(testIndex + 1);
+    else {
+      mysql.end();
+    }
+  };
+
+  var entry = tests[testIndex];
+  var sql = entry[0];
+  var origSql = sql;
+  var expectation = entry[1];
+  // prepared statements do not support multiple statements itself, we need to wrap quey in a stored procedure
+  var sp = procedurise(sql);
+  mysql.query(sp, function(err) {
+    if (err)
+        throw(err);
+    sql = "CALL _as_sp_call()"; // this call is allowed with prepared statements, and result contain multiple statements
+    mysql.query(sql, function(err, _rows, _columns, _numResults) {
+      if (err)
+        throw err;
+
+      var arrOrColumn = function (c) {
+        if (Array.isArray(c))
+          return c.map(arrOrColumn);
+
+        if (typeof c == 'undefined')
+          return void(0);
+
+        return c.inspect();
+      };
+
+      assert.deepEqual(expectation[0], _rows);
+      assert.deepEqual(expectation[1], arrOrColumn(_columns));
+      assert.deepEqual(expectation[2], _numResults);
+
+      var q = mysql.execute(sql);
+      var resIndex = 0;
+      var rowIndex = 0;
+      function checkRow(row, index) {
+
+        if (_numResults == 1) {
+          assert.equal(index, 0);
+          if (row.constructor.name == 'ResultSetHeader')
+            assert.deepEqual(_rows, row);
+          else
+            assert.deepEqual(_rows[rowIndex], row);
+        } else {
+          if (resIndex != index) {
+            rowIndex = 0;
+            resIndex = index;
+          }
+          if (row.constructor.name == 'ResultSetHeader')
+            assert.deepEqual(_rows[index], row);
+          else
+            assert.deepEqual(_rows[index][rowIndex], row);
+        }
+        rowIndex++;
+      }
+      function checkFields(fields, index) {
+        if (_numResults == 1) {
+          assert.equal(index, 0);
+          assert.deepEqual(arrOrColumn(_columns), arrOrColumn(fields));
+        }
+        else
+          assert.deepEqual(arrOrColumn(_columns[index]), arrOrColumn(fields));
+      }
+      q.on('result', checkRow);
+      q.on('fields', checkFields);
+      q.on('end', next);
+    });
+  });
+}
+do_test(0);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-notnull-nulls.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-notnull-nulls.js
new file mode 100644
index 0000000000000000000000000000000000000000..9114ae4ba39a6061080533e7cba06af340b3b389
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-binary-notnull-nulls.js
@@ -0,0 +1,52 @@
+var assert = require('assert');
+
+var FieldFlags = require('../../../lib/constants/field_flags.js');
+var common     = require('../../common');
+var conn       = common.createConnection();
+
+// it's possible to receive null values for columns marked with NOT_NULL flag
+// see https://github.com/sidorares/node-mysql2/issues/178 for info
+
+conn.query('CREATE TEMPORARY TABLE `tmp_account` ( ' +
+  ' `id` int(11) NOT NULL AUTO_INCREMENT, ' +
+  ' `username` varchar(64) NOT NULL, ' +
+  ' `auth_code` varchar(30) NOT NULL, ' +
+  ' `access_token` varchar(30) NOT NULL, ' +
+  ' `refresh_token` tinytext NOT NULL, ' +
+  ' PRIMARY KEY (`id`) ' +
+  ' ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8');
+conn.query("INSERT INTO `tmp_account` VALUES ('1', 'xgredx', '', '', '')");
+
+conn.query('CREATE TEMPORARY TABLE `tmp_account_flags` ( ' +
+  ' `account` int(11) NOT NULL, ' +
+  ' `flag` tinyint(3) NOT NULL, ' +
+  ' PRIMARY KEY (`account`,`flag`) ' +
+  ' ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8');
+
+conn.query("INSERT INTO `tmp_account_flags` VALUES ('1', '100')")
+
+conn.query('CREATE TEMPORARY TABLE `tmp_account_session` ( ' +
+  ' `account` int(11) NOT NULL, ' +
+  ' `ip` varchar(15) NOT NULL, ' +
+  ' `session` varchar(114) NOT NULL, ' +
+  ' `time` int(11) NOT NULL, ' +
+  ' PRIMARY KEY (`account`,`ip`) ' +
+  ' ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8');
+
+conn.query("INSERT INTO `tmp_account_session` VALUES ('1', '::1', '75efb145482ce22f4544390cad233c749c1b43e4', '1')")
+
+
+conn.connect(function(err) {
+    if (err) {
+        console.error(err);
+        return;
+    }
+
+    conn.execute("SELECT `ac`.`username`, CONCAT('[', GROUP_CONCAT(DISTINCT `acf`.`flag` SEPARATOR ','), ']') flags FROM tmp_account ac LEFT JOIN tmp_account_flags acf ON `acf`.account = `ac`.id LEFT JOIN tmp_account_session acs ON `acs`.account = `ac`.id WHERE `acs`.`session`=?", ["asid=75efb145482ce22f4544390cad233c749c1b43e4"], function(err, rows, fields) {
+        var flagNotNull = fields[0].flags & FieldFlags.NOT_NULL;
+        var valueIsNull = rows[0][fields[0].name] === null;
+        assert( flagNotNull && valueIsNull );
+        conn.end();
+    });
+
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-buffer-params.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-buffer-params.js
new file mode 100644
index 0000000000000000000000000000000000000000..b62b8e1349455f3e8f9e08a642da7cf2b49211b6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-buffer-params.js
@@ -0,0 +1,28 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var rows1 = undefined;
+var fields = undefined;
+var fields1 = undefined;
+
+var buf = Buffer([0x80, 0x90, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 100, 255, 255]);
+connection.execute('SELECT HEX(?) as buf', [buf], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+});
+
+connection.query('SELECT HEX(?) as buf', [buf], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+  fields1 = _fields;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{buf: buf.toString('hex').toUpperCase()}]);
+  assert.deepEqual(rows1, [{buf: buf.toString('hex').toUpperCase()}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-change-user.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-change-user.js
new file mode 100644
index 0000000000000000000000000000000000000000..f3715aa4de81ccfd19115b9398a456129daf2706
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-change-user.js
@@ -0,0 +1,57 @@
+var assert     = require('assert');
+var common     = require('../../common');
+var connection = common.createConnection();
+
+// create test user first
+connection.query("GRANT ALL ON *.* TO 'changeuser1'@'localhost' IDENTIFIED BY 'changeuser1pass'");
+connection.query("GRANT ALL ON *.* TO 'changeuser2'@'localhost' IDENTIFIED BY 'changeuser2pass'");
+connection.query('FLUSH PRIVILEGES');
+
+connection.changeUser({
+  user: 'changeuser1',
+  password: 'changeuser1pass'
+});
+connection.query('select user()', function(err, rows) {
+  if (err) throw err;
+  assert.deepEqual(rows, [ { 'user()': 'changeuser1@localhost' } ]);
+});
+
+connection.changeUser({
+  user: 'changeuser2',
+  password: 'changeuser2pass'
+});
+
+connection.query('select user()', function(err, rows) {
+  if (err) throw err;
+  assert.deepEqual(rows, [ { 'user()': 'changeuser2@localhost' } ]);
+});
+
+connection.changeUser({
+  user: 'changeuser1',
+  passwordSha1: new Buffer('f961d39c82138dcec42b8d0dcb3e40a14fb7e8cd', 'hex') // sha1(changeuser1pass)
+});
+connection.query('select user()', function(err, rows) {
+  if (err) throw err;
+  assert.deepEqual(rows, [ { 'user()': 'changeuser1@localhost' } ]);
+});
+
+connection.end();
+
+// from felixge/node-mysql/test/unit/connection/test-change-database-fatal-error.js:
+// This test verifies that changeUser errors are treated as fatal errors.  The
+// rationale for that is that a failure to execute a changeUser sequence may
+// cause unexpected behavior for queries that were enqueued under the
+// assumption of changeUser to succeed.
+
+var beforeChange = 1;
+connection.changeUser({database: 'does-not-exist'}, function (err) {
+  assert.ok(err, 'got error');
+  assert.equal(err.code, 'ER_BAD_DB_ERROR');
+  assert.equal(err.fatal, true);
+});
+
+connection.on('error', function(err) {
+  assert.ok(err, 'got disconnect');
+  assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+  assert.equal(beforeChange, 1);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-connect-sha1.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-connect-sha1.js
new file mode 100644
index 0000000000000000000000000000000000000000..bf7369b0c28af054c0f607f18a61a6acb3b32f05
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-connect-sha1.js
@@ -0,0 +1,68 @@
+var mysql      = require('../../../index.js');
+var auth       = require('../../../lib/auth_41.js');
+var assert     = require('assert');
+
+var server;
+
+function authenticate(params, cb) {
+  var doubleSha = auth.doubleSha1('testpassword');
+  var isValid = auth.verifyToken(params.authPluginData1, params.authPluginData2, params.authToken, doubleSha);
+  assert(isValid);
+  cb(null);
+}
+
+var queryCalls = 0;
+
+var server = mysql.createServer();
+server.listen(3307);
+server.on('connection', function(conn) {
+  conn.serverHandshake({
+    protocolVersion: 10,
+    serverVersion: 'node.js rocks',
+    connectionId: 1234,
+    statusFlags: 2,
+    characterSet: 8,
+    capabilityFlags: 0xffffff,
+    authCallback: authenticate
+  });
+  conn.on('query', function(sql) {
+    assert.equal(sql, 'select 1+1');
+    queryCalls++;
+    conn.close();
+  });
+});
+
+var connection = mysql.createConnection({
+  port: 3307,
+  user: 'testuser',
+  database: 'testdatabase',
+  passwordSha1: Buffer('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex')
+});
+
+connection.on('error', function(err) {
+  assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+});
+
+connection.query('select 1+1', function(err) {
+  assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+  server._server.close();
+});
+
+var _1_2 = false;
+var _1_3 = false;
+
+connection.query('select 1+2', function(err) {
+  assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+  _1_2 = true;
+});
+
+connection.query('select 1+3', function(err) {
+  assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+  _1_3 = true;
+});
+
+process.on('exit', function() {
+  assert.equal(queryCalls, 1);
+  assert.equal(_1_2, true);
+  assert.equal(_1_3, true);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-custom-date-parameter.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-custom-date-parameter.js
new file mode 100644
index 0000000000000000000000000000000000000000..00f3cf810578a9fa9f680fa708f48b10e641ccec
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-custom-date-parameter.js
@@ -0,0 +1,25 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+
+Date = function() {
+  var NativeDate = Date;
+  function CustomDate(str) {
+    return new NativeDate(str);
+  }
+  return CustomDate;
+}();
+
+connection.execute('SELECT UNIX_TIMESTAMP(?) t', [new Date('1990-08-08 UTC')], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  console.log(_rows, _fields);
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{t: 650073600}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-date-parameter.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-date-parameter.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d872097b29b087ebbb9c17f3b585d28acb02275
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-date-parameter.js
@@ -0,0 +1,17 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+
+connection.execute('SELECT UNIX_TIMESTAMP(?) t', [new Date('1990-01-01 UTC')], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  console.log(_rows, _fields);
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{t: 631152000}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-datetime.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-datetime.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fff096cbd05cae523c71ea3826616117b1e140a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-datetime.js
@@ -0,0 +1,72 @@
+var common      = require('../../common');
+var connection  = common.createConnection();
+var connection1 = common.createConnection({ dateStrings: true });
+var assert      = require('assert');
+
+var rows, rows1, rows2, rows3, rows4, rows5;
+
+var date = new Date('1990-01-01 08:15:11 UTC');
+var date1 = new Date('2000-03-03 08:15:11 UTC');
+var date2 = '2010-12-10 14:12:09.019473';
+connection.query('CREATE TEMPORARY TABLE t (d1 DATE)');
+connection.query('INSERT INTO t set d1=?', [date]);
+
+connection1.query('CREATE TEMPORARY TABLE t (d1 DATE, d2 TIMESTAMP, d3 DATETIME)');
+connection1.query('INSERT INTO t set d1=?, d2=?, d3=?', [date, date1, date2]);
+
+var dateAsStringExpected = [
+     { d1: '1990-01-01',
+       d2: '2000-03-03 08:15:11',
+       d3: '2010-12-10 14:12:09' } ];
+
+
+connection.execute('select from_unixtime(?) t', [(+date).valueOf()/1000], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+});
+
+connection.query('select from_unixtime(631152000) t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+});
+
+connection.query('select * from t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows2 = _rows;
+});
+
+connection.execute('select * from t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows3 = _rows;
+  connection.end();
+});
+
+connection1.query('select * from t', function(err, _rows, _fields) {
+  console.log(_rows);
+  if (err) throw err;
+  rows4 = _rows;
+});
+
+connection1.execute('select * from t', function(err, _rows, _fields) {
+  console.log(_rows);
+  if (err) throw err;
+  rows5 = _rows;
+  connection1.end();
+});
+
+process.on('exit', function() {
+  assert.equal(rows[0].t.constructor, Date);
+  assert.equal(rows[0].t.getDate(), date.getDate());
+  assert.equal(rows[0].t.getHours(), date.getHours());
+  assert.equal(rows[0].t.getMinutes(), date.getMinutes());
+  assert.equal(rows[0].t.getSeconds(), date.getSeconds());
+
+  assert.equal(rows1[0].t.constructor, Date);
+  assert.equal(rows1[0].t - new Date('Mon Jan 01 1990 11:00:00 GMT+1100 (EST)'), 0);
+
+  assert.equal(rows2[0].d1.getDate(), date.getDate());
+  assert.equal(rows3[0].d1.getDate(), date.getDate());
+
+  assert.deepEqual(rows4, dateAsStringExpected);
+  assert.deepEqual(rows5, dateAsStringExpected);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-disconnects.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-disconnects.js
new file mode 100644
index 0000000000000000000000000000000000000000..05a5ca0d5e3d4c9af2782edda7687116c64c8ccc
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-disconnects.js
@@ -0,0 +1,47 @@
+var common     = require('../../common');
+var assert     = require('assert');
+
+var rows;
+var fields;
+var err;
+var server;
+
+function test() {
+  var connection = common.createConnection({port: 3307});
+  connection.query('SELECT 123', function(err, _rows, _fields) {
+    if (err) throw err;
+
+    rows = _rows;
+    fields = _fields;
+    connection.on('error', function(_err) {
+      err = _err;
+    });
+    server.connections.forEach(function(conn) { conn.stream.end(); } );
+    server._server.close(function() {
+      assert.equal(err.code, 'PROTOCOL_CONNECTION_LOST');
+    });
+  });
+  // TODO: test connection.end() etc where we expect disconnect to happen
+}
+
+function serverHandler(conn) {
+  conn.on('query', function(q) {
+    conn.writeTextResult([ { '1': '1' } ], [ { catalog: 'def',
+     schema: '',
+     table: '',
+     orgTable: '',
+     name: '1',
+     orgName: '',
+     characterSet: 63,
+     columnLength: 1,
+     columnType: 8,
+     flags: 129,
+     decimals: 0 } ]);
+  });
+}
+server = common.createServer(test, serverHandler);
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{1: 1}]);
+  assert.equal(fields[0].name, '1');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-domains.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-domains.js
new file mode 100644
index 0000000000000000000000000000000000000000..e199a3f848a5c62bd17aebe84a99000d90b54a1f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-domains.js
@@ -0,0 +1,60 @@
+var assert = require('assert');
+var domain = require('domain');
+var d1 = domain.create();
+var d2 = domain.create();
+var d3 = domain.create();
+var d4 = domain.create();
+var err1, err2, err3, err4;
+
+d1.run(function() {
+  var common     = require('../../common');
+  var connection = common.createConnection();
+  var assert     = require('assert');
+
+  d2.run(function() {
+    connection.query('SELECT 1', function(err, _rows, _fields) {
+      if (err) throw err;
+      throw new Error('inside domain 2');
+    });
+  });
+
+  d3.run(function() {
+    connection.execute('SELECT 1', function(err, _rows, _fields) {
+      connection.end();
+      if (err) throw err;
+      throw new Error('inside domain 3');
+    });
+  });
+
+  d4.run(function() {
+   connection.ping(function() {
+     throw new Error('inside domain 4');
+   });
+  });
+
+  setTimeout(function() {
+    throw new Error('inside domain 1');
+  }, 100);
+
+  d2.on('error', function(err) {
+    err2 = err;
+  });
+  d3.on('error', function(err) {
+    err3 = err;
+  });
+  d4.on('error', function(err) {
+    err4 = err;
+  });
+
+});
+
+d1.on('error', function(err) {
+  err1 = err;
+});
+
+process.on('exit', function() {
+  assert.equal(''+err1, 'Error: inside domain 1')
+  assert.equal(''+err2, 'Error: inside domain 2')
+  assert.equal(''+err3, 'Error: inside domain 3')
+  assert.equal(''+err4, 'Error: inside domain 4')
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-errors.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-errors.js
new file mode 100644
index 0000000000000000000000000000000000000000..d33b05d4e292055bcac53d050f7d29dbc8049d1f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-errors.js
@@ -0,0 +1,46 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var onExecuteResultError = undefined;
+var onQueryResultError = undefined;
+var onExecuteErrorEvent = undefined;
+var onQueryErrorEvent = undefined;
+var onExecuteErrorEvent1 = undefined;
+var onQueryErrorEvent1 = undefined;
+
+connection.execute('error in execute', [], function(err, _rows, _fields) {
+  assert.equal(err.errno, 1064);
+  assert.equal(err.code, 'ER_PARSE_ERROR');
+  if (err) {
+    onExecuteResultError = true;
+  }
+}).on('error', function() {
+  onExecuteErrorEvent = true;
+});
+connection.query('error in query', [], function(err, _rows, _fields) {
+  assert.equal(err.errno, 1064);
+  assert.equal(err.code, 'ER_PARSE_ERROR');
+  if (err) {
+    onQueryResultError = true;
+  }
+}).on('error', function() {
+  onQueryErrorEvent = true;
+});
+connection.execute('error in execute 1', []).on('error', function() {
+  onExecuteErrorEvent1 = true;
+});
+connection.query('error in query 1').on('error', function() {
+  onQueryErrorEvent1 = true;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.equal(onExecuteResultError, true);
+  assert.equal(onQueryResultError, true);
+  assert.equal(onExecuteErrorEvent, undefined);
+  assert.equal(onQueryErrorEvent, undefined);
+  assert.equal(onExecuteErrorEvent1, true);
+  assert.equal(onQueryErrorEvent1, true);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-1.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-1.js
new file mode 100644
index 0000000000000000000000000000000000000000..3f8f0a5591b60a386af97b04bcf7d5dd0e65250f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-1.js
@@ -0,0 +1,54 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var rows1 = undefined;
+var fields = undefined;
+
+connection.query([
+  'CREATE TEMPORARY TABLE `announcements` (',
+  '`id` int(11) NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255) DEFAULT NULL,',
+  '`text` varchar(255) DEFAULT NULL,',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'), function(err) {
+  if (err) throw err;
+});
+
+connection.execute('SELECT 1+? as test', [123], function(err, _rows, _fields) {
+  if (err) throw err;
+
+  rows = _rows;
+  fields = _fields;
+});
+connection.execute('SELECT 1 as test', function(err, _rows, _fields) {
+  if (err) throw err;
+
+  rows1 = _rows;
+  fields = _fields;
+});
+
+connection.execute('INSERT INTO announcements(title, text) VALUES(?, ?)', ['Есть место, где заканчивается тротуар', 'Расти борода, расти'], function(err) {
+  if (err) throw err;
+});
+connection.execute('INSERT INTO announcements(title, text) VALUES(?, ?)', ['Граждане Российской Федерации имеют право собираться мирно без оружия', 'проводить собрания, митинги и демонстрации, шествия и пикетирование'], function(err) {
+  if (err) throw err;
+});
+connection.execute('SELECT * FROM announcements', function (err, rows) {
+  if (err) throw err;
+  assert.equal(rows.length, 2);
+  assert.equal(rows[0].title, 'Есть место, где заканчивается тротуар');
+  assert.equal(rows[0].text, 'Расти борода, расти');
+  assert.equal(rows[1].title, 'Граждане Российской Федерации имеют право собираться мирно без оружия');
+  assert.equal(rows[1].text, 'проводить собрания, митинги и демонстрации, шествия и пикетирование');
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{'test': 124}]);
+  assert.deepEqual(rows1, [{'test': 1}]);
+  assert.equal(fields[0].name, 'test');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-and-unprepare.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-and-unprepare.js
new file mode 100644
index 0000000000000000000000000000000000000000..c5c928c88516650a750eef1530944c7d32e56b6b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-and-unprepare.js
@@ -0,0 +1,21 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var max = 500;
+var start = process.hrtime();
+function exec(i) {
+  var query = 'select 1+' + i;
+  connection.execute(query, function(err, rows, columns) {
+    connection.unprepare(query);
+    if (err) throw err;
+    if (i > max)
+      connection.end();
+    else
+      exec(i+1);
+  });
+}
+connection.query('SET GLOBAL max_prepared_stmt_count=10', function(err) {
+  if (err) throw err;
+  exec(1);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-cached.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-cached.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee1b2c72d2448d8477c8e798f252224c9b19286d
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-cached.js
@@ -0,0 +1,35 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var rows1 = undefined;
+var rows3 = undefined;
+
+var q = 'select 1 + ? as test';
+var key = 'undefined/undefined/undefined' + q;
+
+connection.execute(q, [123], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  connection.execute(q, [124], function(err, _rows, _fields) {
+    if (err) throw err;
+    rows1 = _rows;
+    connection.execute(q, [125], function(err, _rows, _fields) {
+      if (err) throw err;
+      rows2 = _rows;
+      assert(Object.keys(connection._statements).length == 1);
+      assert(connection._statements[key].query == q);
+      assert(connection._statements[key].parameters.length == 1);
+      connection.end();
+    });
+  });
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{'test': 124}]);
+  assert.deepEqual(rows1, [{'test': 125}]);
+  assert.deepEqual(rows2, [{'test': 126}]);
+});
+
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-newdecimal.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-newdecimal.js
new file mode 100644
index 0000000000000000000000000000000000000000..c0bebcb4dc947fa46e29da1ecf1381647f48ed21
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-newdecimal.js
@@ -0,0 +1,19 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+connection.query('CREATE TEMPORARY TABLE t (f DECIMAL(19,4))');
+connection.query('INSERT INTO t VALUES(12345.67)');
+
+var rows, fields;
+connection.execute('SELECT f FROM t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{'f': '12345.6700'}]);
+  assert.equal(fields[0].name, 'f');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-nocolumndef.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-nocolumndef.js
new file mode 100644
index 0000000000000000000000000000000000000000..7eb769c4ff19a51c55860094b25c53823eafd761
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-nocolumndef.js
@@ -0,0 +1,149 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+// https://github.com/sidorares/node-mysql2/issues/130
+// https://github.com/sidorares/node-mysql2/issues/37
+// binary protocol examples where `prepare` returns no column definitions but execute() does return fields/rows
+
+var rows;
+var fields;
+
+connection.execute('explain SELECT 1', function(err, _rows, _fields) {
+  if (err) throw err;
+
+  rows = _rows
+  fields = _fields;
+  connection.end();
+});
+
+var expectedRows;
+var expectedFields;
+
+process.on('exit', function() {
+  assert.deepEqual(rows, expectedRows);
+  var fi = fields.map(function(c) { return c.inspect() });
+  assert.deepEqual(fi, expectedFields);
+});
+
+expectedFields = [{ catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'id',
+    orgName: '',
+    characterSet: 63,
+    columnLength: 3,
+    columnType: 8,
+    flags: 161,
+    decimals: 0 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'select_type',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 57,
+    columnType: 253,
+    flags: 1,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'table',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 192,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'type',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 30,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'possible_keys',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 12288,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'key',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 192,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'key_len',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 12288,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'ref',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 3072,
+    columnType: 253,
+    flags: 0,
+    decimals: 31 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'rows',
+    orgName: '',
+    characterSet: 63,
+    columnLength: 10,
+    columnType: 8,
+    flags: 160,
+    decimals: 0 },
+  { catalog: 'def',
+    schema: '',
+    table: '',
+    orgTable: '',
+    name: 'Extra',
+    orgName: '',
+    characterSet: 33,
+    columnLength: 765,
+    columnType: 253,
+    flags: 1,
+    decimals: 31 }];
+
+expectedRows = [ {id: 1,
+    select_type: 'SIMPLE',
+    table: null,
+    type: null,
+    possible_keys: null,
+    key: null,
+    key_len: null,
+    ref: null,
+    rows: null,
+    Extra: 'No tables used' }];
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-null-bitmap.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-null-bitmap.js
new file mode 100644
index 0000000000000000000000000000000000000000..c6a5959b064b927cd9553fcbf814651dcade1ffb
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-null-bitmap.js
@@ -0,0 +1,22 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var params = [1, 2];
+var query = 'select ? + ?';
+
+function dotest() {
+  connection.execute(query + ' as t', params, function(err, _rows, _fields) {
+    assert.equal(err, null);
+    if (params.length < 50) {
+      assert.equal(_rows[0].t, params.reduce(function(x,y) {return x+y;}));
+      query += ' + ?';
+      params.push(params.length);
+      dotest();
+    } else {
+      connection.end();
+    }
+  });
+}
+
+connection.query('SET GLOBAL max_prepared_stmt_count=300', dotest);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-signed.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-signed.js
new file mode 100644
index 0000000000000000000000000000000000000000..f70d82bb208421fc20bcc1e354acd5e38bbe2bcd
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-signed.js
@@ -0,0 +1,31 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var fields = undefined;
+
+connection.query([
+  'CREATE TEMPORARY TABLE `test_table` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`num` int(15),',
+  '`l` long,',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+connection.query('insert into test_table(num,l) values(?, 3)', [1]);
+connection.query('insert into test_table(num,l) values(3-?, -10)', [5]);
+connection.query('insert into test_table(num,l) values(4+?, 4000000-?)', [-5, 8000000]);
+
+connection.execute('SELECT * from test_table', [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{"id":1,"num":1,"l": 3},{"id":2,"num":-2,"l":-10},{"id":3,"num":-1,"l":-4000000}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-type-casting.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-type-casting.js
new file mode 100644
index 0000000000000000000000000000000000000000..107c1ddaa7a01994168f8fe3e30cd6177f76cc63
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-execute-type-casting.js
@@ -0,0 +1,71 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var tests = require('./type-casting-tests')(connection);
+
+var table = 'type_casting';
+
+var schema  = [];
+var inserts = [];
+
+tests.forEach(function(test, index) {
+  var escaped = test.insertRaw || connection.escape(test.insert);
+
+  test.columnName = test.type + '_' + index;
+
+  schema.push('`' + test.columnName + '` ' + test.type + ',');
+  inserts.push('`' + test.columnName + '` = ' + escaped);
+});
+
+var createTable = [
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,'
+  ].concat(schema).concat([
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+]).join('\n');
+
+connection.query(createTable);
+
+connection.query('INSERT INTO ' + table + ' SET' + inserts.join(',\n'));
+
+var row;
+connection.execute('SELECT * FROM ' + table + ' WHERE id = ?;', [1], function(err, rows) {
+  if (err) throw err;
+
+  row = rows[0];
+  connection.end();
+});
+
+process.on('exit', function() {
+  tests.forEach(function(test) {
+    var expected = test.expect || test.insert;
+    var got      = row[test.columnName];
+    var message;
+
+    if (expected instanceof Date) {
+      assert.equal(got instanceof Date, true, test.type);
+
+      expected = String(expected);
+      got      = String(got);
+    } else if (Buffer.isBuffer(expected)) {
+      assert.equal(Buffer.isBuffer(got), true, test.type);
+
+      expected = String(Array.prototype.slice.call(expected));
+      got      = String(Array.prototype.slice.call(got));
+    }
+
+    if (test.deep) {
+      message = 'got: "' + JSON.stringify(got) + '" expected: "' + JSON.stringify(expected) +
+                '" test: ' + test.type + '';
+      assert.deepEqual(expected, got, message);
+    } else {
+      message = 'got: "' + got + '" (' + (typeof got) + ') expected: "' + expected +
+                '" (' + (typeof expected) + ') test: ' + test.type + '';
+      assert.strictEqual(expected, got, message);
+    }
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint-big-number-strings.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint-big-number-strings.js
new file mode 100644
index 0000000000000000000000000000000000000000..82eccaea7c32f3e588a6002c729e8554bf0c3575
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint-big-number-strings.js
@@ -0,0 +1,42 @@
+var common     = require('../../common');
+var connection = common.createConnection({ supportBigNumbers: true, bigNumberStrings: true });
+var assert     = require('assert');
+
+connection.query([
+  'CREATE TEMPORARY TABLE `bigs` (',
+  '`id` bigint NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+connection.query("INSERT INTO bigs SET title='test', id=123");
+connection.query("INSERT INTO bigs SET title='test1'", function(err, result) {
+  if (err) throw err;
+  assert.strictEqual(result.insertId, 124);
+  // > 24 bits
+  connection.query("INSERT INTO bigs SET title='test', id=123456789");
+  connection.query("INSERT INTO bigs SET title='test2'", function(err, result) {
+    assert.strictEqual(result.insertId, 123456790);
+    // big int
+    connection.query("INSERT INTO bigs SET title='test', id=9007199254740992");
+    connection.query("INSERT INTO bigs SET title='test3'", function(err, result) {
+      assert.strictEqual(result.insertId, "9007199254740993");
+      connection.query("INSERT INTO bigs SET title='test', id=90071992547409924");
+      connection.query("INSERT INTO bigs SET title='test4'", function(err, result) {
+        assert.strictEqual(result.insertId, "90071992547409925");
+        connection.query("select * from bigs", function(err, result) {
+          assert.strictEqual(result[0].id, "123");
+          assert.strictEqual(result[1].id, "124");
+          assert.strictEqual(result[2].id, "123456789");
+          assert.strictEqual(result[3].id, "123456790");
+          assert.strictEqual(result[4].id, "9007199254740992");
+          assert.strictEqual(result[5].id, "9007199254740993");
+          assert.strictEqual(result[6].id, "90071992547409924");
+          assert.strictEqual(result[7].id, "90071992547409925");
+          connection.end();
+        });
+      });
+    });
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0175800b1a0996a2a3d6ef852c2e949a30ccad8
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-bigint.js
@@ -0,0 +1,45 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+var bn         = require('bn.js');
+
+var table = 'insert_test';
+connection.query([
+  'CREATE TEMPORARY TABLE `bigs` (',
+  '`id` bigint NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+var result, result2;
+connection.query("INSERT INTO bigs SET title='test', id=123");
+connection.query("INSERT INTO bigs SET title='test1'", function(err, result) {
+  if (err) throw err;
+  assert.strictEqual(result.insertId, 124);
+  // > 24 bits
+  connection.query("INSERT INTO bigs SET title='test', id=123456789");
+  connection.query("INSERT INTO bigs SET title='test2'", function(err, result) {
+    assert.strictEqual(result.insertId, 123456790);
+    // big int
+    connection.query("INSERT INTO bigs SET title='test', id=9007199254740992");
+    connection.query("INSERT INTO bigs SET title='test3'", function(err, result) {
+      assert.strictEqual((new bn("9007199254740993")).cmp(result.insertId), 0);
+      connection.query("INSERT INTO bigs SET title='test', id=90071992547409924");
+      connection.query("INSERT INTO bigs SET title='test4'", function(err, result) {
+        assert.strictEqual((new bn("90071992547409925")).cmp(result.insertId), 0);
+        connection.query("select * from bigs", function(err, result) {
+          assert.strictEqual(result[0].id, 123);
+          assert.strictEqual(result[1].id, 124);
+          assert.strictEqual(result[2].id, 123456789);
+          assert.strictEqual(result[3].id, 123456790);
+          assert.strictEqual(result[4].id, 9007199254740992);
+          assert.strictEqual(result[5].id, "9007199254740993");
+          assert.strictEqual(result[6].id, "90071992547409924");
+          assert.strictEqual(result[7].id, "90071992547409925");
+          connection.end();
+        });
+      });
+    });
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-results.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-results.js
new file mode 100644
index 0000000000000000000000000000000000000000..4fa7fe21a76ec883a650ced0b3537ad62c97a413
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-insert-results.js
@@ -0,0 +1,34 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+//common.useTestDb(connection);
+
+var table = 'insert_test';
+//var text = "本日は晴天なり";
+var text = " test test test ";
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+var result, result2;
+connection.query('INSERT INTO ' + table + ' SET title="' + text + '"', function(err, _result) {
+  if (err) throw err;
+  result = _result;
+  connection.query('SELECT * FROM ' + table + ' WHERE id = ' + result.insertId, function(err, _result2) {
+    result2 = _result2;
+    connection.end();
+  });
+});
+
+process.on('exit', function() {
+  assert.strictEqual(result.insertId, 1);
+  assert.strictEqual(result2.length, 1);
+  // TODO: type conversions
+  assert.equal(result2[0].id, String(result.insertId));
+  assert.equal(result2[0].title, text);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-invalid-date-result.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-invalid-date-result.js
new file mode 100644
index 0000000000000000000000000000000000000000..e22630aa9c309a10fed72e614bfa6687720fa192
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-invalid-date-result.js
@@ -0,0 +1,20 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+
+connection.execute('SELECT TIMESTAMP(0000-00-00) t', [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  connection.end();
+});
+
+function isInvalidTime(t) {
+  return isNaN(t.getTime());
+}
+
+process.on('exit', function() {
+  assert.deepEqual(Object.prototype.toString.call(rows[0].t), "[object Date]");
+  assert.deepEqual(isInvalidTime(rows[0].t), true);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-load-infile.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-load-infile.js
new file mode 100644
index 0000000000000000000000000000000000000000..e33c04d84a52cacefbcd3c19a595695d19910b5f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-load-infile.js
@@ -0,0 +1,73 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var table = 'load_data_test';
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+var path = './test/fixtures/data.csv';
+var sql =
+  'LOAD DATA LOCAL INFILE ? INTO TABLE ' + table + ' ' +
+  'FIELDS TERMINATED BY ? (id, title)';
+
+var ok;
+connection.query(sql, [path, ','], function(err, _ok) {
+  if (err) throw err;
+  ok = _ok;
+});
+
+var rows;
+connection.query('SELECT * FROM ' + table, function(err, _rows) {
+  if (err) throw err;
+  rows = _rows;
+});
+
+// Try to load a file that does not exist to see if we handle this properly
+var loadErr;
+var loadResult;
+var badPath = '/does_not_exist.csv';
+
+connection.query(sql, [badPath, ','], function(err, result) {
+  loadErr    = err;
+  loadResult = result;
+});
+
+// test path mapping
+var Stream = require('readable-stream').PassThrough;
+var myStream = new Stream();
+
+var createMyStream = function(path) { return myStream; };
+var streamResult;
+connection.query({
+    sql: sql,
+    values: [badPath, ','],
+    infileStreamFactory: createMyStream
+  }, function(err, result) {
+    if (err) throw err;
+    streamResult = result;
+  }
+);
+myStream.write('11,Hello World\n');
+myStream.write('21,One ');
+myStream.write('more row\n');
+myStream.end();
+
+connection.end();
+
+process.on('exit', function() {
+  assert.equal(ok.affectedRows, 4);
+  assert.equal(rows.length, 4);
+  assert.equal(rows[0].id, 1);
+  assert.equal(rows[0].title, 'Hello World');
+
+  assert.equal(loadErr.code, 'ENOENT');
+  assert.equal(loadResult.affectedRows, 0);
+
+  assert.equal(streamResult.affectedRows, 2);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-multiple-results.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-multiple-results.js
new file mode 100644
index 0000000000000000000000000000000000000000..491f349cc54cdd8a56c433e39d8e72a0386f841f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-multiple-results.js
@@ -0,0 +1,153 @@
+var mysql = require('../../common.js').createConnection({multipleStatements: true});
+var assert = require('assert');
+mysql.query('CREATE TEMPORARY TABLE no_rows (test int)');
+mysql.query('CREATE TEMPORARY TABLE some_rows (test int)');
+mysql.query('INSERT INTO some_rows values(0)');
+mysql.query('INSERT INTO some_rows values(42)');
+mysql.query('INSERT INTO some_rows values(314149)');
+
+var clone = function(obj) { return JSON.parse(JSON.stringify(obj)); };
+
+var rs1 = {
+  affectedRows: 0,
+  fieldCount: 0,
+  insertId: 0,
+  serverStatus: 10,
+  warningStatus: 0
+};
+var rs2 = clone(rs1);
+rs2.serverStatus = 2;
+
+var twoInsertResult = [[rs1, rs2], [undefined, undefined], 2];
+var select1 = [{"1":"1"}];
+var select2 = [{"2":"2"}];
+var fields1 = [{
+  catalog: "def",
+  characterSet: 63,
+  columnLength: 1,
+  columnType: 8,
+  decimals: 0,
+  flags: 129,
+  name: "1",
+  orgName: "",
+  orgTable: "",
+  schema: "",
+  table: ""
+}];
+var nr_fields = [{
+  catalog: "def",
+  characterSet: 63,
+  columnLength: 11,
+  columnType: 3,
+  decimals: 0,
+  flags: 0,
+  name: "test",
+  orgName: "test",
+  orgTable: "no_rows",
+  schema: mysql.config.database,
+  table: "no_rows"
+}];
+var sr_fields = clone(nr_fields);
+sr_fields[0].orgTable = "some_rows";
+sr_fields[0].table = "some_rows";
+var select3 = [{"test":0},{"test":42},{"test":314149}];
+
+var fields2 = clone(fields1);
+fields2[0].name = "2";
+
+var tests = [
+  ["select * from some_rows", [select3,sr_fields,1]], //  select 3 rows
+  ["SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT; SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;", twoInsertResult],
+  ["/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;", twoInsertResult], // issue #26
+  ["set @a = 1", [rs2, undefined, 1]],  // one insert result
+  ["set @a = 1; set @b = 2", twoInsertResult],
+  ["select 1; select 2", [[select1,select2],[fields1,fields2], 2]],
+  ["set @a = 1; select 1", [[rs1, select1], [undefined, fields1], 2]],
+  ["select 1; set @a = 1", [[select1, rs2], [fields1, undefined], 2]],
+  ["select * from no_rows", [[], nr_fields, 1]],    // select 0 rows"
+  ["set @a = 1; select * from no_rows", [[rs1, []], [undefined, nr_fields], 2]], // insert + select 0 rows
+  ["select * from no_rows; set @a = 1", [[[], rs2], [nr_fields, undefined], 2]], //  select 0 rows + insert
+  ["set @a = 1; select * from some_rows", [[rs1, select3],[undefined,sr_fields],2]], // insert + select 3 rows
+  ["select * from some_rows; set @a = 1", [[select3,rs2],[sr_fields,undefined],2]] //  select 3 rows + insert
+];
+
+// TODO: tests with error in the query with different index
+// TODO: multiple results from single query
+
+function do_test(testIndex) {
+  var entry = tests[testIndex];
+  var sql = entry[0];
+  var expectation = entry[1];
+  mysql.query(sql, function(err, _rows, _columns) {
+    var _numResults = 0;
+    if (_rows.constructor.name == 'ResultSetHeader')
+      _numResults = 1;
+    else if (_rows.length === 0) {
+      // empty select
+      _numResults = 1;
+    }
+    else if (_rows.length > 0) {
+      if (_rows.constructor.name == 'Array' && _rows[0].constructor.name == 'TextRow')
+        _numResults = 1;
+      if (_rows.constructor.name == 'Array' &&
+        (_rows[0].constructor.name == 'Array' || _rows[0].constructor.name =='ResultSetHeader'))
+        _numResults = _rows.length
+    }
+    if (err) {
+      console.log(err);
+      process.exit(-1);
+    }
+    var arrOrColumn = function (c) {
+      if (Array.isArray(c))
+        return c.map(arrOrColumn);
+
+      if (typeof c == 'undefined')
+        return void(0);
+
+      return c.inspect();
+    };
+    assert.deepEqual(expectation, [_rows, arrOrColumn(_columns), _numResults]);
+
+    var q = mysql.query(sql);
+    var resIndex = 0;
+    var rowIndex = 0;
+    function checkRow(row, index) {
+      if (_numResults == 1) {
+        assert.equal(index, 0);
+        if (row.constructor.name == 'ResultSetHeader')
+          assert.deepEqual(_rows, row);
+        else
+          assert.deepEqual(_rows[rowIndex], row);
+      } else {
+        if (resIndex != index) {
+          rowIndex = 0;
+          resIndex = index;
+        }
+        if (row.constructor.name == 'ResultSetHeader')
+          assert.deepEqual(_rows[index], row);
+        else
+          assert.deepEqual(_rows[index][rowIndex], row);
+      }
+      rowIndex++;
+    }
+    function checkFields(fields, index) {
+      if (_numResults == 1) {
+       assert.equal(index, 0);
+       debugger
+       assert.deepEqual(arrOrColumn(_columns), arrOrColumn(fields));
+      }
+      else
+        assert.deepEqual(arrOrColumn(_columns[index]), arrOrColumn(fields));
+    }
+    q.on('result', checkRow);
+    q.on('fields', checkFields);
+    q.on('end', function() {
+      if (testIndex + 1 < tests.length)
+        do_test(testIndex + 1);
+      else {
+        mysql.end();
+      }
+    });
+  });
+}
+do_test(0);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-named-paceholders.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-named-paceholders.js
new file mode 100644
index 0000000000000000000000000000000000000000..492f8a7702693179b07b51f4e7ac2574b587a659
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-named-paceholders.js
@@ -0,0 +1,48 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+
+connection.query([
+  'CREATE TEMPORARY TABLE `test_table` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`num1` int(15),',
+  '`num2` int(15),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+connection.query('insert into test_table(num1,num2) values(?, 3)', [1]);
+connection.query('insert into test_table(num1,num2) values(3-?, -10)', [5]);
+connection.query('insert into test_table(num1,num2) values(4+?, 4000000-?)', [-5, 8000000]);
+connection.query('insert into test_table(num1,num2) values(?, ?)', [-5, 8000000]);
+
+connection.config.namedPlaceholders = true;
+var cmd = connection.execute('SELECT * from test_table where num1 < :numParam and num2 > :lParam', {lParam: 100, numParam: 2}, function(err, rows, fields) {
+  if (err) throw err;
+  assert.deepEqual(rows, [ { id: 4, num1: -5, num2: 8000000 } ]);
+});
+assert.equal(cmd.sql, 'SELECT * from test_table where num1 < ? and num2 > ?');
+assert.deepEqual(cmd.values, [2, 100]);
+
+connection.execute('SELECT :a + :a as sum', {a: 2}, function(err, rows, fields) {
+  if (err) throw err;
+  assert.deepEqual(rows, [{"sum":4}]);
+});
+
+var qCmd = connection.query('SELECT * from test_table where num1 < :numParam and num2 > :lParam', {lParam: 100, numParam: 2}, function(err, rows, fields) {
+  if (err) throw err;
+  assert.deepEqual(rows, [ { id: 4, num1: -5, num2: 8000000 } ]);
+});
+assert.equal(qCmd.sql, 'SELECT * from test_table where num1 < 2 and num2 > 100');
+assert.equal(typeof qCmd.values, 'undefined');
+
+connection.query('SELECT :a + :a as sum', {a: 2}, function(err, rows, fields) {
+  if (err) throw err;
+  assert.deepEqual(rows, [{"sum":4}]);
+});
+
+var sql = connection.format('SELECT * from test_table where num1 < :numParam and num2 > :lParam', {lParam: 100, numParam: 2});
+assert.equal(sql, 'SELECT * from test_table where num1 < 2 and num2 > 100');
+
+connection.end();
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-nested-tables-query.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-nested-tables-query.js
new file mode 100644
index 0000000000000000000000000000000000000000..b7e88f4e3d984e044104879dbac1bfc9a93cdd3e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-nested-tables-query.js
@@ -0,0 +1,84 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var table = 'nested_test';
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255),',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+connection.query('INSERT INTO ' + table + ' SET ?', {title: 'test'});
+
+var options1 = {
+  nestTables: true,
+  sql: 'SELECT * FROM ' + table
+};
+var options2 = {
+  nestTables: '_',
+  sql: 'SELECT * FROM ' + table
+};
+var options3 = {
+  rowsAsArray: true,
+  sql: 'SELECT * FROM ' + table
+};
+var rows1, rows2, rows3, rows1e, rows2e, rows3e;
+
+connection.query(options1, function(err, _rows) {
+  if (err) throw err;
+
+  rows1 = _rows;
+});
+
+connection.query(options2, function(err, _rows) {
+  if (err) throw err;
+
+  rows2 = _rows;
+});
+
+connection.query(options3, function(err, _rows) {
+  if (err) throw err;
+
+  rows3 = _rows;
+});
+
+connection.execute(options1, function(err, _rows) {
+  if (err) throw err;
+
+  rows1e = _rows;
+});
+
+connection.execute(options2, function(err, _rows) {
+  if (err) throw err;
+
+  rows2e = _rows;
+});
+
+connection.execute(options3, function(err, _rows) {
+  if (err) throw err;
+
+  rows3e = _rows;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.equal(rows1.length, 1);
+  assert.equal(rows1[0].nested_test.id, 1);
+  assert.equal(rows1[0].nested_test.title, 'test');
+  assert.equal(rows2.length, 1);
+  assert.equal(rows2[0].nested_test_id, 1);
+  assert.equal(rows2[0].nested_test_title, 'test');
+
+  assert.equal(Array.isArray(rows3[0]), true);
+  assert.equal(rows3[0][0], 1);
+  assert.equal(rows3[0][1], 'test');
+
+  assert.deepEqual(rows1, rows1e);
+  assert.deepEqual(rows2, rows2e);
+  assert.deepEqual(rows3, rows3e);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-double.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-double.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1df45f36fa648371b1265ec39edba13c6c44ec3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-double.js
@@ -0,0 +1,21 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows;
+
+connection.query('CREATE TEMPORARY TABLE t (i int)');
+connection.query('INSERT INTO t VALUES(null)');
+connection.query('INSERT INTO t VALUES(123)');
+
+connection.query('SELECT * from t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows[0], {i: null});
+  assert.deepEqual(rows[1], {i: 123});
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-int.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-int.js
new file mode 100644
index 0000000000000000000000000000000000000000..da6c2e6395c5c893588f0e8ae3a267a53f66df19
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null-int.js
@@ -0,0 +1,20 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows;
+
+connection.query('CREATE TEMPORARY TABLE t (i int)');
+connection.query('INSERT INTO t VALUES(null)');
+connection.query('INSERT INTO t VALUES(123)');
+
+connection.query('SELECT * from t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows[0], {i: null});
+  assert.deepEqual(rows[1], {i: 123});
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null.js
new file mode 100644
index 0000000000000000000000000000000000000000..302a0313f3cfc3bc93faf6ed49be87bb4f0de10b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-null.js
@@ -0,0 +1,27 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows, rows1;
+var fields, fields1;
+
+connection.query('CREATE TEMPORARY TABLE t (i int)');
+connection.query('INSERT INTO t VALUES(null)');
+connection.query('SELECT cast(NULL AS CHAR)', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+});
+connection.query('SELECT * from t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+  fields1 = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{'cast(NULL AS CHAR)': null}]);
+  assert.equal(fields[0].columnType, 253);
+  assert.deepEqual(rows1, [{'i': null}]);
+  assert.equal(fields1[0].columnType, 3);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-and-close.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-and-close.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1ded761afa81a023f0acc338a4fc7b876f6736b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-and-close.js
@@ -0,0 +1,26 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var max = 500;
+var start = process.hrtime();
+function prepare(i) {
+  connection.prepare('select 1+' + i, function(err, stmt) {
+    stmt.close();
+    if (!err) {
+      if (i > max) {
+        var end = process.hrtime(start);
+        var ns = end[0]*1e9+end[1];
+        console.log(max*1e9/ns + ' prepares/sec');
+        return connection.end();
+      }
+      setTimeout(function() {prepare(i+1)}, 2);
+      return;
+    }
+    assert(0, 'Error in prepare!');
+  });
+}
+connection.query('SET GLOBAL max_prepared_stmt_count=10', function(err) {
+  if (err) throw err;
+  prepare(1);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-simple.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-simple.js
new file mode 100644
index 0000000000000000000000000000000000000000..c004a4a0287eec49da8506be3e2f2b6292ff5a11
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-simple.js
@@ -0,0 +1,29 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var _stmt1, _stmt2, _stmt3;
+var query1 = 'select 1 + ? + ? as test';
+var query2 = 'select 1 + 1';  // no parameters
+var query3 = 'create temporary table aaa(i int);' // no parameters, no result columns
+
+connection.prepare(query1, function(err1, stmt1) {
+  _stmt1 = stmt1;
+  _stmt1.close();
+  connection.prepare(query2, function(err2, stmt2) {
+    _stmt2 = stmt2;
+    connection.prepare(query3, function(err3, stmt3) {
+      _stmt3 = stmt3;
+      _stmt2.close();
+      _stmt3.close()
+      connection.end();
+    });
+  });
+});
+
+process.on('exit', function() {
+  assert.equal(_stmt1.query, query1);
+  assert(_stmt1.id >= 0);
+  assert.equal(_stmt1.columns.length, 1);
+  assert.equal(_stmt1.parameters.length, 2);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-then-execute.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-then-execute.js
new file mode 100644
index 0000000000000000000000000000000000000000..e6ed9b07425d0949ea0d8627f004392716f5f266
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-prepare-then-execute.js
@@ -0,0 +1,26 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var _stmt    = null;
+var _columns = null;
+var _rows    = null;
+
+connection.prepare('select 1 + ? + ? as test', function(err, stmt) {
+  if (err) throw err;
+  _stmt = stmt;
+  stmt.execute([111, 123], function(err, rows, columns) {
+    if (err) throw err;
+    _columns = columns;
+    _rows = rows;
+    connection.end();
+  });
+});
+
+
+process.on('exit', function() {
+  assert.equal(_stmt.columns.length, 1);
+  assert.equal(_stmt.parameters.length, 2);
+  assert.deepEqual(_rows, [ { test: 235 } ]);
+  assert.equal(_columns[0].name, 'test');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-protocol-errors.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-protocol-errors.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ebcd97d5971cf9315ef18b321a7a2105640c8b8
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-protocol-errors.js
@@ -0,0 +1,43 @@
+var assert     = require('assert');
+var common     = require('../../common');
+var server       = common.createServer(serverReady, function(conn) {
+  conn.on('query', function(q) {
+    conn.writeTextResult([ { '1': '1' } ], [ { catalog: 'def',
+     schema: '',
+     table: '',
+     orgTable: '',
+     name: '1',
+     orgName: '',
+     characterSet: 63,
+     columnLength: 1,
+     columnType: 8,
+     flags: 129,
+     decimals: 0 } ]);
+    // this is extra (incorrect) packet - client should emit error on receiving it
+    conn.writeOk();
+  });
+});
+
+var fields, error;
+var query = 'SELECT 1';
+function serverReady() {
+  var connection = common.createConnection({ port: 3307 });
+  connection.query(query, function(err, _rows, _fields) {
+    if (err) throw err;
+    rows = _rows;
+    fields = _fields;
+  });
+
+  connection.on('error', function(err) {
+    error = err;
+    server.close();
+  });
+}
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{1: 1}]);
+  assert.equal(fields[0].name, '1');
+  assert.equal(error.message, 'Unexpected packet while no commands in the queue');
+  assert.equal(error.fatal, true);
+  assert.equal(error.code, 'PROTOCOL_UNEXPECTED_PACKET');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-quit.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-quit.js
new file mode 100644
index 0000000000000000000000000000000000000000..5784403da7cd3d6b8e6091a1b7d54a96bd764518
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-quit.js
@@ -0,0 +1,48 @@
+var assert     = require('assert');
+var common     = require('../../common');
+var quitReceived = false;
+var queryCli     = 'SELECT 1';
+var server       = common.createServer(serverReady, function(conn) {
+  conn.on('quit', function() {
+    // COM_QUIT
+    quitReceived = true;
+    conn.stream.end();
+    server.close();
+    console.log('quit!!!');
+  });
+
+  conn.on('query', function(q) {
+    queryServ =  q;
+    conn.writeTextResult([ { '1': '1' } ], [ { catalog: 'def',
+     schema: '',
+     table: '',
+     orgTable: '',
+     name: '1',
+     orgName: '',
+     characterSet: 63,
+     columnLength: 1,
+     columnType: 8,
+     flags: 129,
+     decimals: 0 } ]);
+  });
+});
+
+function serverReady() {
+  var connection = common.createConnection({ port: 3307 });
+
+  connection.query(queryCli, function(err, _rows, _fields) {
+    if (err) throw err;
+    rows = _rows;
+    fields = _fields;
+
+    connection.end();
+  });
+}
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{1: 1}]);
+  assert.equal(fields[0].name, '1');
+  assert.equal(quitReceived, true);
+  assert.equal(queryCli, queryServ);
+
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-1.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-1.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab8c2c5512b526b7f47de38bcea18624571f3d46
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-1.js
@@ -0,0 +1,18 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var fields = undefined;
+connection.query('SELECT 1', function(err, _rows, _fields) {
+  if (err) throw err;
+
+  rows = _rows;
+  fields = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{1: 1}]);
+  assert.equal(fields[0].name, '1');
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-empty-string.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-empty-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..b3be6a3c1d3dc2d1c24628e8ed268f6e506065cc
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-empty-string.js
@@ -0,0 +1,15 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows;
+connection.query('SELECT ""', function(err, _rows) {
+  if (err) throw err;
+
+  rows = _rows;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{'': ''}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-negative.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-negative.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b66aa8436a6180d4b8cc1c111bdcb60326c1e8e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-negative.js
@@ -0,0 +1,26 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var rows1 = undefined;
+var fields = undefined;
+var fields1 = undefined;
+
+connection.execute('SELECT -1 v', [], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+});
+
+connection.query('SELECT -1 v', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+  fields1 = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{v: -1}]);
+  assert.deepEqual(rows1, [{v: -1}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8.js
new file mode 100644
index 0000000000000000000000000000000000000000..c81cac67b3357eaa9d2edbefed3364f4ce411925
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8.js
@@ -0,0 +1,19 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+var fields = undefined;
+var multibyteText = '本日は晴天なり';
+connection.query("SELECT '" + multibyteText + "'", function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.equal(rows[0][multibyteText], multibyteText);
+  assert.equal(fields[0].name, multibyteText);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8mb4.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8mb4.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ad55d0a1953093615178318f431d4b19948fcf6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-select-utf8mb4.js
@@ -0,0 +1,18 @@
+var common     = require('../../common');
+var connection = common.createConnection({charset: 'UTF8MB4_GENERAL_CI'});
+var assert     = require('assert');
+
+var rows = undefined;
+var fields = undefined;
+var multibyteText = '𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕 𠴕 𠵼 𠵿 𠸎 𠸏 𠹷 𠺝 𠺢 ';
+connection.query("SELECT '" + multibyteText + "'", function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.equal(rows[0][multibyteText], multibyteText);
+  assert.equal(fields[0].name, multibyteText);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-server-listen.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-server-listen.js
new file mode 100644
index 0000000000000000000000000000000000000000..3dbe2993423fa40beacab216e154b7f9898a36a6
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-server-listen.js
@@ -0,0 +1,35 @@
+var assert = require('assert');
+var mysql = require('../../../index.js')
+
+// Verifies that the Server.listen can be called with any combination of
+// pararameters valid for net.Server.listen.
+
+var server = mysql.createServer();
+var serverListenCallbackFired = false;
+
+function testListen(argsDescription, listenCaller) {
+  var server = mysql.createServer();
+  var listenCallbackFired = false;
+
+  listenCaller(server, function() {
+    listenCallbackFired = true;
+  });
+  setTimeout(function() {
+    assert.ok(
+      listenCallbackFired,
+      'Callback for call with ' + argsDescription + ' did not fire');
+    server._server.close();
+  }, 100);
+}
+
+testListen('port', function(server, callback) {
+  server.listen(0, callback);
+});
+
+testListen('port, host', function(server, callback) {
+  server.listen(0, '127.0.0.1', callback);
+});
+
+testListen('port, host, backlog', function(server, callback) {
+  server.listen(0, '127.0.0.1', 50, callback);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-signed-tinyint.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-signed-tinyint.js
new file mode 100644
index 0000000000000000000000000000000000000000..e0d93ea54ba3e36da4a0f61b6b7edac9505ce787
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-signed-tinyint.js
@@ -0,0 +1,20 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows = undefined;
+
+connection.query('CREATE TEMPORARY TABLE signed_ints  (b11 tinyint NOT NULL, b12 tinyint NOT NULL, b21 smallint NOT NULL)');
+connection.query('INSERT INTO signed_ints values (-3, -120, 500)');
+connection.query('INSERT INTO signed_ints values (3,  -110, -500)');
+
+connection.execute('SELECT * from signed_ints', [5], function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.deepEqual(rows, [{"b11":-3,"b12":-120,"b21":500},{"b11":3,"b12":-110,"b21":-500}]);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-stream.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-stream.js
new file mode 100644
index 0000000000000000000000000000000000000000..9452d01a884a053d0ef531b5708703a62de9871b
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-stream.js
@@ -0,0 +1,47 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+var rows;
+var rows1 = [];
+var rows2 = [];
+
+connection.query([
+  'CREATE TEMPORARY TABLE `announcements` (',
+  '`id` int(11) NOT NULL AUTO_INCREMENT,',
+  '`title` varchar(255) DEFAULT NULL,',
+  '`text` varchar(255) DEFAULT NULL,',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'), function(err) {
+  if (err) throw err;
+});
+
+connection.execute('INSERT INTO announcements(title, text) VALUES(?, ?)', ['Есть место, где заканчивается тротуар', 'Расти борода, расти'], function(err) {
+  if (err) throw err;
+});
+connection.execute('INSERT INTO announcements(title, text) VALUES(?, ?)', ['Граждане Российской Федерации имеют право собираться мирно без оружия', 'проводить собрания, митинги и демонстрации, шествия и пикетирование'], function(err) {
+  if (err) throw err;
+});
+connection.execute('SELECT * FROM announcements', function(err, _rows, cols) {
+  rows = _rows;
+  var s1 = connection.query('SELECT * FROM announcements').stream();
+  s1.on('data', function(row) {
+    rows1.push(row);
+  });
+  s1.on('end', function() {
+    var s2 = connection.execute('SELECT * FROM announcements').stream();
+    s2.on('data', function(row) {
+      rows2.push(row);
+    });
+    s2.on('end', function() {
+      connection.end();
+    });
+  });
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows.length, 2);
+  assert.deepEqual(rows, rows1);
+  assert.deepEqual(rows, rows2);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-timestamp.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-timestamp.js
new file mode 100644
index 0000000000000000000000000000000000000000..3839ebc35af0d480cc5dfabfe474dd6f31c1b815
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-timestamp.js
@@ -0,0 +1,36 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+connection.query('CREATE TEMPORARY TABLE t (f TIMESTAMP)');
+connection.query('INSERT INTO t VALUES(\'0000-00-00 00:00:00\')');
+connection.query('INSERT INTO t VALUES(\'2013-01-22 01:02:03\')');
+
+var rows, fields;
+var rows1, fields1;
+connection.query('SELECT f FROM t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows = _rows;
+  fields = _fields;
+});
+connection.execute('SELECT f FROM t', function(err, _rows, _fields) {
+  if (err) throw err;
+  rows1 = _rows;
+  fields1 = _fields;
+  connection.end();
+});
+
+process.on('exit', function() {
+  assert.deepEqual(rows[0].f.toString(), 'Invalid Date');
+  assert(rows[0].f instanceof Date);
+  assert(rows[1].f instanceof Date);
+  assert.equal(rows[1].f.getYear(), 113);
+  assert.equal(rows[1].f.getMonth(), 0);
+  assert.equal(rows[1].f.getDate(), 22);
+  assert.equal(rows[1].f.getHours(), 1);
+  assert.equal(rows[1].f.getMinutes(), 2);
+  assert.equal(rows[1].f.getSeconds(), 3);
+  assert.equal(fields[0].name, 'f');
+  assert.deepEqual(rows[1], rows1[1]);
+  assert.deepEqual(fields[0].inspect(), fields1[0].inspect());
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-commit.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-commit.js
new file mode 100644
index 0000000000000000000000000000000000000000..88386a93be366d2bf7d472b5579de0cb4dcbe685
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-commit.js
@@ -0,0 +1,37 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var table = 'transaction_test';
+connection.query([
+                   'CREATE TEMPORARY TABLE `' + table + '` (',
+                   '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+                   '`title` varchar(255),',
+                   'PRIMARY KEY (`id`)',
+                   ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+                 ].join('\n'));
+
+connection.beginTransaction(function (err) {
+  assert.ifError(err);
+  
+  var row = {
+    id: 1,
+    title: 'Test row'
+  };
+
+  connection.query('INSERT INTO ' + table + ' SET ?', row, function(err) {
+    assert.ifError(err);
+
+    connection.commit(function(err) {
+      assert.ifError(err);
+
+      connection.query('SELECT * FROM ' + table, function(err, rows) {
+        assert.ifError(err);
+        connection.end();
+        assert.equal(rows.length, 1);
+      });
+    });
+  });
+});
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-rollback.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-rollback.js
new file mode 100644
index 0000000000000000000000000000000000000000..7cbae390e8ccae43654ed5b29921f092ac4bab9a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-transaction-rollback.js
@@ -0,0 +1,37 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var table = 'transaction_test';
+connection.query([
+                   'CREATE TEMPORARY TABLE `' + table + '` (',
+                   '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+                   '`title` varchar(255),',
+                   'PRIMARY KEY (`id`)',
+                   ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+                 ].join('\n'));
+
+connection.beginTransaction(function (err) {
+  assert.ifError(err);
+  
+  var row = {
+    id: 1,
+    title: 'Test row'
+  };
+
+  connection.query('INSERT INTO ' + table + ' SET ?', row, function(err) {
+    assert.ifError(err);
+
+    connection.rollback(function(err) {
+      assert.ifError(err);
+
+      connection.query('SELECT * FROM ' + table, function(err, rows) {
+        assert.ifError(err);
+        connection.end();
+        assert.equal(rows.length, 0);
+      });
+    });
+  });
+});
\ No newline at end of file
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-cast-null-fields.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-cast-null-fields.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5aa32d9b7f14b1d4f7b832fe43acf8bc7f00b87
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-cast-null-fields.js
@@ -0,0 +1,34 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var table = 'insert_test';
+connection.query([
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
+  '`date` DATETIME NULL,',
+  '`number` INT NULL,',
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+].join('\n'));
+
+connection.query('INSERT INTO ' + table + ' SET ?', {
+  date   : null,
+  number : null,
+});
+
+var results;
+connection.query('SELECT * FROM ' + table, function(err, _results) {
+  if (err) throw err;
+
+  results = _results;
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  assert.strictEqual(results[0].date, null);
+  assert.strictEqual(results[0].number, null);
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-casting.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-casting.js
new file mode 100644
index 0000000000000000000000000000000000000000..bd5c37ee3d7e63af9a88ee848eba530b356e39c0
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/test-type-casting.js
@@ -0,0 +1,72 @@
+var common     = require('../../common');
+var connection = common.createConnection();
+var assert     = require('assert');
+
+common.useTestDb(connection);
+
+var tests = require('./type-casting-tests')(connection);
+
+var table = 'type_casting';
+
+var schema  = [];
+var inserts = [];
+
+tests.forEach(function(test, index) {
+  var escaped = test.insertRaw || connection.escape(test.insert);
+
+  test.columnName = test.type + '_' + index;
+
+  schema.push('`' + test.columnName + '` ' + test.type + ',');
+  inserts.push('`' + test.columnName + '` = ' + escaped);
+});
+
+var createTable = [
+  'CREATE TEMPORARY TABLE `' + table + '` (',
+  '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,'
+  ].concat(schema).concat([
+  'PRIMARY KEY (`id`)',
+  ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+]).join('\n');
+
+connection.query(createTable);
+
+connection.query('INSERT INTO ' + table + ' SET' + inserts.join(',\n'));
+
+var row;
+connection.query('SELECT * FROM type_casting', function(err, rows) {
+  if (err) throw err;
+
+  row = rows[0];
+  connection.end();
+});
+
+
+process.on('exit', function() {
+  tests.forEach(function(test) {
+    var expected = test.expect || test.insert;
+    var got      = row[test.columnName];
+    var message;
+
+    if (expected instanceof Date) {
+      assert.equal(got instanceof Date, true, test.type);
+
+      expected = String(expected);
+      got      = String(got);
+    } else if (Buffer.isBuffer(expected)) {
+      assert.equal(Buffer.isBuffer(got), true, test.type);
+
+      expected = String(Array.prototype.slice.call(expected));
+      got      = String(Array.prototype.slice.call(got));
+    }
+
+    if (test.deep) {
+      message = 'got: "' + JSON.stringify(got) + '" expected: "' + JSON.stringify(expected) +
+                '" test: ' + test.type + '';
+      assert.deepEqual(expected, got, message);
+    } else {
+      message = 'got: "' + got + '" (' + (typeof got) + ') expected: "' + expected +
+                '" (' + (typeof expected) + ') test: ' + test.type + '';
+      assert.strictEqual(expected, got, message);
+    }
+  });
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/type-casting-tests.js b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/type-casting-tests.js
new file mode 100644
index 0000000000000000000000000000000000000000..66f8173153f2bb6d185f774cb086a5562f267b3a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/integration/connection/type-casting-tests.js
@@ -0,0 +1,53 @@
+module.exports = function(connection){
+  return [
+    {type: 'decimal(4,3)', insert: '1.234'},
+//  {type: 'decimal(3,3)', insert: 0.33},
+    {type: 'tinyint', insert: 1},
+    {type: 'smallint', insert: 2},
+    {type: 'int', insert: 3},
+    {type: 'float', insert: 4.5},
+    {type: 'double', insert: 5.5},
+    {type: 'bigint', insert: '6', expect: 6},
+    {type: 'bigint', insert: 6},
+    {type: 'mediumint', insert: 7},
+    {type: 'year', insert: 2012},
+    {type: 'timestamp', insert: new Date('2012-05-12 11:00:23')},
+    {type: 'datetime', insert: new Date('2012-05-12 12:00:23')},
+    {type: 'date', insert: new Date('2012-05-12 00:00:00')},
+    {type: 'time', insert: '13:13:23'},
+    {type: 'time', insert: '-13:13:23'},
+    {type: 'time', insert: '413:13:23'},
+    {type: 'time', insert: '-413:13:23'},
+    {type: 'binary(4)', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'varbinary(4)', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'tinyblob', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'mediumblob', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'longblob', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'blob', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'bit(32)', insert: new Buffer([0, 1, 254, 255])},
+    {type: 'char(5)', insert: 'Hello'},
+    {type: 'varchar(5)', insert: 'Hello'},
+    {type: 'varchar(3) character set utf8 collate utf8_bin', insert: 'bin'},
+    {type: 'tinytext', insert: 'Hello World'},
+    {type: 'mediumtext', insert: 'Hello World'},
+    {type: 'longtext', insert: 'Hello World'},
+    {type: 'text', insert: 'Hello World'},
+    {type: 'point', insertRaw: 'POINT(1.2,-3.4)', expect: {x:1.2, y:-3.4}, deep: true},
+    {type: 'point', insertRaw: (function() {
+        var buffer = new Buffer(21);
+        buffer.writeUInt8(1, 0);
+        buffer.writeUInt32LE(1, 1);
+        buffer.writeDoubleLE(-5.6, 5);
+        buffer.writeDoubleLE(10.23, 13);
+        return 'GeomFromWKB(' + connection.escape(buffer) + ')';
+      })(), expect: {x:-5.6, y:10.23}, deep: true},
+    {type: 'point', insertRaw: '', insert: null, expect: null},
+    {type: 'linestring', insertRaw: 'LINESTRING(POINT(1.2,-3.4),POINT(-5.6,10.23),POINT(0.2,0.7))', expect: [{x:1.2, y:-3.4}, {x:-5.6, y:10.23}, {x:0.2, y:0.7}], deep: true},
+    {type: 'polygon', insertRaw: "GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))')", expect: [[{x:0,y:0},{x:10,y:0},{x:10,y:10},{x:0,y:10},{x:0,y:0}],[{x:5,y:5},{x:7,y:5},{x:7,y:7},{x:5,y:7},{x:5,y:5}]], deep: true},
+    {type: 'geometry', insertRaw: 'POINT(1.2,-3.4)', expect: {x:1.2, y:-3.4}, deep: true},
+    {type: 'multipoint', insertRaw: "GeomFromText('MULTIPOINT(0 0, 20 20, 60 60)')", expect: [{x:0, y:0}, {x:20, y:20}, {x:60, y:60}], deep: true},
+    {type: 'multilinestring', insertRaw: "GeomFromText('MULTILINESTRING((10 10, 20 20), (15 15, 30 15))')", expect: [[{x:10,y:10},{x:20,y:20}],[{x:15,y:15},{x:30,y:15}]], deep: true},
+    {type: 'multipolygon', insertRaw: "GeomFromText('MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))')", expect: [[[{x:0,y:0},{x:10,y:0},{x:10,y:10},{x:0,y:10},{x:0,y:0}]],[[{x:5,y:5},{x:7,y:5},{x:7,y:7},{x:5,y:7},{x:5,y:5}]]], deep: true},
+    {type: 'geometrycollection', insertRaw: "GeomFromText('GEOMETRYCOLLECTION(POINT(11 10), POINT(31 30), LINESTRING(15 15, 20 20))')", expect: [{x:11,y:10},{x:31,y:30},[{x:15,y:15},{x:20,y:20}]], deep: true}
+  ];
+};
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/run.js b/node_modules/mysql2-promise/node_modules/mysql2/test/run.js
new file mode 100644
index 0000000000000000000000000000000000000000..42fdee2cddf8cdf418c00199625dd8163ff46bf2
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/run.js
@@ -0,0 +1,8 @@
+#!/usr/bin/env node
+
+var options = {};
+
+if (process.env.FILTER) {
+    options.include = new RegExp(process.env.FILTER + '.*\\.js$');
+}
+require('urun')(__dirname, options);
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/template.jade b/node_modules/mysql2-promise/node_modules/mysql2/test/template.jade
new file mode 100644
index 0000000000000000000000000000000000000000..a475e514397b76a2465b6af0576cbd806f5e7f95
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/template.jade
@@ -0,0 +1,5 @@
+html
+  body
+    ul#users
+    each record in records
+      li(class='user-' + record.id) #{record.name}
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/unit/packets/test-ok-autoinc.js b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/packets/test-ok-autoinc.js
new file mode 100644
index 0000000000000000000000000000000000000000..e10c59b25b355b8fd4657dfe1cb07f258386afd9
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/packets/test-ok-autoinc.js
@@ -0,0 +1,9 @@
+var assert     = require('assert');
+var packets    = require('../../../lib/packets/index.js');
+
+var packet = packets.OK.toPacket({affectedRows: 0, insertId: 1});
+
+// 5 bytes for an OK packet, plus one byte to store affectedRows plus one byte to store the insertId
+assert.equal( packet.length(), 11,
+    'OK packets with 0 affectedRows and a minimal insertId should be '+
+    '11 bytes long, got '+packet.length()+' byte(s)' );
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/unit/protocol/test-SqlString.js b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/protocol/test-SqlString.js
new file mode 100644
index 0000000000000000000000000000000000000000..dffede32fc66c17e9eb4898091a9c641768de57e
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/protocol/test-SqlString.js
@@ -0,0 +1,175 @@
+var common    = require('../../common');
+var test      = require('utest');
+var assert    = require('assert');
+var SqlString = common.SqlString;
+
+test('SqlString.escapeId', {
+  'value is quoted': function() {
+    assert.equal('`id`', SqlString.escapeId('id'));
+  },
+
+  'value containing escapes is quoted': function() {
+    assert.equal('`i``d`', SqlString.escapeId('i`d'));
+  },
+
+  'value containing separator is quoted': function() {
+    assert.equal('`id1`.`id2`', SqlString.escapeId('id1.id2'));
+  },
+  'value containing separator and escapes is quoted': function() {
+    assert.equal('`id``1`.`i``d2`', SqlString.escapeId('id`1.i`d2'));
+  },
+
+  'arrays are turned into lists': function() {
+    assert.equal(SqlString.escapeId(['a', 'b', 't.c']), "`a`, `b`, `t`.`c`");
+  },
+
+  'nested arrays are flattened': function() {
+    assert.equal(SqlString.escapeId(['a', ['b', ['t.c']]]), "`a`, `b`, `t`.`c`");
+  },
+});
+
+test('SqlString.escape', {
+  'undefined -> NULL': function() {
+    assert.equal(SqlString.escape(undefined), 'NULL');
+  },
+
+  'null -> NULL': function() {
+    assert.equal(SqlString.escape(null), 'NULL');
+  },
+
+  'booleans convert to strings': function() {
+    assert.equal(SqlString.escape(false), 'false');
+    assert.equal(SqlString.escape(true), 'true');
+  },
+
+  'numbers convert to strings': function() {
+    assert.equal(SqlString.escape(5), '5');
+  },
+
+  'objects are turned into key value pairs': function() {
+    assert.equal(SqlString.escape({a: 'b', c: 'd'}), "`a` = 'b', `c` = 'd'");
+  },
+
+  'objects function properties are ignored': function() {
+    assert.equal(SqlString.escape({a: 'b', c: function() {}}), "`a` = 'b'");
+  },
+
+  'nested objects are cast to strings': function() {
+    assert.equal(SqlString.escape({a: {nested: true}}), "`a` = '[object Object]'");
+  },
+
+  'arrays are turned into lists': function() {
+    assert.equal(SqlString.escape([1, 2, 'c']), "1, 2, 'c'");
+  },
+
+  'nested arrays are turned into grouped lists': function() {
+    assert.equal(SqlString.escape([[1,2,3], [4,5,6], ['a', 'b', {nested: true}]]), "(1, 2, 3), (4, 5, 6), ('a', 'b', '[object Object]')");
+  },
+
+  'nested objects inside arrays are cast to strings': function() {
+    assert.equal(SqlString.escape([1, {nested: true}, 2]), "1, '[object Object]', 2");
+  },
+
+  'strings are quoted': function() {
+    assert.equal(SqlString.escape('Super'), "'Super'");
+  },
+
+  '\0 gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\0er'), "'Sup\\0er'");
+  },
+
+  '\b gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\ber'), "'Sup\\ber'");
+  },
+
+  '\n gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\ner'), "'Sup\\ner'");
+  },
+
+  '\r gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\rer'), "'Sup\\rer'");
+  },
+
+  '\t gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\ter'), "'Sup\\ter'");
+  },
+
+  '\\ gets escaped': function() {
+    assert.equal(SqlString.escape('Sup\\er'), "'Sup\\\\er'");
+  },
+
+  '\u001a (ascii 26) gets replaced with \\Z': function() {
+    assert.equal(SqlString.escape('Sup\u001aer'), "'Sup\\Zer'");
+  },
+
+  'single quotes get escaped': function() {
+    assert.equal(SqlString.escape('Sup\'er'), "'Sup\\'er'");
+  },
+
+  'double quotes get escaped': function() {
+    assert.equal(SqlString.escape('Sup"er'), "'Sup\\\"er'");
+  },
+
+  'dates are converted to YYYY-MM-DD HH:II:SS.sss': function() {
+    var expected = '2012-05-07 11:42:03.002';
+    var date     = new Date(2012, 4, 7, 11, 42, 3, 2);
+    var string   = SqlString.escape(date);
+
+    assert.strictEqual(string, "'" + expected + "'");
+  },
+
+  'buffers are converted to hex': function() {
+    var buffer = new Buffer([0, 1, 254, 255]);
+    var string = SqlString.escape(buffer);
+
+    assert.strictEqual(string, "X'0001feff'");
+  },
+
+  'NaN -> NaN': function() {
+    assert.equal(SqlString.escape(NaN), 'NaN');
+  },
+
+  'Infinity -> Infinity': function() {
+    assert.equal(SqlString.escape(Infinity), 'Infinity');
+  }
+});
+
+test('SqlString.format', {
+  'question marks are replaced with escaped array values': function() {
+    var sql = SqlString.format('? and ?', ['a', 'b']);
+    assert.equal(sql, "'a' and 'b'");
+  },
+
+  'extra question marks are left untouched': function() {
+    var sql = SqlString.format('? and ?', ['a']);
+    assert.equal(sql, "'a' and ?");
+  },
+
+  'extra arguments are not used': function() {
+    var sql = SqlString.format('? and ?', ['a', 'b', 'c']);
+    assert.equal(sql, "'a' and 'b'");
+  },
+
+  'question marks within values do not cause issues': function() {
+    var sql = SqlString.format('? and ?', ['hello?', 'b']);
+    assert.equal(sql, "'hello?' and 'b'");
+  },
+
+  'undefined is ignored': function () {
+    var sql = SqlString.format('?', undefined, false)
+    assert.equal(sql, '?')
+  },
+
+  'objects is converted to values': function () {
+    var sql = SqlString.format('?', { 'hello': 'world' }, false)
+    assert.equal(sql, "`hello` = 'world'")
+  },
+
+  'objects is not converted to values': function () {
+    var sql = SqlString.format('?', { 'hello': 'world' }, true)
+    assert.equal(sql, "'[object Object]'")
+
+    var sql = SqlString.format('?', { toString: function () { return 'hello' } }, true)
+    assert.equal(sql, "'hello'")
+  }
+});
diff --git a/node_modules/mysql2-promise/node_modules/mysql2/test/unit/test-packet-parser.js b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/test-packet-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..7e4ad2711ff2dfc5b8ca5bb2a080c8a3586dc511
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/mysql2/test/unit/test-packet-parser.js
@@ -0,0 +1,127 @@
+var PacketParser = require('../../lib/packet_parser.js');
+var Packet       = require('../../lib/packets/packet.js');
+
+var assert = require('assert');
+
+var pp;
+var packets = [];
+function reset() {
+  pp = new PacketParser(handler);
+  packets = [];
+}
+var handler = function(p) {
+  packets.push(p);
+}
+
+function execute(str, verify) {
+  reset();
+  var buffers = str.split('|').map(function(sb) { return sb.split(',').map(Number) });
+  for(var i=0; i < buffers.length; ++i)
+    pp.execute(new Buffer(buffers[i]));
+  verify();
+}
+
+function p123() {
+  assert(packets.length === 1);
+  assert(packets[0].length() === 10);
+  assert(packets[0].sequenceId === 123);
+}
+
+function p120_121() {
+  packets.forEach(function(p) { p.dump });
+  assert(packets.length === 2);
+  assert(packets[0].length() === 0);
+  assert(packets[0].sequenceId === 120);
+  assert(packets[1].length() === 0);
+  assert(packets[1].sequenceId === 121);
+}
+
+execute("10,0,0,123,1,2,3,4,5,6,7,8,9,0", p123);
+execute("10,0,0,123|1,2,3,4,5,6,7,8,9,0", p123);
+execute("10,0,0|123,1,2,3,4,5,6,7,8,9,0", p123);
+execute("10|0,0|123,1,2,3,4,5,6,7,8,9,0", p123);
+execute("10,0,0,123,1|2,3,4,5,6|7,8,9,0", p123);
+execute("10,0,0,123,1,2|,3,4,5,6|7,8,9,0", p123);
+
+function p42() {
+  assert(packets.length === 1);
+  assert(packets[0].length() === 0);
+  assert(packets[0].sequenceId === 42);
+}
+
+execute("0,0,0,42", p42);
+execute("0|0,0,42", p42);
+execute("0,0|0,42", p42);
+execute("0,0|0|42", p42);
+execute("0,0,0|42", p42);
+execute("0|0|0|42", p42);
+execute("0|0,0|42", p42);
+
+// two zero length packets
+execute("0,0,0,120,0,0,0,121", p120_121);
+execute("0,0,0|120|0|0|0|121", p120_121);
+
+var p122_123 = function() {
+  assert(packets.length === 2);
+  assert(packets[0].length() === 5);
+  assert(packets[0].sequenceId === 122);
+  assert(packets[1].length() === 6);
+  assert(packets[1].sequenceId === 123);
+}
+// two non-zero length packets
+execute("5,0,0,122,1,2,3,4,5,6,0,0,123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5|6,0,0,123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4|5|6|0,0,123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6|0,0,123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6,0|0,123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6,0,0|123,1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6,0,0,123|1,2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6,0,0,123,1|2,3,4,5,6", p122_123);
+execute("5,0,0,122,1,2,3,4,5,6,0,0,123,1|2,3|4,5,6", p122_123);
+
+// test packet > 65536 lengt
+// TODO combine with "execute" function
+
+var length = 123000
+var pbuff = new Buffer(length+4);
+pbuff[4] = 123;
+pbuff[5] = 124;
+pbuff[6] = 125;
+var p = new Packet(144, pbuff, 4, pbuff.length - 4);
+p.writeHeader(42);
+
+function testBigPackets(chunks, cb) {
+  var packets = [];
+  var pp = new PacketParser(function(p) {
+    packets.push(p);
+  });
+  chunks.forEach(function(ch) {
+    pp.execute(ch);
+  });
+  cb(packets);
+}
+
+function assert2FullPackets(packets) {
+  function assertPacket(p) {
+    assert.equal(p.length(), length);
+    assert.equal(p.sequenceId, 42);
+    assert.equal(p.readInt8(), 123);
+    assert.equal(p.readInt8(), 124);
+    assert.equal(p.readInt8(), 125);
+  }
+  //assert.equal(packets[0].buffer.slice(0, 8).toString('hex'), expectation);
+  //assert.equal(packets[1].buffer.slice(0, 8).toString('hex'), expectation);
+  assert.equal(packets.length, 2);
+  assertPacket(packets[0]);
+  assertPacket(packets[1]);
+}
+
+// 2 full packets in 2 chunks
+testBigPackets( [ pbuff, pbuff ], assert2FullPackets);
+
+testBigPackets( [ pbuff.slice(0, 120000), pbuff.slice(120000, 123004), pbuff ], assert2FullPackets);
+var frameEnd = 120000
+testBigPackets( [ pbuff.slice(0, frameEnd), Buffer.concat([pbuff.slice(frameEnd, 123004), pbuff]) ], assert2FullPackets);
+for(var frameStart=1; frameStart < 100; frameStart++) {
+  testBigPackets([ Buffer.concat([pbuff, pbuff.slice(0, frameStart)]), pbuff.slice(frameStart, 123004) ], assert2FullPackets);
+}
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/.npmignore b/node_modules/mysql2-promise/node_modules/named-placeholders/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..59ee6765f9ca3cebfa7c0e0258f22512333455c3
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/.npmignore
@@ -0,0 +1,17 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+.DS_Store
+
+tmp
+pids
+logs
+
+node_modules
+npm-debug.log
+
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/.travis.yml b/node_modules/mysql2-promise/node_modules/named-placeholders/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..05d299e676449634733c2040c619a704e735e49a
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - "0.10"
+  - "0.11"
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/LICENSE b/node_modules/mysql2-promise/node_modules/named-placeholders/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..bc0223fcb0c3d588c073cd53c1028778942f9e5f
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Andrey Sidorov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/README.md b/node_modules/mysql2-promise/node_modules/named-placeholders/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..eb2e7a7a2e2c45dfe89e988118a765015418c58c
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/README.md
@@ -0,0 +1,29 @@
+[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=sidorares&url=https://github.com/sidorares/named-placeholders&title=named-placeholders&language=&tags=github&category=software)
+
+[![NPM](https://nodei.co/npm/named-placeholders.png?downloads=true&stars=true)](https://nodei.co/npm/named-placeholders/)
+
+[![Build Status](https://secure.travis-ci.org/sidorares/named-placeholders.png)](http://travis-ci.org/sidorares/named-placeholders)
+
+# named-placeholders
+
+compiles "select foo where foo.id = :bar and foo.baz < :baz" into "select foo where foo.id = ? and foo.baz < ?" + ["bar", "baz"]
+
+## usage
+
+```sh
+npm install named-placeholders
+```
+
+see [this mysql2 discussion](https://github.com/sidorares/node-mysql2/issues/117)
+
+```js
+var mysql = require('mysql');
+var toUnnamed = require('named-placeholders')();
+
+var q = toUnnamed('select 1+:test', { test: 123});
+mysl.createConnection().query(q[0], q[1]);
+```
+
+## credits
+
+parser is based on @mscdex code of his excellent [node-mariasql](https://github.com/mscdex/node-mariasql) library
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/index.js b/node_modules/mysql2-promise/node_modules/named-placeholders/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..912ed058ff901d18b9717f56dde567e77ee787ee
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/index.js
@@ -0,0 +1,110 @@
+// based on code from Brian White @mscdex mariasql library - https://github.com/mscdex/node-mariasql/blob/master/lib/Client.js#L272-L332
+// License: https://github.com/mscdex/node-mariasql/blob/master/LICENSE
+
+var RE_PARAM = /(?:\?)|(?::(\d+|(?:[a-zA-Z][a-zA-Z0-9_]*)))/g,
+    DQUOTE = 34,
+    SQUOTE = 39,
+    BSLASH = 92;
+
+var parse = function(query) {
+  var cqfn;
+  if (this._queryCache && (cqfn = this._queryCache.get(query)))
+    return cqfn;
+
+  var ppos = RE_PARAM.exec(query), curpos = 0, start = 0, end, parts = [],
+      i, chr, inQuote = false, escape = false, qchr, tokens = [], qcnt = 0, fn;
+
+  if (ppos) {
+    do {
+      for (i=curpos,end=ppos.index; i<end; ++i) {
+        chr = query.charCodeAt(i);
+        if (chr === BSLASH)
+          escape = !escape;
+        else {
+          if (escape) {
+            escape = false;
+            continue;
+          }
+          if (inQuote && chr === qchr) {
+            if (query.charCodeAt(i + 1) === qchr) {
+              // quote escaped via "" or ''
+              ++i;
+              continue;
+            }
+            inQuote = false;
+          } else if (chr === DQUOTE || chr === SQUOTE) {
+            inQuote = true;
+            qchr = chr;
+          }
+        }
+      }
+      if (!inQuote) {
+        parts.push(query.substring(start, end));
+        tokens.push(ppos[0].length === 1 ? qcnt++ : ppos[1]);
+        start = end + ppos[0].length;
+      }
+      curpos = end + ppos[0].length;
+    } while (ppos = RE_PARAM.exec(query));
+
+    if (tokens.length) {
+      if (curpos < query.length)
+        parts.push(query.substring(curpos));
+
+      return [parts, tokens];
+    }
+  }
+  return [query];
+};
+
+var EMPTY_LRU_FN = function(key, value) {};
+
+var createCompiler = function(config) {
+  if (!config)
+    config = {};
+  if (!config.placeholder) {
+    config.placeholder = '?';
+  }
+  var ncache = 100;
+  var cache;
+  if (typeof config.cache === 'number')
+    ncache = config.cache;
+  if (typeof config.cache === 'object')
+    cache = config.cache;
+  if (config.cache !== false && !cache) {
+    cache = require('lru-cache')({ max: ncache, dispose: EMPTY_LRU_FN });
+  }
+
+  function toArrayParams(tree, params) {
+    var arr = [];
+    if (tree.length == 1)
+      return [tree[0], []];
+    var tokens = tree[1];
+    for (var i=0; i < tokens.length; ++i)
+      arr.push(params[tokens[i]]);
+    return [tree[0], arr];
+  }
+
+  function join(tree) {
+    if (tree.length == 1)
+      return tree;
+    var unnamed = tree[0].join(config.placeholder);
+    if (tree[0].length == tree[1].length)
+      unnamed += config.placeholder;
+    return [unnamed, tree[1]];
+  }
+
+  var compile = function(query, paramsObj) {
+    var tree;
+    if (cache && (tree = cache.get(query))) {
+      return toArrayParams(tree, paramsObj)
+    }
+    tree = join(parse(query));
+    cache && cache.set(query, tree);
+    return toArrayParams(tree, paramsObj);
+  }
+
+  compile.parse = parse;
+  return compile;
+}
+
+module.exports = createCompiler;
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/package.json b/node_modules/mysql2-promise/node_modules/named-placeholders/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..5de7ca080ce581c894e0fd1c5c119d6cc5ae0afb
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/package.json
@@ -0,0 +1,29 @@
+{
+  "name": "named-placeholders",
+  "version": "0.1.3",
+  "description": "sql named placeholders to unnamed compiler",
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sidorares/named-placeholders"
+  },
+  "keywords": [
+    "sql",
+    "pdo",
+    "named",
+    "placeholders"
+  ],
+  "author": "Andrey Sidorov <sidorares@yandex.com>",
+  "license": "MIT",
+  "devDependencies": {
+    "mocha": "1.21.4",
+    "mocha.md": "0.1.0",
+    "should": "4.0.4"
+  },
+  "dependencies": {
+    "lru-cache": "2.5.0"
+  }
+}
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/test/example.md b/node_modules/mysql2-promise/node_modules/named-placeholders/test/example.md
new file mode 100644
index 0000000000000000000000000000000000000000..9272e33577222d764459e23bbc3d4bd37b033f34
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/test/example.md
@@ -0,0 +1,13 @@
+# given input query with named parameters
+
+it should build corresponding query with `?` placeholders and fill array of parameres from input object
+
+```js
+  var compile = require('..')();
+
+  var query = 'Select users.json,EXISTS(Select 1 from moderators where moderators.id = :id) as is_moderator from users where users.id = :id and users.status = :status and users.complete_status = :complete_status';
+
+  compile(query, {id: 123, status: 'Yes!', complete_status: 'No!'})
+    .should.eql([ 'Select users.json,EXISTS(Select 1 from moderators where moderators.id = ?) as is_moderator from users where users.id = ? and users.status = ? and users.complete_status = ?',
+ [ 123, 123, 'Yes!', 'No!' ] ]);
+```
diff --git a/node_modules/mysql2-promise/node_modules/named-placeholders/test/mocha.opts b/node_modules/mysql2-promise/node_modules/named-placeholders/test/mocha.opts
new file mode 100644
index 0000000000000000000000000000000000000000..d12be27eb16c43f0c1b9f34d7490cccb5d3d3d36
--- /dev/null
+++ b/node_modules/mysql2-promise/node_modules/named-placeholders/test/mocha.opts
@@ -0,0 +1,2 @@
+--require should
+--compilers md:mocha.md
diff --git a/node_modules/mysql2-promise/package.json b/node_modules/mysql2-promise/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2662b48d2b6434cf3ae83977f9c926438eb5bb05
--- /dev/null
+++ b/node_modules/mysql2-promise/package.json
@@ -0,0 +1,44 @@
+{
+  "name": "mysql2-promise",
+  "version": "0.1.4",
+  "description": "Small promises wrapper for mysql2.",
+  "main": "index.js",
+  "scripts": {
+    "test": "jshint index.js && ./node_modules/.bin/mocha test/*.test.js",
+    "release": "npm test && release-it -n -i patch",
+    "release:minor": "npm test && release-it -n -i minor",
+    "release:major": "npm test && release-it -n -i major"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/namshi/node-mysql2-promise"
+  },
+  "keywords": [
+    "mysql2",
+    "promise",
+    "q",
+    "mysql-promise"
+  ],
+  "author": "Hossam Fares <hossam.fares@namshi.com>",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/namshi/node-mysql2-promise/issues"
+  },
+  "dependencies": {
+    "mysql2": "^0.15.7",
+    "q": "^1.3.0"
+  },
+  "devDependencies": {
+    "jshint": "~2.1.10",
+    "mocha": "1.17.1",
+    "release-it": "0.0.9",
+    "should": "3.1.3"
+  },
+  "homepage": "https://github.com/namshi/node-mysql2-promise",
+  "directories": {
+    "test": "test"
+  }
+}
diff --git a/node_modules/mysql2-promise/test/index.test.js b/node_modules/mysql2-promise/test/index.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e3d422854353ef3d4ce7b29d2b99959e8dc33d4
--- /dev/null
+++ b/node_modules/mysql2-promise/test/index.test.js
@@ -0,0 +1,17 @@
+'use strict';
+var db = require('../');
+require('should');
+
+describe('mysql2-promise', function () {
+  it('should return correct instance', function () {
+    var defaultDb = db();
+    var namedDb = db('foo');
+    namedDb.should.equal(db('foo'));
+    namedDb.should.have.property('query').which.is.a.Function;
+    namedDb.should.have.property('execute').which.is.a.Function;
+    defaultDb.should.equal(db());
+    defaultDb.should.not.equal(namedDb);
+    defaultDb.should.have.property('query').which.is.a.Function;
+    defaultDb.should.have.property('execute').which.is.a.Function;
+  });
+});
\ No newline at end of file
diff --git a/node_modules/q/CHANGES.md b/node_modules/q/CHANGES.md
new file mode 100644
index 0000000000000000000000000000000000000000..766fcdc21f88e1a02b8d8ecd780104f10c02271d
--- /dev/null
+++ b/node_modules/q/CHANGES.md
@@ -0,0 +1,800 @@
+
+## 1.5.1
+
+ - Q.any now annotates its error message to clarify that Q.any was involved and
+   includes only the last error emitted. (Ivan Etchart)
+ - Avoid domain.dispose during tests in preparation for Node.js 9. (Anna
+   Henningsen)
+
+## 1.5.0
+
+ - Q.any gives an error message from the last rejected promise
+ - Throw if callback supplied to "finally" is invalid (@grahamrhay)
+ - Long stack trace improvements, can now construct long stack traces
+   across rethrows.
+
+## 1.4.1
+
+ - Address an issue that prevented Q from being used as a `<script>` for
+   Firefox add-ons. Q can now be used in any environment that provides `window`
+   or `self` globals, favoring `window` since add-ons have an an immutable
+   `self` that is distinct from `window`.
+
+## 1.4.0
+
+ - Add `noConflict` support for use in `<script>` (@jahnjw).
+
+## 1.3.0
+
+ - Add tracking for unhandled and handled rejections in Node.js (@benjamingr).
+
+## 1.2.1
+
+ - Fix Node.js environment detection for modern Browserify (@kahnjw).
+
+## 1.2.0
+
+ - Added Q.any(promisesArray) method (@vergara).
+   Returns a promise fulfilled with the value of the first resolved promise in
+   promisesArray. If all promises in promisesArray are rejected, it returns
+   a rejected promise.
+
+## 1.1.2
+
+ - Removed extraneous files from the npm package by using the "files"
+   whitelist in package.json instead of the .npmignore blacklist.
+   (@anton-rudeshko)
+
+## 1.1.1
+
+ - Fix a pair of regressions in bootstrapping, one which precluded
+   WebWorker support, and another that precluded support in
+   ``<script>`` usage outright. #607
+
+## 1.1.0
+
+ - Adds support for enabling long stack traces in node.js by setting
+   environment variable `Q_DEBUG=1`.
+ - Introduces the `tap` method to promises, which will see a value
+   pass through without alteration.
+ - Use instanceof to recognize own promise instances as opposed to
+   thenables.
+ - Construct timeout errors with `code === ETIMEDOUT` (Kornel Lesiński)
+ - More descriminant CommonJS module environment detection.
+ - Dropped continuous integration for Node.js 0.6 and 0.8 because of
+   changes to npm that preclude the use of new `^` version predicate
+   operator in any transitive dependency.
+ - Users can now override `Q.nextTick`.
+
+## 1.0.1
+
+ - Adds support for `Q.Promise`, which implements common usage of the
+   ES6 `Promise` constructor and its methods. `Promise` does not have
+   a valid promise constructor and a proper implementation awaits
+   version 2 of Q.
+ - Removes the console stopgap for a promise inspector. This no longer
+   works with any degree of reliability.
+ - Fixes support for content security policies that forbid eval. Now
+   using the `StopIteration` global to distinguish SpiderMonkey
+   generators from ES6 generators, assuming that they will never
+   coexist.
+
+## 1.0.0
+
+:cake: This is all but a re-release of version 0.9, which has settled
+into a gentle maintenance mode and rightly deserves an official 1.0.
+An ambitious 2.0 release is already around the corner, but 0.9/1.0
+have been distributed far and wide and demand long term support.
+
+ - Q will now attempt to post a debug message in browsers regardless
+   of whether window.Touch is defined. Chrome at least now has this
+   property regardless of whether touch is supported by the underlying
+   hardware.
+ - Remove deprecation warning from `promise.valueOf`. The function is
+   called by the browser in various ways so there is no way to
+   distinguish usage that should be migrated from usage that cannot be
+   altered.
+
+## 0.9.7
+
+ - :warning: `q.min.js` is no longer checked-in.  It is however still
+   created by Grunt and NPM.
+ - Fixes a bug that inhibited `Q.async` with implementations of the new
+   ES6 generators.
+ - Fixes a bug with `nextTick` affecting Safari 6.0.5 the first time a
+   page loads when an `iframe` is involved.
+ - Introduces `passByCopy`, `join`, and `race`.
+ - Shows stack traces or error messages on the console, instead of
+   `Error` objects.
+ - Elimintates wrapper methods for improved performance.
+ - `Q.all` now propagates progress notifications of the form you might
+   expect of ES6 iterations, `{value, index}` where the `value` is the
+   progress notification from the promise at `index`.
+
+## 0.9.6
+
+ - Fixes a bug in recognizing the difference between compatible Q
+   promises, and Q promises from before the implementation of "inspect".
+   The latter are now coerced.
+ - Fixes an infinite asynchronous coercion cycle introduced by former
+   solution, in two independently sufficient ways.  1.) All promises
+   returned by makePromise now implement "inspect", albeit a default
+   that reports that the promise has an "unknown" state.  2.) The
+   implementation of "then/when" is now in "then" instead of "when", so
+   that the responsibility to "coerce" the given promise rests solely in
+   the "when" method and the "then" method may assume that "this" is a
+   promise of the right type.
+ - Refactors `nextTick` to use an unrolled microtask within Q regardless
+   of how new ticks a requested. #316 @rkatic
+
+## 0.9.5
+
+ - Introduces `inspect` for getting the state of a promise as
+   `{state: "fulfilled" | "rejected" | "pending", value | reason}`.
+ - Introduces `allSettled` which produces an array of promises states
+   for the input promises once they have all "settled".  This is in
+   accordance with a discussion on Promises/A+ that "settled" refers to
+   a promise that is "fulfilled" or "rejected".  "resolved" refers to a
+   deferred promise that has been "resolved" to another promise,
+   "sealing its fate" to the fate of the successor promise.
+ - Long stack traces are now off by default.  Set `Q.longStackSupport`
+   to true to enable long stack traces.
+ - Long stack traces can now follow the entire asynchronous history of a
+   promise, not just a single jump.
+ - Introduces `spawn` for an immediately invoked asychronous generator.
+   @jlongster
+ - Support for *experimental* synonyms `mapply`, `mcall`, `nmapply`,
+   `nmcall` for method invocation.
+
+## 0.9.4
+
+ - `isPromise` and `isPromiseAlike` now always returns a boolean
+   (even for falsy values). #284 @lfac-pt
+ - Support for ES6 Generators in `async` #288 @andywingo
+ - Clear duplicate promise rejections from dispatch methods #238 @SLaks
+ - Unhandled rejection API #296 @domenic
+   `stopUnhandledRejectionTracking`, `getUnhandledReasons`,
+   `resetUnhandledRejections`.
+
+## 0.9.3
+
+ - Add the ability to give `Q.timeout`'s errors a custom error message. #270
+   @jgrenon
+ - Fix Q's call-stack busting behavior in Node.js 0.10, by switching from
+   `process.nextTick` to `setImmediate`. #254 #259
+ - Fix Q's behavior when used with the Mocha test runner in the browser, since
+   Mocha introduces a fake `process` global without a `nextTick` property. #267
+ - Fix some, but not all, cases wherein Q would give false positives in its
+   unhandled rejection detection (#252). A fix for other cases (#238) is
+   hopefully coming soon.
+ - Made `Q.promise` throw early if given a non-function.
+
+## 0.9.2
+
+ - Pass through progress notifications when using `timeout`. #229 @omares
+ - Pass through progress notifications when using `delay`.
+ - Fix `nbind` to actually bind the `thisArg`. #232 @davidpadbury
+
+## 0.9.1
+
+ - Made the AMD detection compatible with the RequireJS optimizer's `namespace`
+   option. #225 @terinjokes
+ - Fix side effects from `valueOf`, and thus from `isFulfilled`, `isRejected`,
+   and `isPending`. #226 @benjamn
+
+## 0.9.0
+
+This release removes many layers of deprecated methods and brings Q closer to
+alignment with Mark Miller’s TC39 [strawman][] for concurrency. At the same
+time, it fixes many bugs and adds a few features around error handling. Finally,
+it comes with an updated and comprehensive [API Reference][].
+
+[strawman]: http://wiki.ecmascript.org/doku.php?id=strawman:concurrency
+[API Reference]: https://github.com/kriskowal/q/wiki/API-Reference
+
+### API Cleanup
+
+The following deprecated or undocumented methods have been removed.
+Their replacements are listed here:
+
+<table>
+   <thead>
+      <tr>
+         <th>0.8.x method</th>
+         <th>0.9 replacement</th>
+      </tr>
+   </thead>
+   <tbody>
+      <tr>
+         <td><code>Q.ref</code></td>
+         <td><code>Q</code></td>
+      </tr>
+      <tr>
+         <td><code>call</code>, <code>apply</code>, <code>bind</code> (*)</td>
+         <td><code>fcall</code>/<code>invoke</code>, <code>fapply</code>/<code>post</code>, <code>fbind</code></td>
+      </tr>
+      <tr>
+         <td><code>ncall</code>, <code>napply</code> (*)</td>
+         <td><code>nfcall</code>/<code>ninvoke</code>, <code>nfapply</code>/<code>npost</code></td>
+      </tr>
+      <tr>
+         <td><code>end</code></td>
+         <td><code>done</code></td>
+      </tr>
+      <tr>
+         <td><code>put</code></td>
+         <td><code>set</code></td>
+      </tr>
+      <tr>
+         <td><code>node</code></td>
+         <td><code>nbind</code></td>
+      </tr>
+      <tr>
+         <td><code>nend</code></td>
+         <td><code>nodeify</code></td>
+      </tr>
+      <tr>
+         <td><code>isResolved</code></td>
+         <td><code>isPending</code></td>
+      </tr>
+      <tr>
+         <td><code>deferred.node</code></td>
+         <td><code>deferred.makeNodeResolver</code></td>
+      </tr>
+      <tr>
+         <td><code>Method</code>, <code>sender</code></td>
+         <td><code>dispatcher</code></td>
+      </tr>
+      <tr>
+         <td><code>send</code></td>
+         <td><code>dispatch</code></td>
+      </tr>
+      <tr>
+         <td><code>view</code>, <code>viewInfo</code></td>
+         <td>(none)</td>
+      </tr>
+   </tbody>
+</table>
+
+
+(*) Use of ``thisp`` is discouraged. For calling methods, use ``post`` or
+``invoke``.
+
+### Alignment with the Concurrency Strawman
+
+-   Q now exports a `Q(value)` function, an alias for `resolve`.
+    `Q.call`, `Q.apply`, and `Q.bind` were removed to make room for the
+    same methods on the function prototype.
+-   `invoke` has been aliased to `send` in all its forms.
+-   `post` with no method name acts like `fapply`.
+
+### Error Handling
+
+-   Long stack traces can be turned off by setting `Q.stackJumpLimit` to zero.
+    In the future, this property will be used to fine tune how many stack jumps
+    are retained in long stack traces; for now, anything nonzero is treated as
+    one (since Q only tracks one stack jump at the moment, see #144). #168
+-   In Node.js, if there are unhandled rejections when the process exits, they
+    are output to the console. #115
+
+### Other
+
+-   `delete` and `set` (née `put`) no longer have a fulfillment value.
+-   Q promises are no longer frozen, which
+    [helps with performance](http://code.google.com/p/v8/issues/detail?id=1858).
+-   `thenReject` is now included, as a counterpart to `thenResolve`.
+-   The included browser `nextTick` shim is now faster. #195 @rkatic.
+
+### Bug Fixes
+
+-   Q now works in Internet Explorer 10. #186 @ForbesLindesay
+-   `fbind` no longer hard-binds the returned function's `this` to `undefined`.
+    #202
+-   `Q.reject` no longer leaks memory. #148
+-   `npost` with no arguments now works. #207
+-   `allResolved` now works with non-Q promises ("thenables"). #179
+-   `keys` behavior is now correct even in browsers without native
+    `Object.keys`. #192 @rkatic
+-   `isRejected` and the `exception` property now work correctly if the
+    rejection reason is falsy. #198
+
+### Internals and Advanced
+
+-   The internal interface for a promise now uses
+    `dispatchPromise(resolve, op, operands)` instead of `sendPromise(op,
+    resolve, ...operands)`, which reduces the cases where Q needs to do
+    argument slicing.
+-   The internal protocol uses different operands. "put" is now "set".
+    "del" is now "delete". "view" and "viewInfo" have been removed.
+-   `Q.fulfill` has been added. It is distinct from `Q.resolve` in that
+    it does not pass promises through, nor coerces promises from other
+    systems. The promise becomes the fulfillment value. This is only
+    recommended for use when trying to fulfill a promise with an object that has
+    a `then` function that is at the same time not a promise.
+
+## 0.8.12
+- Treat foreign promises as unresolved in `Q.isFulfilled`; this lets `Q.all`
+  work on arrays containing foreign promises. #154
+- Fix minor incompliances with the [Promises/A+ spec][] and [test suite][]. #157
+  #158
+
+[Promises/A+ spec]: http://promises-aplus.github.com/promises-spec/
+[test suite]: https://github.com/promises-aplus/promises-tests
+
+## 0.8.11
+
+ - Added ``nfcall``, ``nfapply``, and ``nfbind`` as ``thisp``-less versions of
+   ``ncall``, ``napply``, and ``nbind``. The latter are now deprecated. #142
+ - Long stack traces no longer cause linearly-growing memory usage when chaining
+   promises together. #111
+ - Inspecting ``error.stack`` in a rejection handler will now give a long stack
+   trace. #103
+ - Fixed ``Q.timeout`` to clear its timeout handle when the promise is rejected;
+   previously, it kept the event loop alive until the timeout period expired.
+   #145 @dfilatov
+ - Added `q/queue` module, which exports an infinite promise queue
+   constructor.
+
+## 0.8.10
+
+ - Added ``done`` as a replacement for ``end``, taking the usual fulfillment,
+   rejection, and progress handlers. It's essentially equivalent to
+   ``then(f, r, p).end()``.
+ - Added ``Q.onerror``, a settable error trap that you can use to get full stack
+   traces for uncaught errors. #94
+ - Added ``thenResolve`` as a shortcut for returning a constant value once a
+   promise is fulfilled. #108 @ForbesLindesay
+ - Various tweaks to progress notification, including propagation and
+   transformation of progress values and only forwarding a single progress
+   object.
+ - Renamed ``nend`` to ``nodeify``. It no longer returns an always-fulfilled
+   promise when a Node callback is passed.
+ - ``deferred.resolve`` and ``deferred.reject`` no longer (sometimes) return
+   ``deferred.promise``.
+ - Fixed stack traces getting mangled if they hit ``end`` twice. #116 #121 @ef4
+ - Fixed ``ninvoke`` and ``npost`` to work on promises for objects with Node
+   methods. #134
+ - Fixed accidental coercion of objects with nontrivial ``valueOf`` methods,
+   like ``Date``s, by the promise's ``valueOf`` method. #135
+ - Fixed ``spread`` not calling the passed rejection handler if given a rejected
+   promise.
+
+## 0.8.9
+
+ - Added ``nend``
+ - Added preliminary progress notification support, via
+   ``promise.then(onFulfilled, onRejected, onProgress)``,
+   ``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
+ - Made ``put`` and ``del`` return the object acted upon for easier chaining.
+   #84
+ - Fixed coercion cycles with cooperating promises. #106
+
+## 0.8.7
+
+ - Support [Montage Require](http://github.com/kriskowal/mr)
+
+## 0.8.6
+
+ - Fixed ``npost`` and ``ninvoke`` to pass the correct ``thisp``. #74
+ - Fixed various cases involving unorthodox rejection reasons. #73 #90
+   @ef4
+ - Fixed double-resolving of misbehaved custom promises. #75
+ - Sped up ``Q.all`` for arrays contain already-resolved promises or scalar
+   values. @ForbesLindesay
+ - Made stack trace filtering work when concatenating assets. #93 @ef4
+ - Added warnings for deprecated methods. @ForbesLindesay
+ - Added ``.npmignore`` file so that dependent packages get a slimmer
+   ``node_modules`` directory.
+
+## 0.8.5
+
+ - Added preliminary support for long traces (@domenic)
+ - Added ``fapply``, ``fcall``, ``fbind`` for non-thisp
+   promised function calls.
+ - Added ``return`` for async generators, where generators
+   are implemented.
+ - Rejected promises now have an "exception" property.  If an object
+   isRejected(object), then object.valueOf().exception will
+   be the wrapped error.
+ - Added Jasmine specifications
+ - Support Internet Explorers 7–9 (with multiple bug fixes @domenic)
+ - Support Firefox 12
+ - Support Safari 5.1.5
+ - Support Chrome 18
+
+## 0.8.4
+
+ - WARNING: ``promise.timeout`` is now rejected with an ``Error`` object
+   and the message now includes the duration of the timeout in
+   miliseconds.  This doesn't constitute (in my opinion) a
+   backward-incompatibility since it is a change of an undocumented and
+   unspecified public behavior, but if you happened to depend on the
+   exception being a string, you will need to revise your code.
+ - Added ``deferred.makeNodeResolver()`` to replace the more cryptic
+   ``deferred.node()`` method.
+ - Added experimental ``Q.promise(maker(resolve, reject))`` to make a
+   promise inside a callback, such that thrown exceptions in the
+   callback are converted and the resolver and rejecter are arguments.
+   This is a shorthand for making a deferred directly and inspired by
+   @gozala’s stream constructor pattern and the Microsoft Windows Metro
+   Promise constructor interface.
+ - Added experimental ``Q.begin()`` that is intended to kick off chains
+   of ``.then`` so that each of these can be reordered without having to
+   edit the new and former first step.
+
+## 0.8.3
+
+ - Added ``isFulfilled``, ``isRejected``, and ``isResolved``
+   to the promise prototype.
+ - Added ``allResolved`` for waiting for every promise to either be
+   fulfilled or rejected, without propagating an error. @utvara #53
+ - Added ``Q.bind`` as a method to transform functions that
+   return and throw into promise-returning functions. See
+   [an example](https://gist.github.com/1782808). @domenic
+ - Renamed ``node`` export to ``nbind``, and added ``napply`` to
+   complete the set. ``node`` remains as deprecated. @domenic #58
+ - Renamed ``Method`` export to ``sender``.  ``Method``
+   remains as deprecated and will be removed in the next
+   major version since I expect it has very little usage.
+ - Added browser console message indicating a live list of
+   unhandled errors.
+ - Added support for ``msSetImmediate`` (IE10) or ``setImmediate``
+   (available via [polyfill](https://github.com/NobleJS/setImmediate))
+   as a browser-side ``nextTick`` implementation. #44 #50 #59
+ - Stopped using the event-queue dependency, which was in place for
+   Narwhal support: now directly using ``process.nextTick``.
+ - WARNING: EXPERIMENTAL: added ``finally`` alias for ``fin``, ``catch``
+   alias for ``fail``, ``try`` alias for ``call``, and ``delete`` alias
+   for ``del``.  These properties are enquoted in the library for
+   cross-browser compatibility, but may be used as property names in
+   modern engines.
+
+## 0.8.2
+
+ - Deprecated ``ref`` in favor of ``resolve`` as recommended by
+   @domenic.
+ - Update event-queue dependency.
+
+## 0.8.1
+
+ - Fixed Opera bug. #35 @cadorn
+ - Fixed ``Q.all([])`` #32 @domenic
+
+## 0.8.0
+
+ - WARNING: ``enqueue`` removed.  Use ``nextTick`` instead.
+   This is more consistent with NodeJS and (subjectively)
+   more explicit and intuitive.
+ - WARNING: ``def`` removed.  Use ``master`` instead.  The
+   term ``def`` was too confusing to new users.
+ - WARNING: ``spy`` removed in favor of ``fin``.
+ - WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
+ - WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
+ - WARNING: Removed the ``Q`` function module.exports alias
+   for ``Q.ref``. It conflicts with ``Q.apply`` in weird
+   ways, making it uncallable.
+ - Revised ``delay`` so that it accepts both ``(value,
+   timeout)`` and ``(timeout)`` variations based on
+   arguments length.
+ - Added ``ref().spread(cb(...args))``, a variant of
+   ``then`` that spreads an array across multiple arguments.
+   Useful with ``all()``.
+ - Added ``defer().node()`` Node callback generator.  The
+   callback accepts ``(error, value)`` or ``(error,
+   ...values)``.  For multiple value arguments, the
+   fulfillment value is an array, useful in conjunction with
+   ``spread``.
+ - Added ``node`` and ``ncall``, both with the signature
+   ``(fun, thisp_opt, ...args)``.  The former is a decorator
+   and the latter calls immediately.  ``node`` optional
+   binds and partially applies.  ``ncall`` can bind and pass
+   arguments.
+
+## 0.7.2
+
+ - Fixed thenable promise assimilation.
+
+## 0.7.1
+
+ - Stopped shimming ``Array.prototype.reduce``. The
+   enumerable property has bad side-effects.  Libraries that
+   depend on this (for example, QQ) will need to be revised.
+
+## 0.7.0 - BACKWARD INCOMPATIBILITY
+
+ - WARNING: Removed ``report`` and ``asap``
+ - WARNING: The ``callback`` argument of the ``fin``
+   function no longer receives any arguments. Thus, it can
+   be used to call functions that should not receive
+   arguments on resolution.  Use ``when``, ``then``, or
+   ``fail`` if you need a value.
+ - IMPORTANT: Fixed a bug in the use of ``MessageChannel``
+   for ``nextTick``.
+ - Renamed ``enqueue`` to ``nextTick``.
+ - Added experimental ``view`` and ``viewInfo`` for creating
+   views of promises either when or before they're
+   fulfilled.
+ - Shims are now externally applied so subsequent scripts or
+   dependees can use them.
+ - Improved minification results.
+ - Improved readability.
+
+## 0.6.0 - BACKWARD INCOMPATIBILITY
+
+ - WARNING: In practice, the implementation of ``spy`` and
+   the name ``fin`` were useful.  I've removed the old
+   ``fin`` implementation and renamed/aliased ``spy``.
+ - The "q" module now exports its ``ref`` function as a "Q"
+   constructor, with module systems that support exports
+   assignment including NodeJS, RequireJS, and when used as
+   a ``<script>`` tag. Notably, strictly compliant CommonJS
+   does not support this, but UncommonJS does.
+ - Added ``async`` decorator for generators that use yield
+   to "trampoline" promises. In engines that support
+   generators (SpiderMonkey), this will greatly reduce the
+   need for nested callbacks.
+ - Made ``when`` chainable.
+ - Made ``all`` chainable.
+
+## 0.5.3
+
+ - Added ``all`` and refactored ``join`` and ``wait`` to use
+   it.  All of these will now reject at the earliest
+   rejection.
+
+## 0.5.2
+
+ - Minor improvement to ``spy``; now waits for resolution of
+   callback promise.
+
+## 0.5.1
+
+ - Made most Q API methods chainable on promise objects, and
+   turned the previous promise-methods of ``join``,
+   ``wait``, and ``report`` into Q API methods.
+ - Added ``apply`` and ``call`` to the Q API, and ``apply``
+   as a promise handler.
+ - Added ``fail``, ``fin``, and ``spy`` to Q and the promise
+   prototype for convenience when observing rejection,
+   fulfillment and rejection, or just observing without
+   affecting the resolution.
+ - Renamed ``def`` (although ``def`` remains shimmed until
+   the next major release) to ``master``.
+ - Switched to using ``MessageChannel`` for next tick task
+   enqueue in browsers that support it.
+
+## 0.5.0 - MINOR BACKWARD INCOMPATIBILITY
+
+ - Exceptions are no longer reported when consumed.
+ - Removed ``error`` from the API.  Since exceptions are
+   getting consumed, throwing them in an errback causes the
+   exception to silently disappear.  Use ``end``.
+ - Added ``end`` as both an API method and a promise-chain
+   ending method.  It causes propagated rejections to be
+   thrown, which allows Node to write stack traces and
+   emit ``uncaughtException`` events, and browsers to
+   likewise emit ``onerror`` and log to the console.
+ - Added ``join`` and ``wait`` as promise chain functions,
+   so you can wait for variadic promises, returning your own
+   promise back, or join variadic promises, resolving with a
+   callback that receives variadic fulfillment values.
+
+## 0.4.4
+
+ - ``end`` no longer returns a promise. It is the end of the
+   promise chain.
+ - Stopped reporting thrown exceptions in ``when`` callbacks
+   and errbacks.  These must be explicitly reported through
+   ``.end()``, ``.then(null, Q.error)``, or some other
+   mechanism.
+ - Added ``report`` as an API method, which can be used as
+   an errback to report and propagate an error.
+ - Added ``report`` as a promise-chain method, so an error
+   can be reported if it passes such a gate.
+
+## 0.4.3
+
+ - Fixed ``<script>`` support that regressed with 0.4.2
+   because of "use strict" in the module system
+   multi-plexer.
+
+## 0.4.2
+
+ - Added support for RequireJS (jburke)
+
+## 0.4.1
+
+ - Added an "end" method to the promise prototype,
+   as a shorthand for waiting for the promise to
+   be resolved gracefully, and failing to do so,
+   to dump an error message.
+
+## 0.4.0 - BACKWARD INCOMPATIBLE*
+
+ - *Removed the utility modules. NPM and Node no longer
+   expose any module except the main module.  These have
+   been moved and merged into the "qq" package.
+ - *In a non-CommonJS browser, q.js can be used as a script.
+   It now creates a Q global variable.
+ - Fixed thenable assimilation.
+ - Fixed some issues with asap, when it resolves to
+   undefined, or throws an exception.
+
+## 0.3.0 - BACKWARD-INCOMPATIBLE
+
+ - The `post` method has been reverted to its original
+   signature, as provided in Tyler Close's `ref_send` API.
+   That is, `post` accepts two arguments, the second of
+   which is an arbitrary object, but usually invocation
+   arguments as an `Array`.  To provide variadic arguments
+   to `post`, there is a new `invoke` function that posts
+   the variadic arguments to the value given in the first
+   argument.
+ - The `defined` method has been moved from `q` to `q/util`
+   since it gets no use in practice but is still
+   theoretically useful.
+ - The `Promise` constructor has been renamed to
+   `makePromise` to be consistent with the convention that
+   functions that do not require the `new` keyword to be
+   used as constructors have camelCase names.
+ - The `isResolved` function has been renamed to
+   `isFulfilled`.  There is a new `isResolved` function that
+   indicates whether a value is not a promise or, if it is a
+   promise, whether it has been either fulfilled or
+   rejected.  The code has been revised to reflect this
+   nuance in terminology.
+
+## 0.2.10
+
+ - Added `join` to `"q/util"` for variadically joining
+   multiple promises.
+
+## 0.2.9
+
+ - The future-compatible `invoke` method has been added,
+   to replace `post`, since `post` will become backward-
+   incompatible in the next major release.
+ - Exceptions thrown in the callbacks of a `when` call are
+   now emitted to Node's `"uncaughtException"` `process`
+   event in addition to being returned as a rejection reason.
+
+## 0.2.8
+
+ - Exceptions thrown in the callbacks of a `when` call
+   are now consumed, warned, and transformed into
+   rejections of the promise returned by `when`.
+
+## 0.2.7
+
+ - Fixed a minor bug in thenable assimilation, regressed
+   because of the change in the forwarding protocol.
+ - Fixed behavior of "q/util" `deep` method on dates and
+   other primitives. Github issue #11.
+
+## 0.2.6
+
+ - Thenables (objects with a "then" method) are accepted
+   and provided, bringing this implementation of Q
+   into conformance with Promises/A, B, and D.
+ - Added `makePromise`, to replace the `Promise` function
+   eventually.
+ - Rejections are now also duck-typed. A rejection is a
+   promise with a valueOf method that returns a rejection
+   descriptor. A rejection descriptor has a
+   "promiseRejected" property equal to "true" and a
+   "reason" property corresponding to the rejection reason.
+ - Altered the `makePromise` API such that the `fallback`
+   method no longer receives a superfluous `resolved` method
+   after the `operator`.  The fallback method is responsible
+   only for returning a resolution.  This breaks an
+   undocumented API, so third-party API's depending on the
+   previous undocumented behavior may break.
+
+## 0.2.5
+
+ - Changed promises into a duck-type such that multiple
+   instances of the Q module can exchange promise objects.
+   A promise is now defined as "an object that implements the
+   `promiseSend(op, resolved, ...)` method and `valueOf`".
+ - Exceptions in promises are now captured and returned
+   as rejections.
+
+## 0.2.4
+
+ - Fixed bug in `ref` that prevented `del` messages from
+   being received (gozala)
+ - Fixed a conflict with FireFox 4; constructor property
+   is now read-only.
+
+## 0.2.3
+
+ - Added `keys` message to promises and to the promise API.
+
+## 0.2.2
+
+ - Added boilerplate to `q/queue` and `q/util`.
+ - Fixed missing dependency to `q/queue`.
+
+## 0.2.1
+
+ - The `resolve` and `reject` methods of `defer` objects now
+   return the resolution promise for convenience.
+ - Added `q/util`, which provides `step`, `delay`, `shallow`,
+   `deep`, and three reduction orders.
+ - Added `q/queue` module for a promise `Queue`.
+ - Added `q-comm` to the list of compatible libraries.
+ - Deprecated `defined` from `q`, with intent to move it to
+   `q/util`.
+
+## 0.2.0 - BACKWARD INCOMPATIBLE
+
+ - Changed post(ref, name, args) to variadic
+   post(ref, name, ...args). BACKWARD INCOMPATIBLE
+ - Added a def(value) method to annotate an object as being
+   necessarily a local value that cannot be serialized, such
+   that inter-process/worker/vat promise communication
+   libraries will send messages to it, but never send it
+   back.
+ - Added a send(value, op, ...args) method to the public API, for
+   forwarding messages to a value or promise in a future turn.
+
+## 0.1.9
+
+ - Added isRejected() for testing whether a value is a rejected
+   promise.  isResolved() retains the behavior of stating
+   that rejected promises are not resolved.
+
+## 0.1.8
+
+ - Fixed isResolved(null) and isResolved(undefined) [issue #9]
+ - Fixed a problem with the Object.create shim
+
+## 0.1.7
+
+ - shimmed ES5 Object.create in addition to Object.freeze
+   for compatibility on non-ES5 engines (gozala)
+
+## 0.1.6
+
+ - Q.isResolved added
+ - promise.valueOf() now returns the value of resolved
+   and near values
+ - asap retried
+ - promises are frozen when possible
+
+## 0.1.5
+
+ - fixed dependency list for Teleport (gozala)
+ - all unit tests now pass (gozala)
+
+## 0.1.4
+
+ - added support for Teleport as an engine (gozala)
+ - simplified and updated methods for getting internal
+   print and enqueue functions universally (gozala)
+
+## 0.1.3
+
+ - fixed erroneous link to the q module in package.json
+
+## 0.1.2
+
+ - restructured for overlay style package compatibility
+
+## 0.1.0
+
+ - removed asap because it was broken, probably down to the
+   philosophy.
+
+## 0.0.3
+
+ - removed q-util
+ - fixed asap so it returns a value if completed
+
+## 0.0.2
+
+ - added q-util
+
+## 0.0.1
+
+ - initial version
diff --git a/node_modules/q/LICENSE b/node_modules/q/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..9ce1ea591fca2060658d95475291967610763b2b
--- /dev/null
+++ b/node_modules/q/LICENSE
@@ -0,0 +1,18 @@
+Copyright 2009–2017 Kristopher Michael Kowal. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/node_modules/q/README.md b/node_modules/q/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d2f57a6f66e819eb353645ca1759d8d9853c651a
--- /dev/null
+++ b/node_modules/q/README.md
@@ -0,0 +1,874 @@
+[![Build Status](https://secure.travis-ci.org/kriskowal/q.svg?branch=master)](http://travis-ci.org/kriskowal/q)
+[![CDNJS](https://img.shields.io/cdnjs/v/q.js.svg)](https://cdnjs.com/libraries/q.js)
+
+<a href="http://promises-aplus.github.com/promises-spec">
+    <img src="http://kriskowal.github.io/q/q.png" align="right" alt="Q logo" />
+</a>
+
+If a function cannot return a value or throw an exception without
+blocking, it can return a promise instead.  A promise is an object
+that represents the return value or the thrown exception that the
+function may eventually provide.  A promise can also be used as a
+proxy for a [remote object][Q-Connection] to overcome latency.
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+On the first pass, promises can mitigate the “[Pyramid of
+Doom][POD]”: the situation where code marches to the right faster
+than it marches forward.
+
+[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
+
+```javascript
+step1(function (value1) {
+    step2(value1, function(value2) {
+        step3(value2, function(value3) {
+            step4(value3, function(value4) {
+                // Do something with value4
+            });
+        });
+    });
+});
+```
+
+With a promise library, you can flatten the pyramid.
+
+```javascript
+Q.fcall(promisedStep1)
+.then(promisedStep2)
+.then(promisedStep3)
+.then(promisedStep4)
+.then(function (value4) {
+    // Do something with value4
+})
+.catch(function (error) {
+    // Handle any error from all above steps
+})
+.done();
+```
+
+With this approach, you also get implicit error propagation, just like `try`,
+`catch`, and `finally`.  An error in `promisedStep1` will flow all the way to
+the `catch` function, where it’s caught and handled.  (Here `promisedStepN` is
+a version of `stepN` that returns a promise.)
+
+The callback approach is called an “inversion of control”.
+A function that accepts a callback instead of a return value
+is saying, “Don’t call me, I’ll call you.”.  Promises
+[un-invert][IOC] the inversion, cleanly separating the input
+arguments from control flow arguments.  This simplifies the
+use and creation of API’s, particularly variadic,
+rest and spread arguments.
+
+[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
+
+
+## Getting Started
+
+The Q module can be loaded as:
+
+-   A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
+    gzipped.
+-   A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
+    the [q](https://npmjs.org/package/q) package
+-   An AMD module
+-   A [component](https://github.com/component/component) as ``microjs/q``
+-   Using [bower](http://bower.io/) as `q#^1.4.1`
+-   Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
+
+Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
+
+## Resources
+
+Our [wiki][] contains a number of useful resources, including:
+
+- A method-by-method [Q API reference][reference].
+- A growing [examples gallery][examples], showing how Q can be used to make
+  everything better. From XHR to database access to accessing the Flickr API,
+  Q is there for you.
+- There are many libraries that produce and consume Q promises for everything
+  from file system/database access or RPC to templating. For a list of some of
+  the more popular ones, see [Libraries][].
+- If you want materials that introduce the promise concept generally, and the
+  below tutorial isn't doing it for you, check out our collection of
+  [presentations, blog posts, and podcasts][resources].
+- A guide for those [coming from jQuery's `$.Deferred`][jquery].
+
+We'd also love to have you join the Q-Continuum [mailing list][].
+
+[wiki]: https://github.com/kriskowal/q/wiki
+[reference]: https://github.com/kriskowal/q/wiki/API-Reference
+[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
+[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
+[resources]: https://github.com/kriskowal/q/wiki/General-Promise-Resources
+[jquery]: https://github.com/kriskowal/q/wiki/Coming-from-jQuery
+[mailing list]: https://groups.google.com/forum/#!forum/q-continuum
+
+
+## Tutorial
+
+Promises have a ``then`` method, which you can use to get the eventual
+return value (fulfillment) or thrown exception (rejection).
+
+```javascript
+promiseMeSomething()
+.then(function (value) {
+}, function (reason) {
+});
+```
+
+If ``promiseMeSomething`` returns a promise that gets fulfilled later
+with a return value, the first function (the fulfillment handler) will be
+called with the value.  However, if the ``promiseMeSomething`` function
+gets rejected later by a thrown exception, the second function (the
+rejection handler) will be called with the exception.
+
+Note that resolution of a promise is always asynchronous: that is, the
+fulfillment or rejection handler will always be called in the next turn of the
+event loop (i.e. `process.nextTick` in Node). This gives you a nice
+guarantee when mentally tracing the flow of your code, namely that
+``then`` will always return before either handler is executed.
+
+In this tutorial, we begin with how to consume and work with promises. We'll
+talk about how to create them, and thus create functions like
+`promiseMeSomething` that return promises, [below](#the-beginning).
+
+
+### Propagation
+
+The ``then`` method returns a promise, which in this example, I’m
+assigning to ``outputPromise``.
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (input) {
+}, function (reason) {
+});
+```
+
+The ``outputPromise`` variable becomes a new promise for the return
+value of either handler.  Since a function can only either return a
+value or throw an exception, only one handler will ever be called and it
+will be responsible for resolving ``outputPromise``.
+
+-   If you return a value in a handler, ``outputPromise`` will get
+    fulfilled.
+
+-   If you throw an exception in a handler, ``outputPromise`` will get
+    rejected.
+
+-   If you return a **promise** in a handler, ``outputPromise`` will
+    “become” that promise.  Being able to become a new promise is useful
+    for managing delays, combining results, or recovering from errors.
+
+If the ``getInputPromise()`` promise gets rejected and you omit the
+rejection handler, the **error** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (value) {
+});
+```
+
+If the input promise gets fulfilled and you omit the fulfillment handler, the
+**value** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(null, function (error) {
+});
+```
+
+Q promises provide a ``fail`` shorthand for ``then`` when you are only
+interested in handling the error:
+
+```javascript
+var outputPromise = getInputPromise()
+.fail(function (error) {
+});
+```
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `catch` instead of `fail`.
+
+Promises also have a ``fin`` function that is like a ``finally`` clause.
+The final handler gets called, with no arguments, when the promise
+returned by ``getInputPromise()`` either returns a value or throws an
+error.  The value returned or error thrown by ``getInputPromise()``
+passes directly to ``outputPromise`` unless the final handler fails, and
+may be delayed if the final handler returns a promise.
+
+```javascript
+var outputPromise = getInputPromise()
+.fin(function () {
+    // close files, database connections, stop servers, conclude tests
+});
+```
+
+-   If the handler returns a value, the value is ignored
+-   If the handler throws an error, the error passes to ``outputPromise``
+-   If the handler returns a promise, ``outputPromise`` gets postponed.  The
+    eventual value or error has the same effect as an immediate return
+    value or thrown error: a value would be ignored, an error would be
+    forwarded.
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `finally` instead of `fin`.
+
+### Chaining
+
+There are two ways to chain promises.  You can chain promises either
+inside or outside handlers.  The next two examples are equivalent.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username)
+    .then(function (user) {
+        // if we get here without an error,
+        // the value returned here
+        // or the exception thrown here
+        // resolves the promise returned
+        // by the first line
+    })
+});
+```
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username);
+})
+.then(function (user) {
+    // if we get here without an error,
+    // the value returned here
+    // or the exception thrown here
+    // resolves the promise returned
+    // by the first line
+});
+```
+
+The only difference is nesting.  It’s useful to nest handlers if you
+need to capture multiple input values in your closure.
+
+```javascript
+function authenticate() {
+    return getUsername()
+    .then(function (username) {
+        return getUser(username);
+    })
+    // chained because we will not need the user name in the next event
+    .then(function (user) {
+        return getPassword()
+        // nested because we need both user and password next
+        .then(function (password) {
+            if (user.passwordHash !== hash(password)) {
+                throw new Error("Can't authenticate");
+            }
+        });
+    });
+}
+```
+
+
+### Combination
+
+You can turn an array of promises into a promise for the whole,
+fulfilled array using ``all``.
+
+```javascript
+return Q.all([
+    eventualAdd(2, 2),
+    eventualAdd(10, 20)
+]);
+```
+
+If you have a promise for an array, you can use ``spread`` as a
+replacement for ``then``.  The ``spread`` function “spreads” the
+values over the arguments of the fulfillment handler.  The rejection handler
+will get called at the first sign of failure.  That is, whichever of
+the received promises fails first gets handled by the rejection handler.
+
+```javascript
+function eventualAdd(a, b) {
+    return Q.spread([a, b], function (a, b) {
+        return a + b;
+    })
+}
+```
+
+But ``spread`` calls ``all`` initially, so you can skip it in chains.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return [username, getUser(username)];
+})
+.spread(function (username, user) {
+});
+```
+
+The ``all`` function returns a promise for an array of values.  When this
+promise is fulfilled, the array contains the fulfillment values of the original
+promises, in the same order as those promises.  If one of the given promises
+is rejected, the returned promise is immediately rejected, not waiting for the
+rest of the batch.  If you want to wait for all of the promises to either be
+fulfilled or rejected, you can use ``allSettled``.
+
+```javascript
+Q.allSettled(promises)
+.then(function (results) {
+    results.forEach(function (result) {
+        if (result.state === "fulfilled") {
+            var value = result.value;
+        } else {
+            var reason = result.reason;
+        }
+    });
+});
+```
+
+The ``any`` function accepts an array of promises and returns a promise that is
+fulfilled by the first given promise to be fulfilled, or rejected if all of the
+given promises are rejected.
+
+```javascript
+Q.any(promises)
+.then(function (first) {
+    // Any of the promises was fulfilled.
+}, function (error) {
+    // All of the promises were rejected.
+});
+```
+
+### Sequences
+
+If you have a number of promise-producing functions that need
+to be run sequentially, you can of course do so manually:
+
+```javascript
+return foo(initialVal).then(bar).then(baz).then(qux);
+```
+
+However, if you want to run a dynamically constructed sequence of
+functions, you'll want something like this:
+
+```javascript
+var funcs = [foo, bar, baz, qux];
+
+var result = Q(initialVal);
+funcs.forEach(function (f) {
+    result = result.then(f);
+});
+return result;
+```
+
+You can make this slightly more compact using `reduce`:
+
+```javascript
+return funcs.reduce(function (soFar, f) {
+    return soFar.then(f);
+}, Q(initialVal));
+```
+
+Or, you could use the ultra-compact version:
+
+```javascript
+return funcs.reduce(Q.when, Q(initialVal));
+```
+
+### Handling Errors
+
+One sometimes-unintuitive aspect of promises is that if you throw an
+exception in the fulfillment handler, it will not be caught by the error
+handler.
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+}, function (error) {
+    // We only get here if "foo" fails
+});
+```
+
+To see why this is, consider the parallel between promises and
+``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
+handler represents a ``catch`` for ``foo()``, while the fulfillment handler
+represents code that happens *after* the ``try``/``catch`` block.
+That code then needs its own ``try``/``catch`` block.
+
+In terms of promises, this means chaining your rejection handler:
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+})
+.fail(function (error) {
+    // We get here with either foo's error or bar's error
+});
+```
+
+### Progress Notification
+
+It's possible for promises to report their progress, e.g. for tasks that take a
+long time like a file upload. Not all promises will implement progress
+notifications, but for those that do, you can consume the progress values using
+a third parameter to ``then``:
+
+```javascript
+return uploadFile()
+.then(function () {
+    // Success uploading the file
+}, function (err) {
+    // There was an error, and we get the reason for error
+}, function (progress) {
+    // We get notified of the upload's progress as it is executed
+});
+```
+
+Like `fail`, Q also provides a shorthand for progress callbacks
+called `progress`:
+
+```javascript
+return uploadFile().progress(function (progress) {
+    // We get notified of the upload's progress
+});
+```
+
+### The End
+
+When you get to the end of a chain of promises, you should either
+return the last promise or end the chain.  Since handlers catch
+errors, it’s an unfortunate pattern that the exceptions can go
+unobserved.
+
+So, either return it,
+
+```javascript
+return foo()
+.then(function () {
+    return "bar";
+});
+```
+
+Or, end it.
+
+```javascript
+foo()
+.then(function () {
+    return "bar";
+})
+.done();
+```
+
+Ending a promise chain makes sure that, if an error doesn’t get
+handled before the end, it will get rethrown and reported.
+
+This is a stopgap. We are exploring ways to make unhandled errors
+visible without any explicit handling.
+
+
+### The Beginning
+
+Everything above assumes you get a promise from somewhere else.  This
+is the common case.  Every once in a while, you will need to create a
+promise from scratch.
+
+#### Using ``Q.fcall``
+
+You can create a promise from a value using ``Q.fcall``.  This returns a
+promise for 10.
+
+```javascript
+return Q.fcall(function () {
+    return 10;
+});
+```
+
+You can also use ``fcall`` to get a promise for an exception.
+
+```javascript
+return Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+```
+
+As the name implies, ``fcall`` can call functions, or even promised
+functions.  This uses the ``eventualAdd`` function above to add two
+numbers.
+
+```javascript
+return Q.fcall(eventualAdd, 2, 2);
+```
+
+
+#### Using Deferreds
+
+If you have to interface with asynchronous functions that are callback-based
+instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
+friends). But much of the time, the solution will be to use *deferreds*.
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", function (error, text) {
+    if (error) {
+        deferred.reject(new Error(error));
+    } else {
+        deferred.resolve(text);
+    }
+});
+return deferred.promise;
+```
+
+Note that a deferred can be resolved with a value or a promise.  The
+``reject`` function is a shorthand for resolving with a rejected
+promise.
+
+```javascript
+// this:
+deferred.reject(new Error("Can't do it"));
+
+// is shorthand for:
+var rejection = Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+deferred.resolve(rejection);
+```
+
+This is a simplified implementation of ``Q.delay``.
+
+```javascript
+function delay(ms) {
+    var deferred = Q.defer();
+    setTimeout(deferred.resolve, ms);
+    return deferred.promise;
+}
+```
+
+This is a simplified implementation of ``Q.timeout``
+
+```javascript
+function timeout(promise, ms) {
+    var deferred = Q.defer();
+    Q.when(promise, deferred.resolve);
+    delay(ms).then(function () {
+        deferred.reject(new Error("Timed out"));
+    });
+    return deferred.promise;
+}
+```
+
+Finally, you can send a progress notification to the promise with
+``deferred.notify``.
+
+For illustration, this is a wrapper for XML HTTP requests in the browser. Note
+that a more [thorough][XHR] implementation would be in order in practice.
+
+[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
+
+```javascript
+function requestOkText(url) {
+    var request = new XMLHttpRequest();
+    var deferred = Q.defer();
+
+    request.open("GET", url, true);
+    request.onload = onload;
+    request.onerror = onerror;
+    request.onprogress = onprogress;
+    request.send();
+
+    function onload() {
+        if (request.status === 200) {
+            deferred.resolve(request.responseText);
+        } else {
+            deferred.reject(new Error("Status code was " + request.status));
+        }
+    }
+
+    function onerror() {
+        deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
+    }
+
+    function onprogress(event) {
+        deferred.notify(event.loaded / event.total);
+    }
+
+    return deferred.promise;
+}
+```
+
+Below is an example of how to use this ``requestOkText`` function:
+
+```javascript
+requestOkText("http://localhost:3000")
+.then(function (responseText) {
+    // If the HTTP response returns 200 OK, log the response text.
+    console.log(responseText);
+}, function (error) {
+    // If there's an error or a non-200 status code, log the error.
+    console.error(error);
+}, function (progress) {
+    // Log the progress as it comes in.
+    console.log("Request progress: " + Math.round(progress * 100) + "%");
+});
+```
+
+#### Using `Q.Promise`
+
+This is an alternative promise-creation API that has the same power as
+the deferred concept, but without introducing another conceptual entity.
+
+Rewriting the `requestOkText` example above using `Q.Promise`:
+
+```javascript
+function requestOkText(url) {
+    return Q.Promise(function(resolve, reject, notify) {
+        var request = new XMLHttpRequest();
+
+        request.open("GET", url, true);
+        request.onload = onload;
+        request.onerror = onerror;
+        request.onprogress = onprogress;
+        request.send();
+
+        function onload() {
+            if (request.status === 200) {
+                resolve(request.responseText);
+            } else {
+                reject(new Error("Status code was " + request.status));
+            }
+        }
+
+        function onerror() {
+            reject(new Error("Can't XHR " + JSON.stringify(url)));
+        }
+
+        function onprogress(event) {
+            notify(event.loaded / event.total);
+        }
+    });
+}
+```
+
+If `requestOkText` were to throw an exception, the returned promise would be
+rejected with that thrown exception as the rejection reason.
+
+### The Middle
+
+If you are using a function that may return a promise, but just might
+return a value if it doesn’t need to defer, you can use the “static”
+methods of the Q library.
+
+The ``when`` function is the static equivalent for ``then``.
+
+```javascript
+return Q.when(valueOrPromise, function (value) {
+}, function (error) {
+});
+```
+
+All of the other methods on a promise have static analogs with the
+same name.
+
+The following are equivalent:
+
+```javascript
+return Q.all([a, b]);
+```
+
+```javascript
+return Q.fcall(function () {
+    return [a, b];
+})
+.all();
+```
+
+When working with promises provided by other libraries, you should
+convert it to a Q promise.  Not all promise libraries make the same
+guarantees as Q and certainly don’t provide all of the same methods.
+Most libraries only provide a partially functional ``then`` method.
+This thankfully is all we need to turn them into vibrant Q promises.
+
+```javascript
+return Q($.ajax(...))
+.then(function () {
+});
+```
+
+If there is any chance that the promise you receive is not a Q promise
+as provided by your library, you should wrap it using a Q function.
+You can even use ``Q.invoke`` as a shorthand.
+
+```javascript
+return Q.invoke($, 'ajax', ...)
+.then(function () {
+});
+```
+
+
+### Over the Wire
+
+A promise can serve as a proxy for another object, even a remote
+object.  There are methods that allow you to optimistically manipulate
+properties or call functions.  All of these interactions return
+promises, so they can be chained.
+
+```
+direct manipulation         using a promise as a proxy
+--------------------------  -------------------------------
+value.foo                   promise.get("foo")
+value.foo = value           promise.put("foo", value)
+delete value.foo            promise.del("foo")
+value.foo(...args)          promise.post("foo", [args])
+value.foo(...args)          promise.invoke("foo", ...args)
+value(...args)              promise.fapply([args])
+value(...args)              promise.fcall(...args)
+```
+
+If the promise is a proxy for a remote object, you can shave
+round-trips by using these functions instead of ``then``.  To take
+advantage of promises for remote objects, check out [Q-Connection][].
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+Even in the case of non-remote objects, these methods can be used as
+shorthand for particularly-simple fulfillment handlers. For example, you
+can replace
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.then(function (value) {
+    return value[0].foo;
+});
+```
+
+with
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.get(0)
+.get("foo");
+```
+
+
+### Adapting Node
+
+If you're working with functions that make use of the Node.js callback pattern,
+where callbacks are in the form of `function(err, result)`, Q provides a few
+useful utility functions for converting between them. The most straightforward
+are probably `Q.nfcall` and `Q.nfapply` ("Node function call/apply") for calling
+Node.js-style functions and getting back a promise:
+
+```javascript
+return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
+return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
+```
+
+If you are working with methods, instead of simple functions, you can easily
+run in to the usual problems where passing a method to another function—like
+`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
+use `Function.prototype.bind` or some nice shortcut methods we provide:
+
+```javascript
+return Q.ninvoke(redisClient, "get", "user:1:id");
+return Q.npost(redisClient, "get", ["user:1:id"]);
+```
+
+You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
+
+```javascript
+var readFile = Q.denodeify(FS.readFile);
+return readFile("foo.txt", "utf-8");
+
+var redisClientGet = Q.nbind(redisClient.get, redisClient);
+return redisClientGet("user:1:id");
+```
+
+Finally, if you're working with raw deferred objects, there is a
+`makeNodeResolver` method on deferreds that can be handy:
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
+return deferred.promise;
+```
+
+### Long Stack Traces
+
+Q comes with optional support for “long stack traces,” wherein the `stack`
+property of `Error` rejection reasons is rewritten to be traced along
+asynchronous jumps instead of stopping at the most recent one. As an example:
+
+```js
+function theDepthsOfMyProgram() {
+  Q.delay(100).done(function explode() {
+    throw new Error("boo!");
+  });
+}
+
+theDepthsOfMyProgram();
+```
+
+usually would give a rather unhelpful stack trace looking something like
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+    at _fulfilled (/path/to/test.js:q:54)
+    at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
+    at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
+    at pending (/path/to/q.js:397:39)
+    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
+```
+
+But, if you turn this feature on by setting
+
+```js
+Q.longStackSupport = true;
+```
+
+then the above code gives a nice stack trace to the tune of
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+From previous event:
+    at theDepthsOfMyProgram (/path/to/test.js:2:16)
+    at Object.<anonymous> (/path/to/test.js:7:1)
+```
+
+Note how you can see the function that triggered the async operation in the
+stack trace! This is very helpful for debugging, as otherwise you end up getting
+only the first line, plus a bunch of Q internals, with no sign of where the
+operation started.
+
+In node.js, this feature can also be enabled through the Q_DEBUG environment
+variable:
+
+```
+Q_DEBUG=1 node server.js
+```
+
+This will enable long stack support in every instance of Q.
+
+This feature does come with somewhat-serious performance and memory overhead,
+however. If you're working with lots of promises, or trying to scale a server
+to many users, you should probably keep it off. But in development, go for it!
+
+## Tests
+
+You can view the results of the Q test suite [in your browser][tests]!
+
+[tests]: https://rawgithub.com/kriskowal/q/v1/spec/q-spec.html
+
+## License
+
+Copyright 2009–2017 Kristopher Michael Kowal and contributors
+MIT License (enclosed)
+
diff --git a/node_modules/q/package.json b/node_modules/q/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8c3b5fe378311869f4baee1352d184b4a5ba681e
--- /dev/null
+++ b/node_modules/q/package.json
@@ -0,0 +1,76 @@
+{
+  "name": "q",
+  "version": "1.5.1",
+  "description": "A library for promises (CommonJS/Promises/A,B,D)",
+  "homepage": "https://github.com/kriskowal/q",
+  "author": "Kris Kowal <kris@cixar.com> (https://github.com/kriskowal)",
+  "keywords": [
+    "q",
+    "promise",
+    "promises",
+    "promises-a",
+    "promises-aplus",
+    "deferred",
+    "future",
+    "async",
+    "flow control",
+    "fluent",
+    "browser",
+    "node"
+  ],
+  "contributors": [
+    "Kris Kowal <kris@cixar.com> (https://github.com/kriskowal)",
+    "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
+    "Domenic Denicola <domenic@domenicdenicola.com> (http://domenicdenicola.com)"
+  ],
+  "bugs": {
+    "mail": "kris@cixar.com",
+    "url": "http://github.com/kriskowal/q/issues"
+  },
+  "license": "MIT",
+  "main": "q.js",
+  "files": [
+    "LICENSE",
+    "q.js",
+    "queue.js"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/kriskowal/q.git"
+  },
+  "engines": {
+    "node": ">=0.6.0",
+    "teleport": ">=0.2.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "cover": "*",
+    "grunt": "~0.4.1",
+    "grunt-cli": "~0.1.9",
+    "grunt-contrib-uglify": "~0.9.1",
+    "jasmine-node": "1.11.0",
+    "jshint": "~2.1.9",
+    "matcha": "~0.2.0",
+    "opener": "*",
+    "promises-aplus-tests": "1.x"
+  },
+  "scripts": {
+    "test": "npm ls -s && jasmine-node spec && promises-aplus-tests spec/aplus-adapter && npm run -s lint",
+    "test-browser": "opener spec/q-spec.html",
+    "benchmark": "matcha",
+    "lint": "jshint q.js",
+    "cover": "cover run jasmine-node spec && cover report html && opener cover_html/index.html",
+    "minify": "grunt",
+    "prepublish": "grunt"
+  },
+  "overlay": {
+    "teleport": {
+      "dependencies": {
+        "system": ">=0.0.4"
+      }
+    }
+  },
+  "directories": {
+    "test": "./spec"
+  }
+}
diff --git a/node_modules/q/q.js b/node_modules/q/q.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e467958297e2d0f5206a7dc4ae357123d838a2f
--- /dev/null
+++ b/node_modules/q/q.js
@@ -0,0 +1,2076 @@
+// vim:ts=4:sts=4:sw=4:
+/*!
+ *
+ * Copyright 2009-2017 Kris Kowal under the terms of the MIT
+ * license found at https://github.com/kriskowal/q/blob/v1/LICENSE
+ *
+ * With parts by Tyler Close
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
+ * at http://www.opensource.org/licenses/mit-license.html
+ * Forked at ref_send.js version: 2009-05-11
+ *
+ * With parts by Mark Miller
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+(function (definition) {
+    "use strict";
+
+    // This file will function properly as a <script> tag, or a module
+    // using CommonJS and NodeJS or RequireJS module formats.  In
+    // Common/Node/RequireJS, the module exports the Q API and when
+    // executed as a simple <script>, it creates a Q global instead.
+
+    // Montage Require
+    if (typeof bootstrap === "function") {
+        bootstrap("promise", definition);
+
+    // CommonJS
+    } else if (typeof exports === "object" && typeof module === "object") {
+        module.exports = definition();
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+        define(definition);
+
+    // SES (Secure EcmaScript)
+    } else if (typeof ses !== "undefined") {
+        if (!ses.ok()) {
+            return;
+        } else {
+            ses.makeQ = definition;
+        }
+
+    // <script>
+    } else if (typeof window !== "undefined" || typeof self !== "undefined") {
+        // Prefer window over self for add-on scripts. Use self for
+        // non-windowed contexts.
+        var global = typeof window !== "undefined" ? window : self;
+
+        // Get the `window` object, save the previous Q global
+        // and initialize Q as a global.
+        var previousQ = global.Q;
+        global.Q = definition();
+
+        // Add a noConflict function so Q can be removed from the
+        // global namespace.
+        global.Q.noConflict = function () {
+            global.Q = previousQ;
+            return this;
+        };
+
+    } else {
+        throw new Error("This environment was not anticipated by Q. Please file a bug.");
+    }
+
+})(function () {
+"use strict";
+
+var hasStacks = false;
+try {
+    throw new Error();
+} catch (e) {
+    hasStacks = !!e.stack;
+}
+
+// All code after this point will be filtered from stack traces reported
+// by Q.
+var qStartingLine = captureLine();
+var qFileName;
+
+// shims
+
+// used for fallback in "allResolved"
+var noop = function () {};
+
+// Use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick =(function () {
+    // linked list of tasks (single, with head node)
+    var head = {task: void 0, next: null};
+    var tail = head;
+    var flushing = false;
+    var requestTick = void 0;
+    var isNodeJS = false;
+    // queue for late tasks, used by unhandled rejection tracking
+    var laterQueue = [];
+
+    function flush() {
+        /* jshint loopfunc: true */
+        var task, domain;
+
+        while (head.next) {
+            head = head.next;
+            task = head.task;
+            head.task = void 0;
+            domain = head.domain;
+
+            if (domain) {
+                head.domain = void 0;
+                domain.enter();
+            }
+            runSingle(task, domain);
+
+        }
+        while (laterQueue.length) {
+            task = laterQueue.pop();
+            runSingle(task);
+        }
+        flushing = false;
+    }
+    // runs a single function in the async queue
+    function runSingle(task, domain) {
+        try {
+            task();
+
+        } catch (e) {
+            if (isNodeJS) {
+                // In node, uncaught exceptions are considered fatal errors.
+                // Re-throw them synchronously to interrupt flushing!
+
+                // Ensure continuation if the uncaught exception is suppressed
+                // listening "uncaughtException" events (as domains does).
+                // Continue in next event to avoid tick recursion.
+                if (domain) {
+                    domain.exit();
+                }
+                setTimeout(flush, 0);
+                if (domain) {
+                    domain.enter();
+                }
+
+                throw e;
+
+            } else {
+                // In browsers, uncaught exceptions are not fatal.
+                // Re-throw them asynchronously to avoid slow-downs.
+                setTimeout(function () {
+                    throw e;
+                }, 0);
+            }
+        }
+
+        if (domain) {
+            domain.exit();
+        }
+    }
+
+    nextTick = function (task) {
+        tail = tail.next = {
+            task: task,
+            domain: isNodeJS && process.domain,
+            next: null
+        };
+
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+
+    if (typeof process === "object" &&
+        process.toString() === "[object process]" && process.nextTick) {
+        // Ensure Q is in a real Node environment, with a `process.nextTick`.
+        // To see through fake Node environments:
+        // * Mocha test runner - exposes a `process` global without a `nextTick`
+        // * Browserify - exposes a `process.nexTick` function that uses
+        //   `setTimeout`. In this case `setImmediate` is preferred because
+        //    it is faster. Browserify's `process.toString()` yields
+        //   "[object Object]", while in a real Node environment
+        //   `process.toString()` yields "[object process]".
+        isNodeJS = true;
+
+        requestTick = function () {
+            process.nextTick(flush);
+        };
+
+    } else if (typeof setImmediate === "function") {
+        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
+        if (typeof window !== "undefined") {
+            requestTick = setImmediate.bind(window, flush);
+        } else {
+            requestTick = function () {
+                setImmediate(flush);
+            };
+        }
+
+    } else if (typeof MessageChannel !== "undefined") {
+        // modern browsers
+        // http://www.nonblocking.io/2011/06/windownexttick.html
+        var channel = new MessageChannel();
+        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
+        // working message ports the first time a page loads.
+        channel.port1.onmessage = function () {
+            requestTick = requestPortTick;
+            channel.port1.onmessage = flush;
+            flush();
+        };
+        var requestPortTick = function () {
+            // Opera requires us to provide a message payload, regardless of
+            // whether we use it.
+            channel.port2.postMessage(0);
+        };
+        requestTick = function () {
+            setTimeout(flush, 0);
+            requestPortTick();
+        };
+
+    } else {
+        // old browsers
+        requestTick = function () {
+            setTimeout(flush, 0);
+        };
+    }
+    // runs a task after all other tasks have been run
+    // this is useful for unhandled rejection tracking that needs to happen
+    // after all `then`d tasks have been run.
+    nextTick.runAfter = function (task) {
+        laterQueue.push(task);
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+    return nextTick;
+})();
+
+// Attempt to make generics safe in the face of downstream
+// modifications.
+// There is no situation where this is necessary.
+// If you need a security guarantee, these primordials need to be
+// deeply frozen anyway, and if you don’t need a security guarantee,
+// this is just plain paranoid.
+// However, this **might** have the nice side-effect of reducing the size of
+// the minified code by reducing x.call() to merely x()
+// See Mark Miller’s explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+var call = Function.call;
+function uncurryThis(f) {
+    return function () {
+        return call.apply(f, arguments);
+    };
+}
+// This is equivalent, but slower:
+// uncurryThis = Function_bind.bind(Function_bind.call);
+// http://jsperf.com/uncurrythis
+
+var array_slice = uncurryThis(Array.prototype.slice);
+
+var array_reduce = uncurryThis(
+    Array.prototype.reduce || function (callback, basis) {
+        var index = 0,
+            length = this.length;
+        // concerning the initial value, if one is not provided
+        if (arguments.length === 1) {
+            // seek to the first value in the array, accounting
+            // for the possibility that is is a sparse array
+            do {
+                if (index in this) {
+                    basis = this[index++];
+                    break;
+                }
+                if (++index >= length) {
+                    throw new TypeError();
+                }
+            } while (1);
+        }
+        // reduce
+        for (; index < length; index++) {
+            // account for the possibility that the array is sparse
+            if (index in this) {
+                basis = callback(basis, this[index], index);
+            }
+        }
+        return basis;
+    }
+);
+
+var array_indexOf = uncurryThis(
+    Array.prototype.indexOf || function (value) {
+        // not a very good shim, but good enough for our one use of it
+        for (var i = 0; i < this.length; i++) {
+            if (this[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+);
+
+var array_map = uncurryThis(
+    Array.prototype.map || function (callback, thisp) {
+        var self = this;
+        var collect = [];
+        array_reduce(self, function (undefined, value, index) {
+            collect.push(callback.call(thisp, value, index, self));
+        }, void 0);
+        return collect;
+    }
+);
+
+var object_create = Object.create || function (prototype) {
+    function Type() { }
+    Type.prototype = prototype;
+    return new Type();
+};
+
+var object_defineProperty = Object.defineProperty || function (obj, prop, descriptor) {
+    obj[prop] = descriptor.value;
+    return obj;
+};
+
+var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
+
+var object_keys = Object.keys || function (object) {
+    var keys = [];
+    for (var key in object) {
+        if (object_hasOwnProperty(object, key)) {
+            keys.push(key);
+        }
+    }
+    return keys;
+};
+
+var object_toString = uncurryThis(Object.prototype.toString);
+
+function isObject(value) {
+    return value === Object(value);
+}
+
+// generator related shims
+
+// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
+function isStopIteration(exception) {
+    return (
+        object_toString(exception) === "[object StopIteration]" ||
+        exception instanceof QReturnValue
+    );
+}
+
+// FIXME: Remove this helper and Q.return once ES6 generators are in
+// SpiderMonkey.
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+    QReturnValue = ReturnValue;
+} else {
+    QReturnValue = function (value) {
+        this.value = value;
+    };
+}
+
+// long stack traces
+
+var STACK_JUMP_SEPARATOR = "From previous event:";
+
+function makeStackTraceLong(error, promise) {
+    // If possible, transform the error stack trace by removing Node and Q
+    // cruft, then concatenating with the stack trace of `promise`. See #57.
+    if (hasStacks &&
+        promise.stack &&
+        typeof error === "object" &&
+        error !== null &&
+        error.stack
+    ) {
+        var stacks = [];
+        for (var p = promise; !!p; p = p.source) {
+            if (p.stack && (!error.__minimumStackCounter__ || error.__minimumStackCounter__ > p.stackCounter)) {
+                object_defineProperty(error, "__minimumStackCounter__", {value: p.stackCounter, configurable: true});
+                stacks.unshift(p.stack);
+            }
+        }
+        stacks.unshift(error.stack);
+
+        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
+        var stack = filterStackString(concatedStacks);
+        object_defineProperty(error, "stack", {value: stack, configurable: true});
+    }
+}
+
+function filterStackString(stackString) {
+    var lines = stackString.split("\n");
+    var desiredLines = [];
+    for (var i = 0; i < lines.length; ++i) {
+        var line = lines[i];
+
+        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
+            desiredLines.push(line);
+        }
+    }
+    return desiredLines.join("\n");
+}
+
+function isNodeFrame(stackLine) {
+    return stackLine.indexOf("(module.js:") !== -1 ||
+           stackLine.indexOf("(node.js:") !== -1;
+}
+
+function getFileNameAndLineNumber(stackLine) {
+    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
+    // In IE10 function name can have spaces ("Anonymous function") O_o
+    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
+    if (attempt1) {
+        return [attempt1[1], Number(attempt1[2])];
+    }
+
+    // Anonymous functions: "at filename:lineNumber:columnNumber"
+    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
+    if (attempt2) {
+        return [attempt2[1], Number(attempt2[2])];
+    }
+
+    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
+    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
+    if (attempt3) {
+        return [attempt3[1], Number(attempt3[2])];
+    }
+}
+
+function isInternalFrame(stackLine) {
+    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
+
+    if (!fileNameAndLineNumber) {
+        return false;
+    }
+
+    var fileName = fileNameAndLineNumber[0];
+    var lineNumber = fileNameAndLineNumber[1];
+
+    return fileName === qFileName &&
+        lineNumber >= qStartingLine &&
+        lineNumber <= qEndingLine;
+}
+
+// discover own file name and line number range for filtering stack
+// traces
+function captureLine() {
+    if (!hasStacks) {
+        return;
+    }
+
+    try {
+        throw new Error();
+    } catch (e) {
+        var lines = e.stack.split("\n");
+        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
+        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
+        if (!fileNameAndLineNumber) {
+            return;
+        }
+
+        qFileName = fileNameAndLineNumber[0];
+        return fileNameAndLineNumber[1];
+    }
+}
+
+function deprecate(callback, name, alternative) {
+    return function () {
+        if (typeof console !== "undefined" &&
+            typeof console.warn === "function") {
+            console.warn(name + " is deprecated, use " + alternative +
+                         " instead.", new Error("").stack);
+        }
+        return callback.apply(callback, arguments);
+    };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Constructs a promise for an immediate reference, passes promises through, or
+ * coerces promises from different systems.
+ * @param value immediate reference or promise
+ */
+function Q(value) {
+    // If the object is already a Promise, return it directly.  This enables
+    // the resolve function to both be used to created references from objects,
+    // but to tolerably coerce non-promises to promises.
+    if (value instanceof Promise) {
+        return value;
+    }
+
+    // assimilate thenables
+    if (isPromiseAlike(value)) {
+        return coerce(value);
+    } else {
+        return fulfill(value);
+    }
+}
+Q.resolve = Q;
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+Q.nextTick = nextTick;
+
+/**
+ * Controls whether or not long stack traces will be on
+ */
+Q.longStackSupport = false;
+
+/**
+ * The counter is used to determine the stopping point for building
+ * long stack traces. In makeStackTraceLong we walk backwards through
+ * the linked list of promises, only stacks which were created before
+ * the rejection are concatenated.
+ */
+var longStackCounter = 1;
+
+// enable long stacks if Q_DEBUG is set
+if (typeof process === "object" && process && process.env && process.env.Q_DEBUG) {
+    Q.longStackSupport = true;
+}
+
+/**
+ * Constructs a {promise, resolve, reject} object.
+ *
+ * `resolve` is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
+ * thenable, or invoke `reject` with the reason directly. To resolve the
+ * promise to another thenable, thus putting it in the same state, invoke
+ * `resolve` with that other thenable.
+ */
+Q.defer = defer;
+function defer() {
+    // if "messages" is an "Array", that indicates that the promise has not yet
+    // been resolved.  If it is "undefined", it has been resolved.  Each
+    // element of the messages array is itself an array of complete arguments to
+    // forward to the resolved promise.  We coerce the resolution value to a
+    // promise using the `resolve` function because it handles both fully
+    // non-thenable values and other thenables gracefully.
+    var messages = [], progressListeners = [], resolvedPromise;
+
+    var deferred = object_create(defer.prototype);
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, operands) {
+        var args = array_slice(arguments);
+        if (messages) {
+            messages.push(args);
+            if (op === "when" && operands[1]) { // progress operand
+                progressListeners.push(operands[1]);
+            }
+        } else {
+            Q.nextTick(function () {
+                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
+            });
+        }
+    };
+
+    // XXX deprecated
+    promise.valueOf = function () {
+        if (messages) {
+            return promise;
+        }
+        var nearerValue = nearer(resolvedPromise);
+        if (isPromise(nearerValue)) {
+            resolvedPromise = nearerValue; // shorten chain
+        }
+        return nearerValue;
+    };
+
+    promise.inspect = function () {
+        if (!resolvedPromise) {
+            return { state: "pending" };
+        }
+        return resolvedPromise.inspect();
+    };
+
+    if (Q.longStackSupport && hasStacks) {
+        try {
+            throw new Error();
+        } catch (e) {
+            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
+            // accessor around; that causes memory leaks as per GH-111. Just
+            // reify the stack trace as a string ASAP.
+            //
+            // At the same time, cut off the first line; it's always just
+            // "[object Promise]\n", as per the `toString`.
+            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
+            promise.stackCounter = longStackCounter++;
+        }
+    }
+
+    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
+    // consolidating them into `become`, since otherwise we'd create new
+    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
+
+    function become(newPromise) {
+        resolvedPromise = newPromise;
+
+        if (Q.longStackSupport && hasStacks) {
+            // Only hold a reference to the new promise if long stacks
+            // are enabled to reduce memory usage
+            promise.source = newPromise;
+        }
+
+        array_reduce(messages, function (undefined, message) {
+            Q.nextTick(function () {
+                newPromise.promiseDispatch.apply(newPromise, message);
+            });
+        }, void 0);
+
+        messages = void 0;
+        progressListeners = void 0;
+    }
+
+    deferred.promise = promise;
+    deferred.resolve = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(Q(value));
+    };
+
+    deferred.fulfill = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(fulfill(value));
+    };
+    deferred.reject = function (reason) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(reject(reason));
+    };
+    deferred.notify = function (progress) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        array_reduce(progressListeners, function (undefined, progressListener) {
+            Q.nextTick(function () {
+                progressListener(progress);
+            });
+        }, void 0);
+    };
+
+    return deferred;
+}
+
+/**
+ * Creates a Node-style callback that will resolve or reject the deferred
+ * promise.
+ * @returns a nodeback
+ */
+defer.prototype.makeNodeResolver = function () {
+    var self = this;
+    return function (error, value) {
+        if (error) {
+            self.reject(error);
+        } else if (arguments.length > 2) {
+            self.resolve(array_slice(arguments, 1));
+        } else {
+            self.resolve(value);
+        }
+    };
+};
+
+/**
+ * @param resolver {Function} a function that returns nothing and accepts
+ * the resolve, reject, and notify functions for a deferred.
+ * @returns a promise that may be resolved with the given resolve and reject
+ * functions, or rejected by a thrown exception in resolver
+ */
+Q.Promise = promise; // ES6
+Q.promise = promise;
+function promise(resolver) {
+    if (typeof resolver !== "function") {
+        throw new TypeError("resolver must be a function.");
+    }
+    var deferred = defer();
+    try {
+        resolver(deferred.resolve, deferred.reject, deferred.notify);
+    } catch (reason) {
+        deferred.reject(reason);
+    }
+    return deferred.promise;
+}
+
+promise.race = race; // ES6
+promise.all = all; // ES6
+promise.reject = reject; // ES6
+promise.resolve = Q; // ES6
+
+// XXX experimental.  This method is a way to denote that a local value is
+// serializable and should be immediately dispatched to a remote upon request,
+// instead of passing a reference.
+Q.passByCopy = function (object) {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return object;
+};
+
+Promise.prototype.passByCopy = function () {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return this;
+};
+
+/**
+ * If two promises eventually fulfill to the same value, promises that value,
+ * but otherwise rejects.
+ * @param x {Any*}
+ * @param y {Any*}
+ * @returns {Any*} a promise for x and y if they are the same, but a rejection
+ * otherwise.
+ *
+ */
+Q.join = function (x, y) {
+    return Q(x).join(y);
+};
+
+Promise.prototype.join = function (that) {
+    return Q([this, that]).spread(function (x, y) {
+        if (x === y) {
+            // TODO: "===" should be Object.is or equiv
+            return x;
+        } else {
+            throw new Error("Q can't join: not the same: " + x + " " + y);
+        }
+    });
+};
+
+/**
+ * Returns a promise for the first of an array of promises to become settled.
+ * @param answers {Array[Any*]} promises to race
+ * @returns {Any*} the first promise to be settled
+ */
+Q.race = race;
+function race(answerPs) {
+    return promise(function (resolve, reject) {
+        // Switch to this once we can assume at least ES5
+        // answerPs.forEach(function (answerP) {
+        //     Q(answerP).then(resolve, reject);
+        // });
+        // Use this in the meantime
+        for (var i = 0, len = answerPs.length; i < len; i++) {
+            Q(answerPs[i]).then(resolve, reject);
+        }
+    });
+}
+
+Promise.prototype.race = function () {
+    return this.then(Q.race);
+};
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function.  The descriptor contains methods like when(rejected), get(name),
+ * set(name, value), post(name, args), and delete(name), which all
+ * return either a value, a promise for a value, or a rejection.  The fallback
+ * accepts the operation name, a resolver, and any further arguments that would
+ * have been forwarded to the appropriate method above had a method been
+ * provided with the proper name.  The API makes no guarantees about the nature
+ * of the returned object, apart from that it is usable whereever promises are
+ * bought and sold.
+ */
+Q.makePromise = Promise;
+function Promise(descriptor, fallback, inspect) {
+    if (fallback === void 0) {
+        fallback = function (op) {
+            return reject(new Error(
+                "Promise does not support operation: " + op
+            ));
+        };
+    }
+    if (inspect === void 0) {
+        inspect = function () {
+            return {state: "unknown"};
+        };
+    }
+
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, args) {
+        var result;
+        try {
+            if (descriptor[op]) {
+                result = descriptor[op].apply(promise, args);
+            } else {
+                result = fallback.call(promise, op, args);
+            }
+        } catch (exception) {
+            result = reject(exception);
+        }
+        if (resolve) {
+            resolve(result);
+        }
+    };
+
+    promise.inspect = inspect;
+
+    // XXX deprecated `valueOf` and `exception` support
+    if (inspect) {
+        var inspected = inspect();
+        if (inspected.state === "rejected") {
+            promise.exception = inspected.reason;
+        }
+
+        promise.valueOf = function () {
+            var inspected = inspect();
+            if (inspected.state === "pending" ||
+                inspected.state === "rejected") {
+                return promise;
+            }
+            return inspected.value;
+        };
+    }
+
+    return promise;
+}
+
+Promise.prototype.toString = function () {
+    return "[object Promise]";
+};
+
+Promise.prototype.then = function (fulfilled, rejected, progressed) {
+    var self = this;
+    var deferred = defer();
+    var done = false;   // ensure the untrusted promise makes at most a
+                        // single call to one of the callbacks
+
+    function _fulfilled(value) {
+        try {
+            return typeof fulfilled === "function" ? fulfilled(value) : value;
+        } catch (exception) {
+            return reject(exception);
+        }
+    }
+
+    function _rejected(exception) {
+        if (typeof rejected === "function") {
+            makeStackTraceLong(exception, self);
+            try {
+                return rejected(exception);
+            } catch (newException) {
+                return reject(newException);
+            }
+        }
+        return reject(exception);
+    }
+
+    function _progressed(value) {
+        return typeof progressed === "function" ? progressed(value) : value;
+    }
+
+    Q.nextTick(function () {
+        self.promiseDispatch(function (value) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_fulfilled(value));
+        }, "when", [function (exception) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_rejected(exception));
+        }]);
+    });
+
+    // Progress propagator need to be attached in the current tick.
+    self.promiseDispatch(void 0, "when", [void 0, function (value) {
+        var newValue;
+        var threw = false;
+        try {
+            newValue = _progressed(value);
+        } catch (e) {
+            threw = true;
+            if (Q.onerror) {
+                Q.onerror(e);
+            } else {
+                throw e;
+            }
+        }
+
+        if (!threw) {
+            deferred.notify(newValue);
+        }
+    }]);
+
+    return deferred.promise;
+};
+
+Q.tap = function (promise, callback) {
+    return Q(promise).tap(callback);
+};
+
+/**
+ * Works almost like "finally", but not called for rejections.
+ * Original resolution value is passed through callback unaffected.
+ * Callback may return a promise that will be awaited for.
+ * @param {Function} callback
+ * @returns {Q.Promise}
+ * @example
+ * doSomething()
+ *   .then(...)
+ *   .tap(console.log)
+ *   .then(...);
+ */
+Promise.prototype.tap = function (callback) {
+    callback = Q(callback);
+
+    return this.then(function (value) {
+        return callback.fcall(value).thenResolve(value);
+    });
+};
+
+/**
+ * Registers an observer on a promise.
+ *
+ * Guarantees:
+ *
+ * 1. that fulfilled and rejected will be called only once.
+ * 2. that either the fulfilled callback or the rejected callback will be
+ *    called, but not both.
+ * 3. that fulfilled and rejected will not be called in this turn.
+ *
+ * @param value      promise or immediate reference to observe
+ * @param fulfilled  function to be called with the fulfilled value
+ * @param rejected   function to be called with the rejection exception
+ * @param progressed function to be called on any progress notifications
+ * @return promise for the return value from the invoked callback
+ */
+Q.when = when;
+function when(value, fulfilled, rejected, progressed) {
+    return Q(value).then(fulfilled, rejected, progressed);
+}
+
+Promise.prototype.thenResolve = function (value) {
+    return this.then(function () { return value; });
+};
+
+Q.thenResolve = function (promise, value) {
+    return Q(promise).thenResolve(value);
+};
+
+Promise.prototype.thenReject = function (reason) {
+    return this.then(function () { throw reason; });
+};
+
+Q.thenReject = function (promise, reason) {
+    return Q(promise).thenReject(reason);
+};
+
+/**
+ * If an object is not a promise, it is as "near" as possible.
+ * If a promise is rejected, it is as "near" as possible too.
+ * If it’s a fulfilled promise, the fulfillment value is nearer.
+ * If it’s a deferred promise and the deferred has been resolved, the
+ * resolution is "nearer".
+ * @param object
+ * @returns most resolved (nearest) form of the object
+ */
+
+// XXX should we re-do this?
+Q.nearer = nearer;
+function nearer(value) {
+    if (isPromise(value)) {
+        var inspected = value.inspect();
+        if (inspected.state === "fulfilled") {
+            return inspected.value;
+        }
+    }
+    return value;
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+Q.isPromise = isPromise;
+function isPromise(object) {
+    return object instanceof Promise;
+}
+
+Q.isPromiseAlike = isPromiseAlike;
+function isPromiseAlike(object) {
+    return isObject(object) && typeof object.then === "function";
+}
+
+/**
+ * @returns whether the given object is a pending promise, meaning not
+ * fulfilled or rejected.
+ */
+Q.isPending = isPending;
+function isPending(object) {
+    return isPromise(object) && object.inspect().state === "pending";
+}
+
+Promise.prototype.isPending = function () {
+    return this.inspect().state === "pending";
+};
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+Q.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+    return !isPromise(object) || object.inspect().state === "fulfilled";
+}
+
+Promise.prototype.isFulfilled = function () {
+    return this.inspect().state === "fulfilled";
+};
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+Q.isRejected = isRejected;
+function isRejected(object) {
+    return isPromise(object) && object.inspect().state === "rejected";
+}
+
+Promise.prototype.isRejected = function () {
+    return this.inspect().state === "rejected";
+};
+
+//// BEGIN UNHANDLED REJECTION TRACKING
+
+// This promise library consumes exceptions thrown in handlers so they can be
+// handled by a subsequent promise.  The exceptions get added to this array when
+// they are created, and removed when they are handled.  Note that in ES6 or
+// shimmed environments, this would naturally be a `Set`.
+var unhandledReasons = [];
+var unhandledRejections = [];
+var reportedUnhandledRejections = [];
+var trackUnhandledRejections = true;
+
+function resetUnhandledRejections() {
+    unhandledReasons.length = 0;
+    unhandledRejections.length = 0;
+
+    if (!trackUnhandledRejections) {
+        trackUnhandledRejections = true;
+    }
+}
+
+function trackRejection(promise, reason) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+    if (typeof process === "object" && typeof process.emit === "function") {
+        Q.nextTick.runAfter(function () {
+            if (array_indexOf(unhandledRejections, promise) !== -1) {
+                process.emit("unhandledRejection", reason, promise);
+                reportedUnhandledRejections.push(promise);
+            }
+        });
+    }
+
+    unhandledRejections.push(promise);
+    if (reason && typeof reason.stack !== "undefined") {
+        unhandledReasons.push(reason.stack);
+    } else {
+        unhandledReasons.push("(no stack) " + reason);
+    }
+}
+
+function untrackRejection(promise) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    var at = array_indexOf(unhandledRejections, promise);
+    if (at !== -1) {
+        if (typeof process === "object" && typeof process.emit === "function") {
+            Q.nextTick.runAfter(function () {
+                var atReport = array_indexOf(reportedUnhandledRejections, promise);
+                if (atReport !== -1) {
+                    process.emit("rejectionHandled", unhandledReasons[at], promise);
+                    reportedUnhandledRejections.splice(atReport, 1);
+                }
+            });
+        }
+        unhandledRejections.splice(at, 1);
+        unhandledReasons.splice(at, 1);
+    }
+}
+
+Q.resetUnhandledRejections = resetUnhandledRejections;
+
+Q.getUnhandledReasons = function () {
+    // Make a copy so that consumers can't interfere with our internal state.
+    return unhandledReasons.slice();
+};
+
+Q.stopUnhandledRejectionTracking = function () {
+    resetUnhandledRejections();
+    trackUnhandledRejections = false;
+};
+
+resetUnhandledRejections();
+
+//// END UNHANDLED REJECTION TRACKING
+
+/**
+ * Constructs a rejected promise.
+ * @param reason value describing the failure
+ */
+Q.reject = reject;
+function reject(reason) {
+    var rejection = Promise({
+        "when": function (rejected) {
+            // note that the error has been handled
+            if (rejected) {
+                untrackRejection(this);
+            }
+            return rejected ? rejected(reason) : this;
+        }
+    }, function fallback() {
+        return this;
+    }, function inspect() {
+        return { state: "rejected", reason: reason };
+    });
+
+    // Note that the reason has not been handled.
+    trackRejection(rejection, reason);
+
+    return rejection;
+}
+
+/**
+ * Constructs a fulfilled promise for an immediate reference.
+ * @param value immediate reference
+ */
+Q.fulfill = fulfill;
+function fulfill(value) {
+    return Promise({
+        "when": function () {
+            return value;
+        },
+        "get": function (name) {
+            return value[name];
+        },
+        "set": function (name, rhs) {
+            value[name] = rhs;
+        },
+        "delete": function (name) {
+            delete value[name];
+        },
+        "post": function (name, args) {
+            // Mark Miller proposes that post with no name should apply a
+            // promised function.
+            if (name === null || name === void 0) {
+                return value.apply(void 0, args);
+            } else {
+                return value[name].apply(value, args);
+            }
+        },
+        "apply": function (thisp, args) {
+            return value.apply(thisp, args);
+        },
+        "keys": function () {
+            return object_keys(value);
+        }
+    }, void 0, function inspect() {
+        return { state: "fulfilled", value: value };
+    });
+}
+
+/**
+ * Converts thenables to Q promises.
+ * @param promise thenable promise
+ * @returns a Q promise
+ */
+function coerce(promise) {
+    var deferred = defer();
+    Q.nextTick(function () {
+        try {
+            promise.then(deferred.resolve, deferred.reject, deferred.notify);
+        } catch (exception) {
+            deferred.reject(exception);
+        }
+    });
+    return deferred.promise;
+}
+
+/**
+ * Annotates an object such that it will never be
+ * transferred away from this process over any promise
+ * communication channel.
+ * @param object
+ * @returns promise a wrapping of that object that
+ * additionally responds to the "isDef" message
+ * without a rejection.
+ */
+Q.master = master;
+function master(object) {
+    return Promise({
+        "isDef": function () {}
+    }, function fallback(op, args) {
+        return dispatch(object, op, args);
+    }, function () {
+        return Q(object).inspect();
+    });
+}
+
+/**
+ * Spreads the values of a promised array of arguments into the
+ * fulfillment callback.
+ * @param fulfilled callback that receives variadic arguments from the
+ * promised array
+ * @param rejected callback that receives the exception if the promise
+ * is rejected.
+ * @returns a promise for the return value or thrown exception of
+ * either callback.
+ */
+Q.spread = spread;
+function spread(value, fulfilled, rejected) {
+    return Q(value).spread(fulfilled, rejected);
+}
+
+Promise.prototype.spread = function (fulfilled, rejected) {
+    return this.all().then(function (array) {
+        return fulfilled.apply(void 0, array);
+    }, rejected);
+};
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators.  Although generators are only part
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
+ * errors in older engines.  This code should continue to work and will
+ * in fact improve over time as the language improves.
+ *
+ * ES6 generators are currently part of V8 version 3.19 with the
+ * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
+ * for longer, but under an older Python-inspired form.  This function
+ * works on both kinds of generators.
+ *
+ * Decorates a generator function such that:
+ *  - it may yield promises
+ *  - execution will continue when that promise is fulfilled
+ *  - the value of the yield expression will be the fulfilled value
+ *  - it returns a promise for the return value (when the generator
+ *    stops iterating)
+ *  - the decorated function returns a promise for the return value
+ *    of the generator or the first rejected promise among those
+ *    yielded.
+ *  - if an error is thrown in the generator, it propagates through
+ *    every following yield until it is caught, or until it escapes
+ *    the generator function altogether, and is translated into a
+ *    rejection for the promise returned by the decorated generator.
+ */
+Q.async = async;
+function async(makeGenerator) {
+    return function () {
+        // when verb is "send", arg is a value
+        // when verb is "throw", arg is an exception
+        function continuer(verb, arg) {
+            var result;
+
+            // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
+            // engine that has a deployed base of browsers that support generators.
+            // However, SM's generators use the Python-inspired semantics of
+            // outdated ES6 drafts.  We would like to support ES6, but we'd also
+            // like to make it possible to use generators in deployed browsers, so
+            // we also support Python-style generators.  At some point we can remove
+            // this block.
+
+            if (typeof StopIteration === "undefined") {
+                // ES6 Generators
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    return reject(exception);
+                }
+                if (result.done) {
+                    return Q(result.value);
+                } else {
+                    return when(result.value, callback, errback);
+                }
+            } else {
+                // SpiderMonkey Generators
+                // FIXME: Remove this case when SM does ES6 generators.
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    if (isStopIteration(exception)) {
+                        return Q(exception.value);
+                    } else {
+                        return reject(exception);
+                    }
+                }
+                return when(result, callback, errback);
+            }
+        }
+        var generator = makeGenerator.apply(this, arguments);
+        var callback = continuer.bind(continuer, "next");
+        var errback = continuer.bind(continuer, "throw");
+        return callback();
+    };
+}
+
+/**
+ * The spawn function is a small wrapper around async that immediately
+ * calls the generator and also ends the promise chain, so that any
+ * unhandled errors are thrown instead of forwarded to the error
+ * handler. This is useful because it's extremely common to run
+ * generators at the top-level to work with libraries.
+ */
+Q.spawn = spawn;
+function spawn(makeGenerator) {
+    Q.done(Q.async(makeGenerator)());
+}
+
+// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ *
+ * This interface is a stop-gap measure to support generator return
+ * values in older Firefox/SpiderMonkey.  In browsers that support ES6
+ * generators like Chromium 29, just use "return" in your generator
+ * functions.
+ *
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * // ES6 style
+ * Q.async(function* () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      return foo + bar;
+ * })
+ * // Older SpiderMonkey style
+ * Q.async(function () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      Q.return(foo + bar);
+ * })
+ */
+Q["return"] = _return;
+function _return(value) {
+    throw new QReturnValue(value);
+}
+
+/**
+ * The promised function decorator ensures that any promise arguments
+ * are settled and passed as values (`this` is also settled and passed
+ * as a value).  It will also ensure that the result of a function is
+ * always a promise.
+ *
+ * @example
+ * var add = Q.promised(function (a, b) {
+ *     return a + b;
+ * });
+ * add(Q(a), Q(B));
+ *
+ * @param {function} callback The function to decorate
+ * @returns {function} a function that has been decorated.
+ */
+Q.promised = promised;
+function promised(callback) {
+    return function () {
+        return spread([this, all(arguments)], function (self, args) {
+            return callback.apply(self, args);
+        });
+    };
+}
+
+/**
+ * sends a message to a value in a future turn
+ * @param object* the recipient
+ * @param op the name of the message operation, e.g., "when",
+ * @param args further arguments to be forwarded to the operation
+ * @returns result {Promise} a promise for the result of the operation
+ */
+Q.dispatch = dispatch;
+function dispatch(object, op, args) {
+    return Q(object).dispatch(op, args);
+}
+
+Promise.prototype.dispatch = function (op, args) {
+    var self = this;
+    var deferred = defer();
+    Q.nextTick(function () {
+        self.promiseDispatch(deferred.resolve, op, args);
+    });
+    return deferred.promise;
+};
+
+/**
+ * Gets the value of a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to get
+ * @return promise for the property value
+ */
+Q.get = function (object, key) {
+    return Q(object).dispatch("get", [key]);
+};
+
+Promise.prototype.get = function (key) {
+    return this.dispatch("get", [key]);
+};
+
+/**
+ * Sets the value of a property in a future turn.
+ * @param object    promise or immediate reference for object object
+ * @param name      name of property to set
+ * @param value     new value of property
+ * @return promise for the return value
+ */
+Q.set = function (object, key, value) {
+    return Q(object).dispatch("set", [key, value]);
+};
+
+Promise.prototype.set = function (key, value) {
+    return this.dispatch("set", [key, value]);
+};
+
+/**
+ * Deletes a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to delete
+ * @return promise for the return value
+ */
+Q.del = // XXX legacy
+Q["delete"] = function (object, key) {
+    return Q(object).dispatch("delete", [key]);
+};
+
+Promise.prototype.del = // XXX legacy
+Promise.prototype["delete"] = function (key) {
+    return this.dispatch("delete", [key]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param value     a value to post, typically an array of
+ *                  invocation arguments for promises that
+ *                  are ultimately backed with `resolve` values,
+ *                  as opposed to those backed with URLs
+ *                  wherein the posted value can be any
+ *                  JSON serializable object.
+ * @return promise for the return value
+ */
+// bound locally because it is used by other methods
+Q.mapply = // XXX As proposed by "Redsandro"
+Q.post = function (object, name, args) {
+    return Q(object).dispatch("post", [name, args]);
+};
+
+Promise.prototype.mapply = // XXX As proposed by "Redsandro"
+Promise.prototype.post = function (name, args) {
+    return this.dispatch("post", [name, args]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param ...args   array of invocation arguments
+ * @return promise for the return value
+ */
+Q.send = // XXX Mark Miller's proposed parlance
+Q.mcall = // XXX As proposed by "Redsandro"
+Q.invoke = function (object, name /*...args*/) {
+    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
+};
+
+Promise.prototype.send = // XXX Mark Miller's proposed parlance
+Promise.prototype.mcall = // XXX As proposed by "Redsandro"
+Promise.prototype.invoke = function (name /*...args*/) {
+    return this.dispatch("post", [name, array_slice(arguments, 1)]);
+};
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param args      array of application arguments
+ */
+Q.fapply = function (object, args) {
+    return Q(object).dispatch("apply", [void 0, args]);
+};
+
+Promise.prototype.fapply = function (args) {
+    return this.dispatch("apply", [void 0, args]);
+};
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q["try"] =
+Q.fcall = function (object /* ...args*/) {
+    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
+};
+
+Promise.prototype.fcall = function (/*...args*/) {
+    return this.dispatch("apply", [void 0, array_slice(arguments)]);
+};
+
+/**
+ * Binds the promised function, transforming return values into a fulfilled
+ * promise and thrown errors into a rejected one.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q.fbind = function (object /*...args*/) {
+    var promise = Q(object);
+    var args = array_slice(arguments, 1);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+Promise.prototype.fbind = function (/*...args*/) {
+    var promise = this;
+    var args = array_slice(arguments);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+
+/**
+ * Requests the names of the owned properties of a promised
+ * object in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @return promise for the keys of the eventually settled object
+ */
+Q.keys = function (object) {
+    return Q(object).dispatch("keys", []);
+};
+
+Promise.prototype.keys = function () {
+    return this.dispatch("keys", []);
+};
+
+/**
+ * Turns an array of promises into a promise for an array.  If any of
+ * the promises gets rejected, the whole array is rejected immediately.
+ * @param {Array*} an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns a promise for an array of the corresponding values
+ */
+// By Mark Miller
+// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
+Q.all = all;
+function all(promises) {
+    return when(promises, function (promises) {
+        var pendingCount = 0;
+        var deferred = defer();
+        array_reduce(promises, function (undefined, promise, index) {
+            var snapshot;
+            if (
+                isPromise(promise) &&
+                (snapshot = promise.inspect()).state === "fulfilled"
+            ) {
+                promises[index] = snapshot.value;
+            } else {
+                ++pendingCount;
+                when(
+                    promise,
+                    function (value) {
+                        promises[index] = value;
+                        if (--pendingCount === 0) {
+                            deferred.resolve(promises);
+                        }
+                    },
+                    deferred.reject,
+                    function (progress) {
+                        deferred.notify({ index: index, value: progress });
+                    }
+                );
+            }
+        }, void 0);
+        if (pendingCount === 0) {
+            deferred.resolve(promises);
+        }
+        return deferred.promise;
+    });
+}
+
+Promise.prototype.all = function () {
+    return all(this);
+};
+
+/**
+ * Returns the first resolved promise of an array. Prior rejected promises are
+ * ignored.  Rejects only if all promises are rejected.
+ * @param {Array*} an array containing values or promises for values
+ * @returns a promise fulfilled with the value of the first resolved promise,
+ * or a rejected promise if all promises are rejected.
+ */
+Q.any = any;
+
+function any(promises) {
+    if (promises.length === 0) {
+        return Q.resolve();
+    }
+
+    var deferred = Q.defer();
+    var pendingCount = 0;
+    array_reduce(promises, function (prev, current, index) {
+        var promise = promises[index];
+
+        pendingCount++;
+
+        when(promise, onFulfilled, onRejected, onProgress);
+        function onFulfilled(result) {
+            deferred.resolve(result);
+        }
+        function onRejected(err) {
+            pendingCount--;
+            if (pendingCount === 0) {
+                var rejection = err || new Error("" + err);
+
+                rejection.message = ("Q can't get fulfillment value from any promise, all " +
+                    "promises were rejected. Last error message: " + rejection.message);
+
+                deferred.reject(rejection);
+            }
+        }
+        function onProgress(progress) {
+            deferred.notify({
+                index: index,
+                value: progress
+            });
+        }
+    }, undefined);
+
+    return deferred.promise;
+}
+
+Promise.prototype.any = function () {
+    return any(this);
+};
+
+/**
+ * Waits for all promises to be settled, either fulfilled or
+ * rejected.  This is distinct from `all` since that would stop
+ * waiting at the first rejection.  The promise returned by
+ * `allResolved` will never be rejected.
+ * @param promises a promise for an array (or an array) of promises
+ * (or values)
+ * @return a promise for an array of promises
+ */
+Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
+function allResolved(promises) {
+    return when(promises, function (promises) {
+        promises = array_map(promises, Q);
+        return when(all(array_map(promises, function (promise) {
+            return when(promise, noop, noop);
+        })), function () {
+            return promises;
+        });
+    });
+}
+
+Promise.prototype.allResolved = function () {
+    return allResolved(this);
+};
+
+/**
+ * @see Promise#allSettled
+ */
+Q.allSettled = allSettled;
+function allSettled(promises) {
+    return Q(promises).allSettled();
+}
+
+/**
+ * Turns an array of promises into a promise for an array of their states (as
+ * returned by `inspect`) when they have all settled.
+ * @param {Array[Any*]} values an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns {Array[State]} an array of states for the respective values.
+ */
+Promise.prototype.allSettled = function () {
+    return this.then(function (promises) {
+        return all(array_map(promises, function (promise) {
+            promise = Q(promise);
+            function regardless() {
+                return promise.inspect();
+            }
+            return promise.then(regardless, regardless);
+        }));
+    });
+};
+
+/**
+ * Captures the failure of a promise, giving an oportunity to recover
+ * with a callback.  If the given promise is fulfilled, the returned
+ * promise is fulfilled.
+ * @param {Any*} promise for something
+ * @param {Function} callback to fulfill the returned promise if the
+ * given promise is rejected
+ * @returns a promise for the return value of the callback
+ */
+Q.fail = // XXX legacy
+Q["catch"] = function (object, rejected) {
+    return Q(object).then(void 0, rejected);
+};
+
+Promise.prototype.fail = // XXX legacy
+Promise.prototype["catch"] = function (rejected) {
+    return this.then(void 0, rejected);
+};
+
+/**
+ * Attaches a listener that can respond to progress notifications from a
+ * promise's originating deferred. This listener receives the exact arguments
+ * passed to ``deferred.notify``.
+ * @param {Any*} promise for something
+ * @param {Function} callback to receive any progress notifications
+ * @returns the given promise, unchanged
+ */
+Q.progress = progress;
+function progress(object, progressed) {
+    return Q(object).then(void 0, void 0, progressed);
+}
+
+Promise.prototype.progress = function (progressed) {
+    return this.then(void 0, void 0, progressed);
+};
+
+/**
+ * Provides an opportunity to observe the settling of a promise,
+ * regardless of whether the promise is fulfilled or rejected.  Forwards
+ * the resolution to the returned promise when the callback is done.
+ * The callback can return a promise to defer completion.
+ * @param {Any*} promise
+ * @param {Function} callback to observe the resolution of the given
+ * promise, takes no arguments.
+ * @returns a promise for the resolution of the given promise when
+ * ``fin`` is done.
+ */
+Q.fin = // XXX legacy
+Q["finally"] = function (object, callback) {
+    return Q(object)["finally"](callback);
+};
+
+Promise.prototype.fin = // XXX legacy
+Promise.prototype["finally"] = function (callback) {
+    if (!callback || typeof callback.apply !== "function") {
+        throw new Error("Q can't apply finally callback");
+    }
+    callback = Q(callback);
+    return this.then(function (value) {
+        return callback.fcall().then(function () {
+            return value;
+        });
+    }, function (reason) {
+        // TODO attempt to recycle the rejection with "this".
+        return callback.fcall().then(function () {
+            throw reason;
+        });
+    });
+};
+
+/**
+ * Terminates a chain of promises, forcing rejections to be
+ * thrown as exceptions.
+ * @param {Any*} promise at the end of a chain of promises
+ * @returns nothing
+ */
+Q.done = function (object, fulfilled, rejected, progress) {
+    return Q(object).done(fulfilled, rejected, progress);
+};
+
+Promise.prototype.done = function (fulfilled, rejected, progress) {
+    var onUnhandledError = function (error) {
+        // forward to a future turn so that ``when``
+        // does not catch it and turn it into a rejection.
+        Q.nextTick(function () {
+            makeStackTraceLong(error, promise);
+            if (Q.onerror) {
+                Q.onerror(error);
+            } else {
+                throw error;
+            }
+        });
+    };
+
+    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
+    var promise = fulfilled || rejected || progress ?
+        this.then(fulfilled, rejected, progress) :
+        this;
+
+    if (typeof process === "object" && process && process.domain) {
+        onUnhandledError = process.domain.bind(onUnhandledError);
+    }
+
+    promise.then(void 0, onUnhandledError);
+};
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @param {Any*} custom error message or Error object (optional)
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+Q.timeout = function (object, ms, error) {
+    return Q(object).timeout(ms, error);
+};
+
+Promise.prototype.timeout = function (ms, error) {
+    var deferred = defer();
+    var timeoutId = setTimeout(function () {
+        if (!error || "string" === typeof error) {
+            error = new Error(error || "Timed out after " + ms + " ms");
+            error.code = "ETIMEDOUT";
+        }
+        deferred.reject(error);
+    }, ms);
+
+    this.then(function (value) {
+        clearTimeout(timeoutId);
+        deferred.resolve(value);
+    }, function (exception) {
+        clearTimeout(timeoutId);
+        deferred.reject(exception);
+    }, deferred.notify);
+
+    return deferred.promise;
+};
+
+/**
+ * Returns a promise for the given value (or promised value), some
+ * milliseconds after it resolved. Passes rejections immediately.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after milliseconds
+ * time has elapsed since the resolution of the given promise.
+ * If the given promise rejects, that is passed immediately.
+ */
+Q.delay = function (object, timeout) {
+    if (timeout === void 0) {
+        timeout = object;
+        object = void 0;
+    }
+    return Q(object).delay(timeout);
+};
+
+Promise.prototype.delay = function (timeout) {
+    return this.then(function (value) {
+        var deferred = defer();
+        setTimeout(function () {
+            deferred.resolve(value);
+        }, timeout);
+        return deferred.promise;
+    });
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided as an array, and returns a promise.
+ *
+ *      Q.nfapply(FS.readFile, [__filename])
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfapply = function (callback, args) {
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfapply = function (args) {
+    var deferred = defer();
+    var nodeArgs = array_slice(args);
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided individually, and returns a promise.
+ * @example
+ * Q.nfcall(FS.readFile, __filename)
+ * .then(function (content) {
+ * })
+ *
+ */
+Q.nfcall = function (callback /*...args*/) {
+    var args = array_slice(arguments, 1);
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfcall = function (/*...args*/) {
+    var nodeArgs = array_slice(arguments);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ * @example
+ * Q.nfbind(FS.readFile, __filename)("utf-8")
+ * .then(console.log)
+ * .done()
+ */
+Q.nfbind =
+Q.denodeify = function (callback /*...args*/) {
+    if (callback === undefined) {
+        throw new Error("Q can't wrap an undefined function");
+    }
+    var baseArgs = array_slice(arguments, 1);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        Q(callback).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nfbind =
+Promise.prototype.denodeify = function (/*...args*/) {
+    var args = array_slice(arguments);
+    args.unshift(this);
+    return Q.denodeify.apply(void 0, args);
+};
+
+Q.nbind = function (callback, thisp /*...args*/) {
+    var baseArgs = array_slice(arguments, 2);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        function bound() {
+            return callback.apply(thisp, arguments);
+        }
+        Q(bound).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nbind = function (/*thisp, ...args*/) {
+    var args = array_slice(arguments, 0);
+    args.unshift(this);
+    return Q.nbind.apply(void 0, args);
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback with a given array of arguments, plus a provided callback.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param {Array} args arguments to pass to the method; the callback
+ * will be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nmapply = // XXX As proposed by "Redsandro"
+Q.npost = function (object, name, args) {
+    return Q(object).npost(name, args);
+};
+
+Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
+Promise.prototype.npost = function (name, args) {
+    var nodeArgs = array_slice(args || []);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback, forwarding the given variadic arguments, plus a provided
+ * callback argument.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param ...args arguments to pass to the method; the callback will
+ * be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nsend = // XXX Based on Mark Miller's proposed "send"
+Q.nmcall = // XXX Based on "Redsandro's" proposal
+Q.ninvoke = function (object, name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 2);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
+Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
+Promise.prototype.ninvoke = function (name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 1);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * If a function would like to support both Node continuation-passing-style and
+ * promise-returning-style, it can end its internal promise chain with
+ * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
+ * elects to use a nodeback, the result will be sent there.  If they do not
+ * pass a nodeback, they will receive the result promise.
+ * @param object a result (or a promise for a result)
+ * @param {Function} nodeback a Node.js-style callback
+ * @returns either the promise or nothing
+ */
+Q.nodeify = nodeify;
+function nodeify(object, nodeback) {
+    return Q(object).nodeify(nodeback);
+}
+
+Promise.prototype.nodeify = function (nodeback) {
+    if (nodeback) {
+        this.then(function (value) {
+            Q.nextTick(function () {
+                nodeback(null, value);
+            });
+        }, function (error) {
+            Q.nextTick(function () {
+                nodeback(error);
+            });
+        });
+    } else {
+        return this;
+    }
+};
+
+Q.noConflict = function() {
+    throw new Error("Q.noConflict only works when Q is used as a global");
+};
+
+// All code before this point will be filtered from stack traces.
+var qEndingLine = captureLine();
+
+return Q;
+
+});
diff --git a/node_modules/q/queue.js b/node_modules/q/queue.js
new file mode 100644
index 0000000000000000000000000000000000000000..1505fd0b369a44ee62081501b5a0454f11b9d918
--- /dev/null
+++ b/node_modules/q/queue.js
@@ -0,0 +1,35 @@
+
+var Q = require("./q");
+
+module.exports = Queue;
+function Queue() {
+    var ends = Q.defer();
+    var closed = Q.defer();
+    return {
+        put: function (value) {
+            var next = Q.defer();
+            ends.resolve({
+                head: value,
+                tail: next.promise
+            });
+            ends.resolve = next.resolve;
+        },
+        get: function () {
+            var result = ends.promise.get("head");
+            ends.promise = ends.promise.get("tail");
+            return result.fail(function (error) {
+                closed.resolve(error);
+                throw error;
+            });
+        },
+        closed: closed.promise,
+        close: function (error) {
+            error = error || new Error("Can't get value from closed queue");
+            var end = {head: Q.reject(error)};
+            end.tail = end;
+            ends.resolve(end);
+            return closed.promise;
+        }
+    };
+}
+
diff --git a/node_modules/readable-stream/.npmignore b/node_modules/readable-stream/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..38344f87a627666b74f24036111558589b0bf508
--- /dev/null
+++ b/node_modules/readable-stream/.npmignore
@@ -0,0 +1,5 @@
+build/
+test/
+examples/
+fs.js
+zlib.js
\ No newline at end of file
diff --git a/node_modules/readable-stream/LICENSE b/node_modules/readable-stream/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e3d4e695a4cff2bf9c1da6c69841ca22bc9f0224
--- /dev/null
+++ b/node_modules/readable-stream/LICENSE
@@ -0,0 +1,18 @@
+Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/node_modules/readable-stream/README.md b/node_modules/readable-stream/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3fb3e8023eb3bd323487a2317defcce20b310b94
--- /dev/null
+++ b/node_modules/readable-stream/README.md
@@ -0,0 +1,15 @@
+# readable-stream
+
+***Node-core streams for userland***
+
+[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/)
+[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/)
+
+This package is a mirror of the Streams2 and Streams3 implementations in Node-core.
+
+If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core.
+
+**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12.
+
+**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"`
+
diff --git a/node_modules/readable-stream/duplex.js b/node_modules/readable-stream/duplex.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca807af87620dd789b4f72984b813618fc1a76ff
--- /dev/null
+++ b/node_modules/readable-stream/duplex.js
@@ -0,0 +1 @@
+module.exports = require("./lib/_stream_duplex.js")
diff --git a/node_modules/readable-stream/lib/_stream_duplex.js b/node_modules/readable-stream/lib/_stream_duplex.js
new file mode 100644
index 0000000000000000000000000000000000000000..b513d61a963a4099d226be27850bb7c6edb8fc55
--- /dev/null
+++ b/node_modules/readable-stream/lib/_stream_duplex.js
@@ -0,0 +1,89 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// a duplex stream is just a stream that is both readable and writable.
+// Since JS doesn't have multiple prototypal inheritance, this class
+// prototypally inherits from Readable, and then parasitically from
+// Writable.
+
+module.exports = Duplex;
+
+/*<replacement>*/
+var objectKeys = Object.keys || function (obj) {
+  var keys = [];
+  for (var key in obj) keys.push(key);
+  return keys;
+}
+/*</replacement>*/
+
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+var Readable = require('./_stream_readable');
+var Writable = require('./_stream_writable');
+
+util.inherits(Duplex, Readable);
+
+forEach(objectKeys(Writable.prototype), function(method) {
+  if (!Duplex.prototype[method])
+    Duplex.prototype[method] = Writable.prototype[method];
+});
+
+function Duplex(options) {
+  if (!(this instanceof Duplex))
+    return new Duplex(options);
+
+  Readable.call(this, options);
+  Writable.call(this, options);
+
+  if (options && options.readable === false)
+    this.readable = false;
+
+  if (options && options.writable === false)
+    this.writable = false;
+
+  this.allowHalfOpen = true;
+  if (options && options.allowHalfOpen === false)
+    this.allowHalfOpen = false;
+
+  this.once('end', onend);
+}
+
+// the no-half-open enforcer
+function onend() {
+  // if we allow half-open state, or if the writable side ended,
+  // then we're ok.
+  if (this.allowHalfOpen || this._writableState.ended)
+    return;
+
+  // no more data can be written.
+  // But allow more writes to happen in this tick.
+  process.nextTick(this.end.bind(this));
+}
+
+function forEach (xs, f) {
+  for (var i = 0, l = xs.length; i < l; i++) {
+    f(xs[i], i);
+  }
+}
diff --git a/node_modules/readable-stream/lib/_stream_passthrough.js b/node_modules/readable-stream/lib/_stream_passthrough.js
new file mode 100644
index 0000000000000000000000000000000000000000..895ca50a1d208a8e0a19fb77f61e7264fc9b5a72
--- /dev/null
+++ b/node_modules/readable-stream/lib/_stream_passthrough.js
@@ -0,0 +1,46 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// a passthrough stream.
+// basically just the most minimal sort of Transform stream.
+// Every written chunk gets output as-is.
+
+module.exports = PassThrough;
+
+var Transform = require('./_stream_transform');
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+util.inherits(PassThrough, Transform);
+
+function PassThrough(options) {
+  if (!(this instanceof PassThrough))
+    return new PassThrough(options);
+
+  Transform.call(this, options);
+}
+
+PassThrough.prototype._transform = function(chunk, encoding, cb) {
+  cb(null, chunk);
+};
diff --git a/node_modules/readable-stream/lib/_stream_readable.js b/node_modules/readable-stream/lib/_stream_readable.js
new file mode 100644
index 0000000000000000000000000000000000000000..630722099e9936982f6bf7c2b313df58d85cdfbf
--- /dev/null
+++ b/node_modules/readable-stream/lib/_stream_readable.js
@@ -0,0 +1,982 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module.exports = Readable;
+
+/*<replacement>*/
+var isArray = require('isarray');
+/*</replacement>*/
+
+
+/*<replacement>*/
+var Buffer = require('buffer').Buffer;
+/*</replacement>*/
+
+Readable.ReadableState = ReadableState;
+
+var EE = require('events').EventEmitter;
+
+/*<replacement>*/
+if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
+  return emitter.listeners(type).length;
+};
+/*</replacement>*/
+
+var Stream = require('stream');
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+var StringDecoder;
+
+util.inherits(Readable, Stream);
+
+function ReadableState(options, stream) {
+  options = options || {};
+
+  // the point at which it stops calling _read() to fill the buffer
+  // Note: 0 is a valid value, means "don't call _read preemptively ever"
+  var hwm = options.highWaterMark;
+  this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
+
+  // cast to ints.
+  this.highWaterMark = ~~this.highWaterMark;
+
+  this.buffer = [];
+  this.length = 0;
+  this.pipes = null;
+  this.pipesCount = 0;
+  this.flowing = false;
+  this.ended = false;
+  this.endEmitted = false;
+  this.reading = false;
+
+  // In streams that never have any data, and do push(null) right away,
+  // the consumer can miss the 'end' event if they do some I/O before
+  // consuming the stream.  So, we don't emit('end') until some reading
+  // happens.
+  this.calledRead = false;
+
+  // a flag to be able to tell if the onwrite cb is called immediately,
+  // or on a later tick.  We set this to true at first, becuase any
+  // actions that shouldn't happen until "later" should generally also
+  // not happen before the first write call.
+  this.sync = true;
+
+  // whenever we return null, then we set a flag to say
+  // that we're awaiting a 'readable' event emission.
+  this.needReadable = false;
+  this.emittedReadable = false;
+  this.readableListening = false;
+
+
+  // object stream flag. Used to make read(n) ignore n and to
+  // make all the buffer merging and length checks go away
+  this.objectMode = !!options.objectMode;
+
+  // Crypto is kind of old and crusty.  Historically, its default string
+  // encoding is 'binary' so we have to make this configurable.
+  // Everything else in the universe uses 'utf8', though.
+  this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+  // when piping, we only care about 'readable' events that happen
+  // after read()ing all the bytes and not getting any pushback.
+  this.ranOut = false;
+
+  // the number of writers that are awaiting a drain event in .pipe()s
+  this.awaitDrain = 0;
+
+  // if true, a maybeReadMore has been scheduled
+  this.readingMore = false;
+
+  this.decoder = null;
+  this.encoding = null;
+  if (options.encoding) {
+    if (!StringDecoder)
+      StringDecoder = require('string_decoder/').StringDecoder;
+    this.decoder = new StringDecoder(options.encoding);
+    this.encoding = options.encoding;
+  }
+}
+
+function Readable(options) {
+  if (!(this instanceof Readable))
+    return new Readable(options);
+
+  this._readableState = new ReadableState(options, this);
+
+  // legacy
+  this.readable = true;
+
+  Stream.call(this);
+}
+
+// Manually shove something into the read() buffer.
+// This returns true if the highWaterMark has not been hit yet,
+// similar to how Writable.write() returns true if you should
+// write() some more.
+Readable.prototype.push = function(chunk, encoding) {
+  var state = this._readableState;
+
+  if (typeof chunk === 'string' && !state.objectMode) {
+    encoding = encoding || state.defaultEncoding;
+    if (encoding !== state.encoding) {
+      chunk = new Buffer(chunk, encoding);
+      encoding = '';
+    }
+  }
+
+  return readableAddChunk(this, state, chunk, encoding, false);
+};
+
+// Unshift should *always* be something directly out of read()
+Readable.prototype.unshift = function(chunk) {
+  var state = this._readableState;
+  return readableAddChunk(this, state, chunk, '', true);
+};
+
+function readableAddChunk(stream, state, chunk, encoding, addToFront) {
+  var er = chunkInvalid(state, chunk);
+  if (er) {
+    stream.emit('error', er);
+  } else if (chunk === null || chunk === undefined) {
+    state.reading = false;
+    if (!state.ended)
+      onEofChunk(stream, state);
+  } else if (state.objectMode || chunk && chunk.length > 0) {
+    if (state.ended && !addToFront) {
+      var e = new Error('stream.push() after EOF');
+      stream.emit('error', e);
+    } else if (state.endEmitted && addToFront) {
+      var e = new Error('stream.unshift() after end event');
+      stream.emit('error', e);
+    } else {
+      if (state.decoder && !addToFront && !encoding)
+        chunk = state.decoder.write(chunk);
+
+      // update the buffer info.
+      state.length += state.objectMode ? 1 : chunk.length;
+      if (addToFront) {
+        state.buffer.unshift(chunk);
+      } else {
+        state.reading = false;
+        state.buffer.push(chunk);
+      }
+
+      if (state.needReadable)
+        emitReadable(stream);
+
+      maybeReadMore(stream, state);
+    }
+  } else if (!addToFront) {
+    state.reading = false;
+  }
+
+  return needMoreData(state);
+}
+
+
+
+// if it's past the high water mark, we can push in some more.
+// Also, if we have no data yet, we can stand some
+// more bytes.  This is to work around cases where hwm=0,
+// such as the repl.  Also, if the push() triggered a
+// readable event, and the user called read(largeNumber) such that
+// needReadable was set, then we ought to push more, so that another
+// 'readable' event will be triggered.
+function needMoreData(state) {
+  return !state.ended &&
+         (state.needReadable ||
+          state.length < state.highWaterMark ||
+          state.length === 0);
+}
+
+// backwards compatibility.
+Readable.prototype.setEncoding = function(enc) {
+  if (!StringDecoder)
+    StringDecoder = require('string_decoder/').StringDecoder;
+  this._readableState.decoder = new StringDecoder(enc);
+  this._readableState.encoding = enc;
+};
+
+// Don't raise the hwm > 128MB
+var MAX_HWM = 0x800000;
+function roundUpToNextPowerOf2(n) {
+  if (n >= MAX_HWM) {
+    n = MAX_HWM;
+  } else {
+    // Get the next highest power of 2
+    n--;
+    for (var p = 1; p < 32; p <<= 1) n |= n >> p;
+    n++;
+  }
+  return n;
+}
+
+function howMuchToRead(n, state) {
+  if (state.length === 0 && state.ended)
+    return 0;
+
+  if (state.objectMode)
+    return n === 0 ? 0 : 1;
+
+  if (n === null || isNaN(n)) {
+    // only flow one buffer at a time
+    if (state.flowing && state.buffer.length)
+      return state.buffer[0].length;
+    else
+      return state.length;
+  }
+
+  if (n <= 0)
+    return 0;
+
+  // If we're asking for more than the target buffer level,
+  // then raise the water mark.  Bump up to the next highest
+  // power of 2, to prevent increasing it excessively in tiny
+  // amounts.
+  if (n > state.highWaterMark)
+    state.highWaterMark = roundUpToNextPowerOf2(n);
+
+  // don't have that much.  return null, unless we've ended.
+  if (n > state.length) {
+    if (!state.ended) {
+      state.needReadable = true;
+      return 0;
+    } else
+      return state.length;
+  }
+
+  return n;
+}
+
+// you can override either this method, or the async _read(n) below.
+Readable.prototype.read = function(n) {
+  var state = this._readableState;
+  state.calledRead = true;
+  var nOrig = n;
+  var ret;
+
+  if (typeof n !== 'number' || n > 0)
+    state.emittedReadable = false;
+
+  // if we're doing read(0) to trigger a readable event, but we
+  // already have a bunch of data in the buffer, then just trigger
+  // the 'readable' event and move on.
+  if (n === 0 &&
+      state.needReadable &&
+      (state.length >= state.highWaterMark || state.ended)) {
+    emitReadable(this);
+    return null;
+  }
+
+  n = howMuchToRead(n, state);
+
+  // if we've ended, and we're now clear, then finish it up.
+  if (n === 0 && state.ended) {
+    ret = null;
+
+    // In cases where the decoder did not receive enough data
+    // to produce a full chunk, then immediately received an
+    // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>].
+    // howMuchToRead will see this and coerce the amount to
+    // read to zero (because it's looking at the length of the
+    // first <Buffer > in state.buffer), and we'll end up here.
+    //
+    // This can only happen via state.decoder -- no other venue
+    // exists for pushing a zero-length chunk into state.buffer
+    // and triggering this behavior. In this case, we return our
+    // remaining data and end the stream, if appropriate.
+    if (state.length > 0 && state.decoder) {
+      ret = fromList(n, state);
+      state.length -= ret.length;
+    }
+
+    if (state.length === 0)
+      endReadable(this);
+
+    return ret;
+  }
+
+  // All the actual chunk generation logic needs to be
+  // *below* the call to _read.  The reason is that in certain
+  // synthetic stream cases, such as passthrough streams, _read
+  // may be a completely synchronous operation which may change
+  // the state of the read buffer, providing enough data when
+  // before there was *not* enough.
+  //
+  // So, the steps are:
+  // 1. Figure out what the state of things will be after we do
+  // a read from the buffer.
+  //
+  // 2. If that resulting state will trigger a _read, then call _read.
+  // Note that this may be asynchronous, or synchronous.  Yes, it is
+  // deeply ugly to write APIs this way, but that still doesn't mean
+  // that the Readable class should behave improperly, as streams are
+  // designed to be sync/async agnostic.
+  // Take note if the _read call is sync or async (ie, if the read call
+  // has returned yet), so that we know whether or not it's safe to emit
+  // 'readable' etc.
+  //
+  // 3. Actually pull the requested chunks out of the buffer and return.
+
+  // if we need a readable event, then we need to do some reading.
+  var doRead = state.needReadable;
+
+  // if we currently have less than the highWaterMark, then also read some
+  if (state.length - n <= state.highWaterMark)
+    doRead = true;
+
+  // however, if we've ended, then there's no point, and if we're already
+  // reading, then it's unnecessary.
+  if (state.ended || state.reading)
+    doRead = false;
+
+  if (doRead) {
+    state.reading = true;
+    state.sync = true;
+    // if the length is currently zero, then we *need* a readable event.
+    if (state.length === 0)
+      state.needReadable = true;
+    // call internal read method
+    this._read(state.highWaterMark);
+    state.sync = false;
+  }
+
+  // If _read called its callback synchronously, then `reading`
+  // will be false, and we need to re-evaluate how much data we
+  // can return to the user.
+  if (doRead && !state.reading)
+    n = howMuchToRead(nOrig, state);
+
+  if (n > 0)
+    ret = fromList(n, state);
+  else
+    ret = null;
+
+  if (ret === null) {
+    state.needReadable = true;
+    n = 0;
+  }
+
+  state.length -= n;
+
+  // If we have nothing in the buffer, then we want to know
+  // as soon as we *do* get something into the buffer.
+  if (state.length === 0 && !state.ended)
+    state.needReadable = true;
+
+  // If we happened to read() exactly the remaining amount in the
+  // buffer, and the EOF has been seen at this point, then make sure
+  // that we emit 'end' on the very next tick.
+  if (state.ended && !state.endEmitted && state.length === 0)
+    endReadable(this);
+
+  return ret;
+};
+
+function chunkInvalid(state, chunk) {
+  var er = null;
+  if (!Buffer.isBuffer(chunk) &&
+      'string' !== typeof chunk &&
+      chunk !== null &&
+      chunk !== undefined &&
+      !state.objectMode) {
+    er = new TypeError('Invalid non-string/buffer chunk');
+  }
+  return er;
+}
+
+
+function onEofChunk(stream, state) {
+  if (state.decoder && !state.ended) {
+    var chunk = state.decoder.end();
+    if (chunk && chunk.length) {
+      state.buffer.push(chunk);
+      state.length += state.objectMode ? 1 : chunk.length;
+    }
+  }
+  state.ended = true;
+
+  // if we've ended and we have some data left, then emit
+  // 'readable' now to make sure it gets picked up.
+  if (state.length > 0)
+    emitReadable(stream);
+  else
+    endReadable(stream);
+}
+
+// Don't emit readable right away in sync mode, because this can trigger
+// another read() call => stack overflow.  This way, it might trigger
+// a nextTick recursion warning, but that's not so bad.
+function emitReadable(stream) {
+  var state = stream._readableState;
+  state.needReadable = false;
+  if (state.emittedReadable)
+    return;
+
+  state.emittedReadable = true;
+  if (state.sync)
+    process.nextTick(function() {
+      emitReadable_(stream);
+    });
+  else
+    emitReadable_(stream);
+}
+
+function emitReadable_(stream) {
+  stream.emit('readable');
+}
+
+
+// at this point, the user has presumably seen the 'readable' event,
+// and called read() to consume some data.  that may have triggered
+// in turn another _read(n) call, in which case reading = true if
+// it's in progress.
+// However, if we're not ended, or reading, and the length < hwm,
+// then go ahead and try to read some more preemptively.
+function maybeReadMore(stream, state) {
+  if (!state.readingMore) {
+    state.readingMore = true;
+    process.nextTick(function() {
+      maybeReadMore_(stream, state);
+    });
+  }
+}
+
+function maybeReadMore_(stream, state) {
+  var len = state.length;
+  while (!state.reading && !state.flowing && !state.ended &&
+         state.length < state.highWaterMark) {
+    stream.read(0);
+    if (len === state.length)
+      // didn't get any data, stop spinning.
+      break;
+    else
+      len = state.length;
+  }
+  state.readingMore = false;
+}
+
+// abstract method.  to be overridden in specific implementation classes.
+// call cb(er, data) where data is <= n in length.
+// for virtual (non-string, non-buffer) streams, "length" is somewhat
+// arbitrary, and perhaps not very meaningful.
+Readable.prototype._read = function(n) {
+  this.emit('error', new Error('not implemented'));
+};
+
+Readable.prototype.pipe = function(dest, pipeOpts) {
+  var src = this;
+  var state = this._readableState;
+
+  switch (state.pipesCount) {
+    case 0:
+      state.pipes = dest;
+      break;
+    case 1:
+      state.pipes = [state.pipes, dest];
+      break;
+    default:
+      state.pipes.push(dest);
+      break;
+  }
+  state.pipesCount += 1;
+
+  var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
+              dest !== process.stdout &&
+              dest !== process.stderr;
+
+  var endFn = doEnd ? onend : cleanup;
+  if (state.endEmitted)
+    process.nextTick(endFn);
+  else
+    src.once('end', endFn);
+
+  dest.on('unpipe', onunpipe);
+  function onunpipe(readable) {
+    if (readable !== src) return;
+    cleanup();
+  }
+
+  function onend() {
+    dest.end();
+  }
+
+  // when the dest drains, it reduces the awaitDrain counter
+  // on the source.  This would be more elegant with a .once()
+  // handler in flow(), but adding and removing repeatedly is
+  // too slow.
+  var ondrain = pipeOnDrain(src);
+  dest.on('drain', ondrain);
+
+  function cleanup() {
+    // cleanup event handlers once the pipe is broken
+    dest.removeListener('close', onclose);
+    dest.removeListener('finish', onfinish);
+    dest.removeListener('drain', ondrain);
+    dest.removeListener('error', onerror);
+    dest.removeListener('unpipe', onunpipe);
+    src.removeListener('end', onend);
+    src.removeListener('end', cleanup);
+
+    // if the reader is waiting for a drain event from this
+    // specific writer, then it would cause it to never start
+    // flowing again.
+    // So, if this is awaiting a drain, then we just call it now.
+    // If we don't know, then assume that we are waiting for one.
+    if (!dest._writableState || dest._writableState.needDrain)
+      ondrain();
+  }
+
+  // if the dest has an error, then stop piping into it.
+  // however, don't suppress the throwing behavior for this.
+  function onerror(er) {
+    unpipe();
+    dest.removeListener('error', onerror);
+    if (EE.listenerCount(dest, 'error') === 0)
+      dest.emit('error', er);
+  }
+  // This is a brutally ugly hack to make sure that our error handler
+  // is attached before any userland ones.  NEVER DO THIS.
+  if (!dest._events || !dest._events.error)
+    dest.on('error', onerror);
+  else if (isArray(dest._events.error))
+    dest._events.error.unshift(onerror);
+  else
+    dest._events.error = [onerror, dest._events.error];
+
+
+
+  // Both close and finish should trigger unpipe, but only once.
+  function onclose() {
+    dest.removeListener('finish', onfinish);
+    unpipe();
+  }
+  dest.once('close', onclose);
+  function onfinish() {
+    dest.removeListener('close', onclose);
+    unpipe();
+  }
+  dest.once('finish', onfinish);
+
+  function unpipe() {
+    src.unpipe(dest);
+  }
+
+  // tell the dest that it's being piped to
+  dest.emit('pipe', src);
+
+  // start the flow if it hasn't been started already.
+  if (!state.flowing) {
+    // the handler that waits for readable events after all
+    // the data gets sucked out in flow.
+    // This would be easier to follow with a .once() handler
+    // in flow(), but that is too slow.
+    this.on('readable', pipeOnReadable);
+
+    state.flowing = true;
+    process.nextTick(function() {
+      flow(src);
+    });
+  }
+
+  return dest;
+};
+
+function pipeOnDrain(src) {
+  return function() {
+    var dest = this;
+    var state = src._readableState;
+    state.awaitDrain--;
+    if (state.awaitDrain === 0)
+      flow(src);
+  };
+}
+
+function flow(src) {
+  var state = src._readableState;
+  var chunk;
+  state.awaitDrain = 0;
+
+  function write(dest, i, list) {
+    var written = dest.write(chunk);
+    if (false === written) {
+      state.awaitDrain++;
+    }
+  }
+
+  while (state.pipesCount && null !== (chunk = src.read())) {
+
+    if (state.pipesCount === 1)
+      write(state.pipes, 0, null);
+    else
+      forEach(state.pipes, write);
+
+    src.emit('data', chunk);
+
+    // if anyone needs a drain, then we have to wait for that.
+    if (state.awaitDrain > 0)
+      return;
+  }
+
+  // if every destination was unpiped, either before entering this
+  // function, or in the while loop, then stop flowing.
+  //
+  // NB: This is a pretty rare edge case.
+  if (state.pipesCount === 0) {
+    state.flowing = false;
+
+    // if there were data event listeners added, then switch to old mode.
+    if (EE.listenerCount(src, 'data') > 0)
+      emitDataEvents(src);
+    return;
+  }
+
+  // at this point, no one needed a drain, so we just ran out of data
+  // on the next readable event, start it over again.
+  state.ranOut = true;
+}
+
+function pipeOnReadable() {
+  if (this._readableState.ranOut) {
+    this._readableState.ranOut = false;
+    flow(this);
+  }
+}
+
+
+Readable.prototype.unpipe = function(dest) {
+  var state = this._readableState;
+
+  // if we're not piping anywhere, then do nothing.
+  if (state.pipesCount === 0)
+    return this;
+
+  // just one destination.  most common case.
+  if (state.pipesCount === 1) {
+    // passed in one, but it's not the right one.
+    if (dest && dest !== state.pipes)
+      return this;
+
+    if (!dest)
+      dest = state.pipes;
+
+    // got a match.
+    state.pipes = null;
+    state.pipesCount = 0;
+    this.removeListener('readable', pipeOnReadable);
+    state.flowing = false;
+    if (dest)
+      dest.emit('unpipe', this);
+    return this;
+  }
+
+  // slow case. multiple pipe destinations.
+
+  if (!dest) {
+    // remove all.
+    var dests = state.pipes;
+    var len = state.pipesCount;
+    state.pipes = null;
+    state.pipesCount = 0;
+    this.removeListener('readable', pipeOnReadable);
+    state.flowing = false;
+
+    for (var i = 0; i < len; i++)
+      dests[i].emit('unpipe', this);
+    return this;
+  }
+
+  // try to find the right one.
+  var i = indexOf(state.pipes, dest);
+  if (i === -1)
+    return this;
+
+  state.pipes.splice(i, 1);
+  state.pipesCount -= 1;
+  if (state.pipesCount === 1)
+    state.pipes = state.pipes[0];
+
+  dest.emit('unpipe', this);
+
+  return this;
+};
+
+// set up data events if they are asked for
+// Ensure readable listeners eventually get something
+Readable.prototype.on = function(ev, fn) {
+  var res = Stream.prototype.on.call(this, ev, fn);
+
+  if (ev === 'data' && !this._readableState.flowing)
+    emitDataEvents(this);
+
+  if (ev === 'readable' && this.readable) {
+    var state = this._readableState;
+    if (!state.readableListening) {
+      state.readableListening = true;
+      state.emittedReadable = false;
+      state.needReadable = true;
+      if (!state.reading) {
+        this.read(0);
+      } else if (state.length) {
+        emitReadable(this, state);
+      }
+    }
+  }
+
+  return res;
+};
+Readable.prototype.addListener = Readable.prototype.on;
+
+// pause() and resume() are remnants of the legacy readable stream API
+// If the user uses them, then switch into old mode.
+Readable.prototype.resume = function() {
+  emitDataEvents(this);
+  this.read(0);
+  this.emit('resume');
+};
+
+Readable.prototype.pause = function() {
+  emitDataEvents(this, true);
+  this.emit('pause');
+};
+
+function emitDataEvents(stream, startPaused) {
+  var state = stream._readableState;
+
+  if (state.flowing) {
+    // https://github.com/isaacs/readable-stream/issues/16
+    throw new Error('Cannot switch to old mode now.');
+  }
+
+  var paused = startPaused || false;
+  var readable = false;
+
+  // convert to an old-style stream.
+  stream.readable = true;
+  stream.pipe = Stream.prototype.pipe;
+  stream.on = stream.addListener = Stream.prototype.on;
+
+  stream.on('readable', function() {
+    readable = true;
+
+    var c;
+    while (!paused && (null !== (c = stream.read())))
+      stream.emit('data', c);
+
+    if (c === null) {
+      readable = false;
+      stream._readableState.needReadable = true;
+    }
+  });
+
+  stream.pause = function() {
+    paused = true;
+    this.emit('pause');
+  };
+
+  stream.resume = function() {
+    paused = false;
+    if (readable)
+      process.nextTick(function() {
+        stream.emit('readable');
+      });
+    else
+      this.read(0);
+    this.emit('resume');
+  };
+
+  // now make it start, just in case it hadn't already.
+  stream.emit('readable');
+}
+
+// wrap an old-style stream as the async data source.
+// This is *not* part of the readable stream interface.
+// It is an ugly unfortunate mess of history.
+Readable.prototype.wrap = function(stream) {
+  var state = this._readableState;
+  var paused = false;
+
+  var self = this;
+  stream.on('end', function() {
+    if (state.decoder && !state.ended) {
+      var chunk = state.decoder.end();
+      if (chunk && chunk.length)
+        self.push(chunk);
+    }
+
+    self.push(null);
+  });
+
+  stream.on('data', function(chunk) {
+    if (state.decoder)
+      chunk = state.decoder.write(chunk);
+
+    // don't skip over falsy values in objectMode
+    //if (state.objectMode && util.isNullOrUndefined(chunk))
+    if (state.objectMode && (chunk === null || chunk === undefined))
+      return;
+    else if (!state.objectMode && (!chunk || !chunk.length))
+      return;
+
+    var ret = self.push(chunk);
+    if (!ret) {
+      paused = true;
+      stream.pause();
+    }
+  });
+
+  // proxy all the other methods.
+  // important when wrapping filters and duplexes.
+  for (var i in stream) {
+    if (typeof stream[i] === 'function' &&
+        typeof this[i] === 'undefined') {
+      this[i] = function(method) { return function() {
+        return stream[method].apply(stream, arguments);
+      }}(i);
+    }
+  }
+
+  // proxy certain important events.
+  var events = ['error', 'close', 'destroy', 'pause', 'resume'];
+  forEach(events, function(ev) {
+    stream.on(ev, self.emit.bind(self, ev));
+  });
+
+  // when we try to consume some more bytes, simply unpause the
+  // underlying stream.
+  self._read = function(n) {
+    if (paused) {
+      paused = false;
+      stream.resume();
+    }
+  };
+
+  return self;
+};
+
+
+
+// exposed for testing purposes only.
+Readable._fromList = fromList;
+
+// Pluck off n bytes from an array of buffers.
+// Length is the combined lengths of all the buffers in the list.
+function fromList(n, state) {
+  var list = state.buffer;
+  var length = state.length;
+  var stringMode = !!state.decoder;
+  var objectMode = !!state.objectMode;
+  var ret;
+
+  // nothing in the list, definitely empty.
+  if (list.length === 0)
+    return null;
+
+  if (length === 0)
+    ret = null;
+  else if (objectMode)
+    ret = list.shift();
+  else if (!n || n >= length) {
+    // read it all, truncate the array.
+    if (stringMode)
+      ret = list.join('');
+    else
+      ret = Buffer.concat(list, length);
+    list.length = 0;
+  } else {
+    // read just some of it.
+    if (n < list[0].length) {
+      // just take a part of the first list item.
+      // slice is the same for buffers and strings.
+      var buf = list[0];
+      ret = buf.slice(0, n);
+      list[0] = buf.slice(n);
+    } else if (n === list[0].length) {
+      // first list is a perfect match
+      ret = list.shift();
+    } else {
+      // complex case.
+      // we have enough to cover it, but it spans past the first buffer.
+      if (stringMode)
+        ret = '';
+      else
+        ret = new Buffer(n);
+
+      var c = 0;
+      for (var i = 0, l = list.length; i < l && c < n; i++) {
+        var buf = list[0];
+        var cpy = Math.min(n - c, buf.length);
+
+        if (stringMode)
+          ret += buf.slice(0, cpy);
+        else
+          buf.copy(ret, c, 0, cpy);
+
+        if (cpy < buf.length)
+          list[0] = buf.slice(cpy);
+        else
+          list.shift();
+
+        c += cpy;
+      }
+    }
+  }
+
+  return ret;
+}
+
+function endReadable(stream) {
+  var state = stream._readableState;
+
+  // If we get here before consuming all the bytes, then that is a
+  // bug in node.  Should never happen.
+  if (state.length > 0)
+    throw new Error('endReadable called on non-empty stream');
+
+  if (!state.endEmitted && state.calledRead) {
+    state.ended = true;
+    process.nextTick(function() {
+      // Check that we didn't get one last unshift.
+      if (!state.endEmitted && state.length === 0) {
+        state.endEmitted = true;
+        stream.readable = false;
+        stream.emit('end');
+      }
+    });
+  }
+}
+
+function forEach (xs, f) {
+  for (var i = 0, l = xs.length; i < l; i++) {
+    f(xs[i], i);
+  }
+}
+
+function indexOf (xs, x) {
+  for (var i = 0, l = xs.length; i < l; i++) {
+    if (xs[i] === x) return i;
+  }
+  return -1;
+}
diff --git a/node_modules/readable-stream/lib/_stream_transform.js b/node_modules/readable-stream/lib/_stream_transform.js
new file mode 100644
index 0000000000000000000000000000000000000000..eb188df3e86b41cf6a4e70b1e2b0427a15b61eaf
--- /dev/null
+++ b/node_modules/readable-stream/lib/_stream_transform.js
@@ -0,0 +1,210 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+// a transform stream is a readable/writable stream where you do
+// something with the data.  Sometimes it's called a "filter",
+// but that's not a great name for it, since that implies a thing where
+// some bits pass through, and others are simply ignored.  (That would
+// be a valid example of a transform, of course.)
+//
+// While the output is causally related to the input, it's not a
+// necessarily symmetric or synchronous transformation.  For example,
+// a zlib stream might take multiple plain-text writes(), and then
+// emit a single compressed chunk some time in the future.
+//
+// Here's how this works:
+//
+// The Transform stream has all the aspects of the readable and writable
+// stream classes.  When you write(chunk), that calls _write(chunk,cb)
+// internally, and returns false if there's a lot of pending writes
+// buffered up.  When you call read(), that calls _read(n) until
+// there's enough pending readable data buffered up.
+//
+// In a transform stream, the written data is placed in a buffer.  When
+// _read(n) is called, it transforms the queued up data, calling the
+// buffered _write cb's as it consumes chunks.  If consuming a single
+// written chunk would result in multiple output chunks, then the first
+// outputted bit calls the readcb, and subsequent chunks just go into
+// the read buffer, and will cause it to emit 'readable' if necessary.
+//
+// This way, back-pressure is actually determined by the reading side,
+// since _read has to be called to start processing a new chunk.  However,
+// a pathological inflate type of transform can cause excessive buffering
+// here.  For example, imagine a stream where every byte of input is
+// interpreted as an integer from 0-255, and then results in that many
+// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
+// 1kb of data being output.  In this case, you could write a very small
+// amount of input, and end up with a very large amount of output.  In
+// such a pathological inflating mechanism, there'd be no way to tell
+// the system to stop doing the transform.  A single 4MB write could
+// cause the system to run out of memory.
+//
+// However, even in such a pathological case, only a single written chunk
+// would be consumed, and then the rest would wait (un-transformed) until
+// the results of the previous transformed chunk were consumed.
+
+module.exports = Transform;
+
+var Duplex = require('./_stream_duplex');
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+util.inherits(Transform, Duplex);
+
+
+function TransformState(options, stream) {
+  this.afterTransform = function(er, data) {
+    return afterTransform(stream, er, data);
+  };
+
+  this.needTransform = false;
+  this.transforming = false;
+  this.writecb = null;
+  this.writechunk = null;
+}
+
+function afterTransform(stream, er, data) {
+  var ts = stream._transformState;
+  ts.transforming = false;
+
+  var cb = ts.writecb;
+
+  if (!cb)
+    return stream.emit('error', new Error('no writecb in Transform class'));
+
+  ts.writechunk = null;
+  ts.writecb = null;
+
+  if (data !== null && data !== undefined)
+    stream.push(data);
+
+  if (cb)
+    cb(er);
+
+  var rs = stream._readableState;
+  rs.reading = false;
+  if (rs.needReadable || rs.length < rs.highWaterMark) {
+    stream._read(rs.highWaterMark);
+  }
+}
+
+
+function Transform(options) {
+  if (!(this instanceof Transform))
+    return new Transform(options);
+
+  Duplex.call(this, options);
+
+  var ts = this._transformState = new TransformState(options, this);
+
+  // when the writable side finishes, then flush out anything remaining.
+  var stream = this;
+
+  // start out asking for a readable event once data is transformed.
+  this._readableState.needReadable = true;
+
+  // we have implemented the _read method, and done the other things
+  // that Readable wants before the first _read call, so unset the
+  // sync guard flag.
+  this._readableState.sync = false;
+
+  this.once('finish', function() {
+    if ('function' === typeof this._flush)
+      this._flush(function(er) {
+        done(stream, er);
+      });
+    else
+      done(stream);
+  });
+}
+
+Transform.prototype.push = function(chunk, encoding) {
+  this._transformState.needTransform = false;
+  return Duplex.prototype.push.call(this, chunk, encoding);
+};
+
+// This is the part where you do stuff!
+// override this function in implementation classes.
+// 'chunk' is an input chunk.
+//
+// Call `push(newChunk)` to pass along transformed output
+// to the readable side.  You may call 'push' zero or more times.
+//
+// Call `cb(err)` when you are done with this chunk.  If you pass
+// an error, then that'll put the hurt on the whole operation.  If you
+// never call cb(), then you'll never get another chunk.
+Transform.prototype._transform = function(chunk, encoding, cb) {
+  throw new Error('not implemented');
+};
+
+Transform.prototype._write = function(chunk, encoding, cb) {
+  var ts = this._transformState;
+  ts.writecb = cb;
+  ts.writechunk = chunk;
+  ts.writeencoding = encoding;
+  if (!ts.transforming) {
+    var rs = this._readableState;
+    if (ts.needTransform ||
+        rs.needReadable ||
+        rs.length < rs.highWaterMark)
+      this._read(rs.highWaterMark);
+  }
+};
+
+// Doesn't matter what the args are here.
+// _transform does all the work.
+// That we got here means that the readable side wants more data.
+Transform.prototype._read = function(n) {
+  var ts = this._transformState;
+
+  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
+    ts.transforming = true;
+    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
+  } else {
+    // mark that we need a transform, so that any data that comes in
+    // will get processed, now that we've asked for it.
+    ts.needTransform = true;
+  }
+};
+
+
+function done(stream, er) {
+  if (er)
+    return stream.emit('error', er);
+
+  // if there's nothing in the write buffer, then that means
+  // that nothing more will ever be provided
+  var ws = stream._writableState;
+  var rs = stream._readableState;
+  var ts = stream._transformState;
+
+  if (ws.length)
+    throw new Error('calling transform done when ws.length != 0');
+
+  if (ts.transforming)
+    throw new Error('calling transform done when still transforming');
+
+  return stream.push(null);
+}
diff --git a/node_modules/readable-stream/lib/_stream_writable.js b/node_modules/readable-stream/lib/_stream_writable.js
new file mode 100644
index 0000000000000000000000000000000000000000..4bdaa4fa49188d108dfacd9f33969049d9bd9803
--- /dev/null
+++ b/node_modules/readable-stream/lib/_stream_writable.js
@@ -0,0 +1,386 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// A bit simpler than readable streams.
+// Implement an async ._write(chunk, cb), and it'll handle all
+// the drain event emission and buffering.
+
+module.exports = Writable;
+
+/*<replacement>*/
+var Buffer = require('buffer').Buffer;
+/*</replacement>*/
+
+Writable.WritableState = WritableState;
+
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+var Stream = require('stream');
+
+util.inherits(Writable, Stream);
+
+function WriteReq(chunk, encoding, cb) {
+  this.chunk = chunk;
+  this.encoding = encoding;
+  this.callback = cb;
+}
+
+function WritableState(options, stream) {
+  options = options || {};
+
+  // the point at which write() starts returning false
+  // Note: 0 is a valid value, means that we always return false if
+  // the entire buffer is not flushed immediately on write()
+  var hwm = options.highWaterMark;
+  this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
+
+  // object stream flag to indicate whether or not this stream
+  // contains buffers or objects.
+  this.objectMode = !!options.objectMode;
+
+  // cast to ints.
+  this.highWaterMark = ~~this.highWaterMark;
+
+  this.needDrain = false;
+  // at the start of calling end()
+  this.ending = false;
+  // when end() has been called, and returned
+  this.ended = false;
+  // when 'finish' is emitted
+  this.finished = false;
+
+  // should we decode strings into buffers before passing to _write?
+  // this is here so that some node-core streams can optimize string
+  // handling at a lower level.
+  var noDecode = options.decodeStrings === false;
+  this.decodeStrings = !noDecode;
+
+  // Crypto is kind of old and crusty.  Historically, its default string
+  // encoding is 'binary' so we have to make this configurable.
+  // Everything else in the universe uses 'utf8', though.
+  this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+  // not an actual buffer we keep track of, but a measurement
+  // of how much we're waiting to get pushed to some underlying
+  // socket or file.
+  this.length = 0;
+
+  // a flag to see when we're in the middle of a write.
+  this.writing = false;
+
+  // a flag to be able to tell if the onwrite cb is called immediately,
+  // or on a later tick.  We set this to true at first, becuase any
+  // actions that shouldn't happen until "later" should generally also
+  // not happen before the first write call.
+  this.sync = true;
+
+  // a flag to know if we're processing previously buffered items, which
+  // may call the _write() callback in the same tick, so that we don't
+  // end up in an overlapped onwrite situation.
+  this.bufferProcessing = false;
+
+  // the callback that's passed to _write(chunk,cb)
+  this.onwrite = function(er) {
+    onwrite(stream, er);
+  };
+
+  // the callback that the user supplies to write(chunk,encoding,cb)
+  this.writecb = null;
+
+  // the amount that is being written when _write is called.
+  this.writelen = 0;
+
+  this.buffer = [];
+
+  // True if the error was already emitted and should not be thrown again
+  this.errorEmitted = false;
+}
+
+function Writable(options) {
+  var Duplex = require('./_stream_duplex');
+
+  // Writable ctor is applied to Duplexes, though they're not
+  // instanceof Writable, they're instanceof Readable.
+  if (!(this instanceof Writable) && !(this instanceof Duplex))
+    return new Writable(options);
+
+  this._writableState = new WritableState(options, this);
+
+  // legacy.
+  this.writable = true;
+
+  Stream.call(this);
+}
+
+// Otherwise people can pipe Writable streams, which is just wrong.
+Writable.prototype.pipe = function() {
+  this.emit('error', new Error('Cannot pipe. Not readable.'));
+};
+
+
+function writeAfterEnd(stream, state, cb) {
+  var er = new Error('write after end');
+  // TODO: defer error events consistently everywhere, not just the cb
+  stream.emit('error', er);
+  process.nextTick(function() {
+    cb(er);
+  });
+}
+
+// If we get something that is not a buffer, string, null, or undefined,
+// and we're not in objectMode, then that's an error.
+// Otherwise stream chunks are all considered to be of length=1, and the
+// watermarks determine how many objects to keep in the buffer, rather than
+// how many bytes or characters.
+function validChunk(stream, state, chunk, cb) {
+  var valid = true;
+  if (!Buffer.isBuffer(chunk) &&
+      'string' !== typeof chunk &&
+      chunk !== null &&
+      chunk !== undefined &&
+      !state.objectMode) {
+    var er = new TypeError('Invalid non-string/buffer chunk');
+    stream.emit('error', er);
+    process.nextTick(function() {
+      cb(er);
+    });
+    valid = false;
+  }
+  return valid;
+}
+
+Writable.prototype.write = function(chunk, encoding, cb) {
+  var state = this._writableState;
+  var ret = false;
+
+  if (typeof encoding === 'function') {
+    cb = encoding;
+    encoding = null;
+  }
+
+  if (Buffer.isBuffer(chunk))
+    encoding = 'buffer';
+  else if (!encoding)
+    encoding = state.defaultEncoding;
+
+  if (typeof cb !== 'function')
+    cb = function() {};
+
+  if (state.ended)
+    writeAfterEnd(this, state, cb);
+  else if (validChunk(this, state, chunk, cb))
+    ret = writeOrBuffer(this, state, chunk, encoding, cb);
+
+  return ret;
+};
+
+function decodeChunk(state, chunk, encoding) {
+  if (!state.objectMode &&
+      state.decodeStrings !== false &&
+      typeof chunk === 'string') {
+    chunk = new Buffer(chunk, encoding);
+  }
+  return chunk;
+}
+
+// if we're already writing something, then just put this
+// in the queue, and wait our turn.  Otherwise, call _write
+// If we return false, then we need a drain event, so set that flag.
+function writeOrBuffer(stream, state, chunk, encoding, cb) {
+  chunk = decodeChunk(state, chunk, encoding);
+  if (Buffer.isBuffer(chunk))
+    encoding = 'buffer';
+  var len = state.objectMode ? 1 : chunk.length;
+
+  state.length += len;
+
+  var ret = state.length < state.highWaterMark;
+  // we must ensure that previous needDrain will not be reset to false.
+  if (!ret)
+    state.needDrain = true;
+
+  if (state.writing)
+    state.buffer.push(new WriteReq(chunk, encoding, cb));
+  else
+    doWrite(stream, state, len, chunk, encoding, cb);
+
+  return ret;
+}
+
+function doWrite(stream, state, len, chunk, encoding, cb) {
+  state.writelen = len;
+  state.writecb = cb;
+  state.writing = true;
+  state.sync = true;
+  stream._write(chunk, encoding, state.onwrite);
+  state.sync = false;
+}
+
+function onwriteError(stream, state, sync, er, cb) {
+  if (sync)
+    process.nextTick(function() {
+      cb(er);
+    });
+  else
+    cb(er);
+
+  stream._writableState.errorEmitted = true;
+  stream.emit('error', er);
+}
+
+function onwriteStateUpdate(state) {
+  state.writing = false;
+  state.writecb = null;
+  state.length -= state.writelen;
+  state.writelen = 0;
+}
+
+function onwrite(stream, er) {
+  var state = stream._writableState;
+  var sync = state.sync;
+  var cb = state.writecb;
+
+  onwriteStateUpdate(state);
+
+  if (er)
+    onwriteError(stream, state, sync, er, cb);
+  else {
+    // Check if we're actually ready to finish, but don't emit yet
+    var finished = needFinish(stream, state);
+
+    if (!finished && !state.bufferProcessing && state.buffer.length)
+      clearBuffer(stream, state);
+
+    if (sync) {
+      process.nextTick(function() {
+        afterWrite(stream, state, finished, cb);
+      });
+    } else {
+      afterWrite(stream, state, finished, cb);
+    }
+  }
+}
+
+function afterWrite(stream, state, finished, cb) {
+  if (!finished)
+    onwriteDrain(stream, state);
+  cb();
+  if (finished)
+    finishMaybe(stream, state);
+}
+
+// Must force callback to be called on nextTick, so that we don't
+// emit 'drain' before the write() consumer gets the 'false' return
+// value, and has a chance to attach a 'drain' listener.
+function onwriteDrain(stream, state) {
+  if (state.length === 0 && state.needDrain) {
+    state.needDrain = false;
+    stream.emit('drain');
+  }
+}
+
+
+// if there's something in the buffer waiting, then process it
+function clearBuffer(stream, state) {
+  state.bufferProcessing = true;
+
+  for (var c = 0; c < state.buffer.length; c++) {
+    var entry = state.buffer[c];
+    var chunk = entry.chunk;
+    var encoding = entry.encoding;
+    var cb = entry.callback;
+    var len = state.objectMode ? 1 : chunk.length;
+
+    doWrite(stream, state, len, chunk, encoding, cb);
+
+    // if we didn't call the onwrite immediately, then
+    // it means that we need to wait until it does.
+    // also, that means that the chunk and cb are currently
+    // being processed, so move the buffer counter past them.
+    if (state.writing) {
+      c++;
+      break;
+    }
+  }
+
+  state.bufferProcessing = false;
+  if (c < state.buffer.length)
+    state.buffer = state.buffer.slice(c);
+  else
+    state.buffer.length = 0;
+}
+
+Writable.prototype._write = function(chunk, encoding, cb) {
+  cb(new Error('not implemented'));
+};
+
+Writable.prototype.end = function(chunk, encoding, cb) {
+  var state = this._writableState;
+
+  if (typeof chunk === 'function') {
+    cb = chunk;
+    chunk = null;
+    encoding = null;
+  } else if (typeof encoding === 'function') {
+    cb = encoding;
+    encoding = null;
+  }
+
+  if (typeof chunk !== 'undefined' && chunk !== null)
+    this.write(chunk, encoding);
+
+  // ignore unnecessary end() calls.
+  if (!state.ending && !state.finished)
+    endWritable(this, state, cb);
+};
+
+
+function needFinish(stream, state) {
+  return (state.ending &&
+          state.length === 0 &&
+          !state.finished &&
+          !state.writing);
+}
+
+function finishMaybe(stream, state) {
+  var need = needFinish(stream, state);
+  if (need) {
+    state.finished = true;
+    stream.emit('finish');
+  }
+  return need;
+}
+
+function endWritable(stream, state, cb) {
+  state.ending = true;
+  finishMaybe(stream, state);
+  if (cb) {
+    if (state.finished)
+      process.nextTick(cb);
+    else
+      stream.once('finish', cb);
+  }
+  state.ended = true;
+}
diff --git a/node_modules/readable-stream/package.json b/node_modules/readable-stream/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2f9e1e91db7cefe531a60fcb4c94d108fe2a572c
--- /dev/null
+++ b/node_modules/readable-stream/package.json
@@ -0,0 +1,32 @@
+{
+  "name": "readable-stream",
+  "version": "1.0.33",
+  "description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x",
+  "main": "readable.js",
+  "dependencies": {
+    "core-util-is": "~1.0.0",
+    "isarray": "0.0.1",
+    "string_decoder": "~0.10.x",
+    "inherits": "~2.0.1"
+  },
+  "devDependencies": {
+    "tap": "~0.2.6"
+  },
+  "scripts": {
+    "test": "tap test/simple/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/readable-stream"
+  },
+  "keywords": [
+    "readable",
+    "stream",
+    "pipe"
+  ],
+  "browser": {
+    "util": false
+  },
+  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
+  "license": "MIT"
+}
diff --git a/node_modules/readable-stream/passthrough.js b/node_modules/readable-stream/passthrough.js
new file mode 100644
index 0000000000000000000000000000000000000000..27e8d8a55165f9d1d7d1d1905d8d70e9c5a24f6e
--- /dev/null
+++ b/node_modules/readable-stream/passthrough.js
@@ -0,0 +1 @@
+module.exports = require("./lib/_stream_passthrough.js")
diff --git a/node_modules/readable-stream/readable.js b/node_modules/readable-stream/readable.js
new file mode 100644
index 0000000000000000000000000000000000000000..8b5337b5c500f3c39762de822186f80ad96d4eeb
--- /dev/null
+++ b/node_modules/readable-stream/readable.js
@@ -0,0 +1,8 @@
+var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify
+exports = module.exports = require('./lib/_stream_readable.js');
+exports.Stream = Stream;
+exports.Readable = exports;
+exports.Writable = require('./lib/_stream_writable.js');
+exports.Duplex = require('./lib/_stream_duplex.js');
+exports.Transform = require('./lib/_stream_transform.js');
+exports.PassThrough = require('./lib/_stream_passthrough.js');
diff --git a/node_modules/readable-stream/transform.js b/node_modules/readable-stream/transform.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d482f0780e9934896cd693414fee2b9b425778f
--- /dev/null
+++ b/node_modules/readable-stream/transform.js
@@ -0,0 +1 @@
+module.exports = require("./lib/_stream_transform.js")
diff --git a/node_modules/readable-stream/writable.js b/node_modules/readable-stream/writable.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1e9efdf3c12e938a4fd0659f2af60dbe65bf240
--- /dev/null
+++ b/node_modules/readable-stream/writable.js
@@ -0,0 +1 @@
+module.exports = require("./lib/_stream_writable.js")
diff --git a/node_modules/redeyed/.npmignore b/node_modules/redeyed/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..7dccd970766aff6bd61d92a96b35a805c90678c6
--- /dev/null
+++ b/node_modules/redeyed/.npmignore
@@ -0,0 +1,15 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/node_modules/redeyed/.travis.yml b/node_modules/redeyed/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..84fd7ca248abca3d4407f1a1c2430f55f5d90bf2
--- /dev/null
+++ b/node_modules/redeyed/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.8
+  - 0.9
diff --git a/node_modules/redeyed/Changelog.md b/node_modules/redeyed/Changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1f7bbadea07c4154268a4a94c3dd504e0d9077
--- /dev/null
+++ b/node_modules/redeyed/Changelog.md
@@ -0,0 +1,15 @@
+# Changelog
+
+### 0.4
+- browser support
+
+### 0.3
+- passing more information into {Function} config
+- API change: returning {Object} with code, ast, comments and tokens attached instead of just a code {String}
+- comments support
+
+### 0.2 
+- upgrade to Esprima 1.0.0
+
+### 0.1
+- first working version
diff --git a/node_modules/redeyed/LICENSE b/node_modules/redeyed/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..19c037f3b9ccd64a734039fb973be4b72b944a55
--- /dev/null
+++ b/node_modules/redeyed/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2012 Thorsten Lorenz. 
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/redeyed/README.md b/node_modules/redeyed/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..81b8a533eb5711653ef8ae41387ddba7e4923588
--- /dev/null
+++ b/node_modules/redeyed/README.md
@@ -0,0 +1,192 @@
+# redeyed [![build status](https://secure.travis-ci.org/thlorenz/redeyed.png?branch=master)](http://travis-ci.org/thlorenz/redeyed)
+
+*Add color to your JavaScript!*
+
+![frog](http://allaboutfrogs.org/gallery/photos/redeyes/red1.gif)
+
+[Red Eyed Tree Frog](http://allaboutfrogs.org/info/species/redeye.html) *(Agalychnis callidryas)*
+
+## What?
+
+Takes JavaScript code, along with a config and returns the original code with tokens wrapped and/or replaced as configured.
+
+## Where?
+
+- server side using nodejs
+- in the [browser](#browser-support)
+
+## What for?
+
+One usecase is adding metadata to your code that can then be used to apply syntax highlighting.
+
+## How?
+
+- copy the [config.js](https://github.com/thlorenz/redeyed/blob/master/config.js) and edit it in order to specify how
+  certain tokens are to be surrounded/replaced
+- replace the `undefined` of each token you want to configure with one of the following
+
+### {String} config
+
+`'before:after'`
+
+wraps the token inside before/after 
+
+### {Object} config
+
+`{ _before: 'before', _after: 'after' }`
+
+wraps token inside before/after
+
+#### Missing before and after resolution for {String} and {Object} config
+
+For the `{String}` and `{Object}` configurations, 'before' or 'after' may be omitted:
+
+- `{String}`: 
+  - `'before:'` (omitting 'after')
+  - `':after'` (omitting 'before')
+- `{Object}`: 
+  - `{ _before: 'before' }` (omitting '_after')
+  - `{ _after: 'after' }` (omitting '_before')
+
+In these cases the missing half is resolved as follows:
+
+- from the `parent._default` (i.e., `Keyword._default`) if found
+- otherwise from the `config._default` if found
+- otherwise `''` (empty string)
+
+### {Function} config
+
+`function (tokenString, info) { return {String}|{Object}; }`
+
+#### Inputs
+
+- tokenString: the content of the token that is currently being processed
+- info: an object with the following structure
+
+```js
+{
+    // {Int}
+    // the index of the token being processed inside tokens
+    tokenIndex
+
+    // {Array}
+    // all tokens that are being processed including comments 
+    // (i.e. the result of merging esprima tokens and comments)
+  , tokens  
+
+    // {Object} 
+    // the abstract syntax tree of the parsed code
+  , ast  
+
+    // {String}
+    // the code that was parsed (same string as the one passed to redeyed(code ..)
+  , code
+}
+```
+
+In most cases the `tokenString` is all you need. The extra info object is passed in case you need to gather more
+information about the `token`'s surroundings in order to decide how to transform it. 
+See: [replace-log-example](https://github.com/thlorenz/redeyed/blob/master/examples/replace-log.js)
+
+#### Output
+
+You can return a {String} or an {Object} from a {Function} config.
+
+- when returning a {String}, the token value will be replaced with it
+- when returning an {Object}, it should be of the following form:
+
+```js
+{
+    // {String}
+    // the string that should be substituted for the value of the current and all skipped tokens
+    replacement
+
+    // {Object} (Token)
+    // the token after which processing should continue
+    // all tokens in between the current one and this one inclusive will be ignored
+  , skipPastToken
+}
+```
+
+### Transforming JavaScript code
+
+***redeyed(code, config[, opts])***
+
+Invoke redeyed with your **config**uration, a **code** snippet and maybe **opts** as in the below example:
+
+```javascript
+var redeyed = require('redeyed')
+  , config = require('./path/to/config')
+  , code = 'var a = 3;'
+  , result;
+
+// redeyed will throw an error (caused by the esprima parser) if the code has invalid javascript
+try {
+  result = redeyed(code, config);
+  console.log(result.code);
+} catch(err) {
+  console.error(err);
+}
+```
+
+***opts***:
+```js
+{ // {Boolean}
+  // if true `result.code` is not assigned and therefore `undefined`
+  // if false (default) `result.code` property contains the result of `split.join`
+  nojoin: true|false
+}
+```
+
+***return value***:
+
+```js
+{   ast      
+  , tokens   
+  , comments 
+  , splits   
+  , code     
+}
+```
+
+- ast `{Array}`: [abstract syntax tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) as returned by [esprima
+  parse](http://en.wikipedia.org/wiki/Abstract_syntax_tree)
+- tokens `{Array}`: [tokens](http://en.wikipedia.org/wiki/Token_(parser)) provided by esprima (excluding
+  comments)
+- comments `{Array}`: block and line comments as provided by esprima
+- splits `{Array}`: code pieces split up, some of which where transformed as configured
+- code `{String}`: transformed code, same as `splits.join('')` unless this step has been skipped (see opts)
+
+## Browser Support
+
+### AMD
+
+Ensure to include [esprima](https://github.com/ariya/esprima) as one of your dependencies
+
+```js
+define(['redeyed'], function (redeyed) {
+ [ .. ]
+});
+```
+
+### Attached to global window object
+
+The `redeyed {Function}` will be exposed globally as `window.redeyed` - big surprise!
+
+```html
+<script type="text/javascript" src="https://raw.github.com/ariya/esprima/master/esprima.js"></script>
+<script type="text/javascript" src="path/to/redeyed.js"></script>
+```
+
+## redeyed in the wild
+
+- [cardinal](https://github.com/thlorenz/cardinal): Syntax highlights JavaScript code with ANSI colors to be printed to
+  the terminal
+- [peacock](http://thlorenz.github.com/peacock/): JavaScript syntax highlighter that generates html that is compatible
+  with pygments styles.
+
+## Examples
+
+- `npm explore redeyed; npm demo` will let you try the [browser example](https://github.com/thlorenz/redeyed/tree/master/examples/browser)
+- `npm explore redeyed; npm demo-log` will let you try the [replace log example](https://github.com/thlorenz/redeyed/blob/master/examples/replace-log.js)
+
diff --git a/node_modules/redeyed/config.js b/node_modules/redeyed/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..ade0de8e7250072f51d051702d464f9b8ab15703
--- /dev/null
+++ b/node_modules/redeyed/config.js
@@ -0,0 +1,137 @@
+/* 
+ * Copy this file and use it as a starting point for your redeyed config.
+ * Just fill in the tokens you want to surround/replace.
+ * Keep in mind that more specific configurations override less specific ones.
+ */
+
+module.exports = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  undefined
+    }
+
+  , 'Identifier': {
+      _default: undefined
+    }
+
+  , 'Null': {
+      _default: undefined
+    }
+
+  , 'Numeric': {
+      _default: undefined
+    }
+
+  , 'String': {
+      _default: undefined
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  undefined
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  undefined
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  undefined
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  undefined
+    , 'return'      :  undefined
+    , 'switch'      :  undefined
+
+    , 'this'        :  undefined
+    , 'throw'       :  undefined
+    , 'try'         :  undefined
+    , 'typeof'      :  undefined
+
+    , 'var'         :  undefined
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  undefined
+  }
+  , 'Punctuator': {
+      ';': undefined  
+    , '.': undefined  
+    , ',': undefined  
+
+    , '{': undefined  
+    , '}': undefined  
+    , '(': undefined  
+    , ')': undefined  
+    , '[': undefined
+    , ']': undefined
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: undefined
+  }
+
+  // line comment
+  , Line: {
+     _default: undefined
+    }
+
+  /* block comment */
+  , Block: {
+     _default: undefined
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/redeyed/examples/browser/index.css b/node_modules/redeyed/examples/browser/index.css
new file mode 100644
index 0000000000000000000000000000000000000000..fc9206eeced7daaba1c8ec502ee427e184d31a14
--- /dev/null
+++ b/node_modules/redeyed/examples/browser/index.css
@@ -0,0 +1,31 @@
+.code {
+  width: 500px;
+  height: 500px;
+  display: block;
+}
+
+.config {
+  width: 500px;
+  height: 400px;
+  display: block;
+}
+
+.go {
+  display: block;
+  float: right;
+  font-size: 18px;
+}
+
+.result {
+  width: 500px;
+  height: 1000px;
+  display: block;
+}
+
+.edit {
+  float: left;
+}
+
+.results {
+  float: left;
+}
diff --git a/node_modules/redeyed/examples/browser/index.html b/node_modules/redeyed/examples/browser/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..a20ea4c70a72da5c75a96f043e7ce8e1a9095968
--- /dev/null
+++ b/node_modules/redeyed/examples/browser/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset=utf-8 />
+    <title></title>
+    <link rel="stylesheet" type="text/css" media="screen" href="index.css" />
+</head>
+<body>
+    <header>
+        <span>Change the config and/or the original code in order to affect the "redeyed" result</span>
+    </header>
+    <section class="edit">
+        <section>
+            <h3>Redeyed Config </h3>
+            <textarea class="config"></textarea>
+            <button class="go">Go</button>
+        </section>
+        <section>
+            <h3>Original Code</h3>
+            <textarea class="code"></textarea>
+        </section>
+    </section>
+    <section class="results">
+        <h3>Result</h3>
+        <textarea class="result" readonly="readonly"></textarea>
+    </section>
+
+
+    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
+    <script type="text/javascript" src="https://raw.github.com/ariya/esprima/master/esprima.js"></script>
+    <script type="text/javascript" src="../../redeyed.js"></script>
+    <script type="text/javascript" src="./sample-config.js"></script>
+    <script type="text/javascript" src="./index.js"></script>
+</body>
+</html>
diff --git a/node_modules/redeyed/examples/browser/index.js b/node_modules/redeyed/examples/browser/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..82fd22fc49e22860f9156f123156316f6352cd36
--- /dev/null
+++ b/node_modules/redeyed/examples/browser/index.js
@@ -0,0 +1,33 @@
+var $code   =  $('.code')
+  , $config =  $('.config')
+  , $result =  $('.result')
+  ;
+
+function go () {
+  var config;
+  try {
+     config = JSON.parse($config.val());
+  } catch (e) {
+    $result.val('In "Redeyed Config": ' + e.toString());
+    return;
+  }
+
+  try {
+    var code = $code.val()
+      , result = redeyed(code, config);
+
+    $result.val(result.code);
+  } catch (e) {
+    $result.val('In "Original Code": ' + e.toString());
+  }
+}
+
+$code.val(window.redeyed.toString());
+
+$config.val(JSON.stringify(window.sampleConfig, false, 2));
+
+$('.go').click(go);
+
+go();
+
+
diff --git a/node_modules/redeyed/examples/browser/sample-config.js b/node_modules/redeyed/examples/browser/sample-config.js
new file mode 100644
index 0000000000000000000000000000000000000000..47456efa20479d52e03653c91f96746f2f847f40
--- /dev/null
+++ b/node_modules/redeyed/examples/browser/sample-config.js
@@ -0,0 +1,131 @@
+window.sampleConfig = {
+
+    'Boolean': {
+      'true'   :  undefined
+    , 'false'  :  undefined
+    , _default :  '?:?'
+    }
+
+  , 'Identifier': {
+      _default: '-> : <-'
+    }
+
+  , 'Null': {
+      _default: '**:**'
+    }
+
+  , 'Numeric': {
+      _default: 'n:N'
+    }
+
+  , 'String': {
+      _default: 'string -> :'
+    }
+
+  , 'Keyword': {
+      'break'       :  undefined
+
+    , 'case'        :  undefined
+    , 'catch'       :  undefined
+    , 'continue'    :  undefined
+
+    , 'debugger'    :  undefined
+    , 'default'     :  undefined
+    , 'delete'      :  undefined
+    , 'do'          :  undefined
+
+    , 'else'        :  undefined
+
+    , 'finally'     :  undefined
+    , 'for'         :  undefined
+    , 'function'    :  undefined
+
+    , 'if'          :  undefined
+    , 'in'          :  undefined
+    , 'instanceof'  :  undefined
+
+    , 'new'         :  undefined
+    , 'return'      :  undefined
+    , 'switch'      :  undefined
+
+    , 'this'        :  undefined
+    , 'throw'       :  undefined
+    , 'try'         :  undefined
+    , 'typeof'      :  undefined
+
+    , 'var'         :  undefined
+    , 'void'        :  undefined
+
+    , 'while'       :  undefined
+    , 'with'        :  undefined
+    , _default      :  ': <- keyword'
+  }
+  , 'Punctuator': {
+      ';': undefined  
+    , '.': undefined  
+    , ',': undefined  
+
+    , '{': undefined  
+    , '}': undefined  
+    , '(': undefined  
+    , ')': undefined  
+    , '[': undefined
+    , ']': undefined
+
+    , '<': undefined
+    , '>': undefined
+    , '+': undefined
+    , '-': undefined
+    , '*': undefined
+    , '%': undefined
+    , '&': undefined
+    , '|': undefined
+    , '^': undefined
+    , '!': undefined
+    , '~': undefined
+    , '?': undefined
+    , ':': undefined
+    , '=': undefined
+
+    , '<=': undefined
+    , '>=': undefined
+    , '==': undefined
+    , '!=': undefined
+    , '++': undefined
+    , '--': undefined
+    , '<<': undefined
+    , '>>': undefined
+    , '&&': undefined
+    , '||': undefined
+    , '+=': undefined
+    , '-=': undefined
+    , '*=': undefined
+    , '%=': undefined
+    , '&=': undefined
+    , '|=': undefined
+    , '^=': undefined
+    , '/=': undefined
+
+    , '===': undefined
+    , '!==': undefined
+    , '>>>': undefined
+    , '<<=': undefined
+    , '>>=': undefined
+    
+    , '>>>=': undefined
+
+    , _default: undefined
+  }
+
+  // line comment
+  , Line: {
+     _default: undefined
+    }
+
+  /* block comment */
+  , Block: {
+     _default: undefined
+    }
+
+  , _default: undefined
+};
diff --git a/node_modules/redeyed/examples/replace-log.js b/node_modules/redeyed/examples/replace-log.js
new file mode 100644
index 0000000000000000000000000000000000000000..4b12ccf9b49cbd6b8ec5d76189c7acffa1b0d51a
--- /dev/null
+++ b/node_modules/redeyed/examples/replace-log.js
@@ -0,0 +1,61 @@
+var path    =  require('path')
+  , fs      =  require('fs')
+  , redeyed =  require('..')
+  , vm      =  require('vm')
+  ;
+
+var samplePath =  path.join(__dirname, 'sources', 'log.js')
+  , origCode   =  fs.readFileSync(samplePath, 'utf-8')
+  , kinds = ['silly', 'info', 'warn', 'error' ]
+  ;
+
+function replaceConsole(s, info) {
+  var code        =  info.code
+    , idx         =  info.tokenIndex
+    , tokens      =  info.tokens
+    , next        =  tokens[idx + 1].value
+    , kind        =  tokens[idx + 2].value
+    , openParen   =  tokens[idx + 3].value
+    , firstArgTkn =  tokens[idx + 4]
+    , argIdx      =  idx + 3
+    , open
+    , tkn
+    ;
+
+  if (kind === 'log') kind = 'silly';
+
+  // not a console.xxx(...) statement? -> just return original
+  if (next !== '.' || !~kinds.indexOf(kind) || openParen !== '(') return s;
+
+  // skip past arguments to console.xxx all args from ( to )
+  open = 1;
+  while (open) {
+    tkn = tokens[++argIdx];
+
+    // count open parens vs. closed ones to handle things like console.log(new Error('..'));
+    if (tkn.value === '(') open++;
+    if (tkn.value === ')') open--;
+  }
+
+  // tkn now is the last closing paren
+  var argsIncludingClosingParen =  code.slice(firstArgTkn.range[0], tkn.range[1])
+    , result                    =  'log.' + kind + '("main-logger", ' + argsIncludingClosingParen;
+  
+  // tell redeyed to skip the entire console.xxx(..) statement since we are replacing it all
+  return { replacement: result, skipPastToken: tkn }; 
+}
+
+function transformAndRun () {
+  var config = {
+        Identifier: { console: replaceConsole }
+      }
+    , code        =  redeyed(origCode, config).code
+    , context     =  vm.createContext({ require: require });
+
+  console.log('Original code:\n', origCode);
+  console.log('\nlog calls replaced:\n', code);
+  console.log('\nLets run it:');
+  vm.runInContext(code, context, 'transformed-log.vm');
+}
+
+transformAndRun();
diff --git a/node_modules/redeyed/examples/sources/log.js b/node_modules/redeyed/examples/sources/log.js
new file mode 100644
index 0000000000000000000000000000000000000000..7994d2fb9c07704e7d336d04e1b17ee0ed574426
--- /dev/null
+++ b/node_modules/redeyed/examples/sources/log.js
@@ -0,0 +1,8 @@
+// First two lines will be needed when we replaced all console.xxx statements with log.xxx
+var log = require('npmlog');
+log.level = 'silly';
+
+console.info('info ', 1);
+console.log('log ', 2);
+console.warn('warn ', 3);
+console.error('error ', new Error('oh my!'));
diff --git a/node_modules/redeyed/package.json b/node_modules/redeyed/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..7ceeca2299e5ddb7244e28815e0ad02543b93129
--- /dev/null
+++ b/node_modules/redeyed/package.json
@@ -0,0 +1,33 @@
+{
+  "name": "redeyed",
+  "version": "0.4.4",
+  "description": "Takes JavaScript code, along with a config and returns the original code with tokens wrapped as configured.",
+  "author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
+  "main": "redeyed.js",
+  "scripts": {
+    "test": "tap test/*.js",
+    "demo-log": "node examples/replace-log",
+    "demo": "cd examples/browser; open index.html"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/thlorenz/redeyed.git"
+  },
+  "keywords": [
+    "ast",
+    "syntax",
+    "tree",
+    "source",
+    "wrap",
+    "metadata"
+  ],
+  "license": "MIT",
+  "devDependencies": {
+    "tap": "~0.4.8",
+    "readdirp": "~0.3.3",
+    "cardinal": "~0.4.4"
+  },
+  "dependencies": {
+    "esprima": "~1.0.4"
+  }
+}
diff --git a/node_modules/redeyed/redeyed.js b/node_modules/redeyed/redeyed.js
new file mode 100644
index 0000000000000000000000000000000000000000..7a326cb92f4e2fb58bcd87773a4b0eff7e297daa
--- /dev/null
+++ b/node_modules/redeyed/redeyed.js
@@ -0,0 +1,291 @@
+;(function () {
+
+'use strict';
+/*jshint laxbreak: true,  browser:true */
+/*global define*/
+
+var esprima
+  , exportFn
+  , toString = Object.prototype.toString
+  ;
+
+if (typeof module === 'object' && typeof module.exports === 'object' && typeof require === 'function') {
+  // server side
+  esprima = require('esprima');
+  exportFn = function (redeyed) { module.exports = redeyed; };
+  bootstrap(esprima, exportFn);
+} else if (typeof define === 'function' && define.amd) {
+  // client side
+  // amd
+  define(['esprima'], function (esprima) {
+      return bootstrap(esprima);
+  });
+} else if (typeof window === 'object') {
+  // no amd -> attach to window if it exists
+  // Note that this requires 'esprima' to be defined on the window, so that script has to be loaded first
+  window.redeyed = bootstrap(window.esprima);
+}
+
+function bootstrap(esprima, exportFn) {
+
+  function isFunction (obj) {
+    return toString.call(obj) === '[object Function]';
+  }
+
+  function isString (obj) {
+    return toString.call(obj) === '[object String]';
+  }
+
+  function isNumber (obj) {
+    return toString.call(obj) === '[object Number]';
+  }
+
+  function isObject (obj) {
+    return toString.call(obj) === '[object Object]';
+  }
+
+  function surroundWith (before, after) {
+    return function (s) { return before + s + after; };
+  }
+
+  function isNonCircular(key) { 
+    return key !== '_parent'; 
+  }
+
+  function objectizeString (value) {
+    var vals = value.split(':');
+
+    if (0 === vals.length || vals.length > 2) 
+      throw new Error(
+        'illegal string config: ' + value +
+        '\nShould be of format "before:after"'
+      );
+
+    if (vals.length === 1 || vals[1].length === 0) {
+      return vals.indexOf(':') < 0 ? { _before: vals[0] } : { _after: vals[0] };
+    } else {
+      return { _before: vals[0], _after: vals[1] };
+    }
+  }
+
+  function objectize (node) {
+
+    // Converts 'bef:aft' to { _before: bef, _after: aft } 
+    // and resolves undefined before/after from parent or root
+
+    function resolve (value, key) {
+      // resolve before/after from root or parent if it isn't present on the current node
+      if (!value._parent) return undefined;
+      
+      // Immediate parent
+      if (value._parent._default && value._parent._default[key]) return value._parent._default[key];
+
+      // Root
+      var root = value._parent._parent;
+      if (!root) return undefined;
+
+      return root._default ? root._default[key] : undefined;
+    }
+
+    function process (key) {
+      var value = node[key];
+
+      if (!value) return;
+      if (isFunction(value)) return;
+
+      // normalize all strings to objects
+      if (isString(value)) {
+        node[key] = value = objectizeString(value);
+      }
+      
+      value._parent = node;
+      if (isObject(value)) {
+        if (!value._before && !value._after) return objectize (value);
+
+        // resolve missing _before or _after from parent(s) 
+        // in case we only have either one on this node
+        value._before =  value._before || resolve(value, '_before');
+        value._after  =  value._after  || resolve(value, '_after');
+        
+        return;
+      } 
+
+      throw new Error('nodes need to be either {String}, {Object} or {Function}.' + value + ' is neither.');
+    }
+
+    // Process _default ones first so children can resolve missing before/after from them
+    if (node._default) process('_default');
+
+    Object.keys(node)
+      .filter(function (key) {
+        return isNonCircular(key) 
+          && node.hasOwnProperty(key)
+          && key !== '_before' 
+          && key !== '_after' 
+          && key !== '_default';
+      })
+      .forEach(process);
+  }
+
+  function functionize (node) {
+    Object.keys(node)
+      .filter(function (key) { 
+        return isNonCircular(key) && node.hasOwnProperty(key);
+      })
+      .forEach(function (key) {
+        var value = node[key];
+
+        if (isFunction(value)) return;
+
+        if (isObject(value)) {
+
+          if (!value._before && !value._after) return functionize(value);
+
+          // at this point before/after were "inherited" from the parent or root
+          // (see objectize)
+          var before = value._before || '';
+          var after = value._after || '';
+
+          node[key] = surroundWith (before, after);
+          return node[key];
+        }
+      });
+  }
+
+  function normalize (root) {
+    objectize(root);
+    functionize(root);
+  }
+
+  function mergeTokensAndComments(tokens, comments) {
+    var all = {};
+
+    function addToAllByRangeStart(t) { all[ t.range[0] ] = t; }
+
+    tokens.forEach(addToAllByRangeStart);
+    comments.forEach(addToAllByRangeStart);
+
+    // keys are sorted automatically
+    return Object.keys(all)
+      .map(function (k) { return all[k]; });
+  }
+
+  function redeyed (code, config, opts) {
+    opts = opts || {};
+
+    // remove shebang
+    code = code.replace(/^\#\!.*/, '');
+
+    var ast = esprima.parse(code, { tokens: true, comment: true, range: true, tolerant: true })
+      , tokens = ast.tokens
+      , comments = ast.comments
+      , lastSplitEnd = 0
+      , splits = []
+      , transformedCode
+      , all
+      , info
+      ;
+
+    normalize(config);
+
+    function tokenIndex(tokens, tkn, start) {
+      var current
+        , rangeStart = tkn.range[0];
+
+      for (current = start; current < tokens.length; current++) {
+        if (tokens[current].range[0] === rangeStart) return current;
+      }
+
+      throw new Error('Token %s not found at or after index: %d', tkn, start);
+    }
+
+    function process(surround) {
+      var result
+        , currentIndex
+        , nextIndex
+        , skip = 0
+        , splitEnd
+        ;
+
+      result = surround(code.slice(start, end), info);
+      if (isObject(result)) {
+        splits.push(result.replacement);
+
+        currentIndex =  info.tokenIndex;
+        nextIndex    =  tokenIndex(info.tokens, result.skipPastToken, currentIndex);
+        skip         =  nextIndex - currentIndex;
+        splitEnd     =  skip > 0 ? tokens[nextIndex - 1].range[1] : end;
+      } else {
+        splits.push(result);
+        splitEnd = end;
+      }
+
+      return { skip: skip, splitEnd: splitEnd  };
+    }
+
+    function addSplit (start, end, surround, info) {
+      var result
+        , nextIndex
+        , skip = 0
+        ;
+
+      if (start >= end) return;
+      if (surround) {
+        result       =  process(surround);
+        skip         =  result.skip;
+        lastSplitEnd =  result.splitEnd;
+      } else {
+        splits.push(code.slice(start, end));
+        lastSplitEnd = end;
+      }
+
+      return skip;
+    }
+
+    all = mergeTokensAndComments(tokens, comments);
+    for (var tokenIdx = 0; tokenIdx < all.length; tokenIdx++) {
+      var token = all[tokenIdx]
+        , surroundForType = config[token.type]
+        , surround
+        , start
+        , end;
+      
+      // At least the type (e.g., 'Keyword') needs to be specified for the token to be surrounded
+      if (surroundForType) {
+
+        // root defaults are only taken into account while resolving before/after otherwise
+        // a root default would apply to everything, even if no type default was specified
+        surround = surroundForType 
+          && surroundForType.hasOwnProperty(token.value) 
+          && surroundForType[token.value]
+          && isFunction(surroundForType[token.value])
+            ? surroundForType[token.value] 
+            : surroundForType._default;
+
+        start = token.range[0];
+        end = token.range[1];
+
+        addSplit(lastSplitEnd, start);
+        info = { tokenIndex: tokenIdx, tokens: all, ast: ast, code: code };
+        tokenIdx += addSplit(start, end, surround, info);
+      }
+    }
+
+    if (lastSplitEnd < code.length) {
+      addSplit(lastSplitEnd, code.length);
+    }
+
+  transformedCode = opts.nojoin ? undefined : splits.join('');
+
+    return { 
+        ast      :  ast
+      , tokens   :  tokens
+      , comments :  comments
+      , splits   :  splits
+      , code     :  transformedCode
+    };
+  }
+
+  return exportFn ? exportFn(redeyed) : redeyed;
+}
+})();
diff --git a/node_modules/redeyed/test/redeyed-before-after-config.js b/node_modules/redeyed/test/redeyed-before-after-config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0f8284c762a8a33cdda3dfa655fc0115f38edcb
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-before-after-config.js
@@ -0,0 +1,54 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var result = redeyed(code, opts).code
+    this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
+    return this;
+  }
+
+  t.end() 
+})
+test('\nbefore/after config, keywords', function (t) {
+
+  var opts001 = { Keyword: { _default: { _before: '*', _after: '&' } } };  
+  t.test('\n# ' + inspect(opts001), function (t) {
+    t.assertSurrounds('this', opts001, '*this&')
+    t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
+    t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
+    t.end()
+  })
+  
+  var opts002 = { 
+    Keyword: { 
+        'function': { _before: '^' }
+      , 'return': { _before: '(', _after: ')' }
+      , _default: { _before: '*' , _after: '&' }
+    } 
+  };  
+
+  t.test('\n# ' + inspect(opts002), function (t) {
+    t.assertSurrounds(
+        [ 'function foo (bar) {'
+        , ' var a = 3;'
+        , ' return bar + a;'
+        , '}'
+        ].join('\n')
+      , opts002
+      , [ '^function& foo (bar) {'
+        , ' *var& a = 3;'
+        , ' (return) bar + a;'
+        , '}'
+        ].join('\n'))
+    t.end()
+  })
+})
diff --git a/node_modules/redeyed/test/redeyed-browser.js b/node_modules/redeyed/test/redeyed-browser.js
new file mode 100644
index 0000000000000000000000000000000000000000..ddb25ce46d430c8b36bb4905283f42b8db8bf12a
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-browser.js
@@ -0,0 +1,69 @@
+'use strict'
+/*jshint asi: true, browser: true*/
+/*global define window */
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyedExport = require('..')
+  , redeyedkey = require.resolve('..')
+  , esprima = require('esprima')
+
+function setup() {
+  // remove redeyed from require cache to force re-require for each test
+  delete require.cache[redeyedkey];
+  
+  // remove globals
+  delete global.window;
+  delete global.define;
+}
+
+// TODO: need to run in vm in order to properly simulate require and module not being present
+return;
+test('define and window exist', function (t) {
+  var defineCb
+    , deps
+
+  setup()  
+
+  // declare browser globals
+  global.window = { }
+
+  global.define = function (deps_, cb) { 
+    deps_ = deps 
+    defineCb = cb 
+  }
+
+  define.amd = true
+
+  var redeyed = require('..')
+    , definedredeyed = defineCb(esprima)
+
+  t.equal(window.redeyed, undefined, 'redeyed is not attached to window')
+  t.notEqual(redeyed.toString(), redeyedExport.toString(), 'redeyed is not exported')
+  t.equal(definedredeyed.toString(), redeyedExport.toString(), 'redeyed is defined')
+
+  t.end()
+})
+
+test('window exists, but define doesn\'t', function (t) {
+  setup()  
+
+  // declare browser globals
+  global.window = { esprima: esprima }
+    
+  var redeyed = require('..')
+
+  t.equal(window.redeyed.toString(), redeyedExport.toString(), 'redeyed is attached to window')
+  t.notEqual(redeyed.toString(), redeyedExport.toString(), 'redeyed is not exported')
+  t.end()
+})
+
+test('neither window nor define exist', function (t) {
+  setup()  
+
+  var redeyed = require('..')
+
+  t.equal(redeyed.toString(), redeyedExport.toString(), 'redeyed is exported')
+  t.end()
+})
+
diff --git a/node_modules/redeyed/test/redeyed-comments.js b/node_modules/redeyed/test/redeyed-comments.js
new file mode 100644
index 0000000000000000000000000000000000000000..09392cc5710cbd835c0c0f8276fef324e7ecaed0
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-comments.js
@@ -0,0 +1,71 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var result = redeyed(code, opts)
+    this.equals(result.code, expected, inspect(code) + ' => ' + inspect(expected))
+    return this;
+  }
+
+  t.end() 
+})
+
+test('\nstring config, Line comments', function (t) {
+  var opts = { Line: { _default: '*:&' } };
+  t.test('\n# ' + inspect(opts), function (t) {
+
+    t.assertSurrounds(
+        '// a comment'
+      , opts
+      , '*// a comment&'
+    )
+    t.assertSurrounds(
+        '// comment then new line\nif (a == 1) return'
+      , opts
+      , '*// comment then new line&\nif (a == 1) return'
+    )
+    t.assertSurrounds(
+        'var n = new Test();// some comment after\n//more comment\nvar s = 3;'
+      , opts
+      , 'var n = new Test();*// some comment after&\n*//more comment&\nvar s = 3;'
+    )
+    t.end()
+  })
+})
+
+test('\nstring config, Block comments', function (t) {
+  var opts = { Block: { _default: '_:-' } };
+  t.test('\n# ' + inspect(opts), function (t) {
+
+    t.assertSurrounds(
+        '/* a comment */'
+      , opts
+      , '_/* a comment */-'
+    )
+    t.assertSurrounds(
+        '/* comment then new line*/\nif (a == 1) /* inline */ return'
+      , opts
+      , '_/* comment then new line*/-\nif (a == 1) _/* inline */- return'
+    )
+    t.assertSurrounds(
+        'var n = new Test();/* some comment after*/\n/*more comment*/\nvar s = 3;'
+      , opts
+      , 'var n = new Test();_/* some comment after*/-\n_/*more comment*/-\nvar s = 3;'
+    )
+    t.assertSurrounds(
+        'var a = 4;\n/* Multi line comment\n * Next line\n * and another\n*/ var morecode = "here";'
+      , opts
+      , 'var a = 4;\n_/* Multi line comment\n * Next line\n * and another\n*/- var morecode = "here";'
+    )
+    t.end()
+  })
+})
diff --git a/node_modules/redeyed/test/redeyed-config-with-undefineds.js b/node_modules/redeyed/test/redeyed-config-with-undefineds.js
new file mode 100644
index 0000000000000000000000000000000000000000..5ddc40d8f93b1efb8f1dcf3aa4afa172824dcfb6
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-config-with-undefineds.js
@@ -0,0 +1,60 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var optsi = inspect(opts);
+    var result = redeyed(code, opts).code
+
+    this.equals(  result
+                , expected
+                , util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
+               )
+    return this;
+  }
+
+  t.end() 
+})
+
+test('\n undefineds only', function (t) {
+  t.assertSurrounds('1 + 2', { Numeric: { _default: undefined } }, '1 + 2')
+  t.assertSurrounds('1 + 2', { Numeric: { _default: undefined }, _default: undefined }, '1 + 2')
+
+  t.assertSurrounds(
+      'return true'
+    , { 'Boolean': { 'true': undefined, 'false': undefined, _default: undefined } , _default: undefined }
+    , 'return true'
+  )
+
+  t.end()
+})
+
+test('\n mixed', function (t) {
+  t.assertSurrounds(
+      'return true || false'
+    , { 'Boolean': { 'true': '&:', 'false': undefined, _default: undefined } , _default: undefined }
+    , 'return &true || false'
+  )
+
+  t.assertSurrounds(
+      'return true || false'
+    , { 'Boolean': { 'true': '&:', 'false': undefined, _default: ':?' } , _default: undefined }
+    , 'return &true? || false?'
+  )
+
+  t.assertSurrounds(
+      'return true || false'
+    , { 'Boolean': { 'true': '&:', 'false': undefined, _default: undefined } , _default: ':?' }
+    , 'return &true? || false'
+  )
+  
+  t.end()
+})
diff --git a/node_modules/redeyed/test/redeyed-function-config-extra-params.js b/node_modules/redeyed/test/redeyed-function-config-extra-params.js
new file mode 100644
index 0000000000000000000000000000000000000000..f962b7cf74a6890009cdf286cd2ce2f3663771dd
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-function-config-extra-params.js
@@ -0,0 +1,57 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('function - config passing idx and tokens', function (t) {
+
+  var args = [] 
+    , opts001 = { 
+          Boolean: { 
+            _default: identity 
+          } 
+        , Keyword: { 
+            _default: identity 
+          } 
+        , Identifier: { 
+            _default: identity 
+          } 
+        , Punctuator: { 
+            _default: identity 
+          } 
+      }
+    , code = 'var fn = function () { return true; }'
+
+  function identity (s, info) { 
+    args.push( { value: s, idx: info.tokenIndex, tokens: info.tokens, code: info.code }) 
+    // returning unchanged string will keep the splits be equal to the original tokens
+    return s 
+  } 
+
+  function tokenValue (t) { return t.value; }
+
+  t.test(inspect(opts001) + ' -- ' + code, function (t) {
+
+    var result = redeyed(code, opts001, { splits: true })
+      , tokens = result.tokens
+    
+      t.equals(args.length, tokens.length, 'called with all tokens')
+      
+      for (var i = 0; i < tokens.length; i++) {
+        var token = tokens[i]
+          , arg = args[i]
+
+        t.equals(arg.value, token.value, 'passes correct value: ' + inspect([ arg.value, token.value ]))
+        t.equals(arg.idx, i, 'passes correct index')
+        t.equals(arg.code, code, 'passes code')
+        t.deepEquals(arg.tokens, tokens, 'passes all tokens')
+      }
+    t.end()
+  })
+})
diff --git a/node_modules/redeyed/test/redeyed-function-config-skipping-tokens.js b/node_modules/redeyed/test/redeyed-function-config-skipping-tokens.js
new file mode 100644
index 0000000000000000000000000000000000000000..ff142737b6e2ab28c18ed0f4d097ca8c6cc6f1c6
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-function-config-skipping-tokens.js
@@ -0,0 +1,89 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+          
+test('given i skip 2 more tokens after each semicolon', function (t) {
+  var calls = 0
+    , opts = {
+        Punctuator: {
+          ';':  function identity (s, info) {
+                  // tell it to skip past second to last token that is 2 ahead of the current one
+                  calls++
+                  var skipToken = info.tokens[info.tokenIndex + 2]
+                  return skipToken ? { replacement: s, skipPastToken: skipToken } : s;
+                }
+        }
+      }
+    ;
+
+  [  { code: ';;;'                   ,  expectedCalls: 1 }
+  ,  { code: ';;;;'                  ,  expectedCalls: 2 }
+  ,  { code: '; ; ; ;'               ,  expectedCalls: 2 }
+  ,  { code: ';;; ;;; ;;; ;'         ,  expectedCalls: 4 }
+  ,  { code: ';;; ;;; ;;; ;;; ;'     ,  expectedCalls: 5 }
+  ,  { code: ';;; ;;; ;;; ;;; ;;;'   ,  expectedCalls: 5 }
+  ,  { code: ';;; ;;; ;;; ;;; ;;; ;' ,  expectedCalls: 6 }
+  ].forEach(function (x) {
+      calls = 0
+      redeyed(x.code, opts);
+      t.equals(calls, x.expectedCalls, 'calls ' + x.expectedCalls + ' times for ' + x.code)
+    });
+  t.end()
+})
+
+test('replace log', function (t) {
+  var kinds = [ 'info', 'warn', 'error' ]
+    , opts = {
+        Identifier: { 
+          console: function replaceLog(s, info) {
+            var code        =  info.code
+              , idx         =  info.tokenIndex
+              , tokens      =  info.tokens
+              , kind        =  tokens[idx + 2].value
+              , openParen   =  tokens[idx + 3].value
+              , firstArgTkn =  tokens[idx + 4]
+              , argIdx      =  idx + 3
+              , open
+              , tkn
+              ;
+
+            open = 1;
+            while (open) {
+              tkn = tokens[++argIdx];
+
+              if (tkn.value === '(') open++;
+              if (tkn.value === ')') open--;
+            }
+
+            var argsIncludingClosingParen =  code.slice(firstArgTkn.range[0], tkn.range[1])
+              , result                    =  'log.' + kind + '("main-logger", ' + argsIncludingClosingParen;
+            
+            return { replacement: result, skipPastToken: tkn }; 
+          }
+        }
+      }
+
+   , origCode = [
+       'console.info("info ", 1);'
+     , 'console.warn("warn ", 3);'
+     , 'console.error("error ", new Error("oh my!"));'
+    ].join('\n')
+  
+  , expectedCode = [
+      'log.info("main-logger", "info ", 1));'
+    , 'log.warn("main-logger", "warn ", 3));'
+    , 'log.error("main-logger", "error ", new Error("oh my!")));'
+    ].join('\n')
+  , code = redeyed(origCode, opts).code
+
+  t.equals(code, expectedCode, 'transforms all log statements')
+  t.end()
+});
diff --git a/node_modules/redeyed/test/redeyed-function-config.js b/node_modules/redeyed/test/redeyed-function-config.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c5ed29e68c2388312d0f2d04e1754731c2eb943
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-function-config.js
@@ -0,0 +1,142 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var result = redeyed(code, opts).code
+    this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
+    return this;
+  }
+
+  t.end() 
+})
+
+test('\nfunction config, keywords', function (t) {
+
+  var opts001 = { Keyword: { _default: function (s) { return '*' + s + '&'; } } };
+  t.test('\n# ' + inspect(opts001), function (t) {
+    t.assertSurrounds('this', opts001, '*this&')
+
+    t.assertSurrounds('this ', opts001, '*this& ')
+    t.assertSurrounds(' this', opts001, ' *this&')
+    t.assertSurrounds('  this  ', opts001, '  *this&  ')
+    t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
+    t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
+    t.assertSurrounds(
+        [ 'function foo (bar) {'
+        , ' var a = 3;'
+        , ' return bar + a;'
+        , '}'
+        ].join('\n')
+      , opts001
+      , [ '*function& foo (bar) {'
+        , ' *var& a = 3;'
+        , ' *return& bar + a;'
+        , '}'
+        ].join('\n'))
+    t.end()
+  })
+
+  var opts002 = { 
+    Keyword: { 
+        'function': function (s) { return '^' + s + '&' }
+      , 'return':  function (s) { return '(' + s + ')' }
+      , _default: function (s) { return '*' + s + '&' }
+    } 
+  };  
+
+  t.test('\n# ' + inspect(opts002), function (t) {
+    t.assertSurrounds(
+        [ 'function foo (bar) {'
+        , ' var a = 3;'
+        , ' return bar + a;'
+        , '}'
+        ].join('\n')
+      , opts002
+      , [ '^function& foo (bar) {'
+        , ' *var& a = 3;'
+        , ' (return) bar + a;'
+        , '}'
+        ].join('\n'))
+    t.end()
+  })
+})
+
+test('#\n functin config - resolving', function (t) {
+  var opts001 = { 
+      Keyword: { 
+        'var': function (s) { return '^' + s + '&' }
+      }
+    , _default: function (s) { return '*' + s + '&' }
+  };  
+  t.test('\n# specific but no type default and root default - root default not applied' + inspect(opts001), function (t) {
+    t.assertSurrounds('var n = new Test();', opts001, '^var& n = new Test();').end();
+  })
+
+  var opts002 = { 
+      Keyword: { 
+        'var': function (s) { return '^' + s + '&' }
+      , _default: function (s) { return '*' + s + '&' }
+      }
+    , _default: function (s) { return '(' + s + ')' }
+  };  
+  t.test('\n# no type default but root default' + inspect(opts002), function (t) {
+    t.assertSurrounds('var n = new Test();', opts002, '^var& n = *new& Test();').end();
+  })
+})
+
+test('#\n function config - replacing', function (t) {
+  var opts001 = { 
+      Keyword: { 
+        'var': function () { return 'const' }
+      }
+  };  
+  t.test('\n# type default and root default (type wins)' + inspect(opts001), function (t) {
+    t.assertSurrounds('var n = new Test();', opts001, 'const n = new Test();').end();
+  })
+
+  var opts002 = { 
+      Keyword: { 
+        _default: function () { return 'const' }
+      }
+  };  
+  t.test('\n# type default' + inspect(opts002), function (t) {
+    t.assertSurrounds('var n = new Test();', opts002, 'const n = const Test();').end();
+  })
+  
+  var opts003 = { 
+      Keyword: { 
+          'new': function () { return 'NEW'; }
+        , _default: function () { return 'const' }
+      }
+  };  
+  t.test('\n# specific and type default' + inspect(opts003), function (t) {
+    t.assertSurrounds('var n = new Test();', opts003, 'const n = NEW Test();').end();
+  })
+
+  var opts004 = { 
+      Keyword: { 
+        _default: function (s) { return s.toUpperCase() }
+      }
+      , _default: function (s) { return 'not applied'; }
+  };  
+  t.test('\n# type default and root default (type wins)' + inspect(opts004), function (t) {
+    t.assertSurrounds('var n = new Test();', opts004, 'VAR n = NEW Test();').end();
+  })
+
+  var opts005 = { 
+        Keyword: { }
+      , _default: function (s) { return s.toUpperCase() }
+  };  
+  t.test('\n# no type default only root default - not applied' + inspect(opts005), function (t) {
+    t.assertSurrounds('var n = new Test();', opts005, 'var n = new Test();').end();
+  })
+})
diff --git a/node_modules/redeyed/test/redeyed-mixed.js b/node_modules/redeyed/test/redeyed-mixed.js
new file mode 100644
index 0000000000000000000000000000000000000000..2346ba9cf121bdc967a548ea259af565a4612cf0
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-mixed.js
@@ -0,0 +1,46 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var result = redeyed(code, opts).code
+    this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
+    return this;
+  }
+
+  t.end() 
+})
+
+test('\nmixed config, keywords', function (t) {
+  var opts001 = { 
+    Keyword: { 
+        'this': function (s) { return '_' + s; }
+      , 'if': { _before: '^' }
+      , _default: '*:&' 
+    } 
+  };
+  t.test('\n# ' + inspect(opts001), function (t) {
+   t.assertSurrounds('if (this.hello) return "world";', opts001, '^if& (_this.hello) *return& "world";').end()
+  })
+  
+  var opts002 = { 
+      Keyword: { 
+          'this': function (s) { return '_' + s; }
+        , 'if': { _before: '^' }
+        , 'return': ':)'
+        , _default: ':&' 
+      } 
+    , _default: '*:&' 
+  };
+  t.test('\n# ' + inspect(opts002), function (t) {
+   t.assertSurrounds('if (this.hello) return "world";', opts002, '^if& (_this.hello) *return) "world";').end()
+  })
+})
diff --git a/node_modules/redeyed/test/redeyed-result.js b/node_modules/redeyed/test/redeyed-result.js
new file mode 100644
index 0000000000000000000000000000000000000000..9a138dca1c3a179db13f833427ad12d066340171
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-result.js
@@ -0,0 +1,48 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+  , esprima = require('esprima')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('redeyed result has esprima ast, tokens, comments and splits and transformed code', function (t) {
+  var code = '// a comment\nvar a = 3;'
+    , conf = { Keyword: { _default: '_:-' } }
+
+    , ast    =  esprima.parse(code, { tokens: true, comment: true, range: true, tolerant: true })
+    , tokens =  ast.tokens
+    , comments = ast.comments
+
+    , result = redeyed(code, conf)
+
+    console.log(ast)
+  t.deepEquals(result.ast, ast, 'ast')
+  t.deepEquals(result.tokens, tokens, 'tokens')
+  t.deepEquals(result.comments, comments, 'comments')
+  t.notEquals(result.code, undefined, 'code')
+
+  t.end()
+});
+
+test('redeyed result - { nojoin } has esprima ast, tokens, comments and splits but no transformed code', function (t) {
+  var code = '// a comment\nvar a = 3;'
+    , conf = { Keyword: { _default: '_:-' } }
+
+    , ast    =  esprima.parse(code, { tokens: true, comment: true, range: true, tolerant: true })
+    , tokens =  ast.tokens
+    , comments = ast.comments
+
+    , result = redeyed(code, conf, { nojoin: true })
+
+  t.deepEquals(result.ast, ast, 'ast')
+  t.deepEquals(result.tokens, tokens, 'tokens')
+  t.deepEquals(result.comments, comments, 'comments')
+  t.equals(result.code, undefined, 'code')
+
+  t.end()
+});
diff --git a/node_modules/redeyed/test/redeyed-script-level-return.js b/node_modules/redeyed/test/redeyed-script-level-return.js
new file mode 100644
index 0000000000000000000000000000000000000000..bbdbbb74b0cf841976beb7a3d5f0d1fc46fff224
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-script-level-return.js
@@ -0,0 +1,22 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('properly handles script level return -- no blow up', function (t) {
+  var code = [
+      , 'return 1;'
+      ].join('\n')
+    , opts = { Keyword: { 'return': '%:^' } }
+    , expected = '\n%return^ 1;'
+    , res = redeyed(code, opts).code
+
+  t.equals(res, expected, inspect(code) + ' opts: ' + inspect(opts) + ' => ' + inspect(expected))
+  t.end()
+})
diff --git a/node_modules/redeyed/test/redeyed-shebang.js b/node_modules/redeyed/test/redeyed-shebang.js
new file mode 100644
index 0000000000000000000000000000000000000000..f94ee394a1b75408c2db0e3cec2abeda049ef738
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-shebang.js
@@ -0,0 +1,23 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('removes shebang from the code before parsing it', function (t) {
+  var code = [
+        '#!/usr/bin/env node'
+      , 'var util = require("util");'
+      ].join('\n')
+    , opts = { Keyword: { 'var': '%:^' } }
+    , expected = '\n%var^ util = require("util");'
+    , res = redeyed(code, opts).code
+
+  t.equals(res, expected, inspect(code) + ' opts: ' + inspect(opts) + ' => ' + inspect(expected))
+  t.end()
+})
diff --git a/node_modules/redeyed/test/redeyed-smoke.js b/node_modules/redeyed/test/redeyed-smoke.js
new file mode 100644
index 0000000000000000000000000000000000000000..cf6c81b38a36898b639b92ef53212f26098cfd72
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-smoke.js
@@ -0,0 +1,57 @@
+'use strict';
+/*jshint asi: true*/
+
+// applying redeyed to a bunch of files of contained libraries as a smoke test
+var test     =  require('tap').test
+  , path     =  require('path')
+  , fs       =  require('fs')
+  , readdirp =  require('readdirp')
+  , redeyed  =  require('..')
+  , node_modules =  path.join(__dirname, '..', 'node_modules')
+  , tapdir       =  path.join(node_modules, 'tap')
+  , esprimadir   =  path.join(node_modules, 'esprima')
+
+test('tap', function (t) {
+  var invalidTapFiles = [
+      'async-map-ordered.js'
+    , 'prof.js'
+  ]
+
+  readdirp({ root: tapdir, fileFilter: '*.js' })
+    .on('data', function (entry) {
+      
+      if (~invalidTapFiles.indexOf(entry.name)) return
+
+      var code = fs.readFileSync(entry.fullPath, 'utf-8')
+        , result = redeyed(code, { Keyword: { 'var': '+:-' } }).code
+
+      t.assert(~result.indexOf('+var-') || !(~result.indexOf('var ')), 'redeyed ' + entry.path)
+    })
+    .on('end', t.end.bind(t))
+})
+
+test('esprima', function (t) {
+
+  readdirp({ root: esprimadir, fileFilter: '*.js' })
+    .on('data', function (entry) {
+      
+      var code = fs.readFileSync(entry.fullPath, 'utf-8')
+        , result = redeyed(code, { Keyword: { 'var': '+:-' } }).code
+
+      t.assert(~result.indexOf('+var-') || !(~result.indexOf('var ')), 'redeyed ' + entry.path)
+    })
+    .on('end', t.end.bind(t))
+})
+
+test('redeyed', function (t) {
+
+  readdirp({ root: path.join(__dirname, '..'), fileFilter: '*.js', directoryFilter: ['!.git', '!node_modules' ] })
+    .on('data', function (entry) {
+      
+      var code = fs.readFileSync(entry.fullPath, 'utf-8')
+        , result = redeyed(code, { Keyword: { 'var': '+:-' } }).code
+
+        t.assert(~result.indexOf('+var-') || !(~result.indexOf('var ')), 'redeyed ' + entry.path)
+    })
+    .on('end', t.end.bind(t))
+})
diff --git a/node_modules/redeyed/test/redeyed-string-config.js b/node_modules/redeyed/test/redeyed-string-config.js
new file mode 100644
index 0000000000000000000000000000000000000000..25a8953adf278b2d8609ee6050c484055181717c
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-string-config.js
@@ -0,0 +1,124 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var result = redeyed(code, opts).code
+    this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
+    return this;
+  }
+
+  t.end() 
+})
+
+test('\nstring config, keywords', function (t) {
+
+  var opts001 = { Keyword: { _default: '*:&' } };
+  t.test('\n# ' + inspect(opts001), function (t) {
+    t.assertSurrounds('this', opts001, '*this&')
+    t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
+    t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
+    t.end()
+  })
+
+  var opts002 = { 
+    Keyword: { 
+        'function': '^:'
+      , 'return':  '(:)' 
+      , _default: '*:&'
+    } 
+  };  
+
+  t.test('\n# ' + inspect(opts002), function (t) {
+    t.assertSurrounds(
+        [ 'function foo (bar) {'
+        , ' var a = 3;'
+        , ' return bar + a;'
+        , '}'
+        ].join('\n')
+      , opts002
+      , [ '^function& foo (bar) {'
+        , ' *var& a = 3;'
+        , ' (return) bar + a;'
+        , '}'
+        ].join('\n'))
+    t.end()
+  })
+})
+
+test('\nstring configs resolve from type and root', function (t) {
+  var code = 'var a = new Test();'
+  
+  function run(t, conf, expected, code_) {
+    t.test('\n# '  + inspect(conf), function (t) {
+      t.assertSurrounds(code_ || code, conf, expected);
+      t.end()
+    })
+  }
+
+  // at least the token kind has to be configured in order for the root_default to be applied
+  // otherwise a root._default would affect all tokens, even the ones we want to leave unchanged
+  run(t, { _default: '*:' }, 'var a = new Test();')
+
+  t.test('\n\n# only before or after specified, but no root._default', function (t) {
+    run(t, { Keyword: { _default: '*:' } }, '*var a = *new Test();')
+    run(t, { Keyword: { _default: ':-' } }, 'var- a = new- Test();')
+    t.end()
+  })
+
+  t.test('\n\n# resolve missing from root._default', function (t) {
+    run(t, { Keyword: { _default: '*:' }, _default: '(:-' }, '*var- a = *new- Test();')
+    run(t, { Keyword: { _default: ':-' }, _default: '*:)' }, '*var- a = *new- Test();')
+    t.end()
+  })
+
+  t.test('\n\n# no resolve if all specified', function (t) {
+    run(t, { Keyword: { _default: '+:-' }, _default: '*:)' }, '+var- a = +new- Test();')
+    run(t, { Keyword: { _default: ':-' }, _default: ':)' }, 'var- a = new- Test();')
+    t.end()
+  })
+
+  t.test('\n\n# resolve specific token no defaults', function (t) {
+    run(t, { Keyword: { 'var': '*:' } }, '*var a = new Test();')
+    run(t, { Keyword: { 'var': ':-' } }, 'var- a = new Test();')
+    t.end()
+  })
+
+  t.test('\n\n# resolve specific token with type defaults', function (t) {
+    run(t, { Keyword: { 'var': '*:', _default: ':-' } }, '*var- a = new- Test();')
+    run(t, { Keyword: { 'var': '*:', _default: '(:-' } }, '*var- a = (new- Test();')
+    run(t, { Keyword: { 'var': ':-', _default: '*:' } }, '*var- a = *new Test();')
+    run(t, { Keyword: { 'var': ':-', _default: '*:)' } }, '*var- a = *new) Test();')
+    run(t, { Keyword: { 'var': ':-', 'new': ':&', _default: '*:' } }, '*var- a = *new& Test();')
+    t.end()
+  })
+
+  t.test(
+      '\n\n# resolve specific token with root defaults, but no type default - root default not applied to unspecified tokens'
+    , function (t) {
+        run(t, { Keyword: { 'var': '*:' }, _default: ':-' }, '*var- a = new Test();')
+        run(t, { Keyword: { 'var': ':-' }, _default: '*:' }, '*var- a = new Test();')
+        t.end()
+      }
+  )
+
+  t.test('\n\n# resolve specific token with type and root defaults', function (t) {
+    run(t, { Keyword: { 'var': '*:', _default: '+:-' }, _default: ':)' }, '*var- a = +new- Test();')
+    run(t, { Keyword: { 'var': ':-', _default: '*:+' }, _default: '(:' }, '*var- a = *new+ Test();')
+    t.end()
+  })
+
+  t.test('all exact tokens undefined, but type default', function (t) {
+    run(t, { 'Boolean': { 'true': undefined, 'false': undefined, _default: '+:-' } }, 'return +true- || +false-;', 'return true || false;')
+  })
+  
+  t.end()
+})
diff --git a/node_modules/redeyed/test/redeyed-types.js b/node_modules/redeyed/test/redeyed-types.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca4837d8559daa1c3bac0a00313375a092297e6c
--- /dev/null
+++ b/node_modules/redeyed/test/redeyed-types.js
@@ -0,0 +1,71 @@
+'use strict';
+/*jshint asi: true*/
+
+var test = require('tap').test
+  , util = require('util')
+  , redeyed = require('..')
+
+function inspect (obj) {
+  return util.inspect(obj, false, 5, true)
+}
+
+test('adding custom asserts ... ', function (t) {
+  t.constructor.prototype.assertSurrounds = function (code, opts, expected) {
+    var optsi = inspect(opts);
+    var result = redeyed(code, opts).code
+
+    this.equals(  result
+                , expected
+                , util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
+               )
+    return this;
+  }
+
+  t.end() 
+})
+
+test('types', function (t) {
+  t.test('\n# Boolean', function (t) {
+    t.assertSurrounds('return true;', { 'Boolean': { _default: '$:%' } }, 'return $true%;')
+    t.assertSurrounds(  'return true; return false;'
+                      , { 'Boolean': { 'false': '#:', _default: '$:%' } }
+                      , 'return $true%; return #false%;')
+    t.end()
+  })
+
+  t.test('\n# Identifier', function (t) {
+    t.assertSurrounds('var a = 1;', { 'Identifier': { _default: '$:%' } }, 'var $a% = 1;')
+    t.assertSurrounds(  'var a = 1; const b = 2;'
+                      , { 'Identifier': { 'b': '#:', _default: '$:%' } }
+                      , 'var $a% = 1; const #b% = 2;')
+    t.end()
+  })
+
+  t.test('\n# Null', function (t) {
+    t.assertSurrounds('return null;', { 'Null': { _default: '$:%' } }, 'return $null%;').end()
+  })
+
+  t.test('\n# Numeric', function (t) {
+    t.assertSurrounds('return 1;', { 'Numeric': { _default: '$:%' } }, 'return $1%;')
+    t.assertSurrounds(  'return 1; return 2;'
+                      , { 'Numeric': { '2': '#:', _default: '$:%' } }
+                      , 'return $1%; return #2%;')
+    t.end()
+  })
+
+  t.test('\n# Punctuator', function (t) {
+    t.assertSurrounds('return 2 * 2;', { 'Punctuator': { _default: '$:%' } }, 'return 2 $*% 2$;%')
+    t.assertSurrounds(  'return 2 * 2;'
+                      , { 'Punctuator': {'*': '#:', _default: '$:%' } }
+                      , 'return 2 #*% 2$;%')
+    t.end()
+  })
+
+  t.test('\n# String', function (t) {
+    t.assertSurrounds('return "hello";', { 'String': { _default: '$:%' } }, 'return $"hello"%;')
+    t.assertSurrounds(  'return "hello"; return "world";'
+                      , { 'String': { '"world"': '#:', _default: '$:%' } }
+                      , 'return $"hello"%; return #"world"%;')
+    t.end()
+  })
+})
diff --git a/node_modules/string_decoder/.npmignore b/node_modules/string_decoder/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..206320cc1d21b9cc9e3e0e8a303896045453c524
--- /dev/null
+++ b/node_modules/string_decoder/.npmignore
@@ -0,0 +1,2 @@
+build
+test
diff --git a/node_modules/string_decoder/LICENSE b/node_modules/string_decoder/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6de584a48f5c897d27bfe9922f976297c07cae02
--- /dev/null
+++ b/node_modules/string_decoder/LICENSE
@@ -0,0 +1,20 @@
+Copyright Joyent, Inc. and other Node contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/string_decoder/README.md b/node_modules/string_decoder/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4d2aa001501107cd2792f385ad62237dc3757521
--- /dev/null
+++ b/node_modules/string_decoder/README.md
@@ -0,0 +1,7 @@
+**string_decoder.js** (`require('string_decoder')`) from Node.js core
+
+Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details.
+
+Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.**
+
+The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version.
\ No newline at end of file
diff --git a/node_modules/string_decoder/index.js b/node_modules/string_decoder/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..b00e54fb7909827a02b6fa96ef55bd4dd85a3fe7
--- /dev/null
+++ b/node_modules/string_decoder/index.js
@@ -0,0 +1,221 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var Buffer = require('buffer').Buffer;
+
+var isBufferEncoding = Buffer.isEncoding
+  || function(encoding) {
+       switch (encoding && encoding.toLowerCase()) {
+         case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
+         default: return false;
+       }
+     }
+
+
+function assertEncoding(encoding) {
+  if (encoding && !isBufferEncoding(encoding)) {
+    throw new Error('Unknown encoding: ' + encoding);
+  }
+}
+
+// StringDecoder provides an interface for efficiently splitting a series of
+// buffers into a series of JS strings without breaking apart multi-byte
+// characters. CESU-8 is handled as part of the UTF-8 encoding.
+//
+// @TODO Handling all encodings inside a single object makes it very difficult
+// to reason about this code, so it should be split up in the future.
+// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
+// points as used by CESU-8.
+var StringDecoder = exports.StringDecoder = function(encoding) {
+  this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
+  assertEncoding(encoding);
+  switch (this.encoding) {
+    case 'utf8':
+      // CESU-8 represents each of Surrogate Pair by 3-bytes
+      this.surrogateSize = 3;
+      break;
+    case 'ucs2':
+    case 'utf16le':
+      // UTF-16 represents each of Surrogate Pair by 2-bytes
+      this.surrogateSize = 2;
+      this.detectIncompleteChar = utf16DetectIncompleteChar;
+      break;
+    case 'base64':
+      // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
+      this.surrogateSize = 3;
+      this.detectIncompleteChar = base64DetectIncompleteChar;
+      break;
+    default:
+      this.write = passThroughWrite;
+      return;
+  }
+
+  // Enough space to store all bytes of a single character. UTF-8 needs 4
+  // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
+  this.charBuffer = new Buffer(6);
+  // Number of bytes received for the current incomplete multi-byte character.
+  this.charReceived = 0;
+  // Number of bytes expected for the current incomplete multi-byte character.
+  this.charLength = 0;
+};
+
+
+// write decodes the given buffer and returns it as JS string that is
+// guaranteed to not contain any partial multi-byte characters. Any partial
+// character found at the end of the buffer is buffered up, and will be
+// returned when calling write again with the remaining bytes.
+//
+// Note: Converting a Buffer containing an orphan surrogate to a String
+// currently works, but converting a String to a Buffer (via `new Buffer`, or
+// Buffer#write) will replace incomplete surrogates with the unicode
+// replacement character. See https://codereview.chromium.org/121173009/ .
+StringDecoder.prototype.write = function(buffer) {
+  var charStr = '';
+  // if our last write ended with an incomplete multibyte character
+  while (this.charLength) {
+    // determine how many remaining bytes this buffer has to offer for this char
+    var available = (buffer.length >= this.charLength - this.charReceived) ?
+        this.charLength - this.charReceived :
+        buffer.length;
+
+    // add the new bytes to the char buffer
+    buffer.copy(this.charBuffer, this.charReceived, 0, available);
+    this.charReceived += available;
+
+    if (this.charReceived < this.charLength) {
+      // still not enough chars in this buffer? wait for more ...
+      return '';
+    }
+
+    // remove bytes belonging to the current character from the buffer
+    buffer = buffer.slice(available, buffer.length);
+
+    // get the character that was split
+    charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
+
+    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
+    var charCode = charStr.charCodeAt(charStr.length - 1);
+    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+      this.charLength += this.surrogateSize;
+      charStr = '';
+      continue;
+    }
+    this.charReceived = this.charLength = 0;
+
+    // if there are no more bytes in this buffer, just emit our char
+    if (buffer.length === 0) {
+      return charStr;
+    }
+    break;
+  }
+
+  // determine and set charLength / charReceived
+  this.detectIncompleteChar(buffer);
+
+  var end = buffer.length;
+  if (this.charLength) {
+    // buffer the incomplete character bytes we got
+    buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
+    end -= this.charReceived;
+  }
+
+  charStr += buffer.toString(this.encoding, 0, end);
+
+  var end = charStr.length - 1;
+  var charCode = charStr.charCodeAt(end);
+  // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
+  if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+    var size = this.surrogateSize;
+    this.charLength += size;
+    this.charReceived += size;
+    this.charBuffer.copy(this.charBuffer, size, 0, size);
+    buffer.copy(this.charBuffer, 0, 0, size);
+    return charStr.substring(0, end);
+  }
+
+  // or just emit the charStr
+  return charStr;
+};
+
+// detectIncompleteChar determines if there is an incomplete UTF-8 character at
+// the end of the given buffer. If so, it sets this.charLength to the byte
+// length that character, and sets this.charReceived to the number of bytes
+// that are available for this character.
+StringDecoder.prototype.detectIncompleteChar = function(buffer) {
+  // determine how many bytes we have to check at the end of this buffer
+  var i = (buffer.length >= 3) ? 3 : buffer.length;
+
+  // Figure out if one of the last i bytes of our buffer announces an
+  // incomplete char.
+  for (; i > 0; i--) {
+    var c = buffer[buffer.length - i];
+
+    // See http://en.wikipedia.org/wiki/UTF-8#Description
+
+    // 110XXXXX
+    if (i == 1 && c >> 5 == 0x06) {
+      this.charLength = 2;
+      break;
+    }
+
+    // 1110XXXX
+    if (i <= 2 && c >> 4 == 0x0E) {
+      this.charLength = 3;
+      break;
+    }
+
+    // 11110XXX
+    if (i <= 3 && c >> 3 == 0x1E) {
+      this.charLength = 4;
+      break;
+    }
+  }
+  this.charReceived = i;
+};
+
+StringDecoder.prototype.end = function(buffer) {
+  var res = '';
+  if (buffer && buffer.length)
+    res = this.write(buffer);
+
+  if (this.charReceived) {
+    var cr = this.charReceived;
+    var buf = this.charBuffer;
+    var enc = this.encoding;
+    res += buf.slice(0, cr).toString(enc);
+  }
+
+  return res;
+};
+
+function passThroughWrite(buffer) {
+  return buffer.toString(this.encoding);
+}
+
+function utf16DetectIncompleteChar(buffer) {
+  this.charReceived = buffer.length % 2;
+  this.charLength = this.charReceived ? 2 : 0;
+}
+
+function base64DetectIncompleteChar(buffer) {
+  this.charReceived = buffer.length % 3;
+  this.charLength = this.charReceived ? 3 : 0;
+}
diff --git a/node_modules/string_decoder/package.json b/node_modules/string_decoder/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..f2dd499c465d6fceaccda2bc6052f724a536a915
--- /dev/null
+++ b/node_modules/string_decoder/package.json
@@ -0,0 +1,25 @@
+{
+  "name": "string_decoder",
+  "version": "0.10.31",
+  "description": "The string_decoder module from Node core",
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {
+    "tap": "~0.4.8"
+  },
+  "scripts": {
+    "test": "tap test/simple/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/rvagg/string_decoder.git"
+  },
+  "homepage": "https://github.com/rvagg/string_decoder",
+  "keywords": [
+    "string",
+    "decoder",
+    "browser",
+    "browserify"
+  ],
+  "license": "MIT"
+}
diff --git a/package-lock.json b/package-lock.json
index f584026f7930665ded8a41e558faec74e2ad61d2..3965b2f2fd1f99780870e711462ce2bb78f2a1ff 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,7 @@
         "dotenv": "^16.4.7",
         "ejs": "^3.1.10",
         "express": "^4.21.2",
-        "mysql2": "^3.13.0"
+        "mysql2-promise": "^0.1.4"
       }
     },
     "node_modules/accepts": {
@@ -42,6 +42,11 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/ansicolors": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz",
+      "integrity": "sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w=="
+    },
     "node_modules/array-flatten": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -65,6 +70,11 @@
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
+    "node_modules/bn.js": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.0.tgz",
+      "integrity": "sha512-NmOLApC80+n+P28y06yHgwGlOCkq/X4jRh5s590959FZXSrM+I/61h0xxuIaYsg0mD44mEAZYG/rnclWuRoz+A=="
+    },
     "node_modules/body-parser": {
       "version": "1.20.3",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
@@ -132,6 +142,18 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/cardinal": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.4.tgz",
+      "integrity": "sha512-3MxV0o9wOpQcobrcSrRpaSxlYkohCcZu0ytOjJUww/Yo/223q4Ecloo7odT+M0SI5kPgb1JhvSaF4EEuVXOLAQ==",
+      "dependencies": {
+        "ansicolors": "~0.2.1",
+        "redeyed": "~0.4.0"
+      },
+      "bin": {
+        "cdl": "bin/cdl.js"
+      }
+    },
     "node_modules/chalk": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -200,6 +222,11 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+    },
     "node_modules/debug": {
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -244,6 +271,11 @@
         "url": "https://dotenvx.com"
       }
     },
+    "node_modules/double-ended-queue": {
+      "version": "2.0.0-0",
+      "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.0.0-0.tgz",
+      "integrity": "sha512-t5ouWOpItmHrm0J0+bX/cFrIjBFWnJkk5LbIJq6bbU/M4aLX2c3LrM4QYsBptwvlPe3WzdpQefQ0v1pe/A5wjg=="
+    },
     "node_modules/dunder-proto": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -316,6 +348,18 @@
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
+    "node_modules/esprima": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
+      "integrity": "sha512-rp5dMKN8zEs9dfi9g0X1ClLmV//WRyk/R15mppFNICIFRG5P92VP7Z04p8pk++gABo9W2tY+kHyu6P1mEHgmTA==",
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -565,6 +609,11 @@
       "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
       "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
     },
+    "node_modules/isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+    },
     "node_modules/jake": {
       "version": "10.9.2",
       "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
@@ -706,6 +755,46 @@
         "node": ">= 8.0"
       }
     },
+    "node_modules/mysql2-promise": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/mysql2-promise/-/mysql2-promise-0.1.4.tgz",
+      "integrity": "sha512-/h8ubU/36aIPpbfB6CENw9ZdbzIhZMZOIbstJUHVKp4J9JBRSLScrYImVx+3yZilgag732UhpQMMK5+ktdhLCw==",
+      "dependencies": {
+        "mysql2": "^0.15.7",
+        "q": "^1.3.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/mysql2-promise/node_modules/lru-cache": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
+      "integrity": "sha512-dVmQmXPBlTgFw77hm60ud//l2bCuDKkqC2on1EBoM7s9Urm9IQDrnujwZ93NFnAq0dVZ0HBXTS7PwEG+YE7+EQ=="
+    },
+    "node_modules/mysql2-promise/node_modules/mysql2": {
+      "version": "0.15.8",
+      "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-0.15.8.tgz",
+      "integrity": "sha512-3x5o6C20bfwJYPSoT74MOoad7/chJoq4qXHDL5VAuRBBrIyErovLoj04Dz/5EY9X2kTxWSGNiTegtxpROTd2YQ==",
+      "dependencies": {
+        "bn.js": "2.0.0",
+        "cardinal": "0.4.4",
+        "double-ended-queue": "2.0.0-0",
+        "named-placeholders": "0.1.3",
+        "readable-stream": "1.0.33"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/mysql2-promise/node_modules/named-placeholders": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-0.1.3.tgz",
+      "integrity": "sha512-Mt79RtxZ6MYTIEemPGv/YDKpbuavcAyGHb0r37xB2mnE5jej3uBzc4+nzOeoZ4nZiii1M32URKt9IjkSTZAmTA==",
+      "dependencies": {
+        "lru-cache": "2.5.0"
+      }
+    },
     "node_modules/mysql2/node_modules/iconv-lite": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -783,6 +872,16 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/q": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+      "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+      "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
+      "engines": {
+        "node": ">=0.6.0",
+        "teleport": ">=0.2.0"
+      }
+    },
     "node_modules/qs": {
       "version": "6.13.0",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
@@ -819,6 +918,25 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/readable-stream": {
+      "version": "1.0.33",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz",
+      "integrity": "sha512-72KxhcKi8bAvHP/cyyWSP+ODS5ef0DIRs0OzrhGXw31q41f19aoELCbvd42FjhpyEDxQMRiiC5rq9rfE5PzTqg==",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.1",
+        "isarray": "0.0.1",
+        "string_decoder": "~0.10.x"
+      }
+    },
+    "node_modules/redeyed": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz",
+      "integrity": "sha512-pnk1vsaNLu1UAAClKsImKz9HjBvg9i8cbRqTRzJbiCjGF0fZSMqpdcA5W3juO3c4etFvTrabECkq9wjC45ZyxA==",
+      "dependencies": {
+        "esprima": "~1.0.4"
+      }
+    },
     "node_modules/safe-buffer": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -987,6 +1105,11 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+    },
     "node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
diff --git a/package.json b/package.json
index e57e52ac05dcad50eed5d5ad4f1cb5f27e71fdad..ffab6e8a60b6baf41b307a40765a6b97af20f999 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,6 @@
     "dotenv": "^16.4.7",
     "ejs": "^3.1.10",
     "express": "^4.21.2",
-    "mysql2": "^3.13.0"
+    "mysql2-promise": "^0.1.4"
   }
 }
diff --git a/server.js b/server.js
index b86131497380c529894c891e1b4c57c14553d03b..1a197df800ff92c9e964a12de50330682c32e574 100644
--- a/server.js
+++ b/server.js
@@ -1,6 +1,6 @@
 require("dotenv").config();
 const express = require("express");
-const mysql = require("mysql2");
+const mysql = require('mysql2/promise');
 const bodyParser = require("body-parser");
 
 const app = express();
@@ -33,7 +33,7 @@ async function testConnection() {
     process.exit(1); // Terminate the app if the database connection fails
   }
 }
-
+testConnection();
 
 // ตั้งค่า Middleware
 app.set("view engine", "ejs");