[release] merge master@8aab1a2 into release branch

Change-Id: Ib5639453c6e973e6f23c7e4711b0b5a3121012f3
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index 96e2275..0000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: "Code scanning - action"
-
-on:
-  push:
-  schedule:
-    - cron: '0 22 * * 1'
-
-jobs:
-  CodeQL-Build:
-    if: github.ref == 'refs/heads/master' && github.repository == 'golang/vscode-go'
-
-    # CodeQL runs on ubuntu-latest and windows-latest
-    runs-on: ubuntu-latest
-
-    steps:
-    - name: Checkout repository
-      uses: actions/checkout@v2
-
-    # Initializes the CodeQL tools for scanning.
-    - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
-      with:
-        languages: go, javascript
-
-    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
-    # If this step fails, then you should remove it and run the build manually (see below)
-    - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
-
-    # ℹī¸ Command-line programs to run using the OS shell.
-    # 📚 https://git.io/JvXDl
-
-    # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines
-    #    and modify them (or add more) to build your code if your project
-    #    uses a compiled language
-
-    #- run: |
-    #   make bootstrap
-    #   make release
-
-    - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml
index a04eaae..0df894b 100644
--- a/.github/workflows/release-nightly.yml
+++ b/.github/workflows/release-nightly.yml
@@ -40,37 +40,36 @@
       - name: Compile
         run: npm run vscode:prepublish
 
+      # TODO: use prerelease versions of tools (how? or master?)
+
       - name: Install Go tools (Modules mode)
         run: |
             go version
-            go get github.com/acroca/go-symbols \
-               github.com/davidrjenni/reftools/cmd/fillstruct \
-               github.com/haya14busa/goplay/cmd/goplay \
-               github.com/mdempsky/gocode \
-               github.com/sqs/goreturns \
-               github.com/uudashr/gopkgs/v2/cmd/gopkgs \
-               github.com/zmb3/gogetdoc \
-               golang.org/x/lint/golint \
-               golang.org/x/tools/cmd/gorename \
-               golang.org/x/tools/gopls
-
+            go get github.com/acroca/go-symbols
+            go get github.com/davidrjenni/reftools/cmd/fillstruct
+            go get github.com/haya14busa/goplay/cmd/goplay
+            go get github.com/mdempsky/gocode
+            go get github.com/sqs/goreturns
+            go get github.com/uudashr/gopkgs/v2/cmd/gopkgs
+            go get github.com/zmb3/gogetdoc
+            go get golang.org/x/lint/golint
+            go get golang.org/x/tools/cmd/gorename
+            go get golang.org/x/tools/gopls
         env:
-          GO111MODULE: on
-
+          GO111MODULE: on   
+          
       - name: Install Go tools (GOPATH mode)
         run: |
           go version
-          go get github.com/cweill/gotests/... \
-            github.com/rogpeppe/godef \
-            github.com/ramya-rao-a/go-outline
+          go get github.com/cweill/gotests/...
+          go get github.com/rogpeppe/godef
+          go get github.com/ramya-rao-a/go-outline
             # Because some tests depend on the source code checked in GOPATH. TODO: FIX THEM.
         env:
           GO111MODULE: off
 
-
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
 
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 74b17a3..c984375 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,10 +21,9 @@
 #    the 'Release (golang.go)' workflow specified in this file.
 #      - For stable version release (vX.X.X), check if the package.json has the matching version.
 #      - Packaging using 'vsce package'
-#      - Create a release in Github
+#      - Create a release in GitHub
 #      - Upload the vsix file as an asset of the release
 #      - For stable version release (vX.X.X), upload to the vscode market place
-#        (not implemented in this CL)
 
 on:
   push:
@@ -32,9 +31,10 @@
       - v*
 
 jobs:
-  build:
+  release:
     name: create release
     runs-on: ubuntu-latest
+    if: github.repository == 'golang/vscode-go'
 
     steps:
       - name: checkout code
@@ -95,6 +95,14 @@
           asset_path: ./go-${{ env.EXT_VERSION }}.vsix
           asset_name: go-${{ env.EXT_VERSION }}.vsix
           asset_content_type: application/zip
+
+      - name: publish
+        if: env.EXT_ISPREVIEW != 1 && github.repository == 'golang/vscode-go'
+        uses: lannonbr/vsce-action@704da577da0f27de5cdb4ae018374c2f08b5f523
+        with:
+          args: "publish -p $VSCE_TOKEN"
+        env:
+          VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }}
+
 # TODO: check if the commit is in green state. (test-long.yml results)
-# TODO: publish to the market if VERSION is for a stable version.
 # TODO: after publishing, create a gerrit CL to update 'latest' branch if VERSION is for a stable version.
diff --git a/.github/workflows/test-long.yml b/.github/workflows/test-long.yml
index 1b5f75e..6fcbbd7 100644
--- a/.github/workflows/test-long.yml
+++ b/.github/workflows/test-long.yml
@@ -69,7 +69,6 @@
       
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
         
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml
index 96e517f..150b21a 100644
--- a/.github/workflows/test-smoke.yml
+++ b/.github/workflows/test-smoke.yml
@@ -65,7 +65,6 @@
       
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
         
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.gitignore b/.gitignore
index 68d1f87..d71de02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-out
-node_modules
-.vscode-test
+out/
+dist/
+node_modules/
+.vscode-test/
 .DS_Store
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c6761bb..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-language: go
-
-dist: bionic
-
-go:
-  - 1.13.x
-  - 1.14.x
-  - tip
-
-git:
-  depth: 1
-
-matrix:
-  allow_failures:
-    - go: tip
-
-os:
-  - osx
-  - linux
-
-before_install:
-  # Call xvfb directly on linux runs and give it time to start
-  - if [[ $TRAVIS_OS_NAME == "linux" ]]; then
-    export DISPLAY=:99.0;
-    Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
-    sleep 3;
-    sudo apt-get update && sudo apt-get install -y libsecret-1-0;
-    fi
-
-install:
-  - TRAVIS_NODE_VERSION="12";
-  # Clear out whatever version of NVM Travis has as it is old.
-  - rm -rf ~/.nvm;
-    # Grab NVM.
-  - git clone https://github.com/creationix/nvm.git ~/.nvm;
-    # Checkout the latest stable tag.
-    # Note that you can just hardcode a preferred version here.
-  - (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`);
-    # Install the desired version of Node
-  - source ~/.nvm/nvm.sh;
-  - nvm install $TRAVIS_NODE_VERSION;
-  - npm ci
-  - npm run vscode:prepublish
-  - go get -u -v github.com/acroca/go-symbols
-  - go get -u -v github.com/cweill/gotests/...
-  - go get -u -v github.com/davidrjenni/reftools/cmd/fillstruct
-  - go get -u -v github.com/haya14busa/goplay/cmd/goplay
-  - go get -u -v github.com/mdempsky/gocode
-  - go get -u -v github.com/ramya-rao-a/go-outline
-  - go get -u -v github.com/rogpeppe/godef
-  - go get -u -v github.com/sqs/goreturns
-  - go get -u -v github.com/uudashr/gopkgs/v2/cmd/gopkgs
-  - go get -u -v github.com/zmb3/gogetdoc
-  - go get -u -v golang.org/x/lint/golint
-  - go get -u -v golang.org/x/tools/cmd/gorename
-  - GO111MODULE=on go get golang.org/x/tools/gopls
-
-script:
-  - npm run lint
-  - npm run unit-test
-  - npm test --silent
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 94310ec..4f23b75 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,7 +1,6 @@
 {
 	"version": "0.2.0",
 	"configurations": [
-		
 		{
 			"name": "Launch Extension",
 			"type": "extensionHost",
@@ -12,27 +11,45 @@
 				"--extensionDevelopmentPath=${workspaceFolder}",
 				"--disable-extensions"
 			],
+			"outFiles": [
+                "${workspaceFolder}/dist/**/*.js"
+            ],
 			"stopOnEntry": false,
 			"sourceMaps": true,
-			"outFiles": [
-				"${workspaceFolder}/out/**/*.js"
-			],
-			"preLaunchTask": "npm: watch"
+			"smartStep": true,
+			"preLaunchTask": "npm: webpack",
 		},
 		{
 			"name": "Launch as server",
 			"type": "node",
 			"protocol": "inspector",
 			"request": "launch",
-			"program": "${workspaceFolder}/out/src/debugAdapter/goDebug.js",
+			"program": "${workspaceFolder}/dist/debugAdapter.js",
+			"args": [
+				"--server=4711"
+			],
+			"outFiles": [
+				"${workspaceFolder}/dist/**/*.js"
+			],
+			"sourceMaps": true,
+			"smartStep": true,
+			"preLaunchTask": "npm: webpack"
+		},
+		{
+			"name": "Launch as server (dlv dap)",
+			"type": "node",
+			"protocol": "inspector",
+			"request": "launch",
+			"program": "${workspaceFolder}/dist/debugAdapter2.js",
 			"args": [
 				"--server=4711"
 			],
 			"sourceMaps": true,
+			"smartStep": true,
 			"outFiles": [
-				"${workspaceFolder}/out/**/*.js"
+				"${workspaceFolder}/dist/**/*.js"
 			],
-			"preLaunchTask": "npm"
+			"preLaunchTask": "npm: webpack"
 		},
 		{
 			"name": "Launch Extension Tests",
@@ -49,6 +66,7 @@
 			],
 			"stopOnEntry": false,
 			"sourceMaps": true,
+			"smartStep": true,
 			"outFiles": [
 				"${workspaceFolder}/out/test/**/*.js"
 			],
@@ -87,7 +105,8 @@
 				"--colors",
 				"${workspaceFolder}/out/test/unit"
 			],
-			"internalConsoleOptions": "openOnSessionStart"
+			"internalConsoleOptions": "openOnSessionStart",
+			"preLaunchTask": "npm: watch",
 		},
 	],
 	"compounds": [
@@ -99,4 +118,4 @@
 			]
 		}
 	]
-}
\ No newline at end of file
+}
diff --git a/.vscodeignore b/.vscodeignore
index 529c5c2..c33036f 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -1,18 +1,19 @@
-src/**/*
-test/
-third_party/
-typings/**/*
-.vscode/**/*
-tsconfig.json
-.gitignore
-node_modules/fs-extra
 **/*.map
 **/tslint.json
-build/**/*
-docs/
-*.md.nightly
 .github/**/*
+.gitignore
 .prettierrc.json
-out/test/**
 .vscode-test/**
+.vscode/
 SECURITY.md
+build/
+docs/
+node_modules
+out/
+src/
+test/
+third_party/
+tools/
+tsconfig.json
+typings/
+webpack.config.js
diff --git a/docs/debugging.md b/docs/debugging.md
index e71bfe5..e5b3f47 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -345,15 +345,15 @@
 
 #### OSX
 
-This usually happens on OSX due to signing issues. See the discussions in [Microsoft/vscode-go#717](https://github.com/Microsoft/vscode-go/issues/717), [Microsoft/vscode-go#269](https://github.com/Microsoft/vscode-go/issues/269) and [derekparker/delve#357](https://github.com/derekparker/delve/issues/357).
+This usually happens on OSX due to signing issues. See the discussions in [Microsoft/vscode-go#717](https://github.com/Microsoft/vscode-go/issues/717), [Microsoft/vscode-go#269](https://github.com/Microsoft/vscode-go/issues/269) and [go-delve/delve#357](https://github.com/go-delve/delve/issues/357).
 
-**_Solution_**: You may have to uninstall dlv and install it manually as described in the [Delve instructions](https://github.com/derekparker/delve/blob/master/Documentation/installation/osx/install.md#manual-install).
+**_Solution_**: You may have to uninstall dlv and install it manually as described in the [Delve instructions](https://github.com/go-delve/delve/blob/master/Documentation/installation/osx/install.md#manual-install).
 
 #### Linux/Docker
 
 Docker has security settings preventing `ptrace(2)` operations by default within the container.
 
-**_Solution_**: To run your container insecurely, pass `--security-opt=seccomp:unconfined` to `docker run`. See [derekparker/delve#515](https://github.com/derekparker/delve/issues/515) for references.
+**_Solution_**: To run your container insecurely, pass `--security-opt=seccomp:unconfined` to `docker run`. See [go-delve/delve#515](https://github.com/go-delve/delve/issues/515) for references.
 
 #### could not launch process: exec: "lldb-server": executable file not found in $PATH
 
diff --git a/docs/tools.md b/docs/tools.md
index a99ea96..8a620aa 100644
--- a/docs/tools.md
+++ b/docs/tools.md
@@ -56,7 +56,6 @@
 
 Different versions of `gocode` are used depending on your version of Go.
 
-* Go 1.8 and below: [nsf/gocode](https://github.com/nsf/gocode)
 * Go 1.9 and above: [mdempsky/gocode](https://github.com/mdempsky/gocode)
 * Go 1.11 and above, with modules enabled: [stamblerre/gocode](https://github.com/stamblerre/gocode)
   * This version of `gocode` does not have any caching, so if you find it slow, consider using [gopls] instead.
diff --git a/package-lock.json b/package-lock.json
index 81e1db1..a0e79e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "go",
-  "version": "0.15.2",
+  "version": "0.16.0-dev",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -122,15 +122,15 @@
       "dev": true
     },
     "@types/node": {
-      "version": "13.13.11",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.11.tgz",
-      "integrity": "sha512-FX7mIFKfnGCfq10DGWNhfCNxhACEeqH5uulT6wRRA1KEt7zgLe0HdrAd9/QQkObDqp2Z0KEV3OAmNgs0lTx5tQ==",
+      "version": "13.13.13",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.13.tgz",
+      "integrity": "sha512-UfvBE9oRCAJVzfR+3eWm/sdLFe/qroAPEXP3GPJ1SehQiEVgZT6NQZWYbPMiJ3UdcKM06v4j+S1lTcdWCmw+3g==",
       "dev": true
     },
     "@types/semver": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz",
-      "integrity": "sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.1.tgz",
+      "integrity": "sha512-ooD/FJ8EuwlDKOI6D9HWxgIgJjMg2cuziXm/42npDC8y4NjxplBUn9loewZiBNCt44450lHAU0OSb51/UqXeag==",
       "dev": true,
       "requires": {
         "@types/node": "*"
@@ -152,15 +152,208 @@
       "dev": true
     },
     "@types/vscode": {
-      "version": "1.45.1",
-      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.45.1.tgz",
-      "integrity": "sha512-0NO9qrrEJBO8FsqHCrFMgR2suKnwCsKBWvRSb2OzH5gs4i3QO5AhEMQYrSzDbU/wLPt7N617/rN9lPY213gmwg==",
+      "version": "1.46.0",
+      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.46.0.tgz",
+      "integrity": "sha512-8m9wPEB2mcRqTWNKs9A9Eqs8DrQZt0qNFO8GkxBOnyW6xR//3s77SoMgb/nY1ctzACsZXwZj3YRTDsn4bAoaUw==",
+      "dev": true
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-code-frame": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-fsm": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-module-context": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+      "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+      "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+      "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
+      "dev": true,
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+      "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
+      "dev": true,
+      "requires": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+      "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
+      "dev": true
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+      "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/helper-wasm-section": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-opt": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+      "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+      "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+      "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wast-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+      "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-code-frame": "1.9.0",
+        "@webassemblyjs/helper-fsm": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+      "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true
+    },
+    "@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true
+    },
+    "acorn": {
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+      "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
       "dev": true
     },
     "adm-zip": {
-      "version": "0.4.14",
-      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz",
-      "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==",
+      "version": "0.4.16",
+      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
+      "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==",
       "dev": true
     },
     "agent-base": {
@@ -183,6 +376,18 @@
         "uri-js": "^4.2.2"
       }
     },
+    "ajv-errors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+      "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+      "dev": true
+    },
+    "ajv-keywords": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.0.tgz",
+      "integrity": "sha512-eyoaac3btgU8eJlvh01En8OCKzRqlLe2G5jDsCr3RiE2uLGMEEB1aaGwVVpwR8M95956tGH6R+9edC++OvzaVw==",
+      "dev": true
+    },
     "ansi-colors": {
       "version": "3.2.3",
       "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
@@ -214,6 +419,12 @@
         "picomatch": "^2.0.4"
       }
     },
+    "aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "dev": true
+    },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -223,11 +434,35 @@
         "sprintf-js": "~1.0.2"
       }
     },
+    "arr-diff": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+      "dev": true
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+      "dev": true
+    },
     "array-filter": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
       "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
     },
+    "array-unique": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+      "dev": true
+    },
     "asn1": {
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -236,11 +471,70 @@
         "safer-buffer": "~2.1.0"
       }
     },
+    "asn1.js": {
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "assert": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+      "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.1.1",
+        "util": "0.10.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+          "dev": true
+        },
+        "util": {
+          "version": "0.10.3",
+          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.1"
+          }
+        }
+      }
+    },
     "assert-plus": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
+    "assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+      "dev": true
+    },
+    "async-each": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+      "dev": true,
+      "optional": true
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -252,6 +546,12 @@
       "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
       "dev": true
     },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "dev": true
+    },
     "available-typed-arrays": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
@@ -275,6 +575,67 @@
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "dev": true,
+      "requires": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "base64-js": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+      "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
+      "dev": true
+    },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -288,12 +649,40 @@
       "resolved": "https://registry.npmjs.org/better-curry/-/better-curry-1.6.0.tgz",
       "integrity": "sha1-OPcWskyM7geiYqvEHCLDFOIOOGk="
     },
+    "big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "dev": true
+    },
     "binary-extensions": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
       "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
       "dev": true
     },
+    "bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
+    "bluebird": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+      "dev": true
+    },
+    "bn.js": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
+      "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
+      "dev": true
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -312,18 +701,195 @@
         "fill-range": "^7.0.1"
       }
     },
+    "brorand": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "dev": true
+    },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
       "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
+    "browserify-aes": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+      "dev": true,
+      "requires": {
+        "buffer-xor": "^1.0.3",
+        "cipher-base": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.3",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "browserify-cipher": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+      "dev": true,
+      "requires": {
+        "browserify-aes": "^1.0.4",
+        "browserify-des": "^1.0.0",
+        "evp_bytestokey": "^1.0.0"
+      }
+    },
+    "browserify-des": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+      "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "des.js": "^1.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "browserify-rsa": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "randombytes": "^2.0.1"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "browserify-sign": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
+      "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^5.1.1",
+        "browserify-rsa": "^4.0.1",
+        "create-hash": "^1.2.0",
+        "create-hmac": "^1.1.7",
+        "elliptic": "^6.5.2",
+        "inherits": "^2.0.4",
+        "parse-asn1": "^5.1.5",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "dev": true,
+      "requires": {
+        "pako": "~1.0.5"
+      }
+    },
+    "buffer": {
+      "version": "4.9.2",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+      "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+      "dev": true,
+      "requires": {
+        "base64-js": "^1.0.2",
+        "ieee754": "^1.1.4",
+        "isarray": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        }
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "buffer-xor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "dev": true
+    },
     "builtin-modules": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
       "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
       "dev": true
     },
+    "builtin-status-codes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+      "dev": true
+    },
+    "cacache": {
+      "version": "12.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+      "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+      "dev": true,
+      "requires": {
+        "bluebird": "^3.5.5",
+        "chownr": "^1.1.1",
+        "figgy-pudding": "^3.5.1",
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.1.15",
+        "infer-owner": "^1.0.3",
+        "lru-cache": "^5.1.1",
+        "mississippi": "^3.0.0",
+        "mkdirp": "^0.5.1",
+        "move-concurrently": "^1.0.1",
+        "promise-inflight": "^1.0.1",
+        "rimraf": "^2.6.3",
+        "ssri": "^6.0.1",
+        "unique-filename": "^1.1.1",
+        "y18n": "^4.0.0"
+      }
+    },
+    "cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "dev": true,
+      "requires": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      }
+    },
     "camelcase": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -373,6 +939,54 @@
         "readdirp": "~3.2.0"
       }
     },
+    "chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+      "dev": true
+    },
+    "chrome-trace-event": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+      "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
     "cliui": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -412,6 +1026,16 @@
         }
       }
     },
+    "collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "dev": true,
+      "requires": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      }
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -441,16 +1065,163 @@
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true
     },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
+    "component-emitter": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+      "dev": true
+    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "console-browserify": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+      "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
+      "dev": true
+    },
+    "constants-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+      "dev": true
+    },
+    "copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "fs-write-stream-atomic": "^1.0.8",
+        "iferr": "^0.1.5",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.0"
+      }
+    },
+    "copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+      "dev": true
+    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
+    "create-ecdh": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "elliptic": "^6.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "crypto-browserify": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dev": true,
+      "requires": {
+        "browserify-cipher": "^1.0.0",
+        "browserify-sign": "^4.0.0",
+        "create-ecdh": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "create-hmac": "^1.1.0",
+        "diffie-hellman": "^5.0.0",
+        "inherits": "^2.0.1",
+        "pbkdf2": "^3.0.3",
+        "public-encrypt": "^4.0.0",
+        "randombytes": "^2.0.0",
+        "randomfill": "^1.0.3"
+      }
+    },
+    "cyclist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+      "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+      "dev": true
+    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -463,6 +1234,7 @@
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
       "requires": {
         "ms": "2.0.0"
       }
@@ -473,6 +1245,12 @@
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
+    "decode-uri-component": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "dev": true
+    },
     "deep-equal": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz",
@@ -509,16 +1287,110 @@
         "object-keys": "^1.0.12"
       }
     },
+    "define-property": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+      "dev": true,
+      "requires": {
+        "is-descriptor": "^1.0.2",
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
+    "des.js": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+      "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      }
+    },
+    "detect-file": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+      "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+      "dev": true
+    },
     "diff": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
     },
+    "diffie-hellman": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+      "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "miller-rabin": "^4.0.0",
+        "randombytes": "^2.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "domain-browser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+      "dev": true
+    },
+    "duplexify": {
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+      "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
     "ecc-jsbn": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -528,12 +1400,70 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "elliptic": {
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
+      "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.4.0",
+        "brorand": "^1.0.1",
+        "hash.js": "^1.0.0",
+        "hmac-drbg": "^1.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
     "emoji-regex": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
       "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
       "dev": true
     },
+    "emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "dev": true
+    },
+    "end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "enhanced-resolve": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz",
+      "integrity": "sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "memory-fs": "^0.5.0",
+        "tapable": "^1.0.0"
+      }
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
     "es-abstract": {
       "version": "1.17.5",
       "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
@@ -612,22 +1542,188 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "eslint-scope": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
     "esprima": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
-    "eventemitter3": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
-      "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg="
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true
+    },
+    "events": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+      "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
+      "dev": true
+    },
+    "evp_bytestokey": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "dev": true,
+      "requires": {
+        "md5.js": "^1.3.4",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "expand-brackets": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.3.3",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "posix-character-classes": "^0.1.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "expand-tilde": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+      "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+      "dev": true,
+      "requires": {
+        "homedir-polyfill": "^1.0.1"
+      }
     },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
       "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
     },
+    "extend-shallow": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+      "dev": true,
+      "requires": {
+        "assign-symbols": "^1.0.0",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "extglob": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+      "dev": true,
+      "requires": {
+        "array-unique": "^0.3.2",
+        "define-property": "^1.0.0",
+        "expand-brackets": "^2.1.4",
+        "extend-shallow": "^2.0.1",
+        "fragment-cache": "^0.2.1",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -651,6 +1747,19 @@
         "websocket-driver": ">=0.5.1"
       }
     },
+    "figgy-pudding": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
+      "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
+      "dev": true
+    },
+    "file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "dev": true,
+      "optional": true
+    },
     "fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -660,6 +1769,17 @@
         "to-regex-range": "^5.0.1"
       }
     },
+    "find-cache-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^2.0.0",
+        "pkg-dir": "^3.0.0"
+      }
+    },
     "find-up": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@@ -669,6 +1789,129 @@
         "locate-path": "^3.0.0"
       }
     },
+    "findup-sync": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
+      "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
+      "dev": true,
+      "requires": {
+        "detect-file": "^1.0.0",
+        "is-glob": "^4.0.0",
+        "micromatch": "^3.0.4",
+        "resolve-dir": "^1.0.1"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
     "flat": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
@@ -678,6 +1921,22 @@
         "is-buffer": "~2.0.3"
       }
     },
+    "flush-write-stream": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+      "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.3.6"
+      }
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
     "foreach": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
@@ -698,6 +1957,25 @@
         "mime-types": "^2.1.12"
       }
     },
+    "fragment-cache": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+      "dev": true,
+      "requires": {
+        "map-cache": "^0.2.2"
+      }
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      }
+    },
     "fs-extra": {
       "version": "9.0.1",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
@@ -710,6 +1988,18 @@
         "universalify": "^1.0.0"
       }
     },
+    "fs-write-stream-atomic": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "iferr": "^0.1.5",
+        "imurmurhash": "^0.1.4",
+        "readable-stream": "1 || 2"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -733,6 +2023,12 @@
       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
       "dev": true
     },
+    "get-value": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+      "dev": true
+    },
     "getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -763,6 +2059,41 @@
         "is-glob": "^4.0.1"
       }
     },
+    "global-modules": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+      "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+      "dev": true,
+      "requires": {
+        "global-prefix": "^3.0.0"
+      },
+      "dependencies": {
+        "global-prefix": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+          "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+          "dev": true,
+          "requires": {
+            "ini": "^1.3.5",
+            "kind-of": "^6.0.2",
+            "which": "^1.3.1"
+          }
+        }
+      }
+    },
+    "global-prefix": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+      "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.2",
+        "homedir-polyfill": "^1.0.1",
+        "ini": "^1.3.4",
+        "is-windows": "^1.0.1",
+        "which": "^1.2.14"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
@@ -808,16 +2139,128 @@
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
       "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
     },
+    "has-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+      "dev": true,
+      "requires": {
+        "get-value": "^2.0.6",
+        "has-values": "^1.0.0",
+        "isobject": "^3.0.0"
+      }
+    },
+    "has-values": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "hash-base": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "hash.js": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "minimalistic-assert": "^1.0.1"
+      }
+    },
     "he": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
+    "hmac-drbg": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "dev": true,
+      "requires": {
+        "hash.js": "^1.0.3",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.1"
+      }
+    },
+    "homedir-polyfill": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+      "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+      "dev": true,
+      "requires": {
+        "parse-passwd": "^1.0.0"
+      }
+    },
     "http-parser-js": {
-      "version": "0.4.10",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
-      "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q="
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz",
+      "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ=="
     },
     "http-proxy-agent": {
       "version": "2.1.0",
@@ -850,6 +2293,12 @@
         "sshpk": "^1.7.0"
       }
     },
+    "https-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+      "dev": true
+    },
     "https-proxy-agent": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
@@ -877,6 +2326,40 @@
         }
       }
     },
+    "ieee754": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+      "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+      "dev": true
+    },
+    "iferr": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+      "dev": true
+    },
+    "import-local": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+      "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+      "dev": true,
+      "requires": {
+        "pkg-dir": "^3.0.0",
+        "resolve-cwd": "^2.0.0"
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "infer-owner": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+      "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -891,6 +2374,44 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "interpret": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+      "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+      "dev": true
+    },
+    "is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "is-arguments": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
@@ -926,11 +2447,62 @@
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
       "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
     },
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "is-date-object": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
       "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
     },
+    "is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "dev": true,
+      "requires": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -968,6 +2540,15 @@
       "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
       "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
     },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
     "is-regex": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
@@ -1020,6 +2601,18 @@
       "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
       "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw=="
     },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
+    "is-wsl": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+      "dev": true
+    },
     "isarray": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
@@ -1032,6 +2625,12 @@
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
+    "isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+      "dev": true
+    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -1058,24 +2657,37 @@
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
-    "json-rpc2": {
+    "json-parse-better-errors": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-rpc2/-/json-rpc2-1.0.2.tgz",
-      "integrity": "sha1-63e9J7HfYGwjcCxONdSvxUdCro0=",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-rpc2": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/json-rpc2/-/json-rpc2-2.0.0.tgz",
+      "integrity": "sha512-0jfrGSH0ZDxrpaaHUkigg/oA6MQqsZDpKSpUzeokhP2jyy6h+cH4G+MPoAa4SVdw9sTzc+YK2hzhUgdShMzKow==",
       "requires": {
-        "debug": "2.x.x",
-        "es5class": "2.x.x",
-        "eventemitter3": "1.x.x",
-        "faye-websocket": "0.x.x",
-        "jsonparse": "1.x.x",
-        "lodash": "3.x.x",
-        "object-assign": "4.x"
+        "debug": "^4.1.1",
+        "es5class": "^2.3.1",
+        "faye-websocket": "^0.11.3",
+        "jsonparse": "^1.3.1",
+        "lodash": "^4.17.15",
+        "object-assign": "^4.1.1"
       },
       "dependencies": {
-        "lodash": {
-          "version": "3.10.1",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
         }
       }
     },
@@ -1094,6 +2706,15 @@
       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
     },
+    "json5": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+      "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.0"
+      }
+    },
     "jsonfile": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
@@ -1126,6 +2747,29 @@
       "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==",
       "dev": true
     },
+    "kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true
+    },
+    "loader-runner": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+      "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
+      "dev": true
+    },
+    "loader-utils": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+      "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+      "dev": true,
+      "requires": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^1.0.1"
+      }
+    },
     "locate-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -1137,10 +2781,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-      "dev": true
+      "version": "4.17.19",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+      "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
     },
     "lodash.get": {
       "version": "4.4.2",
@@ -1157,6 +2800,97 @@
         "chalk": "^2.4.2"
       }
     },
+    "lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "requires": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "requires": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+      "dev": true
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "dev": true,
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "md5.js": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "memory-fs": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
+      "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
+      "dev": true,
+      "requires": {
+        "errno": "^0.1.3",
+        "readable-stream": "^2.0.1"
+      }
+    },
+    "micromatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+      "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+      "dev": true,
+      "requires": {
+        "braces": "^3.0.1",
+        "picomatch": "^2.0.5"
+      }
+    },
+    "miller-rabin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "brorand": "^1.0.1"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
     "mime-db": {
       "version": "1.43.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
@@ -1170,6 +2904,18 @@
         "mime-db": "1.43.0"
       }
     },
+    "minimalistic-assert": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+      "dev": true
+    },
+    "minimalistic-crypto-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "dev": true
+    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -1183,6 +2929,45 @@
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
       "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
     },
+    "mississippi": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+      "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+      "dev": true,
+      "requires": {
+        "concat-stream": "^1.5.0",
+        "duplexify": "^3.4.2",
+        "end-of-stream": "^1.1.0",
+        "flush-write-stream": "^1.0.0",
+        "from2": "^2.1.0",
+        "parallel-transform": "^1.1.0",
+        "pump": "^3.0.0",
+        "pumpify": "^1.3.3",
+        "stream-each": "^1.1.0",
+        "through2": "^2.0.0"
+      }
+    },
+    "mixin-deep": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.2",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
     "mkdirp": {
       "version": "0.5.5",
       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
@@ -1261,14 +3046,66 @@
       }
     },
     "moment": {
-      "version": "2.26.0",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
-      "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
+      "version": "2.27.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+      "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
+    },
+    "move-concurrently": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "copy-concurrently": "^1.0.0",
+        "fs-write-stream-atomic": "^1.0.8",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.3"
+      }
     },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "nan": {
+      "version": "2.14.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+      "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+      "dev": true
+    },
+    "nanomatch": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "fragment-cache": "^0.2.1",
+        "is-windows": "^1.0.2",
+        "kind-of": "^6.0.2",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      }
+    },
+    "neo-async": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
     },
     "nise": {
       "version": "4.0.3",
@@ -1301,6 +3138,45 @@
         }
       }
     },
+    "node-libs-browser": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+      "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+      "dev": true,
+      "requires": {
+        "assert": "^1.1.1",
+        "browserify-zlib": "^0.2.0",
+        "buffer": "^4.3.0",
+        "console-browserify": "^1.1.0",
+        "constants-browserify": "^1.0.0",
+        "crypto-browserify": "^3.11.0",
+        "domain-browser": "^1.1.1",
+        "events": "^3.0.0",
+        "https-browserify": "^1.0.0",
+        "os-browserify": "^0.3.0",
+        "path-browserify": "0.0.1",
+        "process": "^0.11.10",
+        "punycode": "^1.2.4",
+        "querystring-es3": "^0.2.0",
+        "readable-stream": "^2.3.3",
+        "stream-browserify": "^2.0.1",
+        "stream-http": "^2.7.2",
+        "string_decoder": "^1.0.0",
+        "timers-browserify": "^2.0.4",
+        "tty-browserify": "0.0.0",
+        "url": "^0.11.0",
+        "util": "^0.11.0",
+        "vm-browserify": "^1.0.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
+      }
+    },
     "normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -1317,6 +3193,43 @@
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
+    "object-copy": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+      "dev": true,
+      "requires": {
+        "copy-descriptor": "^0.1.0",
+        "define-property": "^0.2.5",
+        "kind-of": "^3.0.3"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "object-inspect": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
@@ -1336,6 +3249,15 @@
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
       "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
     },
+    "object-visit": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.0"
+      }
+    },
     "object.assign": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
@@ -1357,6 +3279,15 @@
         "es-abstract": "^1.17.0-next.1"
       }
     },
+    "object.pick": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1365,6 +3296,12 @@
         "wrappy": "1"
       }
     },
+    "os-browserify": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+      "dev": true
+    },
     "p-limit": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@@ -1389,6 +3326,62 @@
       "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
       "dev": true
     },
+    "pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+      "dev": true
+    },
+    "parallel-transform": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+      "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+      "dev": true,
+      "requires": {
+        "cyclist": "^1.0.1",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.1.5"
+      }
+    },
+    "parse-asn1": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+      "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+      "dev": true,
+      "requires": {
+        "asn1.js": "^4.0.0",
+        "browserify-aes": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.0",
+        "pbkdf2": "^3.0.3",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "parse-passwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+      "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+      "dev": true
+    },
+    "pascalcase": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+      "dev": true
+    },
+    "path-browserify": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+      "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+      "dev": true
+    },
+    "path-dirname": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+      "dev": true,
+      "optional": true
+    },
     "path-exists": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -1400,6 +3393,12 @@
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
     },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
     "path-parse": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@@ -1415,6 +3414,19 @@
         "isarray": "0.0.1"
       }
     },
+    "pbkdf2": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
+      "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
+      "dev": true,
+      "requires": {
+        "create-hash": "^1.1.2",
+        "create-hmac": "^1.1.4",
+        "ripemd160": "^2.0.1",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -1426,17 +3438,117 @@
       "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
       "dev": true
     },
+    "pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true
+    },
+    "pkg-dir": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+      "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+      "dev": true,
+      "requires": {
+        "find-up": "^3.0.0"
+      }
+    },
+    "posix-character-classes": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+      "dev": true
+    },
     "prettier": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
       "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
       "dev": true
     },
+    "process": {
+      "version": "0.11.10",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+      "dev": true
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+      "dev": true
+    },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true
+    },
     "psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
       "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
     },
+    "public-encrypt": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+      "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "browserify-rsa": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "parse-asn1": "^5.0.0",
+        "randombytes": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "pumpify": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+      "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+      "dev": true,
+      "requires": {
+        "duplexify": "^3.6.0",
+        "inherits": "^2.0.3",
+        "pump": "^2.0.0"
+      },
+      "dependencies": {
+        "pump": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+          "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        }
+      }
+    },
     "punycode": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -1447,6 +3559,66 @@
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
       "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
     },
+    "querystring": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+      "dev": true
+    },
+    "querystring-es3": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+      "dev": true
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "randomfill": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+      "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.0.5",
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
     "readdirp": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
@@ -1456,6 +3628,16 @@
         "picomatch": "^2.0.4"
       }
     },
+    "regex-not": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
     "regexp.prototype.flags": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
@@ -1465,6 +3647,25 @@
         "es-abstract": "^1.17.0-next.1"
       }
     },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true,
+      "optional": true
+    },
+    "repeat-element": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
     "request": {
       "version": "2.88.2",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
@@ -1513,6 +3714,56 @@
         "path-parse": "^1.0.6"
       }
     },
+    "resolve-cwd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+      "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^3.0.0"
+      }
+    },
+    "resolve-dir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+      "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.0",
+        "global-modules": "^1.0.0"
+      },
+      "dependencies": {
+        "global-modules": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+          "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+          "dev": true,
+          "requires": {
+            "global-prefix": "^1.0.1",
+            "is-windows": "^1.0.1",
+            "resolve-dir": "^1.0.0"
+          }
+        }
+      }
+    },
+    "resolve-from": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+      "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+      "dev": true
+    },
+    "resolve-url": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+      "dev": true
+    },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true
+    },
     "rimraf": {
       "version": "2.7.1",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -1522,27 +3773,129 @@
         "glob": "^7.1.3"
       }
     },
+    "ripemd160": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
+    "run-queue": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1"
+      }
+    },
     "safe-buffer": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
       "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
     },
+    "safe-regex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+      "dev": true,
+      "requires": {
+        "ret": "~0.1.10"
+      }
+    },
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "schema-utils": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+      "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.1.0",
+        "ajv-errors": "^1.0.0",
+        "ajv-keywords": "^3.1.0"
+      }
+    },
     "semver": {
       "version": "7.3.2",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
       "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
     },
+    "serialize-javascript": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
+      "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
+    },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
       "dev": true
     },
+    "set-value": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-extendable": "^0.1.1",
+        "is-plain-object": "^2.0.3",
+        "split-string": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+      "dev": true
+    },
+    "sha.js": {
+      "version": "2.4.11",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
     "side-channel": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
@@ -1584,6 +3937,177 @@
         }
       }
     },
+    "snapdragon": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+      "dev": true,
+      "requires": {
+        "base": "^0.11.1",
+        "debug": "^2.2.0",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "map-cache": "^0.2.2",
+        "source-map": "^0.5.6",
+        "source-map-resolve": "^0.5.0",
+        "use": "^3.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "snapdragon-node": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.0",
+        "snapdragon-util": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "snapdragon-util": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.2.0"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "source-list-map": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+      "dev": true
+    },
+    "source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+      "dev": true
+    },
+    "source-map-resolve": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+      "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+      "dev": true,
+      "requires": {
+        "atob": "^2.1.2",
+        "decode-uri-component": "^0.2.0",
+        "resolve-url": "^0.2.1",
+        "source-map-url": "^0.4.0",
+        "urix": "^0.1.0"
+      }
+    },
+    "source-map-support": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "source-map-url": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+      "dev": true
+    },
+    "split-string": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.0"
+      }
+    },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -1606,6 +4130,75 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "ssri": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+      "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+      "dev": true,
+      "requires": {
+        "figgy-pudding": "^3.5.1"
+      }
+    },
+    "static-extend": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+      "dev": true,
+      "requires": {
+        "define-property": "^0.2.5",
+        "object-copy": "^0.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "stream-browserify": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+      "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.1",
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "stream-each": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+      "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
+    "stream-http": {
+      "version": "2.8.3",
+      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+      "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+      "dev": true,
+      "requires": {
+        "builtin-status-codes": "^3.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.3.6",
+        "to-arraybuffer": "^1.0.0",
+        "xtend": "^4.0.0"
+      }
+    },
+    "stream-shift": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
+      "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
+      "dev": true
+    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -1654,6 +4247,23 @@
         "es-abstract": "^1.17.5"
       }
     },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -1678,6 +4288,119 @@
         "has-flag": "^3.0.0"
       }
     },
+    "tapable": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+      "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+      "dev": true
+    },
+    "terser": {
+      "version": "4.8.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
+      "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.20.0",
+        "source-map": "~0.6.1",
+        "source-map-support": "~0.5.12"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
+      "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
+      "dev": true,
+      "requires": {
+        "cacache": "^12.0.2",
+        "find-cache-dir": "^2.1.0",
+        "is-wsl": "^1.1.0",
+        "schema-utils": "^1.0.0",
+        "serialize-javascript": "^3.1.0",
+        "source-map": "^0.6.1",
+        "terser": "^4.1.2",
+        "webpack-sources": "^1.4.0",
+        "worker-farm": "^1.7.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "through2": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+      "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "~2.3.6",
+        "xtend": "~4.0.1"
+      }
+    },
+    "timers-browserify": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+      "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+      "dev": true,
+      "requires": {
+        "setimmediate": "^1.0.4"
+      }
+    },
+    "to-arraybuffer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+      "dev": true
+    },
+    "to-object-path": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "to-regex": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "regex-not": "^1.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
     "to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1700,6 +4423,27 @@
       "version": "file:third_party/tree-kill",
       "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
     },
+    "ts-loader": {
+      "version": "7.0.5",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.5.tgz",
+      "integrity": "sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.0",
+        "enhanced-resolve": "^4.0.0",
+        "loader-utils": "^1.0.2",
+        "micromatch": "^4.0.0",
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
     "tslib": {
       "version": "1.13.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
@@ -1744,6 +4488,12 @@
         "tslib": "^1.8.1"
       }
     },
+    "tty-browserify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+      "dev": true
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -1763,18 +4513,107 @@
       "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
       "dev": true
     },
-    "typescript": {
-      "version": "3.9.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
-      "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
+    "typescript": {
+      "version": "3.9.6",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
+      "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
+      "dev": true
+    },
+    "union-value": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "get-value": "^2.0.6",
+        "is-extendable": "^0.1.1",
+        "set-value": "^2.0.1"
+      }
+    },
+    "unique-filename": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+      "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+      "dev": true,
+      "requires": {
+        "unique-slug": "^2.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+      "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "^0.1.4"
+      }
+    },
     "universalify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
       "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
       "dev": true
     },
+    "unset-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+      "dev": true,
+      "requires": {
+        "has-value": "^0.3.1",
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "has-value": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+          "dev": true,
+          "requires": {
+            "get-value": "^2.0.3",
+            "has-values": "^0.1.4",
+            "isobject": "^2.0.0"
+          },
+          "dependencies": {
+            "isobject": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+              "dev": true,
+              "requires": {
+                "isarray": "1.0.0"
+              }
+            }
+          }
+        },
+        "has-values": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+          "dev": true
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        }
+      }
+    },
+    "upath": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+      "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+      "dev": true,
+      "optional": true
+    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -1783,11 +4622,70 @@
         "punycode": "^2.1.0"
       }
     },
+    "urix": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+      "dev": true
+    },
+    "url": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+      "dev": true,
+      "requires": {
+        "punycode": "1.3.2",
+        "querystring": "0.2.0"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+          "dev": true
+        }
+      }
+    },
+    "use": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+      "dev": true
+    },
+    "util": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+      "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+          "dev": true
+        }
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
     "uuid": {
       "version": "3.4.0",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
     },
+    "v8-compile-cache": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
+      "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+      "dev": true
+    },
     "verror": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -1798,6 +4696,12 @@
         "extsprintf": "^1.2.0"
       }
     },
+    "vm-browserify": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+      "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+      "dev": true
+    },
     "vscode-debugadapter": {
       "version": "1.41.0",
       "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.41.0.tgz",
@@ -1858,6 +4762,284 @@
         "rimraf": "^2.6.3"
       }
     },
+    "watchpack": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
+      "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==",
+      "dev": true,
+      "requires": {
+        "chokidar": "^3.4.0",
+        "graceful-fs": "^4.1.2",
+        "neo-async": "^2.5.0",
+        "watchpack-chokidar2": "^2.0.0"
+      },
+      "dependencies": {
+        "chokidar": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
+          "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "anymatch": "~3.1.1",
+            "braces": "~3.0.2",
+            "fsevents": "~2.1.2",
+            "glob-parent": "~5.1.0",
+            "is-binary-path": "~2.1.0",
+            "is-glob": "~4.0.1",
+            "normalize-path": "~3.0.0",
+            "readdirp": "~3.4.0"
+          }
+        },
+        "readdirp": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+          "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "picomatch": "^2.2.1"
+          }
+        }
+      }
+    },
+    "watchpack-chokidar2": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
+      "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chokidar": "^2.1.8"
+      },
+      "dependencies": {
+        "anymatch": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+          "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "micromatch": "^3.1.4",
+            "normalize-path": "^2.1.1"
+          },
+          "dependencies": {
+            "normalize-path": {
+              "version": "2.1.1",
+              "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+              "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "remove-trailing-separator": "^1.0.1"
+              }
+            }
+          }
+        },
+        "binary-extensions": {
+          "version": "1.13.1",
+          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+          "dev": true,
+          "optional": true
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "chokidar": {
+          "version": "2.1.8",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "anymatch": "^2.0.0",
+            "async-each": "^1.0.1",
+            "braces": "^2.3.2",
+            "fsevents": "^1.2.7",
+            "glob-parent": "^3.1.0",
+            "inherits": "^2.0.3",
+            "is-binary-path": "^1.0.0",
+            "is-glob": "^4.0.0",
+            "normalize-path": "^3.0.0",
+            "path-is-absolute": "^1.0.0",
+            "readdirp": "^2.2.1",
+            "upath": "^1.1.1"
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fsevents": {
+          "version": "1.2.13",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1"
+          }
+        },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
+        "is-binary-path": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+          "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "binary-extensions": "^1.0.0"
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true,
+          "optional": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "readdirp": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+          "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "graceful-fs": "^4.1.11",
+            "micromatch": "^3.1.10",
+            "readable-stream": "^2.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
     "web-request": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz",
@@ -1866,12 +5048,212 @@
         "request": "^2.69.0"
       }
     },
-    "websocket-driver": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
-      "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+    "webpack": {
+      "version": "4.43.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
+      "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
+      "dev": true,
       "requires": {
-        "http-parser-js": ">=0.4.0 <0.4.11",
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/wasm-edit": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "acorn": "^6.4.1",
+        "ajv": "^6.10.2",
+        "ajv-keywords": "^3.4.1",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^4.1.0",
+        "eslint-scope": "^4.0.3",
+        "json-parse-better-errors": "^1.0.2",
+        "loader-runner": "^2.4.0",
+        "loader-utils": "^1.2.3",
+        "memory-fs": "^0.4.1",
+        "micromatch": "^3.1.10",
+        "mkdirp": "^0.5.3",
+        "neo-async": "^2.6.1",
+        "node-libs-browser": "^2.2.1",
+        "schema-utils": "^1.0.0",
+        "tapable": "^1.1.3",
+        "terser-webpack-plugin": "^1.4.3",
+        "watchpack": "^1.6.1",
+        "webpack-sources": "^1.4.1"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "memory-fs": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+          "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+          "dev": true,
+          "requires": {
+            "errno": "^0.1.3",
+            "readable-stream": "^2.0.1"
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
+    "webpack-cli": {
+      "version": "3.3.12",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz",
+      "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.2",
+        "cross-spawn": "^6.0.5",
+        "enhanced-resolve": "^4.1.1",
+        "findup-sync": "^3.0.0",
+        "global-modules": "^2.0.0",
+        "import-local": "^2.0.0",
+        "interpret": "^1.4.0",
+        "loader-utils": "^1.4.0",
+        "supports-color": "^6.1.0",
+        "v8-compile-cache": "^2.1.1",
+        "yargs": "^13.3.2"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "webpack-sources": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+      "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+      "dev": true,
+      "requires": {
+        "source-list-map": "^2.0.0",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "websocket-driver": {
+      "version": "0.7.4",
+      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+      "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+      "requires": {
+        "http-parser-js": ">=0.5.1",
         "safe-buffer": ">=5.1.0",
         "websocket-extensions": ">=0.1.1"
       }
@@ -1941,6 +5323,15 @@
         "string-width": "^1.0.2 || 2"
       }
     },
+    "worker-farm": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+      "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+      "dev": true,
+      "requires": {
+        "errno": "~0.1.7"
+      }
+    },
     "wrap-ansi": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -1985,12 +5376,24 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "dev": true
+    },
     "y18n": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
       "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
       "dev": true
     },
+    "yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
     "yargs": {
       "version": "13.3.2",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
diff --git a/package.json b/package.json
index ad10ee1..f69a597 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "go",
   "displayName": "Go",
-  "version": "0.15.2",
+  "version": "0.16.0-dev",
   "publisher": "golang",
   "description": "Rich Go language support for Visual Studio Code",
   "author": {
@@ -33,13 +33,15 @@
   ],
   "scripts": {
     "vscode:prepublish": "npm run compile",
-    "compile": "tsc -p ./",
+    "webpack": "webpack --mode development",
+    "webpack-dev": "webpack --mode development --watch",
+    "test-compile": "tsc -p ./",
+    "compile": "webpack --mode production",
     "watch": "tsc -watch -p ./",
-    "pretest": "npm run compile",
-    "test": "node ./out/test/runTest.js",
+    "test": "npm run test-compile && node ./out/test/runTest.js",
     "lint": "node ./node_modules/tslint/bin/tslint --project tsconfig.json",
     "fix-lint": "node ./node_modules/tslint/bin/tslint --fix --project tsconfig.json",
-    "unit-test": "node ./node_modules/mocha/bin/_mocha -u tdd --timeout 5000 --colors ./out/test/unit",
+    "unit-test": "npm run test-compile && node ./node_modules/mocha/bin/_mocha -u tdd --timeout 5000 --colors ./out/test/unit",
     "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
   },
   "extensionDependencies": [],
@@ -47,7 +49,7 @@
     "deep-equal": "^2.0.2",
     "diff": "^4.0.2",
     "glob": "^7.1.6",
-    "json-rpc2": "^1.0.2",
+    "json-rpc2": "^2.0.0",
     "moment": "^2.24.0",
     "semver": "^7.3.2",
     "tree-kill": "file:third_party/tree-kill",
@@ -69,11 +71,15 @@
     "adm-zip": "^0.4.14",
     "fs-extra": "^9.0.0",
     "mocha": "^7.1.1",
+    "nan": "^2.14.1",
     "prettier": "^2.0.4",
     "sinon": "^9.0.2",
+    "ts-loader": "^7.0.5",
     "tslint": "^6.1.1",
     "typescript": "^3.8.3",
     "vscode-test": "^1.3.0",
+    "webpack": "^4.43.0",
+    "webpack-cli": "^3.3.12",
     "yarn": "^1.22.4"
   },
   "engines": {
@@ -86,7 +92,7 @@
     "onCommand:go.tools.install",
     "onDebugResolve:go"
   ],
-  "main": "./out/src/goMain",
+  "main": "./dist/goMain.js",
   "contributes": {
     "languages": [
       {
@@ -361,7 +367,7 @@
       {
         "type": "go",
         "label": "Go",
-        "program": "./out/src/debugAdapter/goDebug.js",
+        "program": "./dist/debugAdapter.js",
         "runtime": "node",
         "languages": [
           "go"
@@ -750,6 +756,381 @@
             }
           }
         }
+      },
+      {
+        "type": "godlvdap",
+        "label": "Go Dlv Dap (Experimental)",
+        "program": "./dist/debugAdapter2.js",
+        "runtime": "node",
+        "languages": [
+          "go"
+        ],
+        "configurationSnippets": [
+          {
+            "label": "Go: Launch package",
+            "description": "Debug the package in the program attribute",
+            "body": {
+              "name": "${2:Launch Package}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "debug",
+              "program": "^\"\\${workspaceFolder}${1:}\""
+            }
+          },
+          {
+            "label": "Go: Launch file",
+            "description": "Debug the file in the program attribute",
+            "body": {
+              "name": "${2:Launch file}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "debug",
+              "program": "^\"${1:\\${file\\}}\""
+            }
+          },
+          {
+            "label": "Go: Launch test package",
+            "description": "Debug the test package in the program attribute",
+            "body": {
+              "name": "${2:Launch test package}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "test",
+              "program": "^\"\\${workspaceFolder}${1:}\""
+            }
+          },
+          {
+            "label": "Go: Launch test function",
+            "description": "Debug the test function in the args, ensure program attributes points to right package",
+            "body": {
+              "name": "${3:Launch test function}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "test",
+              "program": "^\"\\${workspaceFolder}${1:}\"",
+              "args": [
+                "-test.run",
+                "${2:MyTestFunction}"
+              ]
+            }
+          },
+          {
+            "label": "Go: Attach to local process",
+            "description": "Attach to an existing process by process ID",
+            "body": {
+              "name": "${1:Attach to Process}",
+              "type": "godlvdap",
+              "request": "attach",
+              "mode": "local",
+              "processId": 0
+            }
+          },
+          {
+            "label": "Go: Connect to server",
+            "description": "Connect to a remote headless debug server",
+            "body": {
+              "name": "${1:Connect to server}",
+              "type": "godlvdap",
+              "request": "attach",
+              "mode": "remote",
+              "remotePath": "^\"\\${workspaceFolder}\"",
+              "port": 2345,
+              "host": "127.0.0.1"
+            }
+          }
+        ],
+        "configurationAttributes": {
+          "launch": {
+            "required": [],
+            "properties": {
+              "program": {
+                "type": "string",
+                "description": "Path to the program folder (or any file within that folder) when in 'debug' or 'test' mode, and to the pre-built binary file to debug in 'exec' mode.",
+                "default": "${workspaceFolder}"
+              },
+              "mode": {
+                "enum": [
+                  "auto",
+                  "debug",
+                  "test",
+                  "exec"
+                ],
+                "description": "One of 'auto', 'debug', 'test', 'exec'.",
+                "default": "auto"
+              },
+              "stopOnEntry": {
+                "type": "boolean",
+                "description": "Automatically stop program after launch.",
+                "default": false
+              },
+              "args": {
+                "type": "array",
+                "description": "Command line arguments passed to the program.",
+                "items": {
+                  "type": "string"
+                },
+                "default": []
+              },
+              "showLog": {
+                "type": "boolean",
+                "description": "Show log output from the delve debugger.",
+                "default": false
+              },
+              "cwd": {
+                "type": "string",
+                "description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
+                "default": "."
+              },
+              "env": {
+                "type": "object",
+                "description": "Environment variables passed to the program.",
+                "default": {}
+              },
+              "buildFlags": {
+                "type": "string",
+                "description": "Build flags, to be passed to the Go compiler.",
+                "default": ""
+              },
+              "init": {
+                "type": "string",
+                "description": "Init file, executed by the terminal client.",
+                "default": ""
+              },
+              "remotePath": {
+                "type": "string",
+                "description": "Absolute path to the file being debugged on the remote machine in case of remote debugging.",
+                "default": ""
+              },
+              "port": {
+                "type": "number",
+                "description": "The port that the delve debugger will be listening on.",
+                "default": 2345
+              },
+              "host": {
+                "type": "string",
+                "description": "The host name of the machine the delve debugger will be listening on.",
+                "default": "127.0.0.1"
+              },
+              "trace": {
+                "type": "string",
+                "enum": [
+                  "log",
+                  "verbose",
+                  "error"
+                ],
+                "default": "error",
+                "description": "Various levels of logging shown in the debug console. When set to 'log' or 'verbose', the logs will also be written to a file."
+              },
+              "envFile": {
+                "type": [
+                  "string",
+                  "array"
+                ],
+                "items": {
+                  "type": "string"
+                },
+                "description": "Absolute path to a file containing environment variable definitions. Multiple files can be specified by provided an array of absolute paths",
+                "default": "${workspaceFolder}/.env"
+              },
+              "backend": {
+                "type": "string",
+                "enum": [
+                  "default",
+                  "native",
+                  "lldb"
+                ],
+                "description": "Backend used by delve. Only available in delve version 0.12.2 and above."
+              },
+              "output": {
+                "type": "string",
+                "description": "Output path for the binary of delve",
+                "default": "debug"
+              },
+              "logOutput": {
+                "type": "string",
+                "enum": [
+                  "debugger",
+                  "gdbwire",
+                  "lldbout",
+                  "debuglineerr",
+                  "dap"
+                ],
+                "description": "Comma separated list of components that should produce debug output.",
+                "default": "debugger"
+              },
+              "dlvLoadConfig": {
+                "type": "object",
+                "properties": {
+                  "followPointers": {
+                    "type": "boolean",
+                    "description": "FollowPointers requests pointers to be automatically dereferenced",
+                    "default": true
+                  },
+                  "maxVariableRecurse": {
+                    "type": "number",
+                    "description": "MaxVariableRecurse is how far to recurse when evaluating nested types",
+                    "default": 1
+                  },
+                  "maxStringLen": {
+                    "type": "number",
+                    "description": "MaxStringLen is the maximum number of bytes read from a string",
+                    "default": 64
+                  },
+                  "maxArrayValues": {
+                    "type": "number",
+                    "description": "MaxArrayValues is the maximum number of elements read from an array, a slice or a map",
+                    "default": 64
+                  },
+                  "maxStructFields": {
+                    "type": "number",
+                    "description": "MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields",
+                    "default": -1
+                  }
+                },
+                "description": "LoadConfig describes to delve, how to load values from target's memory",
+                "default": {
+                  "followPointers": true,
+                  "maxVariableRecurse": 1,
+                  "maxStringLen": 64,
+                  "maxArrayValues": 64,
+                  "maxStructFields": -1
+                }
+              },
+              "stackTraceDepth": {
+                "type": "number",
+                "description": "Maximum depth of stack trace collected from Delve",
+                "default": 50
+              },
+              "showGlobalVariables": {
+                "type": "boolean",
+                "default": true,
+                "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
+              }
+            }
+          },
+          "attach": {
+            "required": [],
+            "properties": {
+              "processId": {
+                "type": "number",
+                "description": "The ID of the process to be debugged."
+              },
+              "mode": {
+                "enum": [
+                  "local",
+                  "remote"
+                ],
+                "description": "Indicates local or remote debugging.  Local maps to the dlv 'attach' command, remote maps to 'connect'.",
+                "default": "local"
+              },
+              "showLog": {
+                "type": "boolean",
+                "description": "Show log output from the delve debugger.",
+                "default": false
+              },
+              "cwd": {
+                "type": "string",
+                "description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
+                "default": "${workspaceFolder}"
+              },
+              "remotePath": {
+                "type": "string",
+                "description": "If remote debugging, the path to the source code on the remote machine, if different from the local machine.",
+                "default": ""
+              },
+              "port": {
+                "type": "number",
+                "description": "The port that the delve debugger will be listening on.",
+                "default": 2345
+              },
+              "host": {
+                "type": "string",
+                "description": "The host name of the machine the delve debugger will be listening on.",
+                "default": "127.0.0.1"
+              },
+              "trace": {
+                "type": "string",
+                "enum": [
+                  "log",
+                  "verbose",
+                  "error"
+                ],
+                "default": "error",
+                "description": "Various levels of logging shown in the debug console. When set to 'log' or 'verbose', the logs will also be written to a file."
+              },
+              "backend": {
+                "type": "string",
+                "enum": [
+                  "default",
+                  "native",
+                  "lldb"
+                ],
+                "description": "Backend used by delve. Only available in delve version 0.12.2 and above."
+              },
+              "logOutput": {
+                "type": "string",
+                "enum": [
+                  "debugger",
+                  "gdbwire",
+                  "lldbout",
+                  "debuglineerr",
+                  "dap",
+                  "rpc"
+                ],
+                "description": "Comma separated list of components that should produce debug output.",
+                "default": "debugger"
+              },
+              "dlvLoadConfig": {
+                "type": "object",
+                "properties": {
+                  "followPointers": {
+                    "type": "boolean",
+                    "description": "FollowPointers requests pointers to be automatically dereferenced",
+                    "default": true
+                  },
+                  "maxVariableRecurse": {
+                    "type": "number",
+                    "description": "MaxVariableRecurse is how far to recurse when evaluating nested types",
+                    "default": 1
+                  },
+                  "maxStringLen": {
+                    "type": "number",
+                    "description": "MaxStringLen is the maximum number of bytes read from a string",
+                    "default": 64
+                  },
+                  "maxArrayValues": {
+                    "type": "number",
+                    "description": "MaxArrayValues is the maximum number of elements read from an array, a slice or a map",
+                    "default": 64
+                  },
+                  "maxStructFields": {
+                    "type": "number",
+                    "description": "MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields",
+                    "default": -1
+                  }
+                },
+                "description": "LoadConfig describes to delve, how to load values from target's memory",
+                "default": {
+                  "followPointers": true,
+                  "maxVariableRecurse": 1,
+                  "maxStringLen": 64,
+                  "maxArrayValues": 64,
+                  "maxStructFields": -1
+                }
+              },
+              "stackTraceDepth": {
+                "type": "number",
+                "description": "Maximum depth of stack trace collected from Delve",
+                "default": 50
+              },
+              "showGlobalVariables": {
+                "type": "boolean",
+                "default": true,
+                "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
+              }
+            }
+          }
+        }
       }
     ],
     "configuration": {
@@ -999,6 +1380,7 @@
               "description": "Gutter style to indicate covered code."
             }
           },
+          "additionalProperties": false,
           "default": {
             "type": "highlight",
             "coveredHighlightColor": "rgba(64,128,128,0.5)",
@@ -1137,6 +1519,7 @@
               "description": "If true, the language server will provide clickable Godoc links for import statements."
             }
           },
+          "additionalProperties": false,
           "default": {
             "diagnostics": true,
             "documentLink": true
@@ -1184,6 +1567,7 @@
               "description": "If true, enables code lens for running and debugging tests"
             }
           },
+          "additionalProperties": false,
           "default": {
             "references": false,
             "runtest": true
@@ -1219,6 +1603,7 @@
               "description": "Transformation rule used by Go: Add Tags command to add tags"
             }
           },
+          "additionalProperties": false,
           "default": {
             "tags": "json",
             "options": "json=omitempty",
@@ -1242,6 +1627,7 @@
               "description": "The number of milliseconds to delay before execution. Resets with each keystroke."
             }
           },
+          "additionalProperties": false,
           "default": {
             "enabled": false,
             "delay": 500
@@ -1268,6 +1654,7 @@
               "description": "Comma separated tag=options pairs to be used by Go: Remove Tags command"
             }
           },
+          "additionalProperties": false,
           "default": {
             "tags": "",
             "options": "",
@@ -1296,6 +1683,7 @@
             },
             "description": "The flags configured here will be passed through to command `goplay`"
           },
+          "additionalProperties": false,
           "default": {
             "openbrowser": true,
             "share": true,
@@ -1376,6 +1764,7 @@
               "description": "If true, adds command to debug the test under the cursor to the editor context menu"
             }
           },
+          "additionalProperties": false,
           "default": {
             "toggleTestFile": true,
             "addTags": true,
@@ -1509,7 +1898,8 @@
               "default": "guru",
               "description": "Alternate tool to use instead of the guru binary or alternate path to use for the guru binary."
             }
-          }
+          },
+          "additionalProperties": false
         }
       }
     },
diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index 0dc9901..b784148 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -11,7 +11,6 @@
 import { Client, RPCConnection } from 'json-rpc2';
 import * as os from 'os';
 import * as path from 'path';
-import kill = require('tree-kill');
 import * as util from 'util';
 import {
 	DebugSession,
@@ -37,7 +36,8 @@
 	getCurrentGoWorkspaceFromGOPATH,
 	getInferredGopath,
 	parseEnvFile
-} from '../goPath';
+} from '../utils/goPath';
+import {killProcessTree} from '../utils/processUtils';
 
 const fsAccess = util.promisify(fs.access);
 const fsUnlink = util.promisify(fs.unlink);
@@ -514,7 +514,7 @@
 						} or ${envPath}`
 					);
 					return reject(
-						`Cannot find Delve debugger. Install from https://github.com/derekparker/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
+						`Cannot find Delve debugger. Install from https://github.com/go-delve/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
 					);
 				}
 
@@ -695,7 +695,7 @@
 	public async close(): Promise<void> {
 		const forceCleanup = async () => {
 			log(`killing debugee (pid: ${this.debugProcess.pid})...`);
-			await killProcessTree(this.debugProcess);
+			await killProcessTree(this.debugProcess, log);
 			await removeFile(this.localDebugeePath);
 		};
 
@@ -2314,23 +2314,6 @@
 	}
 }
 
-function killProcessTree(p: ChildProcess): Promise<void> {
-	if (!p || !p.pid) {
-		log(`no process to kill`);
-		return Promise.resolve();
-	}
-	return new Promise((resolve) => {
-		kill(p.pid, (err) => {
-			if (err) {
-				logError(`Error killing process ${p.pid}: ${err}`);
-			} else {
-				log(`killed process ${p.pid}`);
-			}
-			resolve();
-		});
-	});
-}
-
 // queryGOROOT returns `go env GOROOT`.
 function queryGOROOT(cwd: any, env: any): Promise<string> {
 	return new Promise<string>((resolve) => {
diff --git a/src/debugAdapter2/README.md b/src/debugAdapter2/README.md
new file mode 100644
index 0000000..f0ca4fb
--- /dev/null
+++ b/src/debugAdapter2/README.md
@@ -0,0 +1,6 @@
+# Debug Adapter
+
+This debug adapter is experimental, in-development code. If you
+actually need to debug Go code, please use the default adapter ("type": "go").
+
+See the [contribution documentation](../../docs/contributing.md) to learn how to develop the debug adapter.
diff --git a/src/debugAdapter2/dapClient.ts b/src/debugAdapter2/dapClient.ts
new file mode 100644
index 0000000..14d38a0
--- /dev/null
+++ b/src/debugAdapter2/dapClient.ts
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+import { EventEmitter } from 'events';
+import stream = require('stream');
+
+import { DebugProtocol } from 'vscode-debugprotocol';
+
+// DapClient implements a simple client for the DAP protocol.
+// It's initialized with a pair of streams that the caller creats and enables
+// sending and receiving DAP messages over these streams.
+// After calling connect():
+//
+//  - For sending messages call send().
+//  - For receiving messages, subscibe to events this class emits.
+//      - 'event', 'respones', 'request' - each carrying an appropriate
+//        DebugProtocol type as an argument.
+export class DAPClient extends EventEmitter {
+	private static readonly TWO_CRLF = '\r\n\r\n';
+
+	private outputStream: stream.Writable;
+
+	private rawData = Buffer.alloc(0);
+	private contentLength: number = -1;
+
+	constructor() {
+		super();
+	}
+
+	public send(req: any): void {
+		const json = JSON.stringify(req);
+		this.outputStream.write(`Content-Length: ${Buffer.byteLength(json, 'utf8')}\r\n\r\n${json}`, 'utf8');
+	}
+
+	// Connect this client to a server, which is represented by read and write
+	// streams. Before this method is called, send() won't work and no messages
+	// from the server will be delivered.
+	protected connect(readable: stream.Readable, writable: stream.Writable): void {
+		this.outputStream = writable;
+
+		readable.on('data', (data: Buffer) => {
+			this.handleData(data);
+		});
+	}
+
+	// Implements parsing of the DAP protocol. We cannot use ProtocolClient
+	// from the vscode-debugadapter package, because it's not exported and
+	// is not meant for external usage.
+	// See https://github.com/microsoft/vscode-debugadapter-node/issues/232
+	private handleData(data: Buffer): void {
+		this.rawData = Buffer.concat([this.rawData, data]);
+
+		while (true) {
+			if (this.contentLength >= 0) {
+				if (this.rawData.length >= this.contentLength) {
+					const message = this.rawData.toString('utf8', 0, this.contentLength);
+					this.rawData = this.rawData.slice(this.contentLength);
+					this.contentLength = -1;
+					if (message.length > 0) {
+						this.dispatch(message);
+					}
+					continue;	// there may be more complete messages to process
+				}
+			} else {
+				const idx = this.rawData.indexOf(DAPClient.TWO_CRLF);
+				if (idx !== -1) {
+					const header = this.rawData.toString('utf8', 0, idx);
+					const lines = header.split('\r\n');
+					for (const line of lines) {
+						const pair = line.split(/: +/);
+						if (pair[0] === 'Content-Length') {
+							this.contentLength = +pair[1];
+						}
+					}
+					this.rawData = this.rawData.slice(idx + DAPClient.TWO_CRLF.length);
+					continue;
+				}
+			}
+			break;
+		}
+	}
+
+	private dispatch(body: string): void {
+		const rawData = JSON.parse(body);
+
+		if (rawData.type === 'event') {
+			const event = <DebugProtocol.Event>rawData;
+			this.emit('event', event);
+		} else if (rawData.type === 'response') {
+			const response = <DebugProtocol.Response>rawData;
+			this.emit('response', response);
+		} else if (rawData.type === 'request') {
+			const request = <DebugProtocol.Request>rawData;
+			this.emit('request', request);
+		} else {
+			throw new Error(`unknown message ${JSON.stringify(rawData)}`);
+		}
+	}
+}
diff --git a/src/debugAdapter2/goDlvDebug.ts b/src/debugAdapter2/goDlvDebug.ts
new file mode 100644
index 0000000..e992bd8
--- /dev/null
+++ b/src/debugAdapter2/goDlvDebug.ts
@@ -0,0 +1,794 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+// NOTE: This debug adapter is experimental, in-development code. If you
+// actually need to debug Go code, please use the default adapter.
+
+import { ChildProcess, spawn } from 'child_process';
+import * as fs from 'fs';
+import net = require('net');
+import * as os from 'os';
+import * as path from 'path';
+
+import {
+	logger,
+	Logger,
+	LoggingDebugSession,
+	OutputEvent,
+	TerminatedEvent
+} from 'vscode-debugadapter';
+import { DebugProtocol } from 'vscode-debugprotocol';
+
+import {
+	envPath,
+	getBinPathWithPreferredGopathGoroot,
+	parseEnvFile
+} from '../utils/goPath';
+
+import { killProcessTree } from '../utils/processUtils';
+
+import { DAPClient } from './dapClient';
+
+interface LoadConfig {
+	// FollowPointers requests pointers to be automatically dereferenced.
+	followPointers: boolean;
+	// MaxVariableRecurse is how far to recurse when evaluating nested types.
+	maxVariableRecurse: number;
+	// MaxStringLen is the maximum number of bytes read from a string
+	maxStringLen: number;
+	// MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
+	maxArrayValues: number;
+	// MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
+	maxStructFields: number;
+}
+
+// This interface should always match the schema found in `package.json`.
+interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
+	request: 'launch';
+	[key: string]: any;
+	program: string;
+	stopOnEntry?: boolean;
+	args?: string[];
+	showLog?: boolean;
+	logOutput?: string;
+	cwd?: string;
+	env?: { [key: string]: string };
+	mode?: 'auto' | 'debug' | 'remote' | 'test' | 'exec';
+	remotePath?: string;
+	port?: number;
+	host?: string;
+	buildFlags?: string;
+	init?: string;
+	trace?: 'verbose' | 'log' | 'error';
+	/** Optional path to .env file. */
+	envFile?: string | string[];
+	backend?: string;
+	output?: string;
+	/** Delve LoadConfig parameters */
+	dlvLoadConfig?: LoadConfig;
+	dlvToolPath: string;
+	/** Delve Version */
+	apiVersion: number;
+	/** Delve maximum stack trace depth */
+	stackTraceDepth: number;
+
+	showGlobalVariables?: boolean;
+	packagePathToGoModPathMap: { [key: string]: string };
+}
+
+interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
+	request: 'attach';
+	processId?: number;
+	stopOnEntry?: boolean;
+	showLog?: boolean;
+	logOutput?: string;
+	cwd?: string;
+	mode?: 'local' | 'remote';
+	remotePath?: string;
+	port?: number;
+	host?: string;
+	trace?: 'verbose' | 'log' | 'error';
+	backend?: string;
+	/** Delve LoadConfig parameters */
+	dlvLoadConfig?: LoadConfig;
+	dlvToolPath: string;
+	/** Delve Version */
+	apiVersion: number;
+	/** Delve maximum stack trace depth */
+	stackTraceDepth: number;
+
+	showGlobalVariables?: boolean;
+}
+
+process.on('uncaughtException', (err: any) => {
+	const errMessage = err && (err.stack || err.message);
+	logger.error(`Unhandled error in debug adapter: ${errMessage}`);
+	throw err;
+});
+
+function logArgsToString(args: any[]): string {
+	return args
+		.map((arg) => {
+			return typeof arg === 'string' ? arg : JSON.stringify(arg);
+		})
+		.join(' ');
+}
+
+function log(...args: any[]) {
+	logger.warn(logArgsToString(args));
+}
+
+function logError(...args: any[]) {
+	logger.error(logArgsToString(args));
+}
+
+// GoDlvDapDebugSession implements a DAP debug adapter to talk to the editor.
+//
+// This adapter serves as a DAP proxy between the editor and the DAP server
+// inside Delve. It relies on functionality inherited from DebugSession to
+// implement the server side interfacing the editor, and on DapClient to
+// implement the client side interfacing Delve:
+//
+//      Editor                GoDlvDapDebugSession                 Delve
+//  +------------+        +--------------+-----------+         +------------+
+//  | DAP Client | <====> | DebugSession | DAPClient |  <====> | DAP Server |
+//  +------------+        +--------------+-----------+         +------------+
+export class GoDlvDapDebugSession extends LoggingDebugSession {
+	private readonly DEFAULT_DELVE_HOST = '127.0.0.1';
+	private readonly DEFAULT_DELVE_PORT = 42042;
+
+	private logLevel: Logger.LogLevel = Logger.LogLevel.Error;
+
+	private dlvClient: DelveClient = null;
+
+	// Child process used to track debugee launched without debugging (noDebug
+	// mode). Either debugProcess or dlvClient are null.
+	private debugProcess: ChildProcess = null;
+
+	public constructor() {
+		super();
+
+		// Invoke logger.init here because we want logging to work in 'inline'
+		// DA mode. It's typically called in the start() method of our parent
+		// class, but this method isn't called in 'inline' mode.
+		logger.init((e) => this.sendEvent(e));
+
+		// this debugger uses zero-based lines and columns
+		this.setDebuggerLinesStartAt1(false);
+		this.setDebuggerColumnsStartAt1(false);
+	}
+
+	protected initializeRequest(
+		response: DebugProtocol.InitializeResponse,
+		args: DebugProtocol.InitializeRequestArguments,
+		request?: DebugProtocol.Request
+	): void {
+		log('InitializeRequest');
+		response.body.supportsConfigurationDoneRequest = true;
+
+		// We respond to InitializeRequest here, because Delve hasn't been
+		// launched yet. Delve will start responding to DAP requests after
+		// LaunchRequest is received, which tell us how to start it.
+
+		// TODO: we could send an InitializeRequest to Delve when
+		// it launches, wait for its response and sanity check the capabilities
+		// it reports. Once DAP support in Delve is complete, this can be part
+		// of making sure that the "dlv" binary we find is sufficiently
+		// up-to-date to talk DAP with us.
+		this.sendResponse(response);
+		log('InitializeResponse');
+	}
+
+	protected launchRequest(
+		response: DebugProtocol.LaunchResponse,
+		args: LaunchRequestArguments,
+		request: DebugProtocol.Request
+	): void {
+		// Setup logger now that we have the 'trace' level passed in from
+		// LaunchRequestArguments.
+		this.logLevel =
+			args.trace === 'verbose'
+				? Logger.LogLevel.Verbose
+				: args.trace === 'log'
+					? Logger.LogLevel.Log
+					: Logger.LogLevel.Error;
+		const logPath =
+			this.logLevel !== Logger.LogLevel.Error ? path.join(os.tmpdir(), 'vscode-godlvdapdebug.txt') : undefined;
+		logger.setup(this.logLevel, logPath);
+		log('launchRequest');
+
+		// In noDebug mode with the 'debug' launch mode, we don't launch Delve
+		// but run the debugee directly.
+		// For other launch modes we currently still defer to Delve, for
+		// compatibility with the old debugAdapter.
+		// See https://github.com/golang/vscode-go/issues/336
+		if (args.noDebug && args.mode === 'debug') {
+			try {
+				this.launchNoDebug(args);
+			} catch (e) {
+				logError(`launchNoDebug failed: "${e}"`);
+				// TODO: define error constants
+				// https://github.com/golang/vscode-go/issues/305
+				this.sendErrorResponse(
+					response,
+					3000,
+					`Failed to launch "${e}"`);
+			}
+			return;
+		}
+
+		if (!args.port) {
+			args.port = this.DEFAULT_DELVE_PORT;
+		}
+		if (!args.host) {
+			args.host = this.DEFAULT_DELVE_HOST;
+		}
+
+		this.dlvClient = new DelveClient(args);
+
+		this.dlvClient.on('stdout', (str) => {
+			log('dlv stdout:', str);
+		});
+
+		this.dlvClient.on('stderr', (str) => {
+			log('dlv stderr:', str);
+		});
+
+		this.dlvClient.on('connected', () => {
+			// Once the client is connected to Delve, forward it the launch
+			// request to begin the actual debugging session.
+			this.dlvClient.send(request);
+		});
+
+		this.dlvClient.on('close', (rc) => {
+			if (rc !== 0) {
+				// TODO: define error constants
+				// https://github.com/golang/vscode-go/issues/305
+				this.sendErrorResponse(
+					response,
+					3000,
+					'Failed to continue: Check the debug console for details.');
+			}
+			log('Sending TerminatedEvent as delve is closed');
+			this.sendEvent(new TerminatedEvent());
+		});
+
+		// Relay events and responses back to vscode. In the future we will
+		// add middleware here to intercept specific kinds of responses/events
+		// for special handling.
+		this.dlvClient.on('event', (event) => {
+			this.sendEvent(event);
+		});
+
+		this.dlvClient.on('response', (resp) => {
+			this.sendResponse(resp);
+		});
+	}
+
+	protected attachRequest(
+		response: DebugProtocol.AttachResponse,
+		args: AttachRequestArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected disconnectRequest(
+		response: DebugProtocol.DisconnectResponse,
+		args: DebugProtocol.DisconnectArguments,
+		request?: DebugProtocol.Request
+	): void {
+		log('DisconnectRequest');
+		// How we handle DisconnectRequest depends on whether Delve was launched
+		// at all.
+		// * In noDebug node, the Go program was spawned directly without
+		//   debugging: this.debugProcess will be non-null, and this.dlvClient
+		//   will be null.
+		// * Otherwise, Delve was spawned: this.debugProcess will be null, and
+		//   this.dlvClient will be non-null.
+		if (this.debugProcess !== null) {
+			log(`killing debugee (pid: ${this.debugProcess.pid})...`);
+
+			// Kill the debugee and notify the client when the killing is
+			// completed, to ensure a clean shutdown sequence.
+			killProcessTree(this.debugProcess, log).then(() => {
+				super.disconnectRequest(response, args);
+				log('DisconnectResponse');
+			});
+		} else if (this.dlvClient !== null) {
+			// Forward this DisconnectRequest to Delve.
+			this.dlvClient.send(request);
+		} else {
+			logError(`both debug process and dlv client are null`);
+			// TODO: define all error codes as constants
+			// https://github.com/golang/vscode-go/issues/305
+			this.sendErrorResponse(
+				response,
+				3000,
+				'Failed to disconnect: Check the debug console for details.');
+		}
+	}
+
+	protected terminateRequest(
+		response: DebugProtocol.TerminateResponse,
+		args: DebugProtocol.TerminateArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected restartRequest(
+		response: DebugProtocol.RestartResponse,
+		args: DebugProtocol.RestartArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setBreakPointsRequest(
+		response: DebugProtocol.SetBreakpointsResponse,
+		args: DebugProtocol.SetBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setFunctionBreakPointsRequest(
+		response: DebugProtocol.SetFunctionBreakpointsResponse,
+		args: DebugProtocol.SetFunctionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setExceptionBreakPointsRequest(
+		response: DebugProtocol.SetExceptionBreakpointsResponse,
+		args: DebugProtocol.SetExceptionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected configurationDoneRequest(
+		response: DebugProtocol.ConfigurationDoneResponse,
+		args: DebugProtocol.ConfigurationDoneArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected continueRequest(
+		response: DebugProtocol.ContinueResponse,
+		args: DebugProtocol.ContinueArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected nextRequest(
+		response: DebugProtocol.NextResponse,
+		args: DebugProtocol.NextArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepInRequest(
+		response: DebugProtocol.StepInResponse,
+		args: DebugProtocol.StepInArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepOutRequest(
+		response: DebugProtocol.StepOutResponse,
+		args: DebugProtocol.StepOutArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepBackRequest(
+		response: DebugProtocol.StepBackResponse,
+		args: DebugProtocol.StepBackArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected reverseContinueRequest(
+		response: DebugProtocol.ReverseContinueResponse,
+		args: DebugProtocol.ReverseContinueArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected restartFrameRequest(
+		response: DebugProtocol.RestartFrameResponse,
+		args: DebugProtocol.RestartFrameArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected gotoRequest(
+		response: DebugProtocol.GotoResponse,
+		args: DebugProtocol.GotoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected pauseRequest(
+		response: DebugProtocol.PauseResponse,
+		args: DebugProtocol.PauseArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected sourceRequest(
+		response: DebugProtocol.SourceResponse,
+		args: DebugProtocol.SourceArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected threadsRequest(
+		response: DebugProtocol.ThreadsResponse,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected terminateThreadsRequest(
+		response: DebugProtocol.TerminateThreadsResponse,
+		args: DebugProtocol.TerminateThreadsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stackTraceRequest(
+		response: DebugProtocol.StackTraceResponse,
+		args: DebugProtocol.StackTraceArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected scopesRequest(
+		response: DebugProtocol.ScopesResponse,
+		args: DebugProtocol.ScopesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected variablesRequest(
+		response: DebugProtocol.VariablesResponse,
+		args: DebugProtocol.VariablesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setVariableRequest(
+		response: DebugProtocol.SetVariableResponse,
+		args: DebugProtocol.SetVariableArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setExpressionRequest(
+		response: DebugProtocol.SetExpressionResponse,
+		args: DebugProtocol.SetExpressionArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected evaluateRequest(
+		response: DebugProtocol.EvaluateResponse,
+		args: DebugProtocol.EvaluateArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepInTargetsRequest(
+		response: DebugProtocol.StepInTargetsResponse,
+		args: DebugProtocol.StepInTargetsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected gotoTargetsRequest(
+		response: DebugProtocol.GotoTargetsResponse,
+		args: DebugProtocol.GotoTargetsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected completionsRequest(
+		response: DebugProtocol.CompletionsResponse,
+		args: DebugProtocol.CompletionsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected exceptionInfoRequest(
+		response: DebugProtocol.ExceptionInfoResponse,
+		args: DebugProtocol.ExceptionInfoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected loadedSourcesRequest(
+		response: DebugProtocol.LoadedSourcesResponse,
+		args: DebugProtocol.LoadedSourcesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected dataBreakpointInfoRequest(
+		response: DebugProtocol.DataBreakpointInfoResponse,
+		args: DebugProtocol.DataBreakpointInfoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setDataBreakpointsRequest(
+		response: DebugProtocol.SetDataBreakpointsResponse,
+		args: DebugProtocol.SetDataBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected readMemoryRequest(
+		response: DebugProtocol.ReadMemoryResponse,
+		args: DebugProtocol.ReadMemoryArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected disassembleRequest(
+		response: DebugProtocol.DisassembleResponse,
+		args: DebugProtocol.DisassembleArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected cancelRequest(
+		response: DebugProtocol.CancelResponse,
+		args: DebugProtocol.CancelArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected breakpointLocationsRequest(
+		response: DebugProtocol.BreakpointLocationsResponse,
+		args: DebugProtocol.BreakpointLocationsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setInstructionBreakpointsRequest(
+		response: DebugProtocol.SetInstructionBreakpointsResponse,
+		args: DebugProtocol.SetInstructionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	// Launch the debugee process without starting a debugger.
+	// This implements the `Run > Run Without Debugger` functionality in vscode.
+	// Note: this method currently assumes launchArgs.mode === 'debug'.
+	private launchNoDebug(launchArgs: LaunchRequestArguments): void {
+		if (launchArgs.mode !== 'debug') {
+			throw new Error('launchNoDebug requires "debug" mode');
+		}
+		const {program, dirname, programIsDirectory} = parseProgramArgSync(launchArgs);
+		const goRunArgs = ['run'];
+		if (launchArgs.buildFlags) {
+			goRunArgs.push(launchArgs.buildFlags);
+		}
+
+		if (programIsDirectory) {
+			goRunArgs.push('.');
+		} else {
+			goRunArgs.push(program);
+		}
+
+		if (launchArgs.args) {
+			goRunArgs.push(...launchArgs.args);
+		}
+
+		// Read env from disk and merge into env variables.
+		const fileEnvs = [];
+		if (typeof launchArgs.envFile === 'string') {
+			fileEnvs.push(parseEnvFile(launchArgs.envFile));
+		}
+		if (Array.isArray(launchArgs.envFile)) {
+			launchArgs.envFile.forEach((envFile) => {
+				fileEnvs.push(parseEnvFile(envFile));
+			});
+		}
+
+		const launchArgsEnv = launchArgs.env || {};
+		const programEnv = Object.assign({}, process.env, ...fileEnvs, launchArgsEnv);
+
+		log(`Current working directory: ${dirname}`);
+		const goExe = getBinPathWithPreferredGopathGoroot('go', []);
+		log(`Running: ${goExe} ${goRunArgs.join(' ')}`);
+
+		this.debugProcess = spawn(goExe, goRunArgs, {
+			cwd: dirname,
+			env: programEnv
+		});
+		this.debugProcess.stderr.on('data', (str) => {
+			this.sendEvent(new OutputEvent(str.toString(), 'stderr'));
+		});
+		this.debugProcess.stdout.on('data', (str) => {
+			this.sendEvent(new OutputEvent(str.toString(), 'stdout'));
+		});
+		this.debugProcess.on('close', (rc) => {
+			this.sendEvent(new TerminatedEvent());
+		});
+	}
+}
+
+// DelveClient provides a DAP client to talk to a DAP server in Delve.
+//
+// After creation, it emits the following events:
+//
+//    'connected':            client is connected to delve
+//    'request (request)':    delve sent request
+//    'response (response)':  delve sent response
+//    'event (event)':        delve sent event
+//    'stdout' (str):         delve emitted str to stdout
+//    'stderr' (str):         delve emitted str to stderr
+//    'close' (rc):           delve exited with return code rc
+class DelveClient extends DAPClient {
+	private debugProcess: ChildProcess;
+	private serverStarted: boolean = false;
+
+	constructor(launchArgs: LaunchRequestArguments) {
+		super();
+
+		const launchArgsEnv = launchArgs.env || {};
+		const env = Object.assign({}, process.env, launchArgsEnv);
+
+		// Let users override direct path to delve by setting it in the env
+		// map in launch.json; if unspecified, fall back to dlvToolPath.
+		let dlvPath = launchArgsEnv['dlvPath'];
+		if (!dlvPath) {
+			dlvPath = launchArgs.dlvToolPath;
+		}
+
+		if (!fs.existsSync(dlvPath)) {
+			log(
+				`Couldn't find dlv at the Go tools path, ${process.env['GOPATH']}${
+				env['GOPATH'] ? ', ' + env['GOPATH'] : ''
+				} or ${envPath}`
+			);
+			throw new Error(
+				`Cannot find Delve debugger. Install from https://github.com/go-delve/delve/ & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
+			);
+		}
+
+		const dlvArgs = new Array<string>();
+		dlvArgs.push('dap');
+		dlvArgs.push(`--listen=${launchArgs.host}:${launchArgs.port}`);
+		if (launchArgs.showLog) {
+			dlvArgs.push('--log=' + launchArgs.showLog.toString());
+		}
+		if (launchArgs.logOutput) {
+			dlvArgs.push('--log-output=' + launchArgs.logOutput);
+		}
+
+		log(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);
+
+		this.debugProcess = spawn(dlvPath, dlvArgs, {
+			cwd: parseProgramArgSync(launchArgs).dirname,
+			env
+		});
+
+		this.debugProcess.stderr.on('data', (chunk) => {
+			const str = chunk.toString();
+			this.emit('stderr', str);
+		});
+
+		this.debugProcess.stdout.on('data', (chunk) => {
+			const str = chunk.toString();
+			this.emit('stdout', str);
+
+			if (!this.serverStarted) {
+				this.serverStarted = true;
+				this.connectSocketToServer(launchArgs.port, launchArgs.host);
+			}
+		});
+
+		this.debugProcess.on('close', (rc) => {
+			if (rc) {
+				logError(`Process exiting with code: ${rc} signal: ${this.debugProcess.killed}`);
+			} else {
+				log(`Process exiting normally ${this.debugProcess.killed}`);
+			}
+			this.emit('close', rc);
+		});
+
+		this.debugProcess.on('error', (err) => {
+			throw err;
+		});
+	}
+
+	// Connect this client to the server. The server is expected to be listening
+	// on host:port.
+	private connectSocketToServer(port: number, host: string) {
+		// Add a slight delay to ensure that Delve started up the server.
+		setTimeout(() => {
+			const socket = net.createConnection(
+				port,
+				host,
+				() => {
+					this.connect(socket, socket);
+					this.emit('connected');
+				});
+
+			socket.on('error', (err) => {
+				throw err;
+			});
+		}, 200);
+	}
+}
+
+// Helper function to parse a program from LaunchRequestArguments. Returns:
+// {
+//    program: the program arg,
+//    dirname: the directory containing the program (or 'program' itself if
+//             it's already a directory),
+//    programIsDirectory: is the program a directory?
+// }
+//
+// The program argument is taken as-is from launchArgs. If the program path
+// is relative, dirname will also be relative. If the program path is absolute,
+// dirname will also be absolute.
+//
+// Throws an exception in case args.program is not a valid file or directory.
+// This function can block because it calls a blocking fs function.
+function parseProgramArgSync(launchArgs: LaunchRequestArguments
+): { program: string, dirname: string, programIsDirectory: boolean } {
+	const program = launchArgs.program;
+	if (!program) {
+		throw new Error('The program attribute is missing in the debug configuration in launch.json');
+	}
+	let programIsDirectory = false;
+	try {
+		programIsDirectory = fs.lstatSync(program).isDirectory();
+	} catch (e) {
+		throw new Error('The program attribute must point to valid directory, .go file or executable.');
+	}
+	if (!programIsDirectory && path.extname(program) !== '.go') {
+		throw new Error('The program attribute must be a directory or .go file in debug mode');
+	}
+	const dirname = programIsDirectory ? program : path.dirname(program);
+	return {program, dirname, programIsDirectory};
+}
diff --git a/src/debugAdapter2/goDlvDebugMain.ts b/src/debugAdapter2/goDlvDebugMain.ts
new file mode 100644
index 0000000..2d4cdb8
--- /dev/null
+++ b/src/debugAdapter2/goDlvDebugMain.ts
@@ -0,0 +1,10 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+// This file is for running the godlvdap debug adapter as a standalone program
+// in a separate process (e.g. when working in --server mode).
+import { GoDlvDapDebugSession } from './goDlvDebug';
+
+GoDlvDapDebugSession.run(GoDlvDapDebugSession);
diff --git a/src/diffUtils.ts b/src/diffUtils.ts
index f001229..e0895a1 100644
--- a/src/diffUtils.ts
+++ b/src/diffUtils.ts
@@ -5,7 +5,7 @@
 
 import jsDiff = require('diff');
 import { Position, Range, TextEditorEdit, Uri, WorkspaceEdit } from 'vscode';
-import { getBinPathFromEnvVar } from './goPath';
+import { getBinPathFromEnvVar } from './utils/goPath';
 
 let diffToolAvailable: boolean | null = null;
 
diff --git a/src/goBrowsePackage.ts b/src/goBrowsePackage.ts
index f27b107..79097a3 100644
--- a/src/goBrowsePackage.ts
+++ b/src/goBrowsePackage.ts
@@ -9,8 +9,8 @@
 import path = require('path');
 import vscode = require('vscode');
 import { getAllPackages } from './goPackages';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 export function browsePackages() {
 	let workDir = '';
diff --git a/src/goBuild.ts b/src/goBuild.ts
index 0aaee96..a265e54 100644
--- a/src/goBuild.ts
+++ b/src/goBuild.ts
@@ -9,7 +9,6 @@
 import { buildDiagnosticCollection } from './goMain';
 import { isModSupported } from './goModules';
 import { getNonVendorPackages } from './goPackages';
-import { getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import { diagnosticsStatusBarItem, outputChannel } from './goStatus';
 import { getTestFlags } from './testUtils';
 import {
@@ -22,6 +21,8 @@
 	ICheckResult,
 	runTool
 } from './util';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+
 /**
  * Builds current package or workspace.
  */
diff --git a/src/goCover.ts b/src/goCover.ts
index 6ebda30..b1d3994 100644
--- a/src/goCover.ts
+++ b/src/goCover.ts
@@ -7,9 +7,9 @@
 
 import fs = require('fs');
 import path = require('path');
-import rl = require('readline');
 import vscode = require('vscode');
 import { isModSupported } from './goModules';
+import { getImportPathToFolder } from './goPackages';
 import { getTestFlags, goTest, showTestOutput, TestConfig } from './testUtils';
 import { getGoConfig } from './util';
 
@@ -29,6 +29,7 @@
 	coveredGutterStyle: string;
 	uncoveredGutterStyle: string;
 };
+
 // a list of modified, unsaved go files with actual code edits (rather than comment edits)
 let modifiedFiles: {
 	[key: string]: boolean;
@@ -93,6 +94,8 @@
 export function updateCodeCoverageDecorators(coverageDecoratorConfig: any) {
 	// These defaults are chosen to be distinguishable in nearly any color scheme (even Red)
 	// as well as by people who have difficulties with color perception.
+	// (how do these relate the defaults in package.json?)
+	// and where do the defaults actually come from? (raised as issue #256)
 	decoratorConfig = {
 		type: 'highlight',
 		coveredHighlightColor: 'rgba(64,128,128,0.5)',
@@ -151,14 +154,14 @@
 	coveredRange: vscode.Range[];
 }
 
-let coverageFiles: { [key: string]: CoverageData } = {};
+let coverageData: { [key: string]: CoverageData } = {};  // actual file path to the coverage data.
 let isCoverageApplied: boolean = false;
 
 /**
  * Clear the coverage on all files
  */
 function clearCoverage() {
-	coverageFiles = {};
+	coverageData = {};
 	disposeDecorators();
 	isCoverageApplied = false;
 }
@@ -167,48 +170,59 @@
  * Extract the coverage data from the given cover profile & apply them on the files in the open editors.
  * @param coverProfilePath Path to the file that has the cover profile data
  * @param packageDirPath Absolute path of the package for which the coverage was calculated
+ * @param testDir Directory to execute go list in, when there is no workspace, for some tests
  */
-export function applyCodeCoverageToAllEditors(coverProfilePath: string, packageDirPath: string): Promise<void> {
-	return new Promise((resolve, reject) => {
+export function applyCodeCoverageToAllEditors(coverProfilePath: string, testDir?: string): Promise<void> {
+	const v = new Promise<void>((resolve, reject) => {
 		try {
+			const coveragePath = new Map<string, CoverageData>();  // <filename> from the cover profile to the coverage data.
+
 			// Clear existing coverage files
 			clearCoverage();
 
-			const lines = rl.createInterface({
-				input: fs.createReadStream(coverProfilePath),
-				output: undefined
-			});
-
-			lines.on('line', (data: string) => {
+			// collect the packages named in the coverage file
+			const seenPaths = new Set<string>();
+			// for now read synchronously and hope for no errors
+			const contents = fs.readFileSync(coverProfilePath).toString();
+			contents.split('\n').forEach((line) => {
 				// go test coverageprofile generates output:
 				//    filename:StartLine.StartColumn,EndLine.EndColumn Hits CoverCount
-				// The first line will be "mode: set" which will be ignored
-				const fileRange = data.match(/([^:]+)\:([\d]+)\.([\d]+)\,([\d]+)\.([\d]+)\s([\d]+)\s([\d]+)/);
-				if (!fileRange) {
-					return;
+				// where the filename is either the import path + '/' + base file name, or
+				// the actual file path (either absolute or starting with .)
+				// See https://golang.org/issues/40251.
+				//
+				// The first line will be like "mode: set" which we will ignore.
+				const parse = line.match(/([^:]+)\:([\d]+)\.([\d]+)\,([\d]+)\.([\d]+)\s([\d]+)\s([\d]+)/);
+				if (!parse) { return; }
+				const lastSlash = parse[1].lastIndexOf('/');
+				if (lastSlash !== -1) {
+					seenPaths.add(parse[1].slice(0, lastSlash));
 				}
 
-				const filePath = path.join(packageDirPath, path.basename(fileRange[1]));
-				const coverage = getCoverageData(filePath);
+				// and fill in coveragePath
+				const coverage = coveragePath.get(parse[1]) || { coveredRange: [], uncoveredRange: [] };
 				const range = new vscode.Range(
 					// Start Line converted to zero based
-					parseInt(fileRange[2], 10) - 1,
+					parseInt(parse[2], 10) - 1,
 					// Start Column converted to zero based
-					parseInt(fileRange[3], 10) - 1,
+					parseInt(parse[3], 10) - 1,
 					// End Line converted to zero based
-					parseInt(fileRange[4], 10) - 1,
+					parseInt(parse[4], 10) - 1,
 					// End Column converted to zero based
-					parseInt(fileRange[5], 10) - 1
+					parseInt(parse[5], 10) - 1
 				);
 				// If is Covered (CoverCount > 0)
-				if (parseInt(fileRange[7], 10) > 0) {
+				if (parseInt(parse[7], 10) > 0) {
 					coverage.coveredRange.push(range);
 				} else {
 					coverage.uncoveredRange.push(range);
 				}
-				setCoverageData(filePath, coverage);
+				coveragePath.set(parse[1], coverage);
 			});
-			lines.on('close', () => {
+
+			getImportPathToFolder([...seenPaths], testDir)
+				.then((pathsToDirs) => {
+				createCoverageData(pathsToDirs, coveragePath);
 				setDecorators();
 				vscode.window.visibleTextEditors.forEach(applyCodeCoverage);
 				resolve();
@@ -218,23 +232,33 @@
 			reject(e);
 		}
 	});
+	return v;
 }
 
-/**
- * Get the object that holds the coverage data for given file path.
- * @param filePath
- */
-function getCoverageData(filePath: string): CoverageData {
-	if (filePath.startsWith('_')) {
-		filePath = filePath.substr(1);
-	}
-	if (process.platform === 'win32') {
-		const parts = filePath.split('/');
-		if (parts.length) {
-			filePath = parts.join(path.sep);
+function createCoverageData(
+	pathsToDirs: Map<string, string>,
+	coveragePath: Map<string, CoverageData>) {
+
+	coveragePath.forEach((cd, ip) => {
+		const lastSlash = ip.lastIndexOf('/');
+		if (lastSlash === -1) {  // malformed
+			console.log(`invalid entry: ${ip}`);
+			return;
 		}
-	}
-	return coverageFiles[filePath] || { coveredRange: [], uncoveredRange: [] };
+		const importPath = ip.slice(0, lastSlash);
+		let fileDir = importPath;
+		if (path.isAbsolute(importPath)) {
+			// This is the true file path.
+		} else if (importPath.startsWith('.')) {
+			fileDir = path.resolve(fileDir);
+		} else {
+			// This is the package import path.
+			// we need to look up `go list` output stored in pathsToDir.
+			fileDir = pathsToDirs.get(importPath) || importPath;
+		}
+		const file = fileDir + path.sep + ip.slice(lastSlash + 1);
+		setCoverageDataByFilePath(file, cd);
+	});
 }
 
 /**
@@ -242,7 +266,7 @@
  * @param filePath
  * @param data
  */
-function setCoverageData(filePath: string, data: CoverageData) {
+function setCoverageDataByFilePath(filePath: string, data: CoverageData) {
 	if (filePath.startsWith('_')) {
 		filePath = filePath.substr(1);
 	}
@@ -252,7 +276,7 @@
 			filePath = parts.join(path.sep);
 		}
 	}
-	coverageFiles[filePath] = data;
+	coverageData[filePath] = data;
 }
 
 /**
@@ -266,16 +290,16 @@
 
 	const cfg = getGoConfig(editor.document.uri);
 	const coverageOptions = cfg['coverageOptions'];
-	for (const filename in coverageFiles) {
+	for (const filename in coverageData) {
 		if (editor.document.uri.fsPath.endsWith(filename)) {
 			isCoverageApplied = true;
-			const coverageData = coverageFiles[filename];
+			const cd = coverageData[filename];
 			if (coverageOptions === 'showCoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
 				editor.setDecorations(
 					decorators.type === 'gutter'
 						? decorators.coveredGutterDecorator
 						: decorators.coveredHighlightDecorator,
-					coverageData.coveredRange
+					cd.coveredRange
 				);
 			}
 
@@ -284,7 +308,7 @@
 					decorators.type === 'gutter'
 						? decorators.uncoveredGutterDecorator
 						: decorators.uncoveredHighlightDecorator,
-					coverageData.uncoveredRange
+					cd.uncoveredRange
 				);
 			}
 		}
@@ -383,3 +407,27 @@
 		return idx > -1 && idx <= change.range.start.character;
 	});
 }
+
+// These routines enable testing without starting an editing session.
+
+export function coverageFilesForTest():  { [key: string]: CoverageData; } {
+	return coverageData;
+}
+
+export function initForTest() {
+	if (!decoratorConfig) {
+		// this code is unnecessary except for testing, where there may be no workspace
+		// nor the normal flow of initializations
+		const x = 'rgba(0,0,0,0)';
+		if (!gutterSvgs) {
+			gutterSvgs = { x };
+		}
+		decoratorConfig = {
+			type: 'highlight',
+			coveredHighlightColor: x,
+			uncoveredHighlightColor: x,
+			coveredGutterStyle: x,
+			uncoveredGutterStyle: x
+		};
+	}
+}
diff --git a/src/goDeclaration.ts b/src/goDeclaration.ts
index 7eb03ee..0d13500 100644
--- a/src/goDeclaration.ts
+++ b/src/goDeclaration.ts
@@ -20,9 +20,10 @@
 	getWorkspaceFolderPath,
 	goKeywords,
 	isPositionInString,
-	killTree,
 	runGodoc
 } from './util';
+import { getCurrentGoRoot } from './utils/goPath';
+import { killProcessTree } from './utils/processUtils';
 
 const missingToolMsg = 'Missing tool: ';
 
@@ -133,9 +134,10 @@
 	}
 	const offset = byteOffsetAt(input.document, input.position);
 	const env = toolExecutionEnvironment();
+	env['GOROOT'] = getCurrentGoRoot();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
@@ -226,7 +228,7 @@
 	const env = toolExecutionEnvironment();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
@@ -300,7 +302,7 @@
 	const env = toolExecutionEnvironment();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
 		p = cp.execFile(
diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
index dbb3d8a..c70757e 100644
--- a/src/goEnvironmentStatus.ts
+++ b/src/goEnvironmentStatus.ts
@@ -5,14 +5,37 @@
 
 'use strict';
 
+import cp = require('child_process');
+import fs = require('fs');
+import os = require('os');
+import path = require('path');
+import { promisify } from 'util';
 import vscode = require('vscode');
+import WebRequest = require('web-request');
+import { toolInstallationEnvironment } from './goEnv';
+import { outputChannel } from './goStatus';
+import { getFromWorkspaceState, updateWorkspaceState } from './stateUtils';
+import { getBinPath, getGoVersion, getTempFilePath, rmdirRecursive } from './util';
+import { correctBinname, getBinPathFromEnvVar, getCurrentGoRoot, pathExists } from './utils/goPath';
 
-import { updateGoVarsFromConfig } from './goInstallTools';
-import { getCurrentGoRoot } from './goPath';
-import { getGoVersion } from './util';
+export class GoEnvironmentOption {
+	public static fromQuickPickItem({ description, label }: vscode.QuickPickItem): GoEnvironmentOption {
+		return new GoEnvironmentOption(description, label);
+	}
+
+	constructor(public binpath: string, public label: string) {}
+
+	public toQuickPickItem(): vscode.QuickPickItem {
+		return {
+			label: this.label,
+			description: this.binpath,
+		};
+	}
+}
 
 // statusbar item for switching the Go environment
 let goEnvStatusbarItem: vscode.StatusBarItem;
+let terminalCreationListener: vscode.Disposable;
 
 /**
  * Initialize the status bar item with current Go binary
@@ -23,9 +46,10 @@
 	}
 	// set Go version and command
 	const version = await getGoVersion();
+	const goOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version.format()));
 
 	hideGoStatusBar();
-	goEnvStatusbarItem.text = formatGoVersion(version.format());
+	goEnvStatusbarItem.text = goOption.label;
 	goEnvStatusbarItem.command = 'go.environment.choose';
 	showGoStatusBar();
 }
@@ -37,6 +61,9 @@
 	if (!!goEnvStatusbarItem) {
 		goEnvStatusbarItem.dispose();
 	}
+	if (!!terminalCreationListener) {
+		terminalCreationListener.dispose();
+	}
 }
 
 /**
@@ -57,12 +84,280 @@
 	}
 }
 
+let environmentVariableCollection: vscode.EnvironmentVariableCollection;
+export function setEnvironmentVariableCollection(env: vscode.EnvironmentVariableCollection) {
+	environmentVariableCollection = env;
+}
+
 /**
  * Present a command palette menu to the user to select their go binary
- * TODO: remove temporary alert and implement correct functionality
  */
-export function chooseGoEnvironment() {
-	vscode.window.showInformationMessage(`Current GOROOT: ${getCurrentGoRoot()}`);
+export async function chooseGoEnvironment() {
+	if (!goEnvStatusbarItem) {
+		return;
+	}
+
+	// if there is no workspace, show GOROOT with message
+	if (!vscode.workspace.name) {
+		vscode.window.showInformationMessage(`GOROOT: ${getCurrentGoRoot()}. Switching Go version is not yet supported in single-file mode.`);
+		return;
+	}
+
+	// fetch default go and uninstalled go versions
+	let defaultOption: GoEnvironmentOption;
+	let uninstalledOptions: GoEnvironmentOption[];
+	let goSDKOptions: GoEnvironmentOption[];
+	try {
+		[defaultOption, uninstalledOptions, goSDKOptions] = await Promise.all([
+			getDefaultGoOption(),
+			fetchDownloadableGoVersions(),
+			getSDKGoOptions()
+		]);
+	} catch (e) {
+		vscode.window.showErrorMessage(e.message);
+		return;
+	}
+
+	// create quick pick items
+	const uninstalledQuickPicks = uninstalledOptions.map((op) => op.toQuickPickItem());
+	const defaultQuickPick = defaultOption.toQuickPickItem();
+	const goSDKQuickPicks = goSDKOptions.map((op) => op.toQuickPickItem());
+
+	// dedup options by eliminating duplicate paths (description)
+	const clearOption: vscode.QuickPickItem = { label: 'Clear selection' };
+	const options = [clearOption, defaultQuickPick, ...goSDKQuickPicks, ...uninstalledQuickPicks]
+		.reduce((opts, nextOption) => {
+			if (opts.find((op) => op.description === nextOption.description || op.label === nextOption.label)) {
+				return opts;
+			}
+			return [...opts, nextOption];
+		}, [] as vscode.QuickPickItem[]);
+
+	// get user's selection, return if none was made
+	const selection = await vscode.window.showQuickPick<vscode.QuickPickItem>(options);
+	if (!selection) {
+		return;
+	}
+
+	// update currently selected go
+	try {
+		const changed = await setSelectedGo(GoEnvironmentOption.fromQuickPickItem(selection));
+		if (changed) {
+			vscode.window.showInformationMessage(`Switched to ${selection.label}`);
+		}
+	} catch (e) {
+		vscode.window.showErrorMessage(e.message);
+	}
+}
+
+/**
+ * update the selected go path and label in the workspace state
+ */
+export async function setSelectedGo(goOption: GoEnvironmentOption, promptReload = true): Promise<boolean> {
+	if (!goOption) {
+		return false;
+	}
+
+	// if the selected go version is not installed, install it
+	if (goOption.binpath?.startsWith('go get')) {
+		// start a loading indicator
+		await downloadGo(goOption);
+	} else if (goOption.label === 'Clear selection') {
+		if (!getSelectedGo()) {
+			return false;  // do nothing.
+		}
+		await updateWorkspaceState('selectedGo', undefined);
+		// TODO: goEnvStatusbarItem?
+	} else {
+		// check that the given binary is not already at the beginning of the PATH
+		const go = await getGoVersion();
+		if (!!go && (go.binaryPath === goOption.binpath || 'Go ' + go.format() === goOption.label)) {
+			return false;
+		}
+		await updateWorkspaceState('selectedGo', goOption);
+	}
+	// prompt the user to reload the window.
+	// promptReload defaults to true and should only be false for tests.
+	if (promptReload) {
+		const choice = await vscode.window.showInformationMessage('Please reload the window to finish applying Go version changes.', 'Reload Window');
+		if (choice === 'Reload Window') {
+			await vscode.commands.executeCommand('workbench.action.reloadWindow');
+		}
+	}
+	goEnvStatusbarItem.text = 'Go: reload required';
+	goEnvStatusbarItem.command = 'workbench.action.reloadWindow';
+
+	return true;
+}
+
+// downloadGo downloads the specified go version available in dl.golang.org.
+async function downloadGo(goOption: GoEnvironmentOption) {
+	const execFile = promisify(cp.execFile);
+	await vscode.window.withProgress({
+		title: `Downloading ${goOption.label}`,
+		location: vscode.ProgressLocation.Notification,
+	}, async () => {
+		outputChannel.show();
+		outputChannel.clear();
+
+		outputChannel.appendLine('Finding Go executable for downloading');
+		const goExecutable = getBinPath('go');
+		if (!goExecutable) {
+			outputChannel.appendLine('Could not find Go executable.');
+			throw new Error('Could not find Go tool.');
+		}
+
+		// TODO(bcloud) dedup repeated logic below which comes from
+		// https://github.com/golang/vscode-go/blob/bc23fa854192d04200c8e4f74dca18d2c3021b46/src/goInstallTools.ts#L184
+		// Install tools in a temporary directory, to avoid altering go.mod files.
+		const mkdtemp = promisify(fs.mkdtemp);
+		const toolsTmpDir = await mkdtemp(getTempFilePath('go-tools-'));
+		let tmpGoModFile: string;
+
+		// Write a temporary go.mod file to avoid version conflicts.
+		tmpGoModFile = path.join(toolsTmpDir, 'go.mod');
+		const writeFile = promisify(fs.writeFile);
+		await writeFile(tmpGoModFile, 'module tools');
+
+		// use the current go executable to download the new version
+		const env = {
+			...toolInstallationEnvironment(),
+			GO111MODULE: 'on',
+		};
+		const [, ...args] = goOption.binpath.split(' ');
+		outputChannel.appendLine(`Running ${goExecutable} ${args.join(' ')}`);
+		try {
+			await execFile(goExecutable, args, {
+				env,
+				cwd: toolsTmpDir,
+			});
+		} catch (getErr) {
+			outputChannel.appendLine(`Error finding Go: ${getErr}`);
+			throw new Error('Could not find Go version.');
+		}
+
+		// run `goX.X download`
+		const newExecutableName = args[1].split('/')[2];
+		const goXExecutable = getBinPath(newExecutableName);
+		outputChannel.appendLine(`Running: ${goXExecutable} download`);
+		try {
+			await execFile(goXExecutable, ['download'], { env });
+		} catch (downloadErr) {
+			outputChannel.appendLine(`Error finishing installation: ${downloadErr}`);
+			throw new Error('Could not download Go version.');
+		}
+
+		outputChannel.appendLine('Finding newly downloaded Go');
+		const sdkPath = path.join(os.homedir(), 'sdk');
+		if (!await pathExists(sdkPath)) {
+			outputChannel.appendLine(`SDK path does not exist: ${sdkPath}`);
+			throw new Error(`SDK path does not exist: ${sdkPath}`);
+		}
+
+		const readdir = promisify(fs.readdir);
+		const subdirs = await readdir(sdkPath);
+		const dir = subdirs.find((subdir) => subdir === newExecutableName);
+		if (!dir) {
+			outputChannel.appendLine('Could not find newly downloaded Go');
+			throw new Error('Could not install Go version.');
+		}
+
+		const binpath = path.join(sdkPath, dir, 'bin', correctBinname('go'));
+		const newOption = new GoEnvironmentOption(binpath, goOption.label);
+		await updateWorkspaceState('selectedGo', newOption);
+
+		// remove tmp directories
+		outputChannel.appendLine('Cleaning up...');
+		rmdirRecursive(toolsTmpDir);
+		outputChannel.appendLine('Success!');
+	});
+}
+
+// PATH value cached before addGoRuntimeBaseToPath modified.
+let defaultPathEnv = '';
+
+// addGoRuntimeBaseToPATH adds the given path to the front of the PATH environment variable.
+// It removes duplicates.
+// TODO: can we avoid changing PATH but utilize toolExecutionEnv?
+export function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
+	if (!newGoRuntimeBase) {
+		return;
+	}
+
+	let pathEnvVar: string;
+	if (process.env.hasOwnProperty('PATH')) {
+		pathEnvVar = 'PATH';
+	} else if (process.platform === 'win32' && process.env.hasOwnProperty('Path')) {
+		pathEnvVar = 'Path';
+	} else {
+		return;
+	}
+
+	if (!defaultPathEnv) {  // cache the default value
+		defaultPathEnv = <string>process.env[pathEnvVar];
+	}
+
+	// calling this multiple times will override the previous value.
+	// environmentVariableCollection.clear();
+	if (process.platform !== 'darwin') {
+		environmentVariableCollection?.prepend(pathEnvVar, newGoRuntimeBase + path.delimiter);
+	} else if (!terminalCreationListener) {  // process.platform === 'darwin'
+		// We don't use EnvironmentVariableCollection on mac
+		// because this gets confusing for users. Instead we send the
+		// shell command to change the PATH env var,
+		// following the suggestion to workaround described in
+		// https://github.com/microsoft/vscode/issues/99878#issuecomment-642808852
+		const terminalShellArgs = <string[]>(
+			vscode.workspace.getConfiguration('terminal.integrated.shellArgs').get('osx') || []);
+		// User explicitly chose to run the login shell. So, don't mess with their config.
+		if (!terminalShellArgs.includes('-l') && !terminalShellArgs.includes('--login')) {
+			for (const term of vscode.window.terminals) {
+				updateIntegratedTerminal(term);
+			}
+			terminalCreationListener = vscode.window.onDidOpenTerminal(updateIntegratedTerminal);
+		}
+	}
+
+	let pathVars = defaultPathEnv.split(path.delimiter);
+	pathVars = pathVars.filter((p) => p !== newGoRuntimeBase);
+	pathVars.unshift(newGoRuntimeBase);
+	process.env[pathEnvVar] = pathVars.join(path.delimiter);
+}
+
+/**
+ * update the PATH variable in the given terminal to default to the currently selected Go
+ */
+export async function updateIntegratedTerminal(terminal: vscode.Terminal): Promise<void> {
+	if (!terminal) { return; }
+	const gorootBin = path.join(getCurrentGoRoot(), 'bin');
+	const defaultGoRuntimeBin = path.dirname(getBinPathFromEnvVar('go', defaultPathEnv, false));
+	if (gorootBin === defaultGoRuntimeBin) {
+		return;
+	}
+
+	// append the goroot to the beginning of the PATH so it takes precedence
+	// TODO: add support for more terminal names
+	// this assumes all non-windows shells are bash-like.
+	if (terminal.name.toLowerCase() === 'cmd') {
+		terminal.sendText(`set PATH=${gorootBin};%Path%`, true);
+		terminal.sendText('cls');
+	} else if (['powershell', 'pwsh'].includes(terminal.name.toLowerCase())) {
+		terminal.sendText(`$env:Path="${gorootBin};$env:Path"`, true);
+		terminal.sendText('clear');
+	} else if (terminal.name.toLowerCase() === 'fish') {
+		terminal.sendText(`set -gx PATH ${gorootBin} $PATH`);
+		terminal.sendText('clear');
+	} else if (['bash', 'sh', 'zsh', 'ksh'].includes(terminal.name.toLowerCase())) {
+		terminal.sendText(`export PATH=${gorootBin}:$PATH`, true);
+		terminal.sendText('clear');
+	}
+}
+
+/**
+ * retreive the current selected Go from the workspace state
+ */
+export function getSelectedGo(): GoEnvironmentOption {
+	return getFromWorkspaceState('selectedGo');
 }
 
 /**
@@ -72,16 +367,6 @@
 	return goEnvStatusbarItem;
 }
 
-export async function getActiveGoRoot(): Promise<string | undefined> {
-	// look for current current go binary
-	let goroot = getCurrentGoRoot();
-	if (!goroot) {
-		await updateGoVarsFromConfig();
-		goroot = getCurrentGoRoot();
-	}
-	return goroot || undefined;
-}
-
 export function formatGoVersion(version: string): string {
 	const versionWords = version.split(' ');
 	if (versionWords[0] === 'devel') {
@@ -95,3 +380,69 @@
 		return `Go ${versionWords[0]}`;
 	}
 }
+
+async function getSDKGoOptions(): Promise<GoEnvironmentOption[]> {
+	// get list of Go versions
+	const sdkPath = path.join(os.homedir(), 'sdk');
+
+	if (!await pathExists(sdkPath)) {
+		return [];
+	}
+	const readdir = promisify(fs.readdir);
+	const subdirs = await readdir(sdkPath);
+	// the dir happens to be the version, which will be used as the label
+	// the path is assembled and used as the description
+	return subdirs.map((dir: string) =>
+		new GoEnvironmentOption(
+			path.join(sdkPath, dir, 'bin', correctBinname('go')),
+			dir.replace('go', 'Go '),
+		)
+	);
+}
+
+export async function getDefaultGoOption(): Promise<GoEnvironmentOption> {
+	// make goroot default to go.goroot
+	const goroot = getCurrentGoRoot();
+	if (!goroot) {
+		throw new Error('No Go command could be found.');
+	}
+
+	// set Go version and command
+	const version = await getGoVersion();
+	return new GoEnvironmentOption(
+		path.join(goroot, 'bin', correctBinname('go')),
+		formatGoVersion(version.format()),
+	);
+}
+
+/**
+ * make a web request to get versions of Go
+ */
+interface GoVersionWebResult {
+	version: string;
+	stable: boolean;
+	files: {
+		filename: string;
+		os: string;
+		arch: string;
+		version: string;
+		sha256: string;
+		size: number;
+		kind: string;
+	}[];
+}
+async function fetchDownloadableGoVersions(): Promise<GoEnvironmentOption[]> {
+	// fetch information about what Go versions are available to install
+	const webResults = await WebRequest.json<GoVersionWebResult[]>('https://golang.org/dl/?mode=json');
+	if (!webResults) {
+		return [];
+	}
+
+	// turn the web result into GoEnvironmentOption model
+	return webResults.reduce((opts, result: GoVersionWebResult) => {
+		// TODO: allow downloading from different sites
+		const dlPath = `go get golang.org/dl/${result.version}`;
+		const label = result.version.replace('go', 'Go ');
+		return [...opts, new GoEnvironmentOption(dlPath, label)];
+	}, []);
+}
diff --git a/src/goFormat.ts b/src/goFormat.ts
index 6321e66..8ad78d7 100644
--- a/src/goFormat.ts
+++ b/src/goFormat.ts
@@ -10,7 +10,8 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { getBinPath, getGoConfig, killTree } from './util';
+import { getBinPath, getGoConfig } from './util';
+import { killProcessTree } from './utils/processUtils';
 
 export class GoDocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
 	public provideDocumentFormattingEdits(
@@ -78,7 +79,7 @@
 
 			// Use spawn instead of exec to avoid maxBufferExceeded error
 			const p = cp.spawn(formatCommandBinPath, formatFlags, { env, cwd });
-			token.onCancellationRequested(() => !p.killed && killTree(p.pid));
+			token.onCancellationRequested(() => !p.killed && killProcessTree(p));
 			p.stdout.setEncoding('utf8');
 			p.stdout.on('data', (data) => (stdout += data));
 			p.stderr.on('data', (data) => (stderr += data));
diff --git a/src/goGetPackage.ts b/src/goGetPackage.ts
index 272a995..bffefeb 100644
--- a/src/goGetPackage.ts
+++ b/src/goGetPackage.ts
@@ -8,9 +8,9 @@
 import cp = require('child_process');
 import vscode = require('vscode');
 import { buildCode } from './goBuild';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 export function goGetPackage() {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goImplementations.ts b/src/goImplementations.ts
index da39a51..05e44bc 100644
--- a/src/goImplementations.ts
+++ b/src/goImplementations.ts
@@ -10,15 +10,15 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool } from './goInstallTools';
-import { envPath, getCurrentGoRoot } from './goPath';
 import {
 	byteOffsetAt,
 	canonicalizeGOPATHPrefix,
 	getBinPath,
 	getGoConfig,
-	getWorkspaceFolderPath,
-	killTree,
+	getWorkspaceFolderPath
 } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
+import {killProcessTree} from './utils/processUtils';
 
 interface GoListOutput {
 	Dir: string;
@@ -130,10 +130,10 @@
 
 						return resolve(results);
 					});
-					token.onCancellationRequested(() => killTree(guruProcess.pid));
+					token.onCancellationRequested(() => killProcessTree(guruProcess));
 				}
 			);
-			token.onCancellationRequested(() => killTree(listProcess.pid));
+			token.onCancellationRequested(() => killProcessTree(listProcess));
 		});
 	}
 }
diff --git a/src/goImport.ts b/src/goImport.ts
index 5a9df7e..82fa2a9 100644
--- a/src/goImport.ts
+++ b/src/goImport.ts
@@ -11,8 +11,8 @@
 import { promptForMissingTool } from './goInstallTools';
 import { documentSymbols, GoOutlineImportsOptions } from './goOutline';
 import { getImportablePackages } from './goPackages';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { getBinPath, getImportPath, parseFilePrelude } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 const missingToolMsg = 'Missing tool: ';
 
diff --git a/src/goInstall.ts b/src/goInstall.ts
index 859da2a..d2131ac 100644
--- a/src/goInstall.ts
+++ b/src/goInstall.ts
@@ -8,9 +8,9 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { isModSupported } from './goModules';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getGoConfig, getModuleCache } from './util';
+import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 export async function installCurrentPackage(): Promise<void> {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 1781391..26ccb8b 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -12,10 +12,9 @@
 import util = require('util');
 import vscode = require('vscode');
 import { toolInstallationEnvironment } from './goEnv';
-import { initGoStatusBar } from './goEnvironmentStatus';
+import { addGoRuntimeBaseToPATH, initGoStatusBar } from './goEnvironmentStatus';
 import { getLanguageServerToolPath } from './goLanguageServer';
 import { restartLanguageServer } from './goMain';
-import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './goPath';
 import { hideGoStatus, outputChannel, showGoStatus } from './goStatus';
 import {
 	containsTool,
@@ -36,6 +35,7 @@
 	GoVersion,
 	rmdirRecursive,
 } from './util';
+import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './utils/goPath';
 
 // declinedUpdates tracks the tools that the user has declined to update.
 const declinedUpdates: Tool[] = [];
@@ -112,7 +112,8 @@
 	if (envForTools['GOBIN']) {
 		installingMsg += `the configured GOBIN: ${envForTools['GOBIN']}`;
 	} else {
-		installingMsg += `${toolsGopath}${path.sep}bin`;
+		const p = toolsGopath.split(path.delimiter).map((e) => path.join(e, 'bin')).join(path.delimiter);
+		installingMsg += `${p}`;
 	}
 
 	// If the user is on Go >= 1.11, tools should be installed with modules enabled.
@@ -176,7 +177,7 @@
 	envForTools: NodeJS.Dict<string>, modulesOn: boolean): Promise<string> {
 	// Some tools may have to be closed before we reinstall them.
 	if (tool.close) {
-		const reason = await tool.close();
+		const reason = await tool.close(envForTools);
 		if (reason) {
 			return reason;
 		}
@@ -235,10 +236,13 @@
 			if (!gopath) {
 				return `GOPATH not configured in environment`;
 			}
-			const outputFile = path.join(gopath, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
+			const destDir = gopath.split(path.delimiter)[0];
+			const outputFile = path.join(destDir, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
 			await execFile(goVersion.binaryPath, ['build', '-o', outputFile, importPath], opts);
 		}
-		outputChannel.appendLine(`Installing ${importPath} SUCCEEDED`);
+		const toolImportPath = tool.version ? importPath + '@' + tool.version : importPath;
+		const toolInstallPath = getBinPath(tool.name);
+		outputChannel.appendLine(`Installing ${toolImportPath} (${toolInstallPath}) SUCCEEDED`);
 	} catch (e) {
 		outputChannel.appendLine(`Installing ${importPath} FAILED`);
 		result = `failed to install ${tool}: ${e} ${output} `;
@@ -326,7 +330,7 @@
 		case 'Release Notes':
 			vscode.commands.executeCommand(
 				'vscode.open',
-				vscode.Uri.parse('https://github.com/golang/go/issues/33030#issuecomment-510151934')
+				vscode.Uri.parse(`https://github.com/golang/tools/releases/tag/${tool.name}/v${newVersion}`)
 			);
 			break;
 		default:
@@ -336,25 +340,16 @@
 }
 
 export function updateGoVarsFromConfig(): Promise<void> {
-	// FIXIT: when user changes the environment variable settings or go.gopath, the following
-	// condition prevents from updating the process.env accordingly, so the extension will lie.
-	// Needs to clean up.
-	if (process.env['GOPATH'] && process.env['GOPROXY'] && process.env['GOBIN']) {
-		return Promise.resolve();
-	}
-
 	// FIXIT: if updateGoVarsFromConfig is called again after addGoRuntimeBaseToPATH sets PATH,
 	// the go chosen by getBinPath based on PATH will not change.
 	const goRuntimePath = getBinPath('go', false);
 	if (!goRuntimePath) {
-		vscode.window.showErrorMessage(
-			`Failed to run "go env" to find GOPATH as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath})`
-		);
+		suggestDownloadGo();
 		return;
 	}
 
 	return new Promise<void>((resolve, reject) => {
-		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN'], (err, stdout, stderr) => {
+		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN', 'GOMODCACHE'], (err, stdout, stderr) => {
 			if (err) {
 				return reject();
 			}
@@ -371,6 +366,9 @@
 			if (!process.env['GOBIN'] && envOutput[3] && envOutput[3].trim()) {
 				process.env['GOBIN'] = envOutput[3].trim();
 			}
+			if (!process.env['GOMODCACHE']) {
+				process.env['GOMODCACHE'] = envOutput[4].trim();
+			}
 
 			// cgo, gopls, and other underlying tools will inherit the environment and attempt
 			// to locate 'go' from the PATH env var.
@@ -383,36 +381,6 @@
 	});
 }
 
-// PATH value cached before addGoRuntimeBaseToPath modified.
-let defaultPathEnv = '';
-
-// addGoRuntimeBaseToPATH adds the given path to the front of the PATH environment variable.
-// It removes duplicates.
-// TODO: can we avoid changing PATH but utilize toolExecutionEnv?
-function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
-	if (!newGoRuntimeBase) {
-		return;
-	}
-
-	let pathEnvVar: string;
-	if (process.env.hasOwnProperty('PATH')) {
-		pathEnvVar = 'PATH';
-	} else if (process.platform === 'win32' && process.env.hasOwnProperty('Path')) {
-		pathEnvVar = 'Path';
-	} else {
-		return;
-	}
-
-	if (!defaultPathEnv) {  // cache the default value
-		defaultPathEnv = <string>process.env[pathEnvVar];
-	}
-
-	let pathVars = defaultPathEnv.split(path.delimiter);
-	pathVars = pathVars.filter((p) => p !== newGoRuntimeBase);
-	pathVars.unshift(newGoRuntimeBase);
-	process.env[pathEnvVar] = pathVars.join(path.delimiter);
-}
-
 let alreadyOfferedToInstallTools = false;
 
 export async function offerToInstallTools() {
@@ -493,3 +461,24 @@
 		return res.filter((x) => x != null);
 	});
 }
+
+let suggestedDownloadGo = false;
+
+async function suggestDownloadGo() {
+	if (suggestedDownloadGo) {
+		vscode.window.showErrorMessage(
+			`Failed to find the "go" binary in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath}).`
+		);
+		return;
+	}
+
+	const choice = await vscode.window.showErrorMessage(
+		`Failed to find the "go" binary in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath}. ` +
+		`Check PATH, or Install Go and reload the window.`,
+		'Go to Download Page'
+	);
+	if (choice === 'Go to Download Page') {
+		vscode.env.openExternal(vscode.Uri.parse('https://golang.org/dl/'));
+	}
+	suggestedDownloadGo = true;
+}
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 03265ee..ff63aab 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -15,8 +15,16 @@
 import util = require('util');
 import vscode = require('vscode');
 import {
-	CloseAction, CompletionItemKind, ErrorAction, HandleDiagnosticsSignature, InitializeError,
-	LanguageClient, Message, ProvideCompletionItemsSignature, ProvideDocumentLinksSignature,
+	CloseAction,
+	CompletionItemKind,
+	ErrorAction,
+	ExecuteCommandSignature,
+	HandleDiagnosticsSignature,
+	InitializeError,
+	LanguageClient,
+	Message,
+	ProvideCompletionItemsSignature,
+	ProvideDocumentLinksSignature,
 	RevealOutputChannelOn,
 } from 'vscode-languageclient';
 import WebRequest = require('web-request');
@@ -32,7 +40,6 @@
 import { restartLanguageServer } from './goMain';
 import { GO_MODE } from './goMode';
 import { GoDocumentSymbolProvider } from './goOutline';
-import { getToolFromToolPath } from './goPath';
 import { GoReferenceProvider } from './goReferences';
 import { GoRenameProvider } from './goRename';
 import { GoSignatureHelpProvider } from './goSignature';
@@ -42,6 +49,7 @@
 import { GoTypeDefinitionProvider } from './goTypeDefinition';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
 import { getBinPath, getCurrentGoPath, getGoConfig } from './util';
+import { getToolFromToolPath } from './utils/goPath';
 
 interface LanguageServerConfig {
 	serverName: string;
@@ -75,31 +83,24 @@
 let restartCommand: vscode.Disposable;
 
 // When enabled, users may be prompted to fill out the gopls survey.
-const goplsSurveyOn: boolean = false;
+// For now, we turn it on in the Nightly extension to test it.
+const goplsSurveyOn: boolean = extensionId === 'golang.go-nightly';
+
+// lastUserAction is the time of the last user-triggered change.
+// A user-triggered change is a didOpen, didChange, didSave, or didClose event.
+let lastUserAction: Date = new Date();
 
 // startLanguageServerWithFallback starts the language server, if enabled,
 // or falls back to the default language providers.
 export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) {
 	const cfg = buildLanguageServerConfig();
 
-	// If the language server is gopls, we can check if the user needs to
-	// update their gopls version. We do this only once per VS Code
-	// activation to avoid inundating the user.
-	if (activation && cfg.enabled && cfg.serverName === 'gopls') {
+	// If the language server is gopls, we enable a few additional features.
+	// These include prompting for updates and surveys.
+	if (activation && cfg.serverName === 'gopls') {
 		const tool = getTool(cfg.serverName);
 		if (tool) {
-			const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg.path, cfg.checkForUpdates);
-			if (versionToUpdate) {
-				promptForUpdatingTool(tool.name, versionToUpdate);
-			} else if (goplsSurveyOn) {
-				// Only prompt users to fill out the gopls survey if we are not
-				// also prompting them to update (both would be too much).
-				const timeout = 1000 * 60 * 60; // 1 hour
-				setTimeout(async () => {
-					const surveyCfg = await maybePromptForGoplsSurvey();
-					flushSurveyConfig(surveyCfg);
-				}, timeout);
-			}
+			scheduleGoplsSuggestions(tool);
 		}
 	}
 
@@ -113,6 +114,40 @@
 	}
 }
 
+// scheduleGoplsSuggestions sets timeouts for the various gopls-specific
+// suggestions. We check user's gopls versions once per day to prompt users to
+// update to the latest version. We also check if we should prompt users to
+// fill out the survey.
+function scheduleGoplsSuggestions(tool: Tool) {
+	const update = async () => {
+		setTimeout(update, timeDay);
+
+		const cfg = buildLanguageServerConfig();
+		if (!cfg.enabled) {
+			return;
+		}
+		const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg);
+		if (versionToUpdate) {
+			promptForUpdatingTool(tool.name, versionToUpdate);
+		}
+	};
+	const survey = async () => {
+		setTimeout(survey, timeDay);
+
+		const cfg = buildLanguageServerConfig();
+		if (!goplsSurveyOn || !cfg.enabled) {
+			return;
+		}
+		const surveyCfg = await maybePromptForGoplsSurvey();
+		if (surveyCfg) {
+			flushSurveyConfig(surveyCfg);
+		}
+	};
+
+	setTimeout(update, 10 * timeMinute);
+	setTimeout(survey, 30 * timeMinute);
+}
+
 async function startLanguageServer(ctx: vscode.ExtensionContext, config: LanguageServerConfig): Promise<boolean> {
 	// If the client has already been started, make sure to clear existing
 	// diagnostics and stop it.
@@ -132,7 +167,7 @@
 		// Track the latest config used to start the language server,
 		// and rebuild the language client.
 		latestConfig = config;
-		languageClient = await buildLanguageClient(config);
+		languageClient = buildLanguageClient(config);
 		crashCount = 0;
 	}
 
@@ -162,7 +197,7 @@
 	return true;
 }
 
-async function buildLanguageClient(config: LanguageServerConfig): Promise<LanguageClient> {
+function buildLanguageClient(config: LanguageServerConfig): LanguageClient {
 	// Reuse the same output channel for each instance of the server.
 	if (config.enabled) {
 		if (!serverOutputChannel) {
@@ -223,6 +258,32 @@
 				},
 			},
 			middleware: {
+				provideCodeLenses: async (doc, token, next): Promise<vscode.CodeLens[]> => {
+					const codeLens = await next(doc, token);
+					return codeLens.map((lens: vscode.CodeLens) => {
+						switch (lens.command.title) {
+							case 'run test': {
+								const args = lens.command.arguments;
+								return new vscode.CodeLens(lens.range, {
+									...lens.command,
+									command: 'go.test.cursor',
+									arguments: [{ functionName: args[args.indexOf('run') + 1] }],
+								});
+							}
+							case 'run benchmark': {
+								const args = lens.command.arguments;
+								return new vscode.CodeLens(lens.range, {
+									...lens.command,
+									command: 'go.benchmark.cursor',
+									arguments: [{ functionName: args[args.indexOf('bench') + 1] }],
+								});
+							}
+							default: {
+								return lens;
+							}
+						}
+					});
+				},
 				handleDiagnostics: (
 					uri: vscode.Uri,
 					diagnostics: vscode.Diagnostic[],
@@ -301,7 +362,21 @@
 						}
 					}
 					return list;
-				}
+				},
+				// Keep track of the last file change in order to not prompt
+				// user if they are actively working.
+				didOpen: () => {
+					lastUserAction = new Date();
+				},
+				didChange: () => {
+					lastUserAction = new Date();
+				},
+				didClose: () => {
+					lastUserAction = new Date();
+				},
+				didSave: () => {
+					lastUserAction = new Date();
+				},
 			}
 		}
 	);
@@ -465,8 +540,7 @@
 
 export async function shouldUpdateLanguageServer(
 	tool: Tool,
-	languageServerToolPath: string,
-	makeProxyCall: boolean
+	cfg: LanguageServerConfig,
 ): Promise<semver.SemVer> {
 	// Only support updating gopls for now.
 	if (tool.name !== 'gopls') {
@@ -474,7 +548,9 @@
 	}
 
 	// First, run the "gopls version" command and parse its results.
-	const usersVersion = await getLocalGoplsVersion(languageServerToolPath);
+	// TODO(rstambler): Confirm that the gopls binary's modtime matches the
+	// modtime in the config. Update it if needed.
+	const usersVersion = await getLocalGoplsVersion(cfg);
 
 	// We might have a developer version. Don't make the user update.
 	if (usersVersion === '(devel)') {
@@ -482,7 +558,7 @@
 	}
 
 	// Get the latest gopls version. If it is for nightly, using the prereleased version is ok.
-	let latestVersion = makeProxyCall ? await getLatestGoplsVersion(tool) : tool.latestVersion;
+	let latestVersion = cfg.checkForUpdates ? await getLatestGoplsVersion(tool) : tool.latestVersion;
 
 	// If we failed to get the gopls version, pick the one we know to be latest at the time of this extension's last update
 	if (!latestVersion) {
@@ -501,7 +577,8 @@
 	const usersTime = parseTimestampFromPseudoversion(usersVersion);
 	// If the user has a pseudoversion, get the timestamp for the latest gopls version and compare.
 	if (usersTime) {
-		let latestTime = makeProxyCall ? await getTimestampForVersion(tool, latestVersion) : tool.latestVersionTimestamp;
+		let latestTime = cfg.checkForUpdates ?
+			await getTimestampForVersion(tool, latestVersion) : tool.latestVersionTimestamp;
 		if (!latestTime) {
 			latestTime = tool.latestVersionTimestamp;
 		}
@@ -510,7 +587,10 @@
 
 	// If the user's version does not contain a timestamp,
 	// default to a semver comparison of the two versions.
-	const usersVersionSemver = semver.coerce(usersVersion, { includePrerelease: true, loose: true });
+	const usersVersionSemver = semver.parse(usersVersion, {
+		includePrerelease: true,
+		loose: true,
+	});
 	return semver.lt(usersVersionSemver, latestVersion) ? latestVersion : null;
 }
 
@@ -601,11 +681,11 @@
 // getLocalGoplsVersion returns the version of gopls that is currently
 // installed on the user's machine. This is determined by running the
 // `gopls version` command.
-export const getLocalGoplsVersion = async (goplsPath: string) => {
+export const getLocalGoplsVersion = async (cfg: LanguageServerConfig) => {
 	const execFile = util.promisify(cp.execFile);
 	let output: any;
 	try {
-		const { stdout } = await execFile(goplsPath, ['version'], { env: toolExecutionEnvironment() });
+		const { stdout } = await execFile(cfg.path, ['version'], { env: toolExecutionEnvironment() });
 		output = stdout;
 	} catch (e) {
 		// The "gopls version" command is not supported, or something else went wrong.
@@ -677,6 +757,7 @@
 				throwResponseError: true
 			});
 		} catch (e) {
+			console.log(`Error sending request to ${proxy}: ${e}`);
 			return null;
 		}
 		return data;
@@ -696,9 +777,13 @@
 	// It is undefined if we have not yet made the determination.
 	promptThisMonth?: boolean;
 
-	// promptThisMonthTimestamp is the date on which we determined if the user
-	// should be prompted this month.
-	promptThisMonthTimestamp?: Date;
+	// dateToPromptThisMonth is the date on which we should prompt the user
+	// this month.
+	dateToPromptThisMonth?: Date;
+
+	// dateComputedPromptThisMonth is the date on which the values of
+	// promptThisMonth and dateToPromptThisMonth were set.
+	dateComputedPromptThisMonth?: Date;
 
 	// lastDatePrompted is the most recent date that the user has been prompted.
 	lastDatePrompted?: Date;
@@ -711,10 +796,81 @@
 async function maybePromptForGoplsSurvey(): Promise<SurveyConfig> {
 	const now = new Date();
 	const cfg = getSurveyConfig();
-	const prompt = shouldPromptForGoplsSurvey(now, cfg);
-	if (!prompt) {
+	const dateToPrompt = shouldPromptForGoplsSurvey(now, cfg);
+	if (!dateToPrompt) {
 		return cfg;
 	}
+	const callback = () => {
+		const currentTime = new Date();
+
+		// Make sure the user has been idle for at least a minute.
+		if (minutesBetween(lastUserAction, currentTime) < 1) {
+			setTimeout(callback, 5 * timeMinute);
+			return;
+		}
+		promptForSurvey(cfg, now);
+	};
+	const ms = msBetween(now, dateToPrompt);
+	setTimeout(callback, ms);
+	return cfg;
+}
+
+export function shouldPromptForGoplsSurvey(now: Date, cfg: SurveyConfig): Date {
+	// If the prompt value is not set, assume we haven't prompted the user
+	// and should do so.
+	if (cfg.prompt === undefined) {
+		cfg.prompt = true;
+	}
+	if (!cfg.prompt) {
+		return;
+	}
+
+	// Check if the user has taken the survey in the last year.
+	// Don't prompt them if they have been.
+	if (cfg.lastDateAccepted) {
+		if (daysBetween(now, cfg.lastDateAccepted) < 365) {
+			return;
+		}
+	}
+
+	// Check if the user has been prompted for the survey in the last 90 days.
+	// Don't prompt them if they have been.
+	if (cfg.lastDatePrompted) {
+		if (daysBetween(now, cfg.lastDatePrompted) < 90) {
+			return;
+		}
+	}
+
+	// Check if the extension has been activated this month.
+	if (cfg.dateComputedPromptThisMonth) {
+		// The extension has been activated this month, so we should have already
+		// decided if the user should be prompted.
+		if (daysBetween(now, cfg.dateComputedPromptThisMonth) < 30) {
+			if (cfg.dateToPromptThisMonth) {
+				return cfg.dateToPromptThisMonth;
+			}
+		}
+	}
+	// This is the first activation this month (or ever), so decide if we
+	// should prompt the user. This is done by generating a random number in
+	// the range [0, 1) and checking if it is < 0.05, for a 5% probability.
+	// We then randomly pick a day in the rest of the month on which to prompt
+	// the user.
+	cfg.promptThisMonth = Math.random() < 0.05;
+	if (cfg.promptThisMonth) {
+		// end is the last day of the month, day is the random day of the
+		// month on which to prompt.
+		const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
+		const day = randomIntInRange(now.getUTCDate(), end.getUTCDate());
+		cfg.dateToPromptThisMonth = new Date(now.getFullYear(), now.getMonth(), day);
+	} else {
+		cfg.dateToPromptThisMonth = undefined;
+	}
+	cfg.dateComputedPromptThisMonth = now;
+	return cfg.dateToPromptThisMonth;
+}
+
+async function promptForSurvey(cfg: SurveyConfig, now: Date) {
 	const selected = await vscode.window.showInformationMessage(`Looks like you're using gopls, the Go language server.
 Would you be willing to fill out a quick survey about your experience with gopls?`, 'Yes', 'Not now', 'Never');
 
@@ -726,8 +882,7 @@
 			cfg.lastDateAccepted = now;
 			cfg.prompt = true;
 
-			// Open the link to the survey.
-			vscode.env.openExternal(vscode.Uri.parse('https://www.whattimeisitrightnow.com/'));
+			await vscode.env.openExternal(vscode.Uri.parse(`https://google.qualtrics.com/jfe/form/SV_ekAdHVcVcvKUojX`));
 			break;
 		case 'Not now':
 			cfg.prompt = true;
@@ -739,52 +894,13 @@
 
 			vscode.window.showInformationMessage(`No problem! We won't ask again.`);
 			break;
-	}
-	return cfg;
-}
+		default:
+			// If the user closes the prompt without making a selection, treat it
+			// like a "Not now" response.
+			cfg.prompt = true;
 
-export function shouldPromptForGoplsSurvey(now: Date, cfg: SurveyConfig): boolean {
-	// If the prompt value is not set, assume we haven't prompted the user
-	// and should do so.
-	if (cfg.prompt === undefined) {
-		cfg.prompt = true;
+			break;
 	}
-	if (!cfg.prompt) {
-		return false;
-	}
-
-	// Check if the user has taken the survey in the last year.
-	// Don't prompt them if they have been.
-	if (cfg.lastDateAccepted) {
-		if (daysBetween(now, cfg.lastDateAccepted) < 365) {
-			return false;
-		}
-	}
-
-	// Check if the user has been prompted for the survey in the last 90 days.
-	// Don't prompt them if they have been.
-	if (cfg.lastDatePrompted) {
-		if (daysBetween(now, cfg.lastDatePrompted) < 90) {
-			return false;
-		}
-	}
-
-	// Check if the extension has been activated this month.
-	if (cfg.promptThisMonthTimestamp) {
-		// The extension has been activated this month, so we should have already
-		// decided if the user should be prompted.
-		if (daysBetween(now, cfg.promptThisMonthTimestamp) < 30) {
-			return cfg.promptThisMonth;
-		}
-	}
-	// This is the first activation this month (or ever), so decide if we
-	// should prompt the user. This is done by generating a random number
-	// and % 20 to get a 5% chance.
-	const r = Math.floor(Math.random() * 20);
-	cfg.promptThisMonth = (r % 20 === 0);
-	cfg.promptThisMonthTimestamp = now;
-
-	return cfg.promptThisMonth;
 }
 
 export const goplsSurveyConfig = 'goplsSurveyConfig';
@@ -797,7 +913,7 @@
 	try {
 		const cfg = JSON.parse(saved, (key: string, value: any) => {
 			// Make sure values that should be dates are correctly converted.
-			if (key.includes('Date')) {
+			if (key.toLowerCase().includes('date') || key.toLowerCase().includes('timestamp')) {
 				return new Date(value);
 			}
 			return value;
@@ -898,9 +1014,27 @@
 	}
 }
 
-// daysBetween returns the number of days between a and b,
-// assuming that a occurs after b.
-function daysBetween(a: Date, b: Date) {
-	const ms = a.getTime() - b.getTime();
-	return ms / (1000 * 60 * 60 * 24);
+// randomIntInRange returns a random integer between min and max, inclusive.
+function randomIntInRange(min: number, max: number): number {
+	const low = Math.ceil(min);
+	const high = Math.floor(max);
+	return Math.floor(Math.random() * (high - low + 1)) + low;
+}
+
+const timeMinute = 1000 * 60;
+const timeHour = timeMinute * 60;
+const timeDay = timeHour * 24;
+
+// daysBetween returns the number of days between a and b.
+function daysBetween(a: Date, b: Date): number {
+	return msBetween(a, b) / timeDay;
+}
+
+// minutesBetween returns the number of days between a and b.
+function minutesBetween(a: Date, b: Date): number {
+	return msBetween(a, b) / timeMinute;
+}
+
+function msBetween(a: Date, b: Date): number {
+	return Math.abs(a.getTime() - b.getTime());
 }
diff --git a/src/goLint.ts b/src/goLint.ts
index 2eb80ea..0e8abfb 100644
--- a/src/goLint.ts
+++ b/src/goLint.ts
@@ -125,6 +125,11 @@
 			// Explicit override in case .golangci.yml calls for a format we don't understand
 			args.push('--out-format=colored-line-number');
 		}
+		if (args.indexOf('--issues-exit-code=') === -1) {
+			// adds an explicit no-error-code return argument, to avoid npm error
+			// message detection logic. See golang/vscode-go/issues/411
+			args.push('--issues-exit-code=0');
+		}
 	}
 
 	if (scope === 'workspace' && currentWorkspace) {
diff --git a/src/goMain.ts b/src/goMain.ts
index aedb95f..4bc637d 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -8,6 +8,7 @@
 
 import * as path from 'path';
 import vscode = require('vscode');
+import { GoDlvDapDebugSession } from './debugAdapter2/goDlvDebug';
 import { browsePackages } from './goBrowsePackage';
 import { buildCode } from './goBuild';
 import { check, notifyIfGeneratedFile, removeTestStatus } from './goCheck';
@@ -18,7 +19,7 @@
 import { GoDebugConfigurationProvider } from './goDebugConfiguration';
 import { extractFunction, extractVariable } from './goDoctor';
 import { toolExecutionEnvironment } from './goEnv';
-import { chooseGoEnvironment } from './goEnvironmentStatus';
+import { chooseGoEnvironment, disposeGoStatusBar, setEnvironmentVariableCollection } from './goEnvironmentStatus';
 import { runFillStruct } from './goFillStruct';
 import * as goGenerateTests from './goGenerateTests';
 import { goGetPackage } from './goGetPackage';
@@ -34,7 +35,6 @@
 import { GO_MODE } from './goMode';
 import { addTags, removeTags } from './goModifytags';
 import { GO111MODULE, isModSupported } from './goModules';
-import { clearCacheForTools, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './goPath';
 import { playgroundCommand } from './goPlayground';
 import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
 import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
@@ -53,12 +53,14 @@
 	getCurrentGoPath,
 	getExtensionCommands,
 	getGoConfig,
+	getGoEnv,
 	getGoVersion,
 	getToolsGopath,
 	getWorkspaceFolderPath,
 	handleDiagnosticErrors,
-	isGoPathSet,
+	isGoPathSet
 } from './util';
+import { clearCacheForTools, envPath, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './utils/goPath';
 
 export let buildDiagnosticCollection: vscode.DiagnosticCollection;
 export let lintDiagnosticCollection: vscode.DiagnosticCollection;
@@ -69,81 +71,20 @@
 // the configuration of the server.
 export let restartLanguageServer = () => { return; };
 
-export function activate(ctx: vscode.ExtensionContext): void {
+export function activate(ctx: vscode.ExtensionContext) {
 	setGlobalState(ctx.globalState);
 	setWorkspaceState(ctx.workspaceState);
+	setEnvironmentVariableCollection(ctx.environmentVariableCollection);
+
 	const configGOROOT = getGoConfig()['goroot'];
 	if (!!configGOROOT) {
 		setCurrentGoRoot(configGOROOT);
 	}
 
 	updateGoVarsFromConfig().then(async () => {
-		const updateToolsCmdText = 'Update tools';
-		interface GoInfo {
-			goroot: string;
-			version: string;
-		}
-		const toolsGoInfo: { [id: string]: GoInfo } = ctx.globalState.get('toolsGoInfo') || {};
-		const toolsGopath = getToolsGopath() || getCurrentGoPath();
-		if (!toolsGoInfo[toolsGopath]) {
-			toolsGoInfo[toolsGopath] = { goroot: null, version: null };
-		}
-		const prevGoroot = toolsGoInfo[toolsGopath].goroot;
-		const currentGoroot: string = getCurrentGoRoot().toLowerCase();
-		if (prevGoroot && prevGoroot.toLowerCase() !== currentGoroot) {
-			vscode.window
-				.showInformationMessage(
-					`Your current goroot (${currentGoroot}) is different than before (${prevGoroot}), a few Go tools may need recompiling`,
-					updateToolsCmdText
-				)
-				.then((selected) => {
-					if (selected === updateToolsCmdText) {
-						installAllTools(true);
-					}
-				});
-		} else {
-			const currentVersion = await getGoVersion();
-			if (currentVersion) {
-				const prevVersion = toolsGoInfo[toolsGopath].version;
-				const currVersionString = currentVersion.format();
-
-				if (prevVersion !== currVersionString) {
-					if (prevVersion) {
-						vscode.window
-							.showInformationMessage(
-								'Your Go version is different than before, a few Go tools may need re-compiling',
-								updateToolsCmdText
-							)
-							.then((selected) => {
-								if (selected === updateToolsCmdText) {
-									installAllTools(true);
-								}
-							});
-					}
-					toolsGoInfo[toolsGopath].version = currVersionString;
-				}
-			}
-		}
-		toolsGoInfo[toolsGopath].goroot = currentGoroot;
-		ctx.globalState.update('toolsGoInfo', toolsGoInfo);
-
+		suggestUpdates(ctx);
 		offerToInstallTools();
-
-		// Subscribe to notifications for changes to the configuration
-		// of the language server, even if it's not currently in use.
-		ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration(
-			(e) => watchLanguageServerConfiguration(e)
-		));
-
-		// Set the function that is used to restart the language server.
-		// This is necessary, even if the language server is not currently
-		// in use.
-		restartLanguageServer = async () => {
-			startLanguageServerWithFallback(ctx, false);
-		};
-
-		// Start the language server, or fallback to the default language providers.
-		startLanguageServerWithFallback(ctx, true);
+		configureLanguageServer(ctx);
 
 		if (
 			vscode.window.activeTextEditor &&
@@ -151,6 +92,7 @@
 			isGoPathSet()
 		) {
 			// Check mod status so that cache is updated and then run build/lint/vet
+			// TODO(hyangah): skip if the language server is used (it will run build too)
 			isModSupported(vscode.window.activeTextEditor.document.uri).then(() => {
 				runBuilds(vscode.window.activeTextEditor.document, getGoConfig());
 			});
@@ -172,7 +114,20 @@
 
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, referencesCodeLensProvider));
-	ctx.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider()));
+
+	// debug
+	ctx.subscriptions.push(
+		vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider()));
+	ctx.subscriptions.push(
+		vscode.debug.registerDebugConfigurationProvider('godlvdap', new GoDebugConfigurationProvider()));
+
+	// Use an InlineDebugAdapterFactory to create a new debug adapter for
+	// the 'godlvdap' command in inline mode, without launching a subprocess.
+	const factory = new InlineDebugAdapterFactory();
+	ctx.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('godlvdap', factory));
+	if ('dispose' in factory) {
+		ctx.subscriptions.push(factory);
+	}
 
 	buildDiagnosticCollection = vscode.languages.createDiagnosticCollection('go');
 	ctx.subscriptions.push(buildDiagnosticCollection);
@@ -187,60 +142,13 @@
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.gopath', () => {
-			const gopath = getCurrentGoPath();
-			let msg = `${gopath} is the current GOPATH.`;
-			const wasInfered = getGoConfig()['inferGopath'];
-			const root = getWorkspaceFolderPath(
-				vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri
-			);
-
-			// not only if it was configured, but if it was successful.
-			if (wasInfered && root && root.indexOf(gopath) === 0) {
-				const inferredFrom = vscode.window.activeTextEditor ? 'current folder' : 'workspace root';
-				msg += ` It is inferred from ${inferredFrom}`;
-			}
-
-			vscode.window.showInformationMessage(msg);
-			return gopath;
-		})
-	);
+			getCurrentGoPathCommand();
+		}));
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.locate.tools', async () => {
-			outputChannel.show();
-			outputChannel.clear();
-			outputChannel.appendLine('Checking configured tools....');
-			// Tool's path search is done by getBinPathWithPreferredGopath
-			// which searches places in the following order
-			// 1) absolute path for the alternateTool
-			// 2) GOBIN
-			// 3) toolsGopath
-			// 4) gopath
-			// 5) GOROOT
-			// 6) PATH
-			outputChannel.appendLine('GOBIN: ' + process.env['GOBIN']);
-			outputChannel.appendLine('toolsGopath: ' + getToolsGopath());
-			outputChannel.appendLine('gopath: ' + getCurrentGoPath());
-			outputChannel.appendLine('GOROOT: ' + getCurrentGoRoot());
-			outputChannel.appendLine('PATH: ' + process.env['PATH']);
-			outputChannel.appendLine('');
-
-			const goVersion = await getGoVersion();
-			const allTools = getConfiguredTools(goVersion);
-
-			allTools.forEach((tool) => {
-				const toolPath = getBinPath(tool.name);
-				// TODO(hyangah): print alternate tool info if set.
-				let msg = 'not installed';
-				if (path.isAbsolute(toolPath)) {
-					// getBinPath returns the absolute path is the tool exists.
-					// (See getBinPathWithPreferredGopath which is called underneath)
-					msg = 'installed';
-				}
-				outputChannel.appendLine(`   ${tool.name}: ${toolPath} ${msg}`);
-			});
-		})
-	);
+			getConfiguredGoToolsCommand();
+		}));
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.add.tags', (args) => {
@@ -292,6 +200,10 @@
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.debug.cursor', (args) => {
+			if (vscode.debug.activeDebugSession) {
+				vscode.window.showErrorMessage('Debug session has already been started.');
+				return;
+			}
 			const goConfig = getGoConfig();
 			testAtCursor(goConfig, 'debug', args);
 		})
@@ -408,7 +320,7 @@
 				e.affectsConfiguration('go.gopath') ||
 				e.affectsConfiguration('go.toolsEnvVars') ||
 				e.affectsConfiguration('go.testEnvFile')) {
-					updateGoVarsFromConfig();
+				updateGoVarsFromConfig();
 			}
 			// If there was a change in "toolsGopath" setting, then clear cache for go tools
 			if (getToolsGopath() !== getToolsGopath(false)) {
@@ -555,8 +467,7 @@
 						updateWorkspaceState(lastCoverProfilePathKey, coverProfilePath);
 					}
 					applyCodeCoverageToAllEditors(
-						coverProfilePath,
-						path.dirname(vscode.window.activeTextEditor.document.fileName)
+						coverProfilePath
 					);
 				});
 		})
@@ -575,7 +486,10 @@
 }
 
 export function deactivate() {
-	return Promise.all([cancelRunningTests(), Promise.resolve(cleanupTempDir())]);
+	return Promise.all([
+		cancelRunningTests(),
+		Promise.resolve(cleanupTempDir()),
+		Promise.resolve(disposeGoStatusBar())]);
 }
 
 function runBuilds(document: vscode.TextDocument, goConfig: vscode.WorkspaceConfiguration) {
@@ -646,3 +560,154 @@
 		promptForMissingTool(tool);
 	}
 }
+
+class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
+	public createDebugAdapterDescriptor(session: vscode.DebugSession
+	): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
+		return new vscode.DebugAdapterInlineImplementation(new GoDlvDapDebugSession());
+	}
+}
+
+async function suggestUpdates(ctx: vscode.ExtensionContext) {
+	const updateToolsCmdText = 'Update tools';
+	interface GoInfo {
+		goroot: string;
+		version: string;
+	}
+	const toolsGoInfo: { [id: string]: GoInfo } = ctx.globalState.get('toolsGoInfo') || {};
+	const toolsGopath = getToolsGopath() || getCurrentGoPath();
+	if (!toolsGoInfo[toolsGopath]) {
+		toolsGoInfo[toolsGopath] = { goroot: null, version: null };
+	}
+	const prevGoroot = toolsGoInfo[toolsGopath].goroot;
+	const currentGoroot: string = getCurrentGoRoot().toLowerCase();
+	if (prevGoroot && prevGoroot.toLowerCase() !== currentGoroot) {
+		vscode.window
+			.showInformationMessage(
+				`Your current goroot (${currentGoroot}) is different than before (${prevGoroot}), a few Go tools may need recompiling`,
+				updateToolsCmdText
+			)
+			.then((selected) => {
+				if (selected === updateToolsCmdText) {
+					installAllTools(true);
+				}
+			});
+	} else {
+		const currentVersion = await getGoVersion();
+		if (currentVersion) {
+			const prevVersion = toolsGoInfo[toolsGopath].version;
+			const currVersionString = currentVersion.format();
+
+			if (prevVersion !== currVersionString) {
+				if (prevVersion) {
+					vscode.window
+						.showInformationMessage(
+							'Your Go version is different than before, a few Go tools may need re-compiling',
+							updateToolsCmdText
+						)
+						.then((selected) => {
+							if (selected === updateToolsCmdText) {
+								installAllTools(true);
+							}
+						});
+				}
+				toolsGoInfo[toolsGopath].version = currVersionString;
+			}
+		}
+	}
+	toolsGoInfo[toolsGopath].goroot = currentGoroot;
+	ctx.globalState.update('toolsGoInfo', toolsGoInfo);
+}
+
+function configureLanguageServer(ctx: vscode.ExtensionContext) {
+	// Subscribe to notifications for changes to the configuration
+	// of the language server, even if it's not currently in use.
+	ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration(
+		(e) => watchLanguageServerConfiguration(e)
+	));
+
+	// Set the function that is used to restart the language server.
+	// This is necessary, even if the language server is not currently
+	// in use.
+	restartLanguageServer = async () => {
+		startLanguageServerWithFallback(ctx, false);
+	};
+
+	// Start the language server, or fallback to the default language providers.
+	startLanguageServerWithFallback(ctx, true);
+
+}
+
+function getCurrentGoPathCommand() {
+	const gopath = getCurrentGoPath();
+	let msg = `${gopath} is the current GOPATH.`;
+	const wasInfered = getGoConfig()['inferGopath'];
+	const root = getWorkspaceFolderPath(
+		vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri
+	);
+
+	// not only if it was configured, but if it was successful.
+	if (wasInfered && root && root.indexOf(gopath) === 0) {
+		const inferredFrom = vscode.window.activeTextEditor ? 'current folder' : 'workspace root';
+		msg += ` It is inferred from ${inferredFrom}`;
+	}
+
+	vscode.window.showInformationMessage(msg);
+	return gopath;
+}
+
+async function getConfiguredGoToolsCommand() {
+	outputChannel.show();
+	outputChannel.clear();
+	outputChannel.appendLine('Checking configured tools....');
+	// Tool's path search is done by getBinPathWithPreferredGopath
+	// which searches places in the following order
+	// 1) absolute path for the alternateTool
+	// 2) GOBIN
+	// 3) toolsGopath
+	// 4) gopath
+	// 5) GOROOT
+	// 6) PATH
+	outputChannel.appendLine('GOBIN: ' + process.env['GOBIN']);
+	outputChannel.appendLine('toolsGopath: ' + getToolsGopath());
+	outputChannel.appendLine('gopath: ' + getCurrentGoPath());
+	outputChannel.appendLine('GOROOT: ' + getCurrentGoRoot());
+	outputChannel.appendLine('PATH: ' + process.env['PATH']);
+	outputChannel.appendLine('');
+
+	const goVersion = await getGoVersion();
+	const allTools = getConfiguredTools(goVersion);
+
+	allTools.forEach((tool) => {
+		const toolPath = getBinPath(tool.name);
+		// TODO(hyangah): print alternate tool info if set.
+		let msg = 'not installed';
+		if (path.isAbsolute(toolPath)) {
+			// getBinPath returns the absolute path is the tool exists.
+			// (See getBinPathWithPreferredGopath which is called underneath)
+			msg = 'installed';
+		}
+		outputChannel.appendLine(`   ${tool.name}: ${toolPath} ${msg}`);
+	});
+
+	let folders = vscode.workspace.workspaceFolders?.map((folder) => {
+		return { name: folder.name, path: folder.uri.fsPath };
+	});
+	if (!folders) {
+		folders = [{ name: 'no folder', path: undefined }];
+	}
+
+	outputChannel.appendLine('');
+	outputChannel.appendLine('go env');
+	for (const folder of folders) {
+		outputChannel.appendLine(`Workspace Folder (${folder.name}): ${folder.path}`);
+		try {
+			const out = await getGoEnv(folder.path);
+			// Append '\t' to the beginning of every line (^) of 'out'.
+			// 'g' = 'global matching', and 'm' = 'multi-line matching'
+			outputChannel.appendLine(out.replace(/^/gm, '\t'));
+		} catch (e) {
+			outputChannel.appendLine(`failed to run 'go env': ${e}`);
+		}
+	}
+}
diff --git a/src/goModules.ts b/src/goModules.ts
index 2a41455..82077ed 100644
--- a/src/goModules.ts
+++ b/src/goModules.ts
@@ -8,10 +8,10 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { installTools } from './goInstallTools';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './goPath';
 import { getTool } from './goTools';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
 import { getBinPath, getGoConfig, getGoVersion, getModuleCache } from './util';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './utils/goPath';
 
 export let GO111MODULE: string;
 
@@ -37,14 +37,14 @@
 	});
 }
 
-export function isModSupported(fileuri: vscode.Uri): Promise<boolean> {
-	return getModFolderPath(fileuri).then((modPath) => !!modPath);
+export function isModSupported(fileuri: vscode.Uri, isDir?: boolean): Promise<boolean> {
+	return getModFolderPath(fileuri, isDir).then((modPath) => !!modPath);
 }
 
 export const packagePathToGoModPathMap: { [key: string]: string } = {};
 
-export async function getModFolderPath(fileuri: vscode.Uri): Promise<string> {
-	const pkgPath = path.dirname(fileuri.fsPath);
+export async function getModFolderPath(fileuri: vscode.Uri, isDir?: boolean): Promise<string> {
+	const pkgPath = isDir ? fileuri.fsPath : path.dirname(fileuri.fsPath);
 	if (packagePathToGoModPathMap[pkgPath]) {
 		return packagePathToGoModPathMap[pkgPath];
 	}
@@ -62,7 +62,6 @@
 
 	let goModEnvResult = await runGoModEnv(pkgPath);
 	if (goModEnvResult) {
-		logModuleUsage();
 		goModEnvResult = path.dirname(goModEnvResult);
 		const goConfig = getGoConfig(fileuri);
 
@@ -73,32 +72,23 @@
 			);
 		}
 
-		// TODO(rstambler): This will offer multiple prompts to the user, but
-		// it's still better than waiting for user input. Ideally, this should
-		// be combined into one prompt.
 		if (goConfig['useLanguageServer'] === false) {
 			const promptMsg =
 				'For better performance using Go modules, you can try the experimental Go language server, gopls.';
-			promptToUpdateToolForModules('gopls', promptMsg, goConfig);
-
-			if (goConfig['formatTool'] === 'goreturns') {
-				const promptMsgForFormatTool = `The goreturns tool does not support Go modules. Please update the "formatTool" setting to goimports.`;
-				promptToUpdateToolForModules('switchFormatToolToGoimports', promptMsgForFormatTool, goConfig);
-			}
+			promptToUpdateToolForModules('gopls', promptMsg, goConfig)
+			.then((choseToUpdate) => {
+				if (choseToUpdate || goConfig['formatTool'] !== 'goreturns') {
+					return;
+				}
+				const promptFormatToolMsg = `The goreturns tool does not support Go modules. Please update the "formatTool" setting to "goimports".`;
+				promptToUpdateToolForModules('switchFormatToolToGoimports', promptFormatToolMsg, goConfig);
+			});
 		}
 	}
 	packagePathToGoModPathMap[pkgPath] = goModEnvResult;
 	return goModEnvResult;
 }
 
-let moduleUsageLogged = false;
-function logModuleUsage() {
-	if (moduleUsageLogged) {
-		return;
-	}
-	moduleUsageLogged = true;
-}
-
 const promptedToolsForCurrentSession = new Set<string>();
 export async function promptToUpdateToolForModules(
 	tool: string,
diff --git a/src/goOutline.ts b/src/goOutline.ts
index 97af953..9e52f6d 100644
--- a/src/goOutline.ts
+++ b/src/goOutline.ts
@@ -13,9 +13,9 @@
 	getBinPath,
 	getFileArchive,
 	getGoConfig,
-	killProcess,
 	makeMemoizedByteOffsetConverter
 } from './util';
+import {killProcess} from './utils/processUtils';
 
 // Keep in sync with https://github.com/ramya-rao-a/go-outline
 export interface GoOutlineRange {
diff --git a/src/goPackages.ts b/src/goPackages.ts
index 5c7fce7..20eefef 100644
--- a/src/goPackages.ts
+++ b/src/goPackages.ts
@@ -8,8 +8,8 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import { getBinPath, getCurrentGoPath, getGoVersion, isVendorSupported } from './util';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 type GopkgsDone = (res: Map<string, PackageInfo>) => void;
 interface Cache {
@@ -258,7 +258,14 @@
 /**
  * Returns mapping between import paths and folder paths for all packages under given folder (vendor will be excluded)
  */
-export function getNonVendorPackages(currentFolderPath: string): Promise<Map<string, string>> {
+export function getNonVendorPackages(
+	currentFolderPath: string, recursive: boolean = true): Promise<Map<string, string>> {
+
+	const target = recursive ? './...' : '.';  // go list ./... excludes vendor dirs since 1.9
+	return getImportPathToFolder([target], currentFolderPath);
+}
+
+export function getImportPathToFolder(targets: string[], cwd?: string): Promise<Map<string, string>> {
 	const goRuntimePath = getBinPath('go');
 	if (!goRuntimePath) {
 		console.warn(
@@ -266,11 +273,12 @@
 		);
 		return;
 	}
+
 	return new Promise<Map<string, string>>((resolve, reject) => {
 		const childProcess = cp.spawn(
 			goRuntimePath,
-			['list', '-f', 'ImportPath: {{.ImportPath}} FolderPath: {{.Dir}}', './...'],
-			{ cwd: currentFolderPath, env: toolExecutionEnvironment() }
+			['list', '-f', 'ImportPath: {{.ImportPath}} FolderPath: {{.Dir}}', ...targets],
+			{ cwd, env: toolExecutionEnvironment() }
 		);
 		const chunks: any[] = [];
 		childProcess.stdout.on('data', (stdout) => {
@@ -281,16 +289,13 @@
 			const lines = chunks.join('').toString().split('\n');
 			const result = new Map<string, string>();
 
-			const version = await getGoVersion();
-			const vendorAlreadyExcluded = version.gt('1.8');
-
 			lines.forEach((line) => {
 				const matches = line.match(pkgToFolderMappingRegex);
 				if (!matches || matches.length !== 3) {
 					return;
 				}
 				const [_, pkgPath, folderPath] = matches;
-				if (!pkgPath || (!vendorAlreadyExcluded && pkgPath.includes('/vendor/'))) {
+				if (!pkgPath) {
 					return;
 				}
 				result.set(pkgPath, folderPath);
diff --git a/src/goReferences.ts b/src/goReferences.ts
index 44a86fc..1aba8d9 100644
--- a/src/goReferences.ts
+++ b/src/goReferences.ts
@@ -15,9 +15,9 @@
 	canonicalizeGOPATHPrefix,
 	getBinPath,
 	getFileArchive,
-	getGoConfig,
-	killTree
+	getGoConfig
 } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 export class GoReferenceProvider implements vscode.ReferenceProvider {
 	public provideReferences(
@@ -102,7 +102,7 @@
 			if (process.pid) {
 				process.stdin.end(getFileArchive(document));
 			}
-			token.onCancellationRequested(() => killTree(process.pid));
+			token.onCancellationRequested(() => killProcessTree(process));
 		});
 	}
 }
diff --git a/src/goRename.ts b/src/goRename.ts
index 55a97f7..ff71aa3 100644
--- a/src/goRename.ts
+++ b/src/goRename.ts
@@ -11,7 +11,8 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool } from './goInstallTools';
 import { outputChannel } from './goStatus';
-import { byteOffsetAt, canonicalizeGOPATHPrefix, getBinPath, getGoConfig, killTree } from './util';
+import { byteOffsetAt, canonicalizeGOPATHPrefix, getBinPath, getGoConfig } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 export class GoRenameProvider implements vscode.RenameProvider {
 	public provideRenameEdits(
@@ -50,7 +51,7 @@
 
 			let p: cp.ChildProcess;
 			if (token) {
-				token.onCancellationRequested(() => killTree(p.pid));
+				token.onCancellationRequested(() => killProcessTree(p));
 			}
 
 			p = cp.execFile(gorename, gorenameArgs, { env }, (err, stdout, stderr) => {
diff --git a/src/goSuggest.ts b/src/goSuggest.ts
index e676ca0..80f3278 100644
--- a/src/goSuggest.ts
+++ b/src/goSuggest.ts
@@ -13,7 +13,6 @@
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
 import { isModSupported } from './goModules';
 import { getImportablePackages, PackageInfo } from './goPackages';
-import { getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import {
 	byteOffsetAt,
 	getBinPath,
@@ -28,6 +27,7 @@
 	parseFilePrelude,
 	runGodoc
 } from './util';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 function vscodeKindFromGoCodeClass(kind: string, type: string): vscode.CompletionItemKind {
 	switch (kind) {
diff --git a/src/goSymbol.ts b/src/goSymbol.ts
index b97e018..9c3bb15 100644
--- a/src/goSymbol.ts
+++ b/src/goSymbol.ts
@@ -9,8 +9,9 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { getCurrentGoRoot } from './goPath';
-import { getBinPath, getGoConfig, getWorkspaceFolderPath, killTree } from './util';
+import { getBinPath, getGoConfig, getWorkspaceFolderPath} from './util';
+import { getCurrentGoRoot } from './utils/goPath';
+import {killProcessTree} from './utils/processUtils';
 
 // Keep in sync with github.com/acroca/go-symbols'
 interface GoSymbolDeclaration {
@@ -118,7 +119,7 @@
 	let p: cp.ChildProcess;
 
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise((resolve, reject) => {
diff --git a/src/goTest.ts b/src/goTest.ts
index b25c78a..5b1576d 100644
--- a/src/goTest.ts
+++ b/src/goTest.ts
@@ -241,11 +241,13 @@
 		vscode.window.showInformationMessage('No workspace is open to run tests.');
 		return;
 	}
+	let workspaceUriIsDir = true;
 	let workspaceUri = vscode.workspace.workspaceFolders[0].uri;
 	if (
 		vscode.window.activeTextEditor &&
 		vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri)
 	) {
+		workspaceUriIsDir = false;
 		workspaceUri = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri).uri;
 	}
 
@@ -258,7 +260,7 @@
 	// Remember this config as the last executed test.
 	lastTestConfig = testConfig;
 
-	isModSupported(workspaceUri).then((isMod) => {
+	isModSupported(workspaceUri, workspaceUriIsDir).then((isMod) => {
 		testConfig.isMod = isMod;
 		goTest(testConfig).then(null, (err) => {
 			console.error(err);
diff --git a/src/goTools.ts b/src/goTools.ts
index 91d72dc..0153fe3 100644
--- a/src/goTools.ts
+++ b/src/goTools.ts
@@ -36,7 +36,7 @@
 	// close performs any shutdown tasks that a tool must execute before a new
 	// version is installed. It returns a string containing an error message on
 	// failure.
-	close?: () => Promise<string>;
+	close?: (env: NodeJS.Dict<string>) => Promise<string>;
 }
 
 /**
@@ -182,19 +182,20 @@
 		importPath: 'github.com/mdempsky/gocode',
 		isImportant: true,
 		description: 'Auto-completion, does not work with modules',
-		close: async (): Promise<string> => {
+		close: async (env: NodeJS.Dict<string>): Promise<string> => {
 			const toolBinPath = getBinPath('gocode');
 			if (!path.isAbsolute(toolBinPath)) {
 				return '';
 			}
 			try {
 				const execFile = util.promisify(cp.execFile);
-				const { stderr } = await execFile(toolBinPath, ['close']);
+				const { stderr } = await execFile(toolBinPath, ['close'], {env, timeout: 10000});  // give 10sec.
 				if (stderr.indexOf(`rpc: can't find service Server.`) > -1) {
 					return `Installing gocode aborted as existing process cannot be closed. Please kill the running process for gocode and try again.`;
 				}
 			} catch (err) {
 				// This may fail if gocode isn't already running.
+				console.log(`gocode close failed: ${err}`);
 			}
 			return '';
 		},
diff --git a/src/goTypeDefinition.ts b/src/goTypeDefinition.ts
index 100deb1..0487d70 100644
--- a/src/goTypeDefinition.ts
+++ b/src/goTypeDefinition.ts
@@ -17,9 +17,9 @@
 	getBinPath,
 	getFileArchive,
 	getGoConfig,
-	goBuiltinTypes,
-	killTree
+	goBuiltinTypes
 } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 interface GuruDescribeOutput {
 	desc: string;
@@ -130,7 +130,7 @@
 			if (process.pid) {
 				process.stdin.end(getFileArchive(document));
 			}
-			token.onCancellationRequested(() => killTree(process.pid));
+			token.onCancellationRequested(() => killProcessTree(process));
 		});
 	}
 }
diff --git a/src/stateUtils.ts b/src/stateUtils.ts
index c7b49c2..7a83832 100644
--- a/src/stateUtils.ts
+++ b/src/stateUtils.ts
@@ -43,3 +43,7 @@
 export function setWorkspaceState(state: vscode.Memento) {
 	workspaceState = state;
 }
+
+export function getWorkspaceState(): vscode.Memento {
+	return workspaceState;
+}
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 092dc45..aafe427 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -12,18 +12,18 @@
 import { getCurrentPackage } from './goModules';
 import { GoDocumentSymbolProvider } from './goOutline';
 import { getNonVendorPackages } from './goPackages';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './goPath';
 import {
 	getBinPath,
 	getCurrentGoPath,
 	getGoVersion,
 	getTempFilePath,
-	killTree,
 	LineBuffer,
-	resolvePath,
+	resolvePath
 } from './util';
+import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './utils/goPath';
+import {killProcessTree} from './utils/processUtils';
 
-const outputChannel = vscode.window.createOutputChannel('Go Tests');
+const testOutputChannel = vscode.window.createOutputChannel('Go Tests');
 const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
 statusBarItem.command = 'go.test.cancel';
 statusBarItem.text = '$(x) Cancel Running Tests';
@@ -77,6 +77,10 @@
 	 * Whether code coverage should be generated and applied.
 	 */
 	applyCodeCoverage?: boolean;
+	/**
+	 * Output channel for test output.
+	 */
+	outputChannel?: vscode.OutputChannel;
 }
 
 export function getTestEnvVars(config: vscode.WorkspaceConfiguration): any {
@@ -224,11 +228,26 @@
 }
 
 /**
+ * go test -json output format.
+ * which is a subset of https://golang.org/cmd/test2json/#hdr-Output_Format
+ * and includes only the fields that we are using.
+ */
+interface GoTestOutput {
+	Action: string;
+	Output?: string;
+	Package?: string;
+}
+
+/**
  * Runs go test and presents the output in the 'Go' channel.
  *
  * @param goConfig Configuration for the Go extension.
  */
 export async function goTest(testconfig: TestConfig): Promise<boolean> {
+	let outputChannel = testOutputChannel;
+	if (testconfig.outputChannel) {
+		outputChannel = testconfig.outputChannel;
+	}
 	const tmpCoverPath = getTempFilePath('go-code-cover');
 	const testResult = await new Promise<boolean>(async (resolve, reject) => {
 		// We do not want to clear it if tests are already running, as that could
@@ -267,32 +286,24 @@
 			return Promise.resolve();
 		}
 
-		const currentGoWorkspace = testconfig.isMod
-			? ''
-			: getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), testconfig.dir);
-		let targets = targetArgs(testconfig);
+		let targets = testconfig.includeSubDirectories ? ['./...'] : targetArgs(testconfig);
+
+		let currentGoWorkspace = '';
 		let getCurrentPackagePromise = Promise.resolve('');
-		if (testconfig.isMod) {
-			getCurrentPackagePromise = getCurrentPackage(testconfig.dir);
-		} else if (currentGoWorkspace) {
-			getCurrentPackagePromise = Promise.resolve(testconfig.dir.substr(currentGoWorkspace.length + 1));
-		}
 		let pkgMapPromise: Promise<Map<string, string> | null> = Promise.resolve(null);
-		if (testconfig.includeSubDirectories) {
-			if (testconfig.isMod) {
-				targets = ['./...'];
-				// We need the mapping to get absolute paths for the files in the test output
-				pkgMapPromise = getNonVendorPackages(testconfig.dir);
-			} else {
+
+		if (testconfig.isMod) {
+			// We need the mapping to get absolute paths for the files in the test output.
+			pkgMapPromise = getNonVendorPackages(testconfig.dir, !!testconfig.includeSubDirectories);
+		} else {  // GOPATH mode
+			currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), testconfig.dir);
+			if (currentGoWorkspace) {
+				getCurrentPackagePromise = Promise.resolve(testconfig.dir.substr(currentGoWorkspace.length + 1));
+			}
+			if (testconfig.includeSubDirectories) {
 				pkgMapPromise = getGoVersion().then((goVersion) => {
-					if (goVersion.gt('1.8')) {
-						targets = ['./...'];
-						return null; // We dont need mapping, as we can derive the absolute paths from package path
-					}
-					return getNonVendorPackages(testconfig.dir).then((pkgMap) => {
-						targets = Array.from(pkgMap.keys());
-						return pkgMap; // We need the individual package paths to pass to `go test`
-					});
+					targets = ['./...'];
+					return null; // We dont need mapping, as we can derive the absolute paths from package path
 				});
 			}
 		}
@@ -303,6 +314,7 @@
 					pkgMap = new Map<string, string>();
 				}
 				// Use the package name to be in the args to enable running tests in symlinked directories
+				// TODO(hyangah): check why modules mode didn't set currentPackage.
 				if (!testconfig.includeSubDirectories && currentPackage) {
 					targets.splice(0, 0, currentPackage);
 				}
@@ -315,6 +327,7 @@
 				}
 
 				args.push(...targets);
+				args.push('-json');
 
 				// ensure that user provided flags are appended last (allow use of -args ...)
 				// ignore user provided -run flag if we are already using it
@@ -331,30 +344,31 @@
 				const outBuf = new LineBuffer();
 				const errBuf = new LineBuffer();
 
-				// 1=ok/FAIL, 2=package, 3=time/(cached)
-				const packageResultLineRE = /^(ok|FAIL)[ \t]+(.+?)[ \t]+([0-9\.]+s|\(cached\))/;
-				const lineWithErrorRE = /^(\t|\s\s\s\s)\S/;
 				const testResultLines: string[] = [];
-
 				const processTestResultLine = (line: string) => {
-					testResultLines.push(line);
-					const result = line.match(packageResultLineRE);
-					if (result && (pkgMap.has(result[2]) || currentGoWorkspace)) {
-						const hasTestFailed = line.startsWith('FAIL');
-						const packageNameArr = result[2].split('/');
-						const baseDir = pkgMap.get(result[2]) || path.join(currentGoWorkspace, ...packageNameArr);
-						testResultLines.forEach((testResultLine) => {
-							if (hasTestFailed && lineWithErrorRE.test(testResultLine)) {
-								outputChannel.appendLine(expandFilePathInOutput(testResultLine, baseDir));
-							} else {
-								outputChannel.appendLine(testResultLine);
-							}
-						});
-						testResultLines.splice(0);
+					try {
+						const m = <GoTestOutput>(JSON.parse(line));
+						if (m.Action !== 'output' || !m.Output) {
+							return;
+						}
+						const out = m.Output;
+						const pkg = m.Package;
+						if (pkg && (pkgMap.has(pkg) || currentGoWorkspace)) {
+							const pkgNameArr = pkg.split('/');
+							const baseDir = pkgMap.get(pkg) || path.join(currentGoWorkspace, ...pkgNameArr);
+							// go test emits test results on stdout, which contain file names relative to the package under test
+							outputChannel.appendLine(expandFilePathInOutput(out, baseDir).trimRight());
+						} else {
+							outputChannel.appendLine(out.trimRight());
+						}
+					} catch (e) {
+						// TODO: disable this log if it becomes too spammy.
+						console.log(`failed to parse JSON: ${e}: ${line}`);
+						// Build failures or other messages come in non-JSON format. So, output as they are.
+						outputChannel.appendLine(line);
 					}
 				};
 
-				// go test emits test results on stdout, which contain file names relative to the package under test
 				outBuf.onLine((line) => processTestResultLine(line));
 				outBuf.onDone((last) => {
 					if (last) {
@@ -411,7 +425,7 @@
  * Reveals the output channel in the UI.
  */
 export function showTestOutput() {
-	outputChannel.show(true);
+	testOutputChannel.show(true);
 }
 
 /**
@@ -420,7 +434,7 @@
 export function cancelRunningTests(): Thenable<boolean> {
 	return new Promise<boolean>((resolve, reject) => {
 		runningTestProcesses.forEach((tp) => {
-			killTree(tp.pid);
+			killProcessTree(tp);
 		});
 		// All processes are now dead. Empty the array to prepare for the next run.
 		runningTestProcesses.splice(0, runningTestProcesses.length);
@@ -431,7 +445,7 @@
 function expandFilePathInOutput(output: string, cwd: string): string {
 	const lines = output.split('\n');
 	for (let i = 0; i < lines.length; i++) {
-		const matches = lines[i].match(/^\s*(.+.go):(\d+):/);
+		const matches = lines[i].match(/\s+(\S+.go):(\d+):\s+/);
 		if (matches && matches[1] && !path.isAbsolute(matches[1])) {
 			lines[i] = lines[i].replace(matches[1], path.join(cwd, matches[1]));
 		}
@@ -464,7 +478,7 @@
 			// which will result in the correct thing to happen
 			if (testFunctions.length > 0) {
 				if (testFunctions.length === 1) {
-					params = params.concat(['-run', util.format('^%s$', testFunctions.pop())]);
+					params = params.concat(['-run', util.format('^%s$', testFunctions[0])]);
 				} else {
 					params = params.concat(['-run', util.format('^(%s)$', testFunctions.join('|'))]);
 				}
diff --git a/src/util.ts b/src/util.ts
index fc24810..9684d9f 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -8,7 +8,6 @@
 import os = require('os');
 import path = require('path');
 import semver = require('semver');
-import kill = require('tree-kill');
 import util = require('util');
 import vscode = require('vscode');
 import { NearestNeighborDict, Node } from './avlTree';
@@ -16,6 +15,8 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { buildDiagnosticCollection, lintDiagnosticCollection, vetDiagnosticCollection } from './goMain';
 import { getCurrentPackage } from './goModules';
+import { outputChannel } from './goStatus';
+import { getFromWorkspaceState } from './stateUtils';
 import {
 	envPath,
 	fixDriveCasingInWindows,
@@ -23,8 +24,8 @@
 	getCurrentGoRoot,
 	getInferredGopath,
 	resolveHomeDir,
-} from './goPath';
-import { outputChannel } from './goStatus';
+} from './utils/goPath';
+import { killProcessTree } from './utils/processUtils';
 
 let userNameHash: number = 0;
 
@@ -88,13 +89,13 @@
 		const matchesRelease = /go version go(\d.\d+).*/.exec(version);
 		const matchesDevel = /go version devel \+(.[a-zA-Z0-9]+).*/.exec(version);
 		if (matchesRelease) {
-			const sv = semver.coerce(matchesRelease[0]);
+			const sv = semver.coerce(matchesRelease[1]);
 			if (sv) {
 				this.sv = sv;
 			}
 		} else if (matchesDevel) {
 			this.isDevel = true;
-			this.commit = matchesDevel[0];
+			this.commit = matchesDevel[1];
 		}
 	}
 
@@ -317,7 +318,7 @@
 		if (cachedGoVersion.isValid()) {
 			return Promise.resolve(cachedGoVersion);
 		}
-		warn(`cached Go version (${cachedGoVersion}) is invalid, recomputing`);
+		warn(`cached Go version (${JSON.stringify(cachedGoVersion)}) is invalid, recomputing`);
 	}
 	try {
 		const execFile = util.promisify(cp.execFile);
@@ -336,6 +337,21 @@
 }
 
 /**
+ * Returns the output of `go env` from the specified directory.
+ * Throws an error if the command fails.
+ */
+export async function getGoEnv(cwd?: string): Promise<string> {
+	const goRuntime = getBinPath('go');
+	const execFile = util.promisify(cp.execFile);
+	const opts = {cwd, env: toolExecutionEnvironment()};
+	const { stdout, stderr } = await execFile(goRuntime, ['env'], opts);
+	if (stderr) {
+		throw new Error(`failed to run 'go env': ${stderr}`);
+	}
+	return stdout;
+}
+
+/**
  * Returns boolean denoting if current version of Go supports vendoring
  */
 export async function isVendorSupported(): Promise<boolean> {
@@ -370,6 +386,7 @@
  */
 export function isGoPathSet(): boolean {
 	if (!getCurrentGoPath()) {
+		// TODO(hyangah): is it still possible after go1.8? (https://golang.org/doc/go1.8#gopath)
 		vscode.window
 			.showInformationMessage(
 				'Set GOPATH environment variable and restart VS Code or set GOPATH in Workspace settings',
@@ -440,11 +457,16 @@
 	const alternateTools: { [key: string]: string } = cfg.get('alternateTools');
 	const alternateToolPath: string = alternateTools[tool];
 
+	let selectedGoPath: string | undefined;
+	if (tool === 'go') {
+		selectedGoPath = getFromWorkspaceState('selectedGo')?.binpath;
+	}
+
 	return getBinPathWithPreferredGopathGoroot(
 		tool,
 		tool === 'go' ? [] : [getToolsGopath(), getCurrentGoPath()],
 		tool === 'go' && cfg.get('goroot') ? cfg.get('goroot') : undefined,
-		resolvePath(alternateToolPath),
+		selectedGoPath ?? resolvePath(alternateToolPath),
 		useCache
 	);
 }
@@ -492,6 +514,9 @@
 }
 
 export function getModuleCache(): string {
+	if (process.env['GOMODCACHE']) {
+		return process.env['GOMODCACHE'];
+	}
 	if (currentGopath) {
 		return path.join(currentGopath.split(path.delimiter)[0], 'pkg', 'mod');
 	}
@@ -684,7 +709,7 @@
 	if (token) {
 		token.onCancellationRequested(() => {
 			if (p) {
-				killTree(p.pid);
+				killProcessTree(p);
 			}
 		});
 	}
@@ -861,28 +886,6 @@
 	}
 }
 
-export const killTree = (processId: number): void => {
-	try {
-		kill(processId, (err) => {
-			if (err) {
-				console.log(`Error killing process tree: ${err}`);
-			}
-		});
-	} catch (err) {
-		console.log(`Error killing process tree: ${err}`);
-	}
-};
-
-export function killProcess(p: cp.ChildProcess) {
-	if (p) {
-		try {
-			p.kill();
-		} catch (e) {
-			console.log('Error killing process: ' + e);
-		}
-	}
-}
-
 export function makeMemoizedByteOffsetConverter(buffer: Buffer): (byteOffset: number) => number {
 	const defaultValue = new Node<number, number>(0, 0); // 0 bytes will always be 0 characters
 	const memo = new NearestNeighborDict(defaultValue, NearestNeighborDict.NUMERIC_DISTANCE_FUNCTION);
@@ -1026,7 +1029,7 @@
 
 			if (token) {
 				token.onCancellationRequested(() => {
-					killTree(p.pid);
+					killProcessTree(p);
 				});
 			}
 		});
diff --git a/src/goPath.ts b/src/utils/goPath.ts
similarity index 96%
rename from src/goPath.ts
rename to src/utils/goPath.ts
index f85e49e..6ad1b1a 100644
--- a/src/goPath.ts
+++ b/src/utils/goPath.ts
@@ -12,6 +12,7 @@
 import fs = require('fs');
 import os = require('os');
 import path = require('path');
+import { promisify } from 'util';
 
 let binPathCache: { [bin: string]: string } = {};
 
@@ -37,7 +38,7 @@
 	preferredGoroot?: string,
 	alternateTool?: string,
 	useCache = true,
-) {
+): string {
 	if (alternateTool && path.isAbsolute(alternateTool) && executableFileExists(alternateTool)) {
 		binPathCache[toolName] = alternateTool;
 		return alternateTool;
@@ -106,7 +107,7 @@
 	currentGoRoot = goroot;
 }
 
-function correctBinname(toolName: string) {
+export function correctBinname(toolName: string) {
 	if (process.platform === 'win32') {
 		return toolName + '.exe';
 	}
@@ -134,6 +135,15 @@
 	}
 }
 
+export async function pathExists(p: string): Promise<boolean> {
+	try {
+		const stat = promisify(fs.stat);
+		return (await stat(p)).isDirectory();
+	} catch (e) {
+		return false;
+	}
+}
+
 export function clearCacheForTools() {
 	binPathCache = {};
 }
diff --git a/src/utils/processUtils.ts b/src/utils/processUtils.ts
new file mode 100644
index 0000000..ddd12ae
--- /dev/null
+++ b/src/utils/processUtils.ts
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { ChildProcess } from 'child_process';
+import kill = require('tree-kill');
+
+// Kill a process and its children, returning a promise.
+export function killProcessTree(
+	p: ChildProcess,
+	logger?: (...args: any[]) => void): Promise<void> {
+	if (!logger) {
+		logger = console.log;
+	}
+	if (!p || !p.pid || p.exitCode !== null) {
+		return Promise.resolve();
+	}
+	return new Promise((resolve) => {
+		kill(p.pid, (err) => {
+			if (err) {
+				logger(`Error killing process ${p.pid}: ${err}`);
+			}
+			resolve();
+		});
+	});
+}
+
+// Kill a process.
+//
+// READ THIS BEFORE USING THE FUNCTION:
+//
+// TODO: This function is kept for historical reasons and should be removed once
+// its user (go-outline) is replaced. Outlining uses this function and not
+// killProcessTree because of performance issues that were observed in the past.
+// See https://go-review.googlesource.com/c/vscode-go/+/242518/ for more
+// details and background.
+export function killProcess(p: ChildProcess) {
+	if (p && p.pid && p.exitCode === null) {
+		try {
+			p.kill();
+		} catch (e) {
+			console.log(`Error killing process ${p.pid}: ${e}`);
+		}
+	}
+}
diff --git a/test/fixtures/coverage/a/a.go b/test/fixtures/coverage/a/a.go
new file mode 100644
index 0000000..06eae93
--- /dev/null
+++ b/test/fixtures/coverage/a/a.go
@@ -0,0 +1,7 @@
+package a
+
+func main() {
+	x := 12
+	y := x + 17
+	panic(y)
+}
diff --git a/test/fixtures/coverage/b/b.go b/test/fixtures/coverage/b/b.go
new file mode 100644
index 0000000..7de3bb6
--- /dev/null
+++ b/test/fixtures/coverage/b/b.go
@@ -0,0 +1,11 @@
+package b
+
+import (
+	"fmt"
+	"os"
+)
+
+func main() {
+	v := os.Env()
+	fmt.Print(v)
+}
diff --git a/test/fixtures/coverage/cover.out b/test/fixtures/coverage/cover.out
new file mode 100644
index 0000000..3157dc6
--- /dev/null
+++ b/test/fixtures/coverage/cover.out
@@ -0,0 +1,3 @@
+mode: set
+github.com/microsoft/vscode-go/gofixtures/coveragetest/a/a.go:19.71,22.25 3 1
+github.com/microsoft/vscode-go/gofixtures/coveragetest/b/b.go:35.2,35.14 1 1
diff --git a/test/fixtures/coverage/go.mod b/test/fixtures/coverage/go.mod
new file mode 100644
index 0000000..5f77dbf
--- /dev/null
+++ b/test/fixtures/coverage/go.mod
@@ -0,0 +1,3 @@
+module github.com/microsoft/vscode-go/gofixtures/coveragetest
+
+go 1.14
diff --git a/test/fixtures/goTestTest/a_test.go b/test/fixtures/goTestTest/a_test.go
new file mode 100644
index 0000000..66a943a
--- /dev/null
+++ b/test/fixtures/goTestTest/a_test.go
@@ -0,0 +1,10 @@
+package main
+
+import (
+	"testing"
+)
+
+func TestA(t *testing.T) {
+	t.Log("log")
+	t.Errorf("error")
+}
diff --git a/test/fixtures/goTestTest/b/b_test.go b/test/fixtures/goTestTest/b/b_test.go
new file mode 100644
index 0000000..2240f6f
--- /dev/null
+++ b/test/fixtures/goTestTest/b/b_test.go
@@ -0,0 +1,8 @@
+package main
+
+import "testing"
+
+func TestB(t *testing.T) {
+	t.Log("log")
+	t.Error("error")
+}
diff --git a/test/fixtures/goTestTest/go.mod b/test/fixtures/goTestTest/go.mod
new file mode 100644
index 0000000..24872e7
--- /dev/null
+++ b/test/fixtures/goTestTest/go.mod
@@ -0,0 +1,3 @@
+module example.com/a
+
+go 1.14
diff --git a/test/fixtures/vendoring/main.go b/test/fixtures/vendoring/main.go
new file mode 100644
index 0000000..85b606a
--- /dev/null
+++ b/test/fixtures/vendoring/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+  "fmt"
+
+  "example.com/vendorpls"
+)
+
+func main() {
+  fmt.Prinln(vendorpls.F())
+}
diff --git a/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go b/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go
new file mode 100644
index 0000000..2993afc
--- /dev/null
+++ b/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go
@@ -0,0 +1,9 @@
+package vendorpls
+
+func F() string {
+  return "vendor please"
+}
+
+func SomethingStrange() {
+
+}
\ No newline at end of file
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 64cddfc..7f5104c 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -46,7 +46,10 @@
 	public async setup() {
 		await this.reset();
 		await this.extension.activate();
-		await sleep(2000);  // allow extension host + gopls to start.
+		await sleep(2000);  // allow the language server to start.
+		// TODO(hyangah): find a better way to check the language server's status.
+		// I thought I'd check the languageClient.onReady(),
+		// but couldn't make it working yet.
 	}
 
 	public async reset(fixtureDirName?: string) {  // name of the fixtures subdirectory to use.
@@ -89,7 +92,9 @@
 	const projectDir = path.join(__dirname, '..', '..', '..');
 	const env = new Env(projectDir);
 
-	suiteSetup(async () => { await env.setup(); });
+	suiteSetup(async () => {
+		await env.setup();
+	});
 	suiteTeardown(async () => { await env.reset(); });
 
 	test('HoverProvider', async () => {
@@ -137,9 +142,23 @@
 			['fmt.<>', new vscode.Position(19, 5), 'Formatter'],
 		];
 		for (const [name, position, wantFilterText] of testCases) {
-			const list = await vscode.commands.executeCommand(
-				'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
-
+			let list: vscode.CompletionList<vscode.CompletionItem>;
+			// Query completion items. We expect the hard coded filter text hack
+			// has been applied and gopls returns an incomplete list by default
+			// to avoid reordering by vscode. But, if the query is made before
+			// gopls is ready, we observed that gopls returns an empty result
+			// as a complete result, and vscode returns a general completion list instead.
+			// Retry a couple of times if we see a complete result as a workaround.
+			// (github.com/golang/vscode-go/issues/363)
+			for (let i = 0; i < 3; i++) {
+				list = await vscode.commands.executeCommand(
+					'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
+				if (list.isIncomplete) {
+					break;
+				}
+				await sleep(100);
+				console.log(`${new Date()}: retrying...`);
+			}
 			// Confirm that the hardcoded filter text hack has been applied.
 			if (!list.isIncomplete) {
 				assert.fail(`gopls should provide an incomplete list by default`);
@@ -157,6 +176,5 @@
 				}
 			}
 		}
-
 	});
 });
diff --git a/test/gopls/index.ts b/test/gopls/index.ts
index be16d86..eae81d7 100644
--- a/test/gopls/index.ts
+++ b/test/gopls/index.ts
@@ -10,7 +10,9 @@
 	const mocha = new Mocha({
 		ui: 'tdd'
 	});
-	mocha.useColors(true);
+
+	// @types/mocha is outdated
+	(mocha as any).color(true);
 
 	const testsRoot = path.resolve(__dirname, '..');
 
diff --git a/test/gopls/survey.test.ts b/test/gopls/survey.test.ts
index bccd3d6..2f04128 100644
--- a/test/gopls/survey.test.ts
+++ b/test/gopls/survey.test.ts
@@ -20,26 +20,26 @@
 			[
 				{
 					lastDateAccepted: new Date('2020-04-02'),
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2020-04-02'),
 					prompt: true,
 					promptThisMonth: false,
 				},
-				false,
+				undefined,
 			],
 			// User who has declined survey prompting.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2020-04-02'),
 					prompt: false,
 				},
-				false,
+				undefined,
 			],
 			// User who hasn't activated the extension in a while, but has opted in to prompting.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2019-04-10'),
+					dateComputedPromptThisMonth: new Date('2019-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 					prompt: true,
 				},
@@ -48,7 +48,7 @@
 			// User who hasn't activated the extension in a while, and has never been prompted.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2019-04-10'),
+					dateComputedPromptThisMonth: new Date('2019-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 				},
 				true,
@@ -57,7 +57,7 @@
 			[
 				{
 					lastDateAccepted: undefined,
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 					prompt: true,
 					promptThisMonth: true,
@@ -69,12 +69,15 @@
 			// Replace Math.Random so that it always returns 1. This means
 			// that we will always choose to prompt, in the event that the
 			// user can be prompted that month.
-			sinon.replace(Math, 'random', () => 1);
+			sinon.replace(Math, 'random', () => 0);
 
 			const now = new Date('2020-04-29');
 			const gotPrompt = shouldPromptForGoplsSurvey(now, testConfig);
-			assert.equal(wantPrompt, gotPrompt, `prompt determination failed for ${i}`);
-
+			if (wantPrompt) {
+				assert.ok(gotPrompt, `prompt determination failed for ${i}`);
+			} else {
+				assert.equal(gotPrompt, wantPrompt, `prompt determination failed for ${i}`);
+			}
 			sinon.restore();
 		});
 	});
diff --git a/test/gopls/update.test.ts b/test/gopls/update.test.ts
index dbe5312..031bea5 100644
--- a/test/gopls/update.test.ts
+++ b/test/gopls/update.test.ts
@@ -14,7 +14,7 @@
 	test('prompt for update', async () => {
 		const tool = getTool('gopls');
 
-		const toSemver = (v: string) => semver.coerce(v, {includePrerelease: true, loose: true});
+		const toSemver = (v: string) => semver.parse(v, { includePrerelease: true, loose: true });
 
 		// Fake data stubbed functions will serve.
 		const latestVersion = toSemver('0.4.1');
@@ -101,7 +101,19 @@
 					return latestPrereleaseVersionTimestamp;
 				}
 			});
-			const got = await lsp.shouldUpdateLanguageServer(tool, 'bad/path/to/gopls', true);
+			const got = await lsp.shouldUpdateLanguageServer(tool, {
+				enabled: true,
+				path: 'bad/path/to/gopls',
+				checkForUpdates: true,
+				env: {},
+				features: {
+					diagnostics: true,
+					documentLink: true,
+				},
+				flags: [],
+				modtime: new Date(),
+				serverName: 'gopls',
+			});
 			assert.deepEqual(got, want, `${name}: failed (got: '${got}' ${typeof got} want: '${want}' ${typeof want})`);
 			sinon.restore();
 		}
diff --git a/test/integration/coverage.test.ts b/test/integration/coverage.test.ts
new file mode 100644
index 0000000..fe38424
--- /dev/null
+++ b/test/integration/coverage.test.ts
@@ -0,0 +1,44 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import * as assert from 'assert';
+import fs = require('fs-extra');
+import path = require('path');
+import sinon = require('sinon');
+import vscode = require('vscode');
+import { applyCodeCoverageToAllEditors, coverageFilesForTest, initForTest } from '../../src/goCover';
+import { updateGoVarsFromConfig } from '../../src/goInstallTools';
+import { getCurrentGoPath, getWorkspaceFolderPath } from '../../src/util';
+
+// The ideal test would check that each open editor containing a file with coverage
+// information is displayed correctly. We cannot see the applied decorations, so the
+// test checks that the cover.out file has been read correctly, and the import paths
+// have been correctly converted to file system paths, which are what vscode uses.
+suite('Coverage for tests', function () {
+	this.timeout(10000);
+
+	let fixtureSourcePath: string;
+	let coverFilePath: string;
+
+	suiteSetup(async () => {
+		await updateGoVarsFromConfig();
+
+		// Set up the test fixtures.
+		fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'coverage');
+		coverFilePath = path.join(fixtureSourcePath, 'cover.out');
+		return;
+	});
+	test('resolve import paths', async () => {
+		initForTest();
+		const x = vscode.workspace.openTextDocument(coverFilePath);
+		await applyCodeCoverageToAllEditors(coverFilePath, fixtureSourcePath);
+		const files = Object.keys(coverageFilesForTest());
+		const aDotGo = files.includes(path.join(fixtureSourcePath, 'a', 'a.go'));
+		const bDotGo = files.includes(path.join(fixtureSourcePath, 'b', 'b.go'));
+		assert.equal(aDotGo && bDotGo, true, `seen a.go:${aDotGo}, seen b.go:${bDotGo}\n${files}\n`);
+	});
+});
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index b8c752d..d16d35b 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -364,8 +364,9 @@
 
 	test('Linting - concurrent process cancelation', async () => {
 		const util = require('../../src/util');
+		const processutil = require('../../src/utils/processUtils');
 		sinon.spy(util, 'runTool');
-		sinon.spy(util, 'killTree');
+		sinon.spy(processutil, 'killProcessTree');
 
 		const config = Object.create(vscode.workspace.getConfiguration('go'), {
 			vetOnSave: { value: 'package' },
@@ -373,8 +374,8 @@
 			buildOnSave: { value: 'package' },
 			lintOnSave: { value: 'package' },
 			// simulate a long running lint process by sleeping for a couple seconds
-			lintTool: { value: 'sleep' },
-			lintFlags: { value: ['2'] }
+			lintTool: { value: process.platform !== 'win32' ? 'sleep' : 'timeout' },
+			lintFlags: { value: process.platform !== 'win32' ? ['2'] : ['/t', '2'] }
 		});
 
 		const results = await Promise.all([
@@ -382,7 +383,7 @@
 			goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go')), config)
 		]);
 		assert.equal(util.runTool.callCount, 2, 'should have launched 2 lint jobs');
-		assert.equal(util.killTree.callCount, 1, 'should have killed 1 lint job before launching the next');
+		assert.equal(processutil.killProcessTree.callCount, 1, 'should have killed 1 lint job before launching the next');
 	});
 
 	test('Error checking', async () => {
@@ -472,7 +473,12 @@
 		assert.equal(testFileGenerated, true, 'Test file not generated.');
 	});
 
-	test('Test diffUtils.getEditsFromUnifiedDiffStr', async () => {
+	test('Test diffUtils.getEditsFromUnifiedDiffStr', async function () {
+		if (process.platform === 'win32') {
+			// This test requires diff tool that's not available on windows
+			this.skip();
+		}
+
 		const file1path = path.join(fixturePath, 'diffTest1Data', 'file1.go');
 		const file2path = path.join(fixturePath, 'diffTest1Data', 'file2.go');
 		const file1uri = vscode.Uri.file(file1path);
@@ -628,21 +634,13 @@
 	});
 
 	test('Replace vendor packages with relative path', async () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
 		const vendorSupport = await isVendorSupported();
-		const filePath = path.join(toolsGopath, 'src', 'github.com', 'rogpeppe', 'godef', 'go', 'ast', 'ast.go');
+		const filePath = path.join(fixturePath, 'vendoring', 'main.go');
 		const workDir = path.dirname(filePath);
 		const vendorPkgsFullPath = [
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/acme',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9/client'
+			'test/testfixture/vendoring/vendor/example.com/vendorpls',
 		];
-		const vendorPkgsRelativePath = ['9fans.net/go/acme', '9fans.net/go/plan9', '9fans.net/go/plan9/client'];
+		const vendorPkgsRelativePath = ['example.com/vendorpls'];
 
 		const gopkgsPromise = getAllPackages(workDir).then((pkgMap) => {
 			const pkgs = Array.from(pkgMap.keys()).filter((p) => {
@@ -696,18 +694,10 @@
 	});
 
 	test('Vendor pkgs from other projects should not be allowed to import', async () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
 		const vendorSupport = await isVendorSupported();
-		const filePath = path.join(toolsGopath, 'src', 'github.com', 'ramya-rao-a', 'go-outline', 'main.go');
+		const filePath = path.join(fixturePath, 'baseTest', 'test.go');
 		const vendorPkgs = [
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/acme',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9/client'
+			'test/testfixture/vendoring/vendor/example.com/vendorpls',
 		];
 
 		const gopkgsPromise = new Promise<void>((resolve, reject) => {
@@ -751,13 +741,7 @@
 	});
 
 	test('Workspace Symbols', () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
-		const workspacePath = path.join(toolsGopath, 'src', 'github.com', 'rogpeppe', 'godef');
+		const workspacePath = path.join(fixturePath, 'vendoring');
 		const configWithoutIgnoringFolders = Object.create(vscode.workspace.getConfiguration('go'), {
 			gotoSymbol: {
 				value: {
@@ -789,16 +773,16 @@
 
 		const withoutIgnoringFolders = getWorkspaceSymbols(
 			workspacePath,
-			'WinInfo',
+			'SomethingStr',
 			dummyCancellationSource.token,
 			configWithoutIgnoringFolders
 		).then((results) => {
-			assert.equal(results[0].name, 'WinInfo');
-			assert.equal(results[0].path, path.join(workspacePath, 'vendor/9fans.net/go/acme/acme.go'));
+			assert.equal(results[0].name, 'SomethingStrange');
+			assert.equal(results[0].path, path.join(workspacePath, 'vendor/example.com/vendorpls/lib.go'));
 		});
 		const withIgnoringFolders = getWorkspaceSymbols(
 			workspacePath,
-			'WinInfo',
+			'SomethingStr',
 			dummyCancellationSource.token,
 			configWithIgnoringFolders
 		).then((results) => {
@@ -1444,12 +1428,19 @@
 		assert.equal(result4, false);
 	});
 
+	function fixEOL(eol: vscode.EndOfLine, strWithLF: string): string {
+		if (eol === vscode.EndOfLine.LF) {
+			return strWithLF;
+		}
+		return strWithLF.split('\n').join('\r\n');  // replaceAll.
+	}
+
 	test('Add imports when no imports', async () => {
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'noimports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
 
-		const expectedText = document.getText() + '\n' + 'import (\n\t"bytes"\n)\n';
+		const expectedText = document.getText() + fixEOL(document.eol, '\n' + 'import (\n\t"bytes"\n)\n');
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
 		edit.set(document.uri, edits);
@@ -1466,8 +1457,11 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'groupImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
-		const expectedText = document.getText().replace('\t"fmt"\n\t"math"', '\t"bytes"\n\t"fmt"\n\t"math"');
+		const expectedText = document.getText().replace(
+			fixEOL(eol, '\t"fmt"\n\t"math"'),
+			fixEOL(eol, '\t"bytes"\n\t"fmt"\n\t"math"'));
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
 		edit.set(document.uri, edits);
@@ -1479,12 +1473,13 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'singleImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
 		const expectedText = document
 			.getText()
 			.replace(
-				'import "fmt"\nimport . "math" // comment',
-				'import (\n\t"bytes"\n\t"fmt"\n\t. "math" // comment\n)'
+				fixEOL(eol, 'import "fmt"\nimport . "math" // comment'),
+				fixEOL(eol, 'import (\n\t"bytes"\n\t"fmt"\n\t. "math" // comment\n)')
 			);
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
@@ -1497,12 +1492,13 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'cgoImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
 		const expectedText = document
 			.getText()
 			.replace(
-				'import "math"',
-				'import (\n\t"bytes"\n\t"math"\n)'
+				fixEOL(eol, 'import "math"'),
+				fixEOL(eol, 'import (\n\t"bytes"\n\t"math"\n)')
 			);
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
diff --git a/test/integration/index.ts b/test/integration/index.ts
index 2d964a1..0cc6ddd 100644
--- a/test/integration/index.ts
+++ b/test/integration/index.ts
@@ -9,7 +9,9 @@
 	const mocha = new Mocha({
 		ui: 'tdd',
 	});
-	mocha.useColors(true);
+
+	// @types/mocha is outdated
+	(mocha as any).color(true);
 
 	const testsRoot = path.resolve(__dirname, '..');
 
diff --git a/test/integration/install.test.ts b/test/integration/install.test.ts
index 2c663f5..e61f606 100644
--- a/test/integration/install.test.ts
+++ b/test/integration/install.test.ts
@@ -10,12 +10,14 @@
 import os = require('os');
 import path = require('path');
 import sinon = require('sinon');
+import url = require('url');
 import util = require('util');
 import vscode = require('vscode');
 import { toolInstallationEnvironment } from '../../src/goEnv';
 import { installTools } from '../../src/goInstallTools';
 import { allToolsInformation, getTool, getToolAtVersion } from '../../src/goTools';
 import { getBinPath, getGoVersion, rmdirRecursive } from '../../src/util';
+import { correctBinname } from '../../src/utils/goPath';
 
 suite('Installation Tests', function () {
 	// Disable timeout when we are running slow tests.
@@ -26,18 +28,22 @@
 	this.timeout(timeout);
 
 	let tmpToolsGopath: string;
+	let tmpToolsGopath2: string;
 	let sandbox: sinon.SinonSandbox;
 	let toolsGopathStub: sinon.SinonStub;
 
 	setup(() => {
 		// Create a temporary directory in which to install tools.
 		tmpToolsGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test'));
-		fs.mkdirSync(path.join(tmpToolsGopath, 'bin'));
-		fs.mkdirSync(path.join(tmpToolsGopath, 'src'));
+
+		// a temporary directory to be used as the second GOPATH element.
+		tmpToolsGopath2 = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test2'));
+
+		const toolsGopath = tmpToolsGopath + path.delimiter + tmpToolsGopath2;
 
 		sandbox = sinon.createSandbox();
 		const utils = require('../../src/util');
-		toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(tmpToolsGopath);
+		toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(toolsGopath);
 	});
 
 	teardown(async () => {
@@ -46,12 +52,15 @@
 		// Clean up the temporary GOPATH. To delete the module cache, run `go clean -modcache`.
 		const goRuntimePath = getBinPath('go');
 		const envForTest = Object.assign({}, process.env);
-		envForTest['GOPATH'] = tmpToolsGopath;
-		const execFile = util.promisify(cp.execFile);
-		await execFile(goRuntimePath, ['clean', '-modcache'], {
-			env: envForTest,
-		});
-		rmdirRecursive(tmpToolsGopath);
+
+		for (const p of [tmpToolsGopath, tmpToolsGopath2]) {
+			envForTest['GOPATH'] = p;
+			const execFile = util.promisify(cp.execFile);
+			await execFile(goRuntimePath, ['clean', '-modcache'], {
+				env: envForTest,
+			});
+			rmdirRecursive(p);
+		}
 	});
 
 	// runTest actually executes the logic of the test.
@@ -64,7 +73,7 @@
 			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
 				toolsEnvVars: {
 					value: {
-						GOPROXY: `file://${proxyDir}`,
+						GOPROXY: url.pathToFileURL(proxyDir),
 						GOSUMDB: 'off',
 					}
 				},
@@ -86,7 +95,7 @@
 		for (const tool of testCases) {
 			checks.push(new Promise<void>(async (resolve) => {
 				// Check that the expect tool has been installed to $GOPATH/bin.
-				const ok = await exists(path.join(tmpToolsGopath, 'bin', tool));
+				const ok = await exists(path.join(tmpToolsGopath, 'bin', correctBinname(tool)));
 				if (!ok) {
 					assert.fail(`expected ${tmpToolsGopath}/bin/${tool}, not found`);
 				}
@@ -145,7 +154,7 @@
 		// Write the zip file.
 		const zip = new AdmZip();
 		const content = `package main; func main() {};`;
-		zip.addFile(path.join(`${module}@${version}`, 'main.go'), Buffer.alloc(content.length, content));
+		zip.addFile(`${module}@${version}/main.go`, Buffer.alloc(content.length, content));
 		zip.writeZip(path.join(dir, `${version}.zip`));
 	}
 	return proxyDir;
diff --git a/test/integration/statusbar.test.ts b/test/integration/statusbar.test.ts
index 42d166e..6f982ad 100644
--- a/test/integration/statusbar.test.ts
+++ b/test/integration/statusbar.test.ts
@@ -5,18 +5,28 @@
  *--------------------------------------------------------*/
 
 import * as assert from 'assert';
-import cp = require('child_process');
-import fs = require('fs');
+import * as cp from 'child_process';
+import * as fs from 'fs-extra';
 import { describe, it } from 'mocha';
-import os = require('os');
-import path = require('path');
-import sinon = require('sinon');
-import util = require('util');
-import { WorkspaceConfiguration } from 'vscode';
-import { disposeGoStatusBar, formatGoVersion, getGoEnvironmentStatusbarItem } from '../../src/goEnvironmentStatus';
+import * as os from 'os';
+import * as path from 'path';
+import * as sinon from 'sinon';
+import * as util from 'util';
+import * as vscode from 'vscode';
+
+import {
+	disposeGoStatusBar,
+	formatGoVersion,
+	getGoEnvironmentStatusbarItem,
+	getSelectedGo,
+	GoEnvironmentOption,
+	setSelectedGo,
+} from '../../src/goEnvironmentStatus';
 import { updateGoVarsFromConfig } from '../../src/goInstallTools';
-import { getCurrentGoRoot } from '../../src/goPath';
+import { getWorkspaceState, setWorkspaceState } from '../../src/stateUtils';
 import ourutil = require('../../src/util');
+import { getCurrentGoRoot } from '../../src/utils/goPath';
+import { MockMemento } from '../mocks/MockMemento';
 
 describe('#initGoStatusBar()', function () {
 	this.beforeAll(async () => {
@@ -42,16 +52,76 @@
 	});
 });
 
-describe('#updateGoVarsFromConfig()', function () {
+describe('#setSelectedGo()', async function () {
+	this.timeout(40000);
+	let sandbox: sinon.SinonSandbox | undefined;
+	let goOption: GoEnvironmentOption;
+	let defaultMemento: vscode.Memento;
+	const version = await ourutil.getGoVersion();
+	const defaultGoOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version.format()));
+
+	this.beforeAll(async () => {
+		defaultMemento = getWorkspaceState();
+		setWorkspaceState(new MockMemento());
+		await setSelectedGo(defaultGoOption);
+	});
+	this.afterAll(async () => {
+		setWorkspaceState(defaultMemento);
+	});
+	this.beforeEach(async () => {
+		goOption = await getSelectedGo();
+		sandbox = sinon.createSandbox();
+	});
+	this.afterEach(async () => {
+		await setSelectedGo(goOption, false);
+		sandbox.restore();
+	});
+
+	it('should update the workspace memento storage', async () => {
+		// set workspace setting
+		const workspaceTestOption = new GoEnvironmentOption('workspacetestpath', 'testlabel');
+		await setSelectedGo(workspaceTestOption, false);
+
+		// check that the new config is set
+		assert.equal(getSelectedGo()?.binpath, 'workspacetestpath');
+	});
+
+	it('should download an uninstalled version of Go', async () => {
+		if (!process.env['VSCODEGO_BEFORE_RELEASE_TESTS']) {
+			return;
+		}
+
+		// setup tmp home directory for sdk installation
+		const envCache = Object.assign({}, process.env);
+		process.env.HOME = os.tmpdir();
+
+		// set selected go as a version to download
+		const option = new GoEnvironmentOption('go get golang.org/dl/go1.13.12', 'Go 1.13.12');
+		await setSelectedGo(option, false);
+
+		// the temp sdk directory should now contain go1.13.12
+		const subdirs = await fs.readdir(path.join(os.tmpdir(), 'sdk'));
+		assert.ok(subdirs.includes('go1.13.12'), 'Go 1.13.12 was not installed');
+
+		// cleanup
+		process.env = envCache;
+	});
+});
+
+describe('#updateGoVarsFromConfig()', async function () {
 	this.timeout(10000);
 
-	let defaultGoConfig: WorkspaceConfiguration | undefined;
+	let defaultMemento: vscode.Memento;
 	let tmpRoot: string | undefined;
 	let tmpRootBin: string | undefined;
 	let sandbox: sinon.SinonSandbox | undefined;
+	const version = await ourutil.getGoVersion();
+	const defaultGoOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version.format()));
 
 	this.beforeAll(async () => {
-		defaultGoConfig = ourutil.getGoConfig();
+		defaultMemento = getWorkspaceState();
+		setWorkspaceState(new MockMemento());
+		await setSelectedGo(defaultGoOption);
 
 		tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'rootchangetest'));
 		tmpRootBin = path.join(tmpRoot, 'bin');
@@ -62,15 +132,17 @@
 		const fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'testhelpers');
 		const execFile = util.promisify(cp.execFile);
 		const goRuntimePath = ourutil.getBinPath('go');
-		const { stdout, stderr } = await execFile(
+		const { stderr } = await execFile(
 			goRuntimePath, ['build', '-o', path.join(tmpRootBin, 'go'), path.join(fixtureSourcePath, 'fakego.go')]);
 		if (stderr) {
 			assert.fail(`failed to build the fake go binary required for testing: ${stderr}`);
 		}
 	});
 
-	this.afterAll(() => {
+	this.afterAll(async () => {
+		setWorkspaceState(defaultMemento);
 		ourutil.rmdirRecursive(tmpRoot);
+		await updateGoVarsFromConfig();
 	});
 
 	this.beforeEach(() => {
@@ -101,21 +173,12 @@
 	});
 
 	it('should recognize the adjusted goroot using go.goroot', async () => {
-		// stub geteGoConfig to return "go.goroot": tmpRoot.
-		const getGoConfigStub = sandbox.stub(ourutil, 'getGoConfig').returns({
-			get: (s: string) => {
-				if (s === 'goroot') { return tmpRoot; }
-				return defaultGoConfig.get(s);
-			},
-		} as WorkspaceConfiguration);
-
 		// adjust the fake go binary's behavior.
 		process.env['FAKEGOROOT'] = tmpRoot;
 		process.env['FAKEGOVERSION'] = 'go version go2.0.0 darwin/amd64';
 
 		await updateGoVarsFromConfig();
 
-		sandbox.assert.calledWith(getGoConfigStub);
 		assert.equal((await ourutil.getGoVersion()).format(), '2.0.0');
 		assert.equal(getGoEnvironmentStatusbarItem().text, 'Go 2.0.0');
 		assert.equal(pathEnvVar()[0], [path.join(getCurrentGoRoot(), 'bin')],
@@ -126,21 +189,11 @@
 		// "go.alternateTools" : {"go": "go3"}
 		fs.copyFileSync(path.join(tmpRootBin, 'go'), path.join(tmpRootBin, 'go3'));
 
-		const getGoConfigStub = sandbox.stub(ourutil, 'getGoConfig').returns({
-			get: (s: string) => {
-				if (s === 'alternateTools') {
-					return { go: path.join(tmpRootBin, 'go3') };
-				}
-				return defaultGoConfig.get(s);
-			},
-		} as WorkspaceConfiguration);
-
 		process.env['FAKEGOROOT'] = tmpRoot;
 		process.env['FAKEGOVERSION'] = 'go version go3.0.0 darwin/amd64';
 
 		await updateGoVarsFromConfig();
 
-		sandbox.assert.calledWith(getGoConfigStub);
 		assert.equal((await ourutil.getGoVersion()).format(), '3.0.0');
 		assert.equal(getGoEnvironmentStatusbarItem().text, 'Go 3.0.0');
 		assert.equal(pathEnvVar()[0], [path.join(getCurrentGoRoot(), 'bin')],
diff --git a/test/integration/test.test.ts b/test/integration/test.test.ts
new file mode 100644
index 0000000..6287f7a
--- /dev/null
+++ b/test/integration/test.test.ts
@@ -0,0 +1,137 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import * as assert from 'assert';
+import fs = require('fs-extra');
+import os = require('os');
+import path = require('path');
+import sinon = require('sinon');
+import vscode = require('vscode');
+import { getTestFlags, goTest } from '../../src/testUtils';
+import { rmdirRecursive } from '../../src/util';
+
+suite('Test Go Test', function () {
+	this.timeout(10000);
+
+	const sourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'goTestTest');
+
+	let tmpGopath: string;
+	let repoPath: string;
+
+	let previousEnv: any;
+
+	setup(() => {
+		previousEnv = Object.assign({}, process.env);
+	});
+
+	teardown(async () => {
+		process.env = previousEnv;
+		rmdirRecursive(tmpGopath);
+	});
+
+	function setupRepo(modulesMode: boolean) {
+		tmpGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'go-test-test'));
+		fs.mkdirSync(path.join(tmpGopath, 'src'));
+		repoPath = path.join(tmpGopath, 'src', 'goTestTest');
+		fs.copySync(sourcePath, repoPath, {
+			recursive: true,
+			filter: (src: string): boolean => {
+				if (modulesMode) {
+					return true;
+				}
+				return path.basename(src) !== 'go.mod';  // skip go.mod file.
+			},
+		});
+		process.env.GOPATH = tmpGopath;
+	}
+
+	async function runTest(
+		input: { isMod: boolean, includeSubDirectories: boolean, testFlags?: string[] },
+		wantFiles: string[]) {
+
+		fs.copySync(sourcePath, repoPath, { recursive: true });
+
+		const config = Object.create(vscode.workspace.getConfiguration('go'));
+		const outputChannel = new FakeOutputChannel();
+
+		const testConfig = {
+			goConfig: config,
+			outputChannel,
+			dir: repoPath,
+			flags: input.testFlags ? input.testFlags : getTestFlags(config),
+			isMod: input.isMod,
+			includeSubDirectories: input.includeSubDirectories,
+		};
+		try {
+			const result = await goTest(testConfig);
+			assert.equal(result, false);  // we expect tests to fail.
+		} catch (e) {
+			console.log('exception: ${e}');
+		}
+
+		const testOutput = outputChannel.toString();
+		for (const want of wantFiles) {
+			assert.ok(testOutput.includes(want), `\nFully resolved file path "${want}" not found in \n${testOutput}`);
+		}
+	}
+
+	test('resolves file names in logs (modules)', async () => {
+		setupRepo(true);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false },
+			[path.join(repoPath, 'a_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go')]);
+	});
+
+	test('resolves file names in logs (GOPATH)', async () => {
+		setupRepo(true);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false },
+			[path.join(repoPath, 'a_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go')]);
+	});
+});
+
+// FakeOutputChannel is a fake output channel used to buffer
+// the output of the tested language client in an in-memory
+// string array until cleared.
+class FakeOutputChannel implements vscode.OutputChannel {
+	public name = 'FakeOutputChannel';
+	public show = sinon.fake(); // no-empty
+	public hide = sinon.fake(); // no-empty
+	public dispose = sinon.fake();  // no-empty
+
+	private buf = [] as string[];
+
+	public append = (v: string) => this.enqueue(v);
+	public appendLine = (v: string) => this.enqueue(v);
+	public clear = () => { this.buf = []; };
+	public toString = () => {
+		return this.buf.join('\n');
+	}
+
+	private enqueue = (v: string) => {
+		if (this.buf.length > 1024) { this.buf.shift(); }
+		this.buf.push(v.trim());
+	}
+}
diff --git a/test/mocks/MockMemento.ts b/test/mocks/MockMemento.ts
new file mode 100644
index 0000000..4c55f16
--- /dev/null
+++ b/test/mocks/MockMemento.ts
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Modification copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { Memento } from 'vscode';
+
+export class MockMemento implements Memento {
+	// _value must be named this way in order to match vscode's memento
+	private _value: Record<string, {}> = {};
+
+	public get(key: any, defaultValue?: any): any;
+	public get<T>(key: string, defaultValue?: T): T {
+		const exists = this._value.hasOwnProperty(key);
+		return exists ? this._value[key] : (defaultValue! as any);
+	}
+
+	public update(key: string, value: any): Thenable<void> {
+		this._value[key] = value;
+		return Promise.resolve();
+	}
+	public clear() {
+		this._value = {};
+	}
+}
diff --git a/test/runTest.ts b/test/runTest.ts
index d7656e6..edb587e 100644
--- a/test/runTest.ts
+++ b/test/runTest.ts
@@ -1,7 +1,5 @@
-import * as fs from 'fs-extra';
 import * as path from 'path';
 import { runTests } from 'vscode-test';
-import { extensionId } from '../src/const';
 
 async function main() {
 		// The folder containing the Extension Manifest package.json
diff --git a/tools/license.sh b/tools/license.sh
index 9647e1f..8750bca 100755
--- a/tools/license.sh
+++ b/tools/license.sh
@@ -40,6 +40,9 @@
   "Unlicense": 1,
   "0BSD": 1,
   "(Unlicense OR Apache-2.0)": 1,
+  "(MIT OR Apache-2.0)": 1,
+  "(MIT AND Zlib)": 1,
+  "(MIT AND BSD-3-Clause)": 1,
 } as $allowed_licenses |
 {
   "json-schema@0.2.3": 1,
diff --git a/tsconfig.json b/tsconfig.json
index 6045bef..df30337 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -20,4 +20,4 @@
 		"node_modules",
 		"third_party"
 	]
-}
\ No newline at end of file
+}
diff --git a/tslint.json b/tslint.json
index 41739c7..d9108ea 100644
--- a/tslint.json
+++ b/tslint.json
@@ -151,7 +151,8 @@
 			true,
 			"ban-keywords",
 			"check-format",
-			"allow-pascal-case"
+			"allow-pascal-case",
+			"allow-leading-underscore"
 		],
 		"whitespace": [
 			true,
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..65d2b3f
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,48 @@
+//@ts-check
+
+'use strict';
+
+const path = require('path');
+
+/**@type {import('webpack').Configuration}*/
+const config = {
+	target: 'node',
+	entry: {
+		goMain: './src/goMain.ts',
+		debugAdapter: './src/debugAdapter/goDebug.ts',
+		debugAdapter2: './src/debugAdapter2/goDlvDebugMain.ts',
+	},
+	output: {
+		path: path.resolve(__dirname, 'dist'),
+		filename: '[name].js',
+		libraryTarget: 'commonjs2',
+		devtoolModuleFilenameTemplate: '../[resource-path]',
+		sourceMapFilename: '[name].js.map'
+	},
+	devtool: 'source-map',
+	externals: {
+		// the vscode-module is created on-the-fly and must be excluded.
+		vscode: 'commonjs vscode'
+	},
+	resolve: {
+		extensions: ['.ts', '.js']
+	},
+	module: {
+		rules: [
+			{
+				test: /\.ts$/,
+				exclude: /node_modules/,
+				use: [
+					{
+						loader: 'ts-loader'
+					}
+				]
+			}
+		]
+	},
+	optimization: {
+		// when this is true, the debugger breaks...
+		minimize: false
+	},
+};
+module.exports = config;