Index: frontend/node_modules/v8-to-istanbul/CHANGELOG.md
===================================================================
--- frontend/node_modules/v8-to-istanbul/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,380 @@
+# Changelog
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+### [8.1.1](https://github.com/istanbuljs/v8-to-istanbul/compare/v8.1.0...v8.1.1) (2022-01-10)
+
+
+### Bug Fixes
+
+* handle undefined sourcesContent and null sourcesContent entry ([6c2e2ec](https://github.com/istanbuljs/v8-to-istanbul/commit/6c2e2ecd2aece8b01543f75dfa203744f8a785b9))
+* **perf:** optimize hit counting and source map performance ([3f83226](https://github.com/istanbuljs/v8-to-istanbul/commit/3f83226212e9fd26231bb313b36db4f2d0661970)), closes [#159](https://github.com/istanbuljs/v8-to-istanbul/issues/159)
+
+## [8.1.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v8.0.0...v8.1.0) (2021-09-27)
+
+
+### Features
+
+* function to cleanup allocated resources after usage ([#161](https://www.github.com/istanbuljs/v8-to-istanbul/issues/161)) ([a3925e9](https://www.github.com/istanbuljs/v8-to-istanbul/commit/a3925e9951fa88daee0aae5a7d35546b10f063a8))
+
+## [8.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.1.2...v8.0.0) (2021-06-03)
+
+
+### ⚠ BREAKING CHANGES
+
+* minimum Node version now 10.12.
+
+### Bug Fixes
+
+* address file URL path regression on Windows ([#146](https://www.github.com/istanbuljs/v8-to-istanbul/issues/146)) ([bb04c56](https://www.github.com/istanbuljs/v8-to-istanbul/commit/bb04c561bffe9802b7d2e7e91216aa1d9230490a))
+
+### [7.1.2](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.1.1...v7.1.2) (2021-05-05)
+
+
+### Bug Fixes
+
+* fix undefined line in branches and functions ([#139](https://www.github.com/istanbuljs/v8-to-istanbul/issues/139)) ([f5ed83d](https://www.github.com/istanbuljs/v8-to-istanbul/commit/f5ed83d185129db48e5c05c5225470ad114c7609))
+
+### [7.1.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.1.0...v7.1.1) (2021-03-30)
+
+
+### Bug Fixes
+
+* use original source path if no sources ([#135](https://www.github.com/istanbuljs/v8-to-istanbul/issues/135)) ([64b2c86](https://www.github.com/istanbuljs/v8-to-istanbul/commit/64b2c86099afe3ea9d484324902d4ec4c3965347))
+
+## [7.1.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.0.0...v7.1.0) (2020-12-22)
+
+
+### Features
+
+* support comment c8 ignore start/stop ([#130](https://www.github.com/istanbuljs/v8-to-istanbul/issues/130)) ([591126b](https://www.github.com/istanbuljs/v8-to-istanbul/commit/591126b102244465b27906cdb8cdb82df1f4e760))
+
+## [7.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v6.0.1...v7.0.0) (2020-10-25)
+
+
+### ⚠ BREAKING CHANGES
+
+* address off by one error processing branches (#127)
+
+### Bug Fixes
+
+* address off by one error processing branches ([#127](https://www.github.com/istanbuljs/v8-to-istanbul/issues/127)) ([746390f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/746390f871fb2d1c6ec9738892a605a9ea59af5c))
+* drop special shebang handling ([#125](https://www.github.com/istanbuljs/v8-to-istanbul/issues/125)) ([0d3b57f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/0d3b57f245003d934c0a824f1b6fe54dcebacdb7))
+* shebang handling supported in Node v12 ([#128](https://www.github.com/istanbuljs/v8-to-istanbul/issues/128)) ([522e4c2](https://www.github.com/istanbuljs/v8-to-istanbul/commit/522e4c25e6693e31191b47fc5729b6aff9909ce3))
+
+### [6.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v6.0.0...v6.0.1) (2020-10-08)
+
+
+### Bug Fixes
+
+* **build:** use new relese-please strategy ([c8edd37](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c8edd3741f803dd7485d01ee6f4fcf6a73570700))
+* **source-maps:** reverts off by one fix for ignore ([#123](https://www.github.com/istanbuljs/v8-to-istanbul/issues/123)) ([a886fb8](https://www.github.com/istanbuljs/v8-to-istanbul/commit/a886fb82d7e2c5332c6e507e201a9378dda84f50))
+
+## [6.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v5.0.1...v6.0.0) (2020-10-08)
+
+
+### ⚠ BREAKING CHANGES
+
+* address off by one error processing branches (#118)
+
+### Features
+
+* add support for 1:1 sourcesContent ([ac3c79a](https://www.github.com/istanbuljs/v8-to-istanbul/commit/ac3c79a688665e9f3f05aafe9295a3d71a21267d))
+
+
+### Bug Fixes
+
+* address off by one error processing branches ([#118](https://www.github.com/istanbuljs/v8-to-istanbul/issues/118)) ([abe51ea](https://www.github.com/istanbuljs/v8-to-istanbul/commit/abe51ea344171c827a014a8c86b3d3a2be5370ce))
+* favor mapping at 0th column ([#120](https://www.github.com/istanbuljs/v8-to-istanbul/issues/120)) ([770f17f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/770f17f49e2bf323bdc26f55f91adfedcbb94e25))
+
+### [5.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v5.0.0...v5.0.1) (2020-08-07)
+
+
+### Bug Fixes
+
+* add missing type in TS definition ([#113](https://www.github.com/istanbuljs/v8-to-istanbul/issues/113)) ([a14ebc2](https://www.github.com/istanbuljs/v8-to-istanbul/commit/a14ebc2f3c71cb854dacb06490ea3e0f9bc17dbd))
+
+## [5.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.4...v5.0.0) (2020-08-02)
+
+
+### ⚠ BREAKING CHANGES
+
+* drop Node 8 support (#110)
+* source map files with multiple sources will now be  parsed differently than  source map files with a single source.
+
+### Features
+
+* support source map with multiple sources ([#102](https://www.github.com/istanbuljs/v8-to-istanbul/issues/102)) ([d1f435c](https://www.github.com/istanbuljs/v8-to-istanbul/commit/d1f435cf183c510188ec5e43781d5bc10989a4e0)), closes [#21](https://www.github.com/istanbuljs/v8-to-istanbul/issues/21)
+
+
+### Bug Fixes
+
+* address path related bugs with 1:many source maps ([#108](https://www.github.com/istanbuljs/v8-to-istanbul/issues/108)) ([9a618bc](https://www.github.com/istanbuljs/v8-to-istanbul/commit/9a618bc374ef6e2205c26c5ebf728bc69f4a9288))
+
+
+### Build System
+
+* drop Node 8 support ([#110](https://www.github.com/istanbuljs/v8-to-istanbul/issues/110)) ([c8bf7a1](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c8bf7a1bdcf8b911943bb1ffc97e401d979aa11f))
+
+### [4.1.4](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.3...v4.1.4) (2020-05-06)
+
+
+### Bug Fixes
+
+* handle relative sourceRoots in source map files ([#100](https://www.github.com/istanbuljs/v8-to-istanbul/issues/100)) ([16ad3aa](https://www.github.com/istanbuljs/v8-to-istanbul/commit/16ad3aabd6144e2bf15fb4065e697bf40d1caaf4))
+
+### [4.1.3](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.2...v4.1.3) (2020-03-27)
+
+
+### Bug Fixes
+
+* handle sourcemap `sources` emtpy edge case ([#94](https://www.github.com/istanbuljs/v8-to-istanbul/issues/94)) ([628af48](https://www.github.com/istanbuljs/v8-to-istanbul/commit/628af48e2f7ab279c52f4355c0ccb92ac16b2c1a))
+* v8 coverage ranges that fall on \n characters cause exceptions ([#96](https://www.github.com/istanbuljs/v8-to-istanbul/issues/96)) ([c5731a3](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c5731a3b2fe4dccfae9ee581a5bf7a6e362f5cb8))
+
+### [4.1.2](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.1...v4.1.2) (2020-02-09)
+
+
+### Bug Fixes
+
+* protect against undefined sourcesContent ([#89](https://www.github.com/istanbuljs/v8-to-istanbul/issues/89)) ([5b94fe3](https://www.github.com/istanbuljs/v8-to-istanbul/commit/5b94fe37f9b86686386ad01f1fb8a42182f35ad8))
+
+### [4.1.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.0...v4.1.1) (2020-02-07)
+
+
+### Bug Fixes
+
+* **build:** repository field should have type ([#87](https://www.github.com/istanbuljs/v8-to-istanbul/issues/87)) ([f064542](https://www.github.com/istanbuljs/v8-to-istanbul/commit/f064542844c333d83fc25e0ad7f989f0999f8ceb))
+
+## [4.1.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.0.1...v4.1.0) (2020-02-06)
+
+
+### Features
+
+* use the inline source content if available ([#85](https://www.github.com/istanbuljs/v8-to-istanbul/issues/85)) ([1a6d47f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/1a6d47f1412d7c2b072fe794b6bd08bfbf4bbd55))
+
+### [4.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.0.0...v4.0.1) (2019-12-12)
+
+
+### Bug Fixes
+
+* loosen engine requirement so it can be installed on node 8 ([#82](https://www.github.com/istanbuljs/v8-to-istanbul/issues/82)) ([18f2587](https://www.github.com/istanbuljs/v8-to-istanbul/commit/18f2587481617e4db5ae1565c4f7052a8314af92))
+
+## [4.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v3.2.6...v4.0.0) (2019-11-23)
+
+
+### ⚠ BREAKING CHANGES
+
+* paths are now consistently absolute.
+
+### Features
+
+* adds special (empty-report) block ([#74](https://www.github.com/istanbuljs/v8-to-istanbul/issues/74)) ([e981cc1](https://www.github.com/istanbuljs/v8-to-istanbul/commit/e981cc156b447ce7a936114dafac591126fd65dd))
+
+
+### Bug Fixes
+
+* consistently resolve paths to absolute form ([#72](https://www.github.com/istanbuljs/v8-to-istanbul/issues/72)) ([55f4116](https://www.github.com/istanbuljs/v8-to-istanbul/commit/55f411624841f89f8309dc460387f8dd15c8b8f4))
+
+### [3.2.6](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.5...v3.2.6) (2019-10-24)
+
+
+### Bug Fixes
+
+* remove scheme from paths before joining ([#69](https://github.com/bcoe/v8-to-istanbul/issues/69)) ([10612fa](https://github.com/bcoe/v8-to-istanbul/commit/10612fa))
+
+### [3.2.5](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.4...v3.2.5) (2019-10-07)
+
+
+### Bug Fixes
+
+* fs.promises was not introduced until 10 ([#67](https://github.com/bcoe/v8-to-istanbul/issues/67)) ([cdcc225](https://github.com/bcoe/v8-to-istanbul/commit/cdcc225))
+
+### [3.2.4](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.3...v3.2.4) (2019-10-06)
+
+### [3.2.3](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.2...v3.2.3) (2019-06-24)
+
+
+### Bug Fixes
+
+* regex for detecting Node < 10.16 was off ([4ca7220](https://github.com/bcoe/v8-to-istanbul/commit/4ca7220))
+
+
+
+### [3.2.2](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.1...v3.2.2) (2019-06-24)
+
+
+### Bug Fixes
+
+* Node >10.16.0 now uses new module wrap API ([7d7c9cb](https://github.com/bcoe/v8-to-istanbul/commit/7d7c9cb))
+
+
+
+### [3.2.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.0...v3.2.1) (2019-06-23)
+
+
+### Bug Fixes
+
+* logic for handling sourceRoot did not take into account process.cwd() ([#39](https://github.com/bcoe/v8-to-istanbul/issues/39)) ([6ed9524](https://github.com/bcoe/v8-to-istanbul/commit/6ed9524))
+
+
+
+## [3.2.0](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.3...v3.2.0) (2019-06-23)
+
+
+### Build System
+
+* update testing matrix and deps ([#34](https://github.com/bcoe/v8-to-istanbul/issues/34)) ([204afca](https://github.com/bcoe/v8-to-istanbul/commit/204afca))
+
+
+### Features
+
+* add a sources option allowing to bypass fs operations ([#36](https://github.com/bcoe/v8-to-istanbul/issues/36)) ([4f5a681](https://github.com/bcoe/v8-to-istanbul/commit/4f5a681))
+* add TS typings ([#35](https://github.com/bcoe/v8-to-istanbul/issues/35)) ([5251108](https://github.com/bcoe/v8-to-istanbul/commit/5251108))
+* allow sourceMaps with sourceRoot ([#32](https://github.com/bcoe/v8-to-istanbul/issues/32)) ([8eb2ed0](https://github.com/bcoe/v8-to-istanbul/commit/8eb2ed0))
+
+
+
+### [3.1.3](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.2...v3.1.3) (2019-05-11)
+
+
+### Bug Fixes
+
+* **deps:** source-map should be dependency not dev-dependency ([3f6208e](https://github.com/bcoe/v8-to-istanbul/commit/3f6208e))
+
+
+
+## [3.1.2](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.1...v3.1.2) (2019-05-02)
+
+
+### Bug Fixes
+
+* the line with the ignore comment itself should be skipped ([#25](https://github.com/bcoe/v8-to-istanbul/issues/25)) ([e939594](https://github.com/bcoe/v8-to-istanbul/commit/e939594))
+
+
+
+## [3.1.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.0...v3.1.1) (2019-05-02)
+
+
+### Bug Fixes
+
+* we should ignore functions and branches ([#24](https://github.com/bcoe/v8-to-istanbul/issues/24)) ([d468559](https://github.com/bcoe/v8-to-istanbul/commit/d468559))
+
+
+
+# [3.1.0](https://github.com/bcoe/v8-to-istanbul/compare/v3.0.1...v3.1.0) (2019-05-02)
+
+
+### Features
+
+* allow uncovered lines to be ignored with special comment ([#23](https://github.com/bcoe/v8-to-istanbul/issues/23)) ([f585cfa](https://github.com/bcoe/v8-to-istanbul/commit/f585cfa))
+
+
+
+## [3.0.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.0.0...v3.0.1) (2019-05-01)
+
+
+### Bug Fixes
+
+* initial column could be 0 on Node 10, after wrapper taken into account ([#22](https://github.com/bcoe/v8-to-istanbul/issues/22)) ([aa3f73b](https://github.com/bcoe/v8-to-istanbul/commit/aa3f73b))
+
+
+
+# [3.0.0](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.2...v3.0.0) (2019-04-29)
+
+### Features
+
+* initial support for source-maps ([#19](https://github.com/bcoe/v8-to-istanbul/issues/19)) ([ab0fcdd](https://github.com/bcoe/v8-to-istanbul/commit/ab0fcdd))
+
+### BREAKING CHANGES
+
+* v8-to-istanbul is now async, making it possible to use the latest source-map library
+
+
+# [2.1.0](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.5...v2.1.0) (2019-04-21)
+
+
+### Features
+
+* store source so that it can be used by SourceMaps ([#18](https://github.com/bcoe/v8-to-istanbul/issues/18)) ([5afafd6](https://github.com/bcoe/v8-to-istanbul/commit/5afafd6))
+
+
+
+## [2.0.5](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.4...v2.0.5) (2019-04-18)
+
+
+### Bug Fixes
+
+* don't assume files to have CR characters on Windows ([#16](https://github.com/bcoe/v8-to-istanbul/issues/16)) ([c59a21a](https://github.com/bcoe/v8-to-istanbul/commit/c59a21a))
+
+
+
+## [2.0.4](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.3...v2.0.4) (2019-04-07)
+
+
+### Bug Fixes
+
+* Node 11 no longer wraps scripts by default ([#15](https://github.com/bcoe/v8-to-istanbul/issues/15)) ([fbbd113](https://github.com/bcoe/v8-to-istanbul/commit/fbbd113))
+
+
+
+## [2.0.3](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.2...v2.0.3) (2019-04-07)
+
+
+
+<a name="2.0.2"></a>
+## [2.0.2](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.1...v2.0.2) (2019-01-20)
+
+
+### Bug Fixes
+
+* windows has \r\n line separator ([#11](https://github.com/bcoe/v8-to-istanbul/issues/11)) ([c10b888](https://github.com/bcoe/v8-to-istanbul/commit/c10b888))
+
+
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.0...v2.0.1) (2019-01-20)
+
+
+### Bug Fixes
+
+* functions were not always counted ([#10](https://github.com/bcoe/v8-to-istanbul/issues/10)) ([464a1f0](https://github.com/bcoe/v8-to-istanbul/commit/464a1f0))
+
+
+
+<a name="2.0.0"></a>
+# [2.0.0](https://github.com/bcoe/v8-to-istanbul/compare/v1.2.1...v2.0.0) (2018-12-21)
+
+
+### Features
+
+* allow wrapper length to be configured ([#9](https://github.com/bcoe/v8-to-istanbul/issues/9)) ([5e76198](https://github.com/bcoe/v8-to-istanbul/commit/5e76198))
+
+
+### BREAKING CHANGES
+
+* we no longer attempt to detect ESM modules, rather the consumer sets a wrapper length
+
+
+
+<a name="1.2.1"></a>
+## [1.2.1](https://github.com/bcoe/v8-to-istanbul/compare/v1.2.0...v1.2.1) (2018-09-12)
+
+
+
+<a name="1.2.0"></a>
+# [1.2.0](https://github.com/bcoe/v8-to-istanbul/compare/v1.1.0...v1.2.0) (2017-12-05)
+
+
+### Features
+
+* support ESM modules ([#3](https://github.com/bcoe/v8-to-istanbul/issues/3)) ([992d13a](https://github.com/bcoe/v8-to-istanbul/commit/992d13a))
+
+
+
+<a name="1.1.0"></a>
+# 1.1.0 (2017-12-01)
+
+
+### Features
+
+* initial implementation ([6140c6c](https://github.com/bcoe/v8-to-istanbul/commit/6140c6c))
Index: frontend/node_modules/v8-to-istanbul/LICENSE.txt
===================================================================
--- frontend/node_modules/v8-to-istanbul/LICENSE.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/LICENSE.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,14 @@
+Copyright (c) 2017, Contributors
+
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Index: frontend/node_modules/v8-to-istanbul/README.md
===================================================================
--- frontend/node_modules/v8-to-istanbul/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,90 @@
+# v8-to-istanbul
+
+[![Build Status](https://travis-ci.org/istanbuljs/v8-to-istanbul.svg?branch=master)](https://travis-ci.org/istanbuljs/v8-to-istanbul)
+[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
+![nycrc config on GitHub](https://img.shields.io/nycrc/istanbuljs/v8-to-istanbul)
+
+converts from v8 coverage format to [istanbul's coverage format](https://github.com/gotwarlost/istanbul/blob/master/coverage.json.md).
+
+## Usage
+
+```js
+const v8toIstanbul = require('v8-to-istanbul')
+// the path to the original source-file is required, as its contents are
+// used during the conversion algorithm.
+const converter = v8toIstanbul('./path-to-instrumented-file.js')
+await converter.load() // this is required due to the async source-map dependency.
+// provide an array of coverage information in v8 format.
+converter.applyCoverage([
+  {
+    "functionName": "",
+    "ranges": [
+      {
+        "startOffset": 0,
+        "endOffset": 520,
+        "count": 1
+      }
+    ],
+    "isBlockCoverage": true
+  },
+  // ...
+])
+// output coverage information in a form that can
+// be consumed by Istanbul.
+console.info(JSON.stringify(converter.toIstanbul()))
+
+// cleanup resources allocated in "load" (i.e. by the source-map dependency),
+// the converter may not be used anymore afterwards
+converter.destroy() 
+```
+
+## Ignoring Uncovered Lines
+
+Sometimes you might find yourself wanting to ignore uncovered lines
+in your application (for example, perhaps you run your tests in Linux, but
+there's code that only executes on Windows).
+
+To ignore lines, use the special comment `/* c8 ignore next */`.
+
+### ignoring the next line
+
+```js
+const myVariable = 99
+/* c8 ignore next */
+if (process.platform === 'win32') console.info('hello world')
+```
+
+### ignoring the next N lines
+
+```js
+const myVariable = 99
+/* c8 ignore next 3 */
+if (process.platform === 'win32') {
+  console.info('hello world')
+}
+```
+
+### ignoring all lines until told
+
+```js
+/* c8 ignore start */
+function dontMindMe() {
+  // ...
+}
+/* c8 ignore stop */
+```
+
+### ignoring the same line as the comment
+
+```js
+const myVariable = 99
+const os = process.platform === 'darwin' ? 'OSXy' /* c8 ignore next */ : 'Windowsy' 
+```
+
+## Testing
+
+To execute tests, simply run:
+
+```bash
+npm test
+```
Index: frontend/node_modules/v8-to-istanbul/index.d.ts
===================================================================
--- frontend/node_modules/v8-to-istanbul/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,25 @@
+/// <reference types="node" />
+
+import { Profiler } from 'inspector'
+import { CoverageMapData } from 'istanbul-lib-coverage'
+import { RawSourceMap } from 'source-map'
+
+declare type Sources =
+  | {
+      source: string
+    }
+  | {
+      source: string
+      originalSource: string
+      sourceMap: { sourcemap: RawSourceMap }
+    }
+declare class V8ToIstanbul {
+  load(): Promise<void>
+  destroy(): void
+  applyCoverage(blocks: ReadonlyArray<Profiler.FunctionCoverage>): void
+  toIstanbul(): CoverageMapData
+}
+
+declare function v8ToIstanbul(scriptPath: string, wrapperLength?: number, sources?: Sources, excludePath?: (path: string) => boolean): V8ToIstanbul
+
+export = v8ToIstanbul
Index: frontend/node_modules/v8-to-istanbul/index.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,5 @@
+const V8ToIstanbul = require('./lib/v8-to-istanbul')
+
+module.exports = function (path, wrapperLength, sources, excludePath) {
+  return new V8ToIstanbul(path, wrapperLength, sources, excludePath)
+}
Index: frontend/node_modules/v8-to-istanbul/lib/branch.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/branch.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/branch.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,28 @@
+module.exports = class CovBranch {
+  constructor (startLine, startCol, endLine, endCol, count) {
+    this.startLine = startLine
+    this.startCol = startCol
+    this.endLine = endLine
+    this.endCol = endCol
+    this.count = count
+  }
+
+  toIstanbul () {
+    const location = {
+      start: {
+        line: this.startLine,
+        column: this.startCol
+      },
+      end: {
+        line: this.endLine,
+        column: this.endCol
+      }
+    }
+    return {
+      type: 'branch',
+      line: this.startLine,
+      loc: location,
+      locations: [Object.assign({}, location)]
+    }
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/lib/function.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/function.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/function.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+module.exports = class CovFunction {
+  constructor (name, startLine, startCol, endLine, endCol, count) {
+    this.name = name
+    this.startLine = startLine
+    this.startCol = startCol
+    this.endLine = endLine
+    this.endCol = endCol
+    this.count = count
+  }
+
+  toIstanbul () {
+    const loc = {
+      start: {
+        line: this.startLine,
+        column: this.startCol
+      },
+      end: {
+        line: this.endLine,
+        column: this.endCol
+      }
+    }
+    return {
+      name: this.name,
+      decl: loc,
+      loc: loc,
+      line: this.startLine
+    }
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/lib/line.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/line.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/line.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,34 @@
+module.exports = class CovLine {
+  constructor (line, startCol, lineStr) {
+    this.line = line
+    // note that startCol and endCol are absolute positions
+    // within a file, not relative to the line.
+    this.startCol = startCol
+
+    // the line length itself does not include the newline characters,
+    // these are however taken into account when enumerating absolute offset.
+    const matchedNewLineChar = lineStr.match(/\r?\n$/u)
+    const newLineLength = matchedNewLineChar ? matchedNewLineChar[0].length : 0
+    this.endCol = startCol + lineStr.length - newLineLength
+
+    // we start with all lines having been executed, and work
+    // backwards zeroing out lines based on V8 output.
+    this.count = 1
+
+    // set by source.js during parsing, if /* c8 ignore next */ is found.
+    this.ignore = false
+  }
+
+  toIstanbul () {
+    return {
+      start: {
+        line: this.line,
+        column: 0
+      },
+      end: {
+        line: this.line,
+        column: this.endCol - this.startCol
+      }
+    }
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/lib/range.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/range.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/range.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,33 @@
+/**
+ * ...something resembling a binary search, to find the lowest line within the range.
+ * And then you could break as soon as the line is longer than the range...
+ */
+module.exports.sliceRange = (lines, startCol, endCol, inclusive = false) => {
+  let start = 0
+  let end = lines.length - 1
+
+  /**
+   * I consider this a temporary solution until I find an alternaive way to fix the "off by one issue"
+   */
+  const extStartCol = inclusive ? startCol - 1 : startCol
+
+  while (start < end) {
+    const mid = (start + end) >> 1
+    if (lines[mid].startCol <= startCol && lines[mid].endCol > extStartCol) {
+      start = mid
+      end = start
+    } else if (lines[mid].startCol > startCol) {
+      end = mid - 1
+    } else {
+      start = mid + 1
+    }
+  }
+  if (start === end) {
+    while (end < lines.length && extStartCol < lines[end].endCol && endCol >= lines[end].startCol) {
+      ++end
+    }
+    return lines.slice(start, end)
+  } else {
+    return []
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/lib/source.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/source.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/source.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,245 @@
+const CovLine = require('./line')
+const { sliceRange } = require('./range')
+const { GREATEST_LOWER_BOUND, LEAST_UPPER_BOUND } = require('source-map').SourceMapConsumer
+
+module.exports = class CovSource {
+  constructor (sourceRaw, wrapperLength) {
+    sourceRaw = sourceRaw ? sourceRaw.trimEnd() : ''
+    this.lines = []
+    this.eof = sourceRaw.length
+    this.shebangLength = getShebangLength(sourceRaw)
+    this.wrapperLength = wrapperLength - this.shebangLength
+    this._buildLines(sourceRaw)
+  }
+
+  _buildLines (source) {
+    let position = 0
+    let ignoreCount = 0
+    let ignoreAll = false
+    for (const [i, lineStr] of source.split(/(?<=\r?\n)/u).entries()) {
+      const line = new CovLine(i + 1, position, lineStr)
+      if (ignoreCount > 0) {
+        line.ignore = true
+        ignoreCount--
+      } else if (ignoreAll) {
+        line.ignore = true
+      }
+      this.lines.push(line)
+      position += lineStr.length
+
+      const ignoreToken = this._parseIgnore(lineStr)
+      if (!ignoreToken) continue
+
+      line.ignore = true
+      if (ignoreToken.count !== undefined) {
+        ignoreCount = ignoreToken.count
+      }
+      if (ignoreToken.start || ignoreToken.stop) {
+        ignoreAll = ignoreToken.start
+        ignoreCount = 0
+      }
+    }
+  }
+
+  /**
+   * Parses for comments:
+   *    c8 ignore next
+   *    c8 ignore next 3
+   *    c8 ignore start
+   *    c8 ignore stop
+   * @param {string} lineStr
+   * @return {{count?: number, start?: boolean, stop?: boolean}|undefined}
+   */
+  _parseIgnore (lineStr) {
+    const testIgnoreNextLines = lineStr.match(/^\W*\/\* c8 ignore next (?<count>[0-9]+) *\*\/\W*$/)
+    if (testIgnoreNextLines) {
+      return { count: Number(testIgnoreNextLines.groups.count) }
+    }
+
+    // Check if comment is on its own line.
+    if (lineStr.match(/^\W*\/\* c8 ignore next *\*\/\W*$/)) {
+      return { count: 1 }
+    }
+
+    if (lineStr.match(/\/\* c8 ignore next \*\//)) {
+      // Won't ignore successive lines, but the current line will be ignored.
+      return { count: 0 }
+    }
+
+    const testIgnoreStartStop = lineStr.match(/\/\* c8 ignore (?<mode>start|stop) *\*\//)
+    if (testIgnoreStartStop) {
+      if (testIgnoreStartStop.groups.mode === 'start') return { start: true }
+      if (testIgnoreStartStop.groups.mode === 'stop') return { stop: true }
+    }
+  }
+
+  // given a start column and end column in absolute offsets within
+  // a source file (0 - EOF), returns the relative line column positions.
+  offsetToOriginalRelative (sourceMap, startCol, endCol) {
+    const lines = sliceRange(this.lines, startCol, endCol, true)
+    if (!lines.length) return {}
+
+    const start = originalPositionTryBoth(
+      sourceMap,
+      lines[0].line,
+      Math.max(0, startCol - lines[0].startCol)
+    )
+    if (!(start && start.source)) {
+      return {}
+    }
+
+    let end = originalEndPositionFor(
+      sourceMap,
+      lines[lines.length - 1].line,
+      endCol - lines[lines.length - 1].startCol
+    )
+    if (!(end && end.source)) {
+      return {}
+    }
+
+    if (start.source !== end.source) {
+      return {}
+    }
+
+    if (start.line === end.line && start.column === end.column) {
+      end = sourceMap.originalPositionFor({
+        line: lines[lines.length - 1].line,
+        column: endCol - lines[lines.length - 1].startCol,
+        bias: LEAST_UPPER_BOUND
+      })
+      end.column -= 1
+    }
+
+    return {
+      source: start.source,
+      startLine: start.line,
+      relStartCol: start.column,
+      endLine: end.line,
+      relEndCol: end.column
+    }
+  }
+
+  relativeToOffset (line, relCol) {
+    line = Math.max(line, 1)
+    if (this.lines[line - 1] === undefined) return this.eof
+    return Math.min(this.lines[line - 1].startCol + relCol, this.lines[line - 1].endCol)
+  }
+}
+
+// this implementation is pulled over from istanbul-lib-sourcemap:
+// https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-lib-source-maps/lib/get-mapping.js
+//
+/**
+ * AST ranges are inclusive for start positions and exclusive for end positions.
+ * Source maps are also logically ranges over text, though interacting with
+ * them is generally achieved by working with explicit positions.
+ *
+ * When finding the _end_ location of an AST item, the range behavior is
+ * important because what we're asking for is the _end_ of whatever range
+ * corresponds to the end location we seek.
+ *
+ * This boils down to the following steps, conceptually, though the source-map
+ * library doesn't expose primitives to do this nicely:
+ *
+ * 1. Find the range on the generated file that ends at, or exclusively
+ *    contains the end position of the AST node.
+ * 2. Find the range on the original file that corresponds to
+ *    that generated range.
+ * 3. Find the _end_ location of that original range.
+ */
+function originalEndPositionFor (sourceMap, line, column) {
+  // Given the generated location, find the original location of the mapping
+  // that corresponds to a range on the generated file that overlaps the
+  // generated file end location. Note however that this position on its
+  // own is not useful because it is the position of the _start_ of the range
+  // on the original file, and we want the _end_ of the range.
+  const beforeEndMapping = originalPositionTryBoth(
+    sourceMap,
+    line,
+    Math.max(column - 1, 1)
+  )
+
+  if (beforeEndMapping.source === null) {
+    return null
+  }
+
+  // Convert that original position back to a generated one, with a bump
+  // to the right, and a rightward bias. Since 'generatedPositionFor' searches
+  // for mappings in the original-order sorted list, this will find the
+  // mapping that corresponds to the one immediately after the
+  // beforeEndMapping mapping.
+  const afterEndMapping = sourceMap.generatedPositionFor({
+    source: beforeEndMapping.source,
+    line: beforeEndMapping.line,
+    column: beforeEndMapping.column + 1,
+    bias: LEAST_UPPER_BOUND
+  })
+  if (
+  // If this is null, it means that we've hit the end of the file,
+  // so we can use Infinity as the end column.
+    afterEndMapping.line === null ||
+      // If these don't match, it means that the call to
+      // 'generatedPositionFor' didn't find any other original mappings on
+      // the line we gave, so consider the binding to extend to infinity.
+      sourceMap.originalPositionFor(afterEndMapping).line !==
+          beforeEndMapping.line
+  ) {
+    return {
+      source: beforeEndMapping.source,
+      line: beforeEndMapping.line,
+      column: Infinity
+    }
+  }
+
+  // Convert the end mapping into the real original position.
+  return sourceMap.originalPositionFor(afterEndMapping)
+}
+
+function originalPositionTryBoth (sourceMap, line, column) {
+  let original = sourceMap.originalPositionFor({
+    line,
+    column,
+    bias: GREATEST_LOWER_BOUND
+  })
+  if (original.line === null) {
+    original = sourceMap.originalPositionFor({
+      line,
+      column,
+      bias: LEAST_UPPER_BOUND
+    })
+  }
+  // The source maps generated by https://github.com/istanbuljs/istanbuljs
+  // (using @babel/core 7.7.5) have behavior, such that a mapping
+  // mid-way through a line maps to an earlier line than a mapping
+  // at position 0. Using the line at positon 0 seems to provide better reports:
+  //
+  //     if (true) {
+  //        cov_y5divc6zu().b[1][0]++;
+  //        cov_y5divc6zu().s[3]++;
+  //        console.info('reachable');
+  //     }  else { ... }
+  //  ^  ^
+  // l5  l3
+  const min = sourceMap.originalPositionFor({
+    line,
+    column: 0,
+    bias: GREATEST_LOWER_BOUND
+  })
+  if (min.line > original.line) {
+    original = min
+  }
+  return original
+}
+
+// Not required since Node 12, see: https://github.com/nodejs/node/pull/27375
+const isPreNode12 = /^v1[0-1]\./u.test(process.version)
+function getShebangLength (source) {
+  if (isPreNode12 && source.indexOf('#!') === 0) {
+    const match = source.match(/(?<shebang>#!.*)/)
+    if (match) {
+      return match.groups.shebang.length
+    }
+  } else {
+    return 0
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,318 @@
+const assert = require('assert')
+const convertSourceMap = require('convert-source-map')
+const util = require('util')
+const debuglog = util.debuglog('c8')
+const { dirname, isAbsolute, join, resolve } = require('path')
+const { fileURLToPath } = require('url')
+const CovBranch = require('./branch')
+const CovFunction = require('./function')
+const CovSource = require('./source')
+const { sliceRange } = require('./range')
+const compatError = Error(`requires Node.js ${require('../package.json').engines.node}`)
+let readFile = () => { throw compatError }
+try {
+  readFile = require('fs').promises.readFile
+} catch (_err) {
+  // most likely we're on an older version of Node.js.
+}
+const { SourceMapConsumer } = require('source-map')
+const isOlderNode10 = /^v10\.(([0-9]\.)|(1[0-5]\.))/u.test(process.version)
+const isNode8 = /^v8\./.test(process.version)
+
+// Injected when Node.js is loading script into isolate pre Node 10.16.x.
+// see: https://github.com/nodejs/node/pull/21573.
+const cjsWrapperLength = isOlderNode10 ? require('module').wrapper[0].length : 0
+
+module.exports = class V8ToIstanbul {
+  constructor (scriptPath, wrapperLength, sources, excludePath) {
+    assert(typeof scriptPath === 'string', 'scriptPath must be a string')
+    assert(!isNode8, 'This module does not support node 8 or lower, please upgrade to node 10')
+    this.path = parsePath(scriptPath)
+    this.wrapperLength = wrapperLength === undefined ? cjsWrapperLength : wrapperLength
+    this.excludePath = excludePath || (() => false)
+    this.sources = sources || {}
+    this.generatedLines = []
+    this.branches = {}
+    this.functions = {}
+    this.covSources = []
+    this.rawSourceMap = undefined
+    this.sourceMap = undefined
+    this.sourceTranspiled = undefined
+    // Indicate that this report was generated with placeholder data from
+    // running --all:
+    this.all = false
+  }
+
+  async load () {
+    const rawSource = this.sources.source || await readFile(this.path, 'utf8')
+    this.rawSourceMap = this.sources.sourceMap ||
+      // if we find a source-map (either inline, or a .map file) we load
+      // both the transpiled and original source, both of which are used during
+      // the backflips we perform to remap absolute to relative positions.
+      convertSourceMap.fromSource(rawSource) || convertSourceMap.fromMapFileSource(rawSource, dirname(this.path))
+
+    if (this.rawSourceMap) {
+      if (this.rawSourceMap.sourcemap.sources.length > 1) {
+        this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap)
+        if (!this.sourceMap.sourcesContent) {
+          this.sourceMap.sourcesContent = await this.sourcesContentFromSources()
+        }
+        this.covSources = this.sourceMap.sourcesContent.map((rawSource, i) => ({ source: new CovSource(rawSource, this.wrapperLength), path: this.sourceMap.sources[i] }))
+        this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength)
+      } else {
+        const candidatePath = this.rawSourceMap.sourcemap.sources.length >= 1 ? this.rawSourceMap.sourcemap.sources[0] : this.rawSourceMap.sourcemap.file
+        this.path = this._resolveSource(this.rawSourceMap, candidatePath || this.path)
+        this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap)
+
+        let originalRawSource
+        if (this.sources.sourceMap && this.sources.sourceMap.sourcemap && this.sources.sourceMap.sourcemap.sourcesContent && this.sources.sourceMap.sourcemap.sourcesContent.length === 1) {
+          // If the sourcesContent field has been provided, return it rather than attempting
+          // to load the original source from disk.
+          // TODO: investigate whether there's ever a case where we hit this logic with 1:many sources.
+          originalRawSource = this.sources.sourceMap.sourcemap.sourcesContent[0]
+        } else if (this.sources.originalSource) {
+          // Original source may be populated on the sources object.
+          originalRawSource = this.sources.originalSource
+        } else if (this.sourceMap.sourcesContent && this.sourceMap.sourcesContent[0]) {
+          // perhaps we loaded sourcesContent was populated by an inline source map, or .map file?
+          // TODO: investigate whether there's ever a case where we hit this logic with 1:many sources.
+          originalRawSource = this.sourceMap.sourcesContent[0]
+        } else {
+          // We fallback to reading the original source from disk.
+          originalRawSource = await readFile(this.path, 'utf8')
+        }
+        this.covSources = [{ source: new CovSource(originalRawSource, this.wrapperLength), path: this.path }]
+        this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength)
+      }
+    } else {
+      this.covSources = [{ source: new CovSource(rawSource, this.wrapperLength), path: this.path }]
+    }
+  }
+
+  async sourcesContentFromSources () {
+    const fileList = this.sourceMap.sources.map(relativePath => {
+      const realPath = this._resolveSource(this.rawSourceMap, relativePath)
+      return readFile(realPath, 'utf-8')
+        .then(result => result)
+        .catch(err => {
+          debuglog(`failed to load ${realPath}: ${err.message}`)
+        })
+    })
+    return await Promise.all(fileList)
+  }
+
+  destroy () {
+    if (this.sourceMap) {
+      this.sourceMap.destroy()
+      this.sourceMap = undefined
+    }
+  }
+
+  _resolveSource (rawSourceMap, sourcePath) {
+    if (sourcePath.startsWith('file://')) {
+      return fileURLToPath(sourcePath)
+    }
+    sourcePath = sourcePath.replace(/^webpack:\/\//, '')
+    const sourceRoot = rawSourceMap.sourcemap.sourceRoot ? rawSourceMap.sourcemap.sourceRoot.replace('file://', '') : ''
+    const candidatePath = join(sourceRoot, sourcePath)
+
+    if (isAbsolute(candidatePath)) {
+      return candidatePath
+    } else {
+      return resolve(dirname(this.path), candidatePath)
+    }
+  }
+
+  applyCoverage (blocks) {
+    blocks.forEach(block => {
+      block.ranges.forEach((range, i) => {
+        const { startCol, endCol, path, covSource } = this._maybeRemapStartColEndCol(range)
+        if (this.excludePath(path)) {
+          return
+        }
+        let lines
+        if (block.functionName === '(empty-report)') {
+          // (empty-report), this will result in a report that has all lines zeroed out.
+          lines = covSource.lines.filter((line) => {
+            line.count = 0
+            return true
+          })
+          this.all = lines.length > 0
+        } else {
+          lines = sliceRange(covSource.lines, startCol, endCol)
+        }
+        if (!lines.length) {
+          return
+        }
+
+        const startLineInstance = lines[0]
+        const endLineInstance = lines[lines.length - 1]
+
+        if (block.isBlockCoverage) {
+          this.branches[path] = this.branches[path] || []
+          // record branches.
+          this.branches[path].push(new CovBranch(
+            startLineInstance.line,
+            startCol - startLineInstance.startCol,
+            endLineInstance.line,
+            endCol - endLineInstance.startCol,
+            range.count
+          ))
+
+          // if block-level granularity is enabled, we still create a single
+          // CovFunction tracking object for each set of ranges.
+          if (block.functionName && i === 0) {
+            this.functions[path] = this.functions[path] || []
+            this.functions[path].push(new CovFunction(
+              block.functionName,
+              startLineInstance.line,
+              startCol - startLineInstance.startCol,
+              endLineInstance.line,
+              endCol - endLineInstance.startCol,
+              range.count
+            ))
+          }
+        } else if (block.functionName) {
+          this.functions[path] = this.functions[path] || []
+          // record functions.
+          this.functions[path].push(new CovFunction(
+            block.functionName,
+            startLineInstance.line,
+            startCol - startLineInstance.startCol,
+            endLineInstance.line,
+            endCol - endLineInstance.startCol,
+            range.count
+          ))
+        }
+
+        // record the lines (we record these as statements, such that we're
+        // compatible with Istanbul 2.0).
+        lines.forEach(line => {
+          // make sure branch spans entire line; don't record 'goodbye'
+          // branch in `const foo = true ? 'hello' : 'goodbye'` as a
+          // 0 for line coverage.
+          //
+          // All lines start out with coverage of 1, and are later set to 0
+          // if they are not invoked; line.ignore prevents a line from being
+          // set to 0, and is set if the special comment /* c8 ignore next */
+          // is used.
+
+          if (startCol <= line.startCol && endCol >= line.endCol && !line.ignore) {
+            line.count = range.count
+          }
+        })
+      })
+    })
+  }
+
+  _maybeRemapStartColEndCol (range) {
+    let covSource = this.covSources[0].source
+    let startCol = Math.max(0, range.startOffset - covSource.wrapperLength)
+    let endCol = Math.min(covSource.eof, range.endOffset - covSource.wrapperLength)
+    let path = this.path
+
+    if (this.sourceMap) {
+      startCol = Math.max(0, range.startOffset - this.sourceTranspiled.wrapperLength)
+      endCol = Math.min(this.sourceTranspiled.eof, range.endOffset - this.sourceTranspiled.wrapperLength)
+
+      const { startLine, relStartCol, endLine, relEndCol, source } = this.sourceTranspiled.offsetToOriginalRelative(
+        this.sourceMap,
+        startCol,
+        endCol
+      )
+
+      const matchingSource = this.covSources.find(covSource => covSource.path === source)
+      covSource = matchingSource ? matchingSource.source : this.covSources[0].source
+      path = matchingSource ? matchingSource.path : this.covSources[0].path
+
+      // next we convert these relative positions back to absolute positions
+      // in the original source (which is the format expected in the next step).
+      startCol = covSource.relativeToOffset(startLine, relStartCol)
+      endCol = covSource.relativeToOffset(endLine, relEndCol)
+    }
+
+    return {
+      path,
+      covSource,
+      startCol,
+      endCol
+    }
+  }
+
+  getInnerIstanbul (source, path) {
+    // We apply the "Resolving Sources" logic (as defined in
+    // sourcemaps.info/spec.html) as a final step for 1:many source maps.
+    // for 1:1 source maps, the resolve logic is applied while loading.
+    //
+    // TODO: could we move the resolving logic for 1:1 source maps to the final
+    // step as well? currently this breaks some tests in c8.
+    let resolvedPath = path
+    if (this.rawSourceMap && this.rawSourceMap.sourcemap.sources.length > 1) {
+      resolvedPath = this._resolveSource(this.rawSourceMap, path)
+    }
+
+    if (this.excludePath(resolvedPath)) {
+      return
+    }
+
+    return {
+      [resolvedPath]: {
+        path: resolvedPath,
+        all: this.all,
+        ...this._statementsToIstanbul(source, path),
+        ...this._branchesToIstanbul(source, path),
+        ...this._functionsToIstanbul(source, path)
+      }
+    }
+  }
+
+  toIstanbul () {
+    return this.covSources.reduce((istanbulOuter, { source, path }) => Object.assign(istanbulOuter, this.getInnerIstanbul(source, path)), {})
+  }
+
+  _statementsToIstanbul (source, path) {
+    const statements = {
+      statementMap: {},
+      s: {}
+    }
+    source.lines.forEach((line, index) => {
+      statements.statementMap[`${index}`] = line.toIstanbul()
+      statements.s[`${index}`] = line.count
+    })
+    return statements
+  }
+
+  _branchesToIstanbul (source, path) {
+    const branches = {
+      branchMap: {},
+      b: {}
+    }
+    this.branches[path] = this.branches[path] || []
+    this.branches[path].forEach((branch, index) => {
+      const srcLine = source.lines[branch.startLine - 1]
+      const ignore = srcLine === undefined ? true : srcLine.ignore
+      branches.branchMap[`${index}`] = branch.toIstanbul()
+      branches.b[`${index}`] = [ignore ? 1 : branch.count]
+    })
+    return branches
+  }
+
+  _functionsToIstanbul (source, path) {
+    const functions = {
+      fnMap: {},
+      f: {}
+    }
+    this.functions[path] = this.functions[path] || []
+    this.functions[path].forEach((fn, index) => {
+      const srcLine = source.lines[fn.startLine - 1]
+      const ignore = srcLine === undefined ? true : srcLine.ignore
+      functions.fnMap[`${index}`] = fn.toIstanbul()
+      functions.f[`${index}`] = ignore ? 1 : fn.count
+    })
+    return functions
+  }
+}
+
+function parsePath (scriptPath) {
+  return scriptPath.startsWith('file://') ? fileURLToPath(scriptPath) : scriptPath
+}
Index: frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/LICENSE
===================================================================
--- frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,23 @@
+Copyright 2013 Thorsten Lorenz. 
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
Index: frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/README.md
===================================================================
--- frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,123 @@
+# convert-source-map [![Build Status][ci-image]][ci-url]
+
+Converts a source-map from/to  different formats and allows adding/changing properties.
+
+```js
+var convert = require('convert-source-map');
+
+var json = convert
+  .fromComment('//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQvZm9vLm1pbi5qcyIsInNvdXJjZXMiOlsic3JjL2Zvby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIvIn0=')
+  .toJSON();
+
+var modified = convert
+  .fromComment('//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQvZm9vLm1pbi5qcyIsInNvdXJjZXMiOlsic3JjL2Zvby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIvIn0=')
+  .setProperty('sources', [ 'SRC/FOO.JS' ])
+  .toJSON();
+
+console.log(json);
+console.log(modified);
+```
+
+```json
+{"version":3,"file":"build/foo.min.js","sources":["src/foo.js"],"names":[],"mappings":"AAAA","sourceRoot":"/"}
+{"version":3,"file":"build/foo.min.js","sources":["SRC/FOO.JS"],"names":[],"mappings":"AAAA","sourceRoot":"/"}
+```
+
+## API
+
+### fromObject(obj)
+
+Returns source map converter from given object.
+
+### fromJSON(json)
+
+Returns source map converter from given json string.
+
+### fromBase64(base64)
+
+Returns source map converter from given base64 encoded json string.
+
+### fromComment(comment)
+
+Returns source map converter from given base64 encoded json string prefixed with `//# sourceMappingURL=...`.
+
+### fromMapFileComment(comment, mapFileDir)
+
+Returns source map converter from given `filename` by parsing `//# sourceMappingURL=filename`.
+
+`filename` must point to a file that is found inside the `mapFileDir`. Most tools store this file right next to the
+generated file, i.e. the one containing the source map.
+
+### fromSource(source)
+
+Finds last sourcemap comment in file and returns source map converter or returns null if no source map comment was found.
+
+### fromMapFileSource(source, mapFileDir)
+
+Finds last sourcemap comment in file and returns source map converter or returns null if no source map comment was
+found.
+
+The sourcemap will be read from the map file found by parsing `# sourceMappingURL=file` comment. For more info see
+fromMapFileComment.
+
+### toObject()
+
+Returns a copy of the underlying source map.
+
+### toJSON([space])
+
+Converts source map to json string. If `space` is given (optional), this will be passed to
+[JSON.stringify](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify) when the
+JSON string is generated.
+
+### toBase64()
+
+Converts source map to base64 encoded json string.
+
+### toComment([options])
+
+Converts source map to an inline comment that can be appended to the source-file.
+
+By default, the comment is formatted like: `//# sourceMappingURL=...`, which you would
+normally see in a JS source file.
+
+When `options.multiline == true`, the comment is formatted like: `/*# sourceMappingURL=... */`, which you would find in a CSS source file.
+
+### addProperty(key, value)
+
+Adds given property to the source map. Throws an error if property already exists.
+
+### setProperty(key, value)
+
+Sets given property to the source map. If property doesn't exist it is added, otherwise its value is updated.
+
+### getProperty(key)
+
+Gets given property of the source map.
+
+### removeComments(src)
+
+Returns `src` with all source map comments removed
+
+### removeMapFileComments(src)
+
+Returns `src` with all source map comments pointing to map files removed.
+
+### commentRegex
+
+Provides __a fresh__ RegExp each time it is accessed. Can be used to find source map comments.
+
+### mapFileCommentRegex
+
+Provides __a fresh__ RegExp each time it is accessed. Can be used to find source map comments pointing to map files.
+
+### generateMapFileComment(file, [options])
+
+Returns a comment that links to an external source map via `file`.
+
+By default, the comment is formatted like: `//# sourceMappingURL=...`, which you would normally see in a JS source file.
+
+When `options.multiline == true`, the comment is formatted like: `/*# sourceMappingURL=... */`, which you would find in a CSS source file.
+
+[ci-url]: https://github.com/thlorenz/convert-source-map/actions?query=workflow:ci
+[ci-image]: https://img.shields.io/github/workflow/status/thlorenz/convert-source-map/CI?style=flat-square
Index: frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/index.js
===================================================================
--- frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,179 @@
+'use strict';
+var fs = require('fs');
+var path = require('path');
+
+Object.defineProperty(exports, 'commentRegex', {
+  get: function getCommentRegex () {
+    return /^\s*\/(?:\/|\*)[@#]\s+sourceMappingURL=data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(?:.*)$/mg;
+  }
+});
+
+Object.defineProperty(exports, 'mapFileCommentRegex', {
+  get: function getMapFileCommentRegex () {
+    // Matches sourceMappingURL in either // or /* comment styles.
+    return /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"`]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/){1}[ \t]*$)/mg;
+  }
+});
+
+var decodeBase64;
+if (typeof Buffer !== 'undefined') {
+  if (typeof Buffer.from === 'function') {
+    decodeBase64 = decodeBase64WithBufferFrom;
+  } else {
+    decodeBase64 = decodeBase64WithNewBuffer;
+  }
+} else {
+  decodeBase64 = decodeBase64WithAtob;
+}
+
+function decodeBase64WithBufferFrom(base64) {
+  return Buffer.from(base64, 'base64').toString();
+}
+
+function decodeBase64WithNewBuffer(base64) {
+  if (typeof value === 'number') {
+    throw new TypeError('The value to decode must not be of type number.');
+  }
+  return new Buffer(base64, 'base64').toString();
+}
+
+function decodeBase64WithAtob(base64) {
+  return decodeURIComponent(escape(atob(base64)));
+}
+
+function stripComment(sm) {
+  return sm.split(',').pop();
+}
+
+function readFromFileMap(sm, dir) {
+  // NOTE: this will only work on the server since it attempts to read the map file
+
+  var r = exports.mapFileCommentRegex.exec(sm);
+
+  // for some odd reason //# .. captures in 1 and /* .. */ in 2
+  var filename = r[1] || r[2];
+  var filepath = path.resolve(dir, filename);
+
+  try {
+    return fs.readFileSync(filepath, 'utf8');
+  } catch (e) {
+    throw new Error('An error occurred while trying to read the map file at ' + filepath + '\n' + e);
+  }
+}
+
+function Converter (sm, opts) {
+  opts = opts || {};
+
+  if (opts.isFileComment) sm = readFromFileMap(sm, opts.commentFileDir);
+  if (opts.hasComment) sm = stripComment(sm);
+  if (opts.isEncoded) sm = decodeBase64(sm);
+  if (opts.isJSON || opts.isEncoded) sm = JSON.parse(sm);
+
+  this.sourcemap = sm;
+}
+
+Converter.prototype.toJSON = function (space) {
+  return JSON.stringify(this.sourcemap, null, space);
+};
+
+if (typeof Buffer !== 'undefined') {
+  if (typeof Buffer.from === 'function') {
+    Converter.prototype.toBase64 = encodeBase64WithBufferFrom;
+  } else {
+    Converter.prototype.toBase64 = encodeBase64WithNewBuffer;
+  }
+} else {
+  Converter.prototype.toBase64 = encodeBase64WithBtoa;
+}
+
+function encodeBase64WithBufferFrom() {
+  var json = this.toJSON();
+  return Buffer.from(json, 'utf8').toString('base64');
+}
+
+function encodeBase64WithNewBuffer() {
+  var json = this.toJSON();
+  if (typeof json === 'number') {
+    throw new TypeError('The json to encode must not be of type number.');
+  }
+  return new Buffer(json, 'utf8').toString('base64');
+}
+
+function encodeBase64WithBtoa() {
+  var json = this.toJSON();
+  return btoa(unescape(encodeURIComponent(json)));
+}
+
+Converter.prototype.toComment = function (options) {
+  var base64 = this.toBase64();
+  var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
+  return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
+};
+
+// returns copy instead of original
+Converter.prototype.toObject = function () {
+  return JSON.parse(this.toJSON());
+};
+
+Converter.prototype.addProperty = function (key, value) {
+  if (this.sourcemap.hasOwnProperty(key)) throw new Error('property "' + key + '" already exists on the sourcemap, use set property instead');
+  return this.setProperty(key, value);
+};
+
+Converter.prototype.setProperty = function (key, value) {
+  this.sourcemap[key] = value;
+  return this;
+};
+
+Converter.prototype.getProperty = function (key) {
+  return this.sourcemap[key];
+};
+
+exports.fromObject = function (obj) {
+  return new Converter(obj);
+};
+
+exports.fromJSON = function (json) {
+  return new Converter(json, { isJSON: true });
+};
+
+exports.fromBase64 = function (base64) {
+  return new Converter(base64, { isEncoded: true });
+};
+
+exports.fromComment = function (comment) {
+  comment = comment
+    .replace(/^\/\*/g, '//')
+    .replace(/\*\/$/g, '');
+
+  return new Converter(comment, { isEncoded: true, hasComment: true });
+};
+
+exports.fromMapFileComment = function (comment, dir) {
+  return new Converter(comment, { commentFileDir: dir, isFileComment: true, isJSON: true });
+};
+
+// Finds last sourcemap comment in file or returns null if none was found
+exports.fromSource = function (content) {
+  var m = content.match(exports.commentRegex);
+  return m ? exports.fromComment(m.pop()) : null;
+};
+
+// Finds last sourcemap comment in file or returns null if none was found
+exports.fromMapFileSource = function (content, dir) {
+  var m = content.match(exports.mapFileCommentRegex);
+  return m ? exports.fromMapFileComment(m.pop(), dir) : null;
+};
+
+exports.removeComments = function (src) {
+  return src.replace(exports.commentRegex, '');
+};
+
+exports.removeMapFileComments = function (src) {
+  return src.replace(exports.mapFileCommentRegex, '');
+};
+
+exports.generateMapFileComment = function (file, options) {
+  var data = 'sourceMappingURL=' + file;
+  return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
+};
Index: frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/package.json
===================================================================
--- frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/node_modules/convert-source-map/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,41 @@
+{
+  "name": "convert-source-map",
+  "version": "1.9.0",
+  "description": "Converts a source-map from/to  different formats and allows adding/changing properties.",
+  "main": "index.js",
+  "scripts": {
+    "test": "tap test/*.js --color"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/thlorenz/convert-source-map.git"
+  },
+  "homepage": "https://github.com/thlorenz/convert-source-map",
+  "devDependencies": {
+    "inline-source-map": "~0.6.2",
+    "tap": "~9.0.0"
+  },
+  "keywords": [
+    "convert",
+    "sourcemap",
+    "source",
+    "map",
+    "browser",
+    "debug"
+  ],
+  "author": {
+    "name": "Thorsten Lorenz",
+    "email": "thlorenz@gmx.de",
+    "url": "http://thlorenz.com"
+  },
+  "license": "MIT",
+  "engine": {
+    "node": ">=0.6"
+  },
+  "files": [
+    "index.js"
+  ],
+  "browser": {
+    "fs": false
+  }
+}
Index: frontend/node_modules/v8-to-istanbul/package.json
===================================================================
--- frontend/node_modules/v8-to-istanbul/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/v8-to-istanbul/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,48 @@
+{
+  "name": "v8-to-istanbul",
+  "version": "8.1.1",
+  "description": "convert from v8 coverage format to istanbul's format",
+  "main": "index.js",
+  "types": "index.d.ts",
+  "scripts": {
+    "fix": "standard --fix",
+    "snapshot": "TAP_SNAPSHOT=1 tap test/*.js",
+    "test": "c8 --reporter=html --reporter=text tap --no-coverage test/*.js",
+    "posttest": "standard",
+    "coverage": "c8 report --check-coverage"
+  },
+  "repository": "istanbuljs/v8-to-istanbul",
+  "keywords": [
+    "istanbul",
+    "v8",
+    "coverage"
+  ],
+  "standard": {
+    "ignore": [
+      "**/test/fixtures"
+    ]
+  },
+  "author": "Ben Coe <ben@npmjs.com>",
+  "license": "ISC",
+  "dependencies": {
+    "@types/istanbul-lib-coverage": "^2.0.1",
+    "convert-source-map": "^1.6.0",
+    "source-map": "^0.7.3"
+  },
+  "devDependencies": {
+    "@types/node": "^16.0.0",
+    "c8": "^7.2.1",
+    "semver": "^7.3.2",
+    "should": "13.2.3",
+    "standard": "^16.0.4",
+    "tap": "^15.1.6"
+  },
+  "engines": {
+    "node": ">=10.12.0"
+  },
+  "files": [
+    "lib/*.js",
+    "index.js",
+    "index.d.ts"
+  ]
+}
