[Pkg-javascript-devel] Bug#986439: [pre-approval] unblock: node-xmldom/0.5.0-1

Yadd yadd at debian.org
Mon Apr 5 23:48:59 BST 2021


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock
X-Debbugs-Cc: pkg-javascript-devel at lists.alioth.debian.org

Please unblock package node-xmldom

[ Reason ]
node-xmldom ≤ 0.4 do not correctly preserve system identifiers, FPIs or
namespaces when repeatedly parsing and serializing maliciously crafted
documents. This may lead to unexpected syntactic changes during XML
processing in some downstream applications (CVE-2021-21366).

[ Impact ]
Medium vulnerability

[ Tests ]
Upstream provides new test for this vulnerability. Tested during build
and autopkgtest. I verified also that node-jsonld autopkgtest is OK with
this new version.
Upstream test are not trivial tests but real ones.

[ Risks ]
Upstream changed lib/dom-parser.js lib/dom.js and lib/sax.js to have a
better XML doc check. Other changes have no impact.
Note that license is changed, reported in debian/copyright

[ Checklist ]
  [X] all changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in testing

Cheers,
Yadd

unblock node-xmldom/0.5.0-1
-------------- next part --------------
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56925b6..302dd48 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 0.5.0
+
+### Fixes
+- Avoid misinterpretation of malicious XML input - `GHSA-h6q6-9hqw-rwfv` (CVE-2021-21366)
+- Fix breaking preprocessors' directives when parsing attributes [`#171`](https://github.com/xmldom/xmldom/pull/171)
+- fix(dom): Escape `]]>` when serializing CharData [`#181`](https://github.com/xmldom/xmldom/pull/181)
+- Switch to (only) MIT license (drop problematic LGPL license option) [`#178`](https://github.com/xmldom/xmldom/pull/178)
+- Export DOMException; remove custom assertions; etc.  [`#174`](https://github.com/xmldom/xmldom/pull/174)
+
+### Docs
+- Update MDN links in `readme.md` [`#188`](https://github.com/xmldom/xmldom/pull/188)
+
 ## 0.4.0
 
 [Commits](https://github.com/xmldom/xmldom/compare/0.3.0...0.4.0)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b95f569
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,8 @@
+Copyright 2019 - present Christopher J. Brody and other contributors, as listed in: https://github.com/xmldom/xmldom/graphs/contributors
+Copyright 2012 - 2017 @jindw <jindw at xidea.org> and other contributors, as listed in: https://github.com/jindw/xmldom/graphs/contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LICENSE.md b/LICENSE.md
deleted file mode 100644
index dc140c7..0000000
--- a/LICENSE.md
+++ /dev/null
@@ -1,4 +0,0 @@
-You can choose any one of these licenses:
-
-- MIT: https://opensource.org/licenses/MIT
-- LGPL: http://www.gnu.org/licenses/lgpl.html
diff --git a/debian/changelog b/debian/changelog
index 649f423..41abbd3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+node-xmldom (0.5.0-1) unstable; urgency=medium
+
+  * Team upload
+  * Fix debian/watch (GitHub change)
+  * New upstream version 0.5.0 (Closes: CVE-2021-21366)
+  * Update copyright
+
+ -- Yadd <yadd at debian.org>  Tue, 06 Apr 2021 00:36:51 +0200
+
 node-xmldom (0.4.0-2) unstable; urgency=medium
 
   * Team upload
diff --git a/debian/copyright b/debian/copyright
index 5a32307..1b54fa4 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -5,34 +5,16 @@ Source: https://github.com/jindw/xmldom
 Comment: package.json said LGPL-2 or MIT (expat according to link in LICENSE)
 
 Files: *
-Copyright: 2013-2017 jindw <jindw at xidea.org> (https://www.xidea.org)
-    2013-2017 Yaron Naveh <yaronn01 at gmail.com> (https://webservices20.blogspot.com/)
-    2013-2017 Harutyun Amirjanyan <amirjanyan at gmail.com> (https://github.com/nightwing)
-    2013-2017 Alan Gutierrez <alan at prettyrobots.com>  (https://www.prettyrobots.com/)
-License: LGPL-2 or Expat
+Copyright: 2019-present Christopher J. Brody and other contributors
+ 2012-2017 @jindw <jindw at xidea.org> and other contributors
+License: Expat
+Comment: Contributors:
+ 2019-present: https://github.com/xmldom/xmldom/graphs/contributors
+ 2012-2017:    https://github.com/jindw/xmldom/graphs/contributors
 
 Files: debian/*
 Copyright: 2018 Bastien Roucariès <rouca at debian.org>
-License: LGPL-2 or Expat
-
-License: LGPL-2
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- .
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- Library General Public License for more details.
- .
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- .
- On Debian systems, the full text of the GNU Library General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/LGPL-2'.
+License: Expat
 
 License: Expat
  Permission is hereby granted, free of charge, to any person obtaining
diff --git a/debian/watch b/debian/watch
index a7f0683..f85b703 100644
--- a/debian/watch
+++ b/debian/watch
@@ -3,4 +3,4 @@ opts=\
 ctype=nodejs,\
 dversionmangle=auto,\
 filenamemangle=s/.*\/v?([\d\.-]+)\.tar\.gz/node-xmldom-$1.tar.gz/ \
- https://github.com/xmldom/xmldom/tags .*/archive/v?([\d\.]+).tar.gz
+ https://github.com/xmldom/xmldom/tags .*/archive/.*/v?([\d\.]+).tar.gz
diff --git a/lib/dom-parser.js b/lib/dom-parser.js
index bb4dda7..2ad090d 100644
--- a/lib/dom-parser.js
+++ b/lib/dom-parser.js
@@ -178,8 +178,7 @@ DOMHandler.prototype = {
 		console.error('[xmldom error]\t'+error,_locator(this.locator));
 	},
 	fatalError:function(error) {
-		console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
-	    throw error;
+		throw new ParseError(error, this.locator);
 	}
 }
 function _locator(l){
@@ -244,8 +243,11 @@ function appendElement (hander,node) {
 
 //if(typeof require == 'function'){
 var htmlEntity = require('./entities');
-var XMLReader = require('./sax').XMLReader;
+var sax = require('./sax');
+var XMLReader = sax.XMLReader;
+var ParseError = sax.ParseError;
 var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation;
 exports.XMLSerializer = require('./dom').XMLSerializer ;
 exports.DOMParser = DOMParser;
+exports.__DOMHandler = DOMHandler;
 //}
diff --git a/lib/dom.js b/lib/dom.js
index 22cdb5c..78ab770 100644
--- a/lib/dom.js
+++ b/lib/dom.js
@@ -1,10 +1,3 @@
-/*
- * DOM Level 2
- * Object DOMException
- * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
- * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
- */
-
 function copy(src,dest){
 	for(var p in src){
 		dest[p] = src[p];
@@ -66,7 +59,12 @@ var INVALID_MODIFICATION_ERR 	= ExceptionCode.INVALID_MODIFICATION_ERR 	= ((Exce
 var NAMESPACE_ERR            	= ExceptionCode.NAMESPACE_ERR           	= ((ExceptionMessage[14]="Invalid namespace"),14);
 var INVALID_ACCESS_ERR       	= ExceptionCode.INVALID_ACCESS_ERR      	= ((ExceptionMessage[15]="Invalid access"),15);
 
-
+/**
+ * DOM Level 2
+ * Object DOMException
+ * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
+ * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
+ */
 function DOMException(code, message) {
 	if(message instanceof Error){
 		var error = message;
@@ -1066,9 +1064,27 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
 		}
 		return;
 	case ATTRIBUTE_NODE:
-		return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
+		return buf.push(' ',node.name,'="',node.value.replace(/[&"]/g,_xmlEncoder),'"');
 	case TEXT_NODE:
-		return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
+		/**
+		 * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
+		 * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.
+		 * If they are needed elsewhere, they must be escaped using either numeric character references or the strings
+		 * `&` and `<` respectively.
+		 * The right angle bracket (>) may be represented using the string " > ", and must, for compatibility,
+		 * be escaped using either `>` or a character reference when it appears in the string `]]>` in content,
+		 * when that string is not marking the end of a CDATA section.
+		 *
+		 * In the content of elements, character data is any string of characters
+		 * which does not contain the start-delimiter of any markup
+		 * and does not include the CDATA-section-close delimiter, `]]>`.
+		 *
+		 * @see https://www.w3.org/TR/xml/#NT-CharData
+		 */
+		return buf.push(node.data
+			.replace(/[<&]/g,_xmlEncoder)
+			.replace(/]]>/g, ']]>')
+		);
 	case CDATA_SECTION_NODE:
 		return buf.push( '<![CDATA[',node.data,']]>');
 	case COMMENT_NODE:
@@ -1078,13 +1094,13 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
 		var sysid = node.systemId;
 		buf.push('<!DOCTYPE ',node.name);
 		if(pubid){
-			buf.push(' PUBLIC "',pubid);
+			buf.push(' PUBLIC ', pubid);
 			if (sysid && sysid!='.') {
-				buf.push( '" "',sysid);
+				buf.push(' ', sysid);
 			}
-			buf.push('">');
+			buf.push('>');
 		}else if(sysid && sysid!='.'){
-			buf.push(' SYSTEM "',sysid,'">');
+			buf.push(' SYSTEM ', sysid, '>');
 		}else{
 			var sub = node.internalSubset;
 			if(sub){
@@ -1251,6 +1267,7 @@ try{
 
 //if(typeof require == 'function'){
 	exports.Node = Node;
+	exports.DOMException = DOMException;
 	exports.DOMImplementation = DOMImplementation;
 	exports.XMLSerializer = XMLSerializer;
 //}
diff --git a/lib/sax.js b/lib/sax.js
index c46d146..395b13f 100644
--- a/lib/sax.js
+++ b/lib/sax.js
@@ -18,6 +18,21 @@ var S_ATTR_END = 5;//attr value end and no space(quot end)
 var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
 var S_TAG_CLOSE = 7;//closed el<el />
 
+/**
+ * Creates an error that will not be caught by XMLReader aka the SAX parser.
+ *
+ * @param {string} message
+ * @param {any?} locator Optional, can provide details about the location in the source
+ * @constructor
+ */
+function ParseError(message, locator) {
+	this.message = message
+	this.locator = locator
+	if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError);
+}
+ParseError.prototype = new Error();
+ParseError.prototype.name = ParseError.name
+
 function XMLReader(){
 	
 }
@@ -126,7 +141,7 @@ function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
 						}
 					}
 					if(!endMatch){
-		            	errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
+		            	errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case
 					}
 		        }else{
 		        	parseStack.push(config)
@@ -187,10 +202,11 @@ function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
 				}
 			}
 		}catch(e){
+			if (e instanceof ParseError) {
+				throw e;
+			}
 			errorHandler.error('element parse error: '+e)
-			//errorHandler.error('element parse error: '+e);
 			end = -1;
-			//throw e;
 		}
 		if(end>start){
 			start = end;
@@ -211,6 +227,16 @@ function copyLocator(f,t){
  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
  */
 function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
+
+	/**
+	 * @param {string} qname
+	 * @param {string} value
+	 * @param {number} startIndex
+	 */
+	function addAttribute(qname, value, startIndex) {
+		if (qname in el.attributeNames) errorHandler.fatalError('Attribute ' + qname + ' redefined')
+		el.addValue(qname, value, startIndex)
+	}
 	var attrName;
 	var value;
 	var p = ++start;
@@ -226,7 +252,7 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 				s = S_EQ;
 			}else{
 				//fatalError: equal must after attrName or space after attrName
-				throw new Error('attribute equal must after attrName');
+				throw new Error('attribute equal must after attrName'); // No known test case
 			}
 			break;
 		case '\'':
@@ -241,7 +267,7 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 				p = source.indexOf(c,start)
 				if(p>0){
 					value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
-					el.add(attrName,value,start-1);
+					addAttribute(attrName, value, start-1);
 					s = S_ATTR_END;
 				}else{
 					//fatalError: no end quot match
@@ -250,14 +276,14 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 			}else if(s == S_ATTR_NOQUOT_VALUE){
 				value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
 				//console.log(attrName,value,start,p)
-				el.add(attrName,value,start);
+				addAttribute(attrName, value, start);
 				//console.dir(el)
 				errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
 				start = p+1;
 				s = S_ATTR_END
 			}else{
 				//fatalError: no equal before
-				throw new Error('attribute value must after "="');
+				throw new Error('attribute value must after "="'); // No known test case
 			}
 			break;
 		case '/':
@@ -275,11 +301,10 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 				break;
 			//case S_EQ:
 			default:
-				throw new Error("attribute invalid close char('/')")
+				throw new Error("attribute invalid close char('/')") // No known test case
 			}
 			break;
 		case ''://end document
-			//throw new Error('unexpected end of input')
 			errorHandler.error('unexpected end of input');
 			if(s == S_TAG){
 				el.setTagName(source.slice(start,p));
@@ -305,13 +330,13 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 					value = attrName;
 				}
 				if(s == S_ATTR_NOQUOT_VALUE){
-					errorHandler.warning('attribute "'+value+'" missed quot(")!!');
-					el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start)
+					errorHandler.warning('attribute "'+value+'" missed quot(")!');
+					addAttribute(attrName, value.replace(/&#?\w+;/g,entityReplacer), start)
 				}else{
 					if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
 						errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
 					}
-					el.add(value,value,start)
+					addAttribute(value, value, start)
 				}
 				break;
 			case S_EQ:
@@ -336,7 +361,7 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 				case S_ATTR_NOQUOT_VALUE:
 					var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
 					errorHandler.warning('attribute "'+value+'" missed quot(")!!');
-					el.add(attrName,value,start)
+					addAttribute(attrName, value, start)
 				case S_ATTR_END:
 					s = S_TAG_SPACE;
 					break;
@@ -359,7 +384,7 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error
 					if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
 						errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
 					}
-					el.add(attrName,attrName,start);
+					addAttribute(attrName, attrName, start);
 					start = p;
 					s = S_ATTR;
 					break;
@@ -542,8 +567,7 @@ function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
 				}
 			}
 			var lastMatch = matchs[len-1]
-			domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
-					sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
+			domBuilder.startDTD(name, pubid, sysid);
 			domBuilder.endDTD();
 			
 			return lastMatch.index+lastMatch[0].length
@@ -569,11 +593,8 @@ function parseInstruction(source,start,domBuilder){
 	return -1;
 }
 
-/**
- * @param source
- */
-function ElementAttributes(source){
-	
+function ElementAttributes(){
+	this.attributeNames = {}
 }
 ElementAttributes.prototype = {
 	setTagName:function(tagName){
@@ -582,10 +603,11 @@ ElementAttributes.prototype = {
 		}
 		this.tagName = tagName
 	},
-	add:function(qName,value,offset){
+	addValue:function(qName, value, offset) {
 		if(!tagNamePattern.test(qName)){
 			throw new Error('invalid attribute:'+qName)
 		}
+		this.attributeNames[qName] = this.length;
 		this[this.length++] = {qName:qName,value:value,offset:offset}
 	},
 	length:0,
@@ -621,4 +643,4 @@ function split(source,start){
 }
 
 exports.XMLReader = XMLReader;
-
+exports.ParseError = ParseError;
diff --git a/package-lock.json b/package-lock.json
index d500b7a..c4f92a4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "xmldom",
-  "version": "0.4.0",
+  "version": "0.5.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -37,51 +37,6 @@
         "source-map": "^0.5.0"
       },
       "dependencies": {
-        "@babel/generator": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz",
-          "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.12.1",
-            "jsesc": "^2.5.1",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.12.3",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz",
-          "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz",
-          "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.12.1",
-            "@babel/helper-function-name": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.11.0",
-            "@babel/parser": "^7.12.1",
-            "@babel/types": "^7.12.1",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.19"
-          }
-        },
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
         "debug": {
           "version": "4.2.0",
           "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
@@ -100,12 +55,12 @@
       }
     },
     "@babel/generator": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz",
-      "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz",
+      "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.11.0",
+        "@babel/types": "^7.12.5",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       },
@@ -118,6 +73,19 @@
         }
       }
     },
+    "@babel/helper-create-class-features-plugin": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz",
+      "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-member-expression-to-functions": "^7.12.1",
+        "@babel/helper-optimise-call-expression": "^7.10.4",
+        "@babel/helper-replace-supers": "^7.12.1",
+        "@babel/helper-split-export-declaration": "^7.10.4"
+      }
+    },
     "@babel/helper-function-name": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
@@ -145,41 +113,15 @@
       "dev": true,
       "requires": {
         "@babel/types": "^7.12.1"
-      },
-      "dependencies": {
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        }
       }
     },
     "@babel/helper-module-imports": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz",
-      "integrity": "sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
+      "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.12.1"
-      },
-      "dependencies": {
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        }
+        "@babel/types": "^7.12.5"
       }
     },
     "@babel/helper-module-transforms": {
@@ -197,68 +139,6 @@
         "@babel/traverse": "^7.12.1",
         "@babel/types": "^7.12.1",
         "lodash": "^4.17.19"
-      },
-      "dependencies": {
-        "@babel/generator": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz",
-          "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.12.1",
-            "jsesc": "^2.5.1",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.12.3",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz",
-          "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz",
-          "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.12.1",
-            "@babel/helper-function-name": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.11.0",
-            "@babel/parser": "^7.12.1",
-            "@babel/types": "^7.12.1",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.19"
-          }
-        },
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
-        "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
       }
     },
     "@babel/helper-optimise-call-expression": {
@@ -277,77 +157,15 @@
       "dev": true
     },
     "@babel/helper-replace-supers": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz",
-      "integrity": "sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz",
+      "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==",
       "dev": true,
       "requires": {
         "@babel/helper-member-expression-to-functions": "^7.12.1",
         "@babel/helper-optimise-call-expression": "^7.10.4",
-        "@babel/traverse": "^7.12.1",
-        "@babel/types": "^7.12.1"
-      },
-      "dependencies": {
-        "@babel/generator": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz",
-          "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.12.1",
-            "jsesc": "^2.5.1",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.12.3",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz",
-          "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz",
-          "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.12.1",
-            "@babel/helper-function-name": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.11.0",
-            "@babel/parser": "^7.12.1",
-            "@babel/types": "^7.12.1",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.19"
-          }
-        },
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
-        "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
+        "@babel/traverse": "^7.12.5",
+        "@babel/types": "^7.12.5"
       }
     },
     "@babel/helper-simple-access": {
@@ -357,19 +175,6 @@
       "dev": true,
       "requires": {
         "@babel/types": "^7.12.1"
-      },
-      "dependencies": {
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        }
       }
     },
     "@babel/helper-split-export-declaration": {
@@ -387,77 +192,21 @@
       "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
       "dev": true
     },
+    "@babel/helper-validator-option": {
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz",
+      "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==",
+      "dev": true
+    },
     "@babel/helpers": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz",
-      "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz",
+      "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.12.1",
-        "@babel/types": "^7.12.1"
-      },
-      "dependencies": {
-        "@babel/generator": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz",
-          "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.12.1",
-            "jsesc": "^2.5.1",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.12.3",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz",
-          "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz",
-          "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.12.1",
-            "@babel/helper-function-name": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.11.0",
-            "@babel/parser": "^7.12.1",
-            "@babel/types": "^7.12.1",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.19"
-          }
-        },
-        "@babel/types": {
-          "version": "7.12.1",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz",
-          "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
-            "lodash": "^4.17.19",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
-        "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
+        "@babel/traverse": "^7.12.5",
+        "@babel/types": "^7.12.5"
       }
     },
     "@babel/highlight": {
@@ -509,11 +258,42 @@
       }
     },
     "@babel/parser": {
-      "version": "7.11.3",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz",
-      "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz",
+      "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==",
       "dev": true
     },
+    "@babel/plugin-proposal-class-properties": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz",
+      "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-proposal-decorators": {
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.12.tgz",
+      "integrity": "sha512-fhkE9lJYpw2mjHelBpM2zCbaA11aov2GJs7q4cFaXNrWx0H3bW58H9Esy2rdtYOghFBEYUDRIpvlgi+ZD+AvvQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-decorators": "^7.12.1"
+      }
+    },
+    "@babel/plugin-proposal-private-methods": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz",
+      "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-syntax-async-generators": {
       "version": "7.8.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -541,6 +321,15 @@
         "@babel/helper-plugin-utils": "^7.10.4"
       }
     },
+    "@babel/plugin-syntax-decorators": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.1.tgz",
+      "integrity": "sha512-ir9YW5daRrTYiy9UJ2TzdNIJEZu8KclVzDcfSt4iEmOtwQ4llPtWInNKJyKnVXp1vE4bbVd5S31M/im3mYMO1w==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-syntax-import-meta": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
@@ -613,6 +402,46 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-top-level-await": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz",
+      "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-syntax-typescript": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz",
+      "integrity": "sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-transform-typescript": {
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz",
+      "integrity": "sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-create-class-features-plugin": "^7.12.1",
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-typescript": "^7.12.1"
+      }
+    },
+    "@babel/preset-typescript": {
+      "version": "7.12.7",
+      "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz",
+      "integrity": "sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-validator-option": "^7.12.1",
+        "@babel/plugin-transform-typescript": "^7.12.1"
+      }
+    },
     "@babel/template": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
@@ -625,17 +454,17 @@
       }
     },
     "@babel/traverse": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz",
-      "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz",
+      "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.11.0",
+        "@babel/generator": "^7.12.5",
         "@babel/helper-function-name": "^7.10.4",
         "@babel/helper-split-export-declaration": "^7.11.0",
-        "@babel/parser": "^7.11.0",
-        "@babel/types": "^7.11.0",
+        "@babel/parser": "^7.12.5",
+        "@babel/types": "^7.12.5",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
         "lodash": "^4.17.19"
@@ -653,9 +482,9 @@
       }
     },
     "@babel/types": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
-      "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.5.tgz",
+      "integrity": "sha512-gyTcvz7JFa4V45C0Zklv//GmFOAal5fL23OWpBLqc4nZ4Yrz67s4kCNwSK1Gu0MXGTU8mRY3zJYtacLdKXlzig==",
       "dev": true,
       "requires": {
         "@babel/helper-validator-identifier": "^7.10.4",
@@ -680,9 +509,9 @@
       }
     },
     "@eslint/eslintrc": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.0.tgz",
-      "integrity": "sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz",
+      "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==",
       "dev": true,
       "requires": {
         "ajv": "^6.12.4",
@@ -692,15 +521,15 @@
         "ignore": "^4.0.6",
         "import-fresh": "^3.2.1",
         "js-yaml": "^3.13.1",
-        "lodash": "^4.17.19",
+        "lodash": "^4.17.20",
         "minimatch": "^3.0.4",
         "strip-json-comments": "^3.1.1"
       },
       "dependencies": {
         "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -751,16 +580,16 @@
       "dev": true
     },
     "@jest/console": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.1.tgz",
-      "integrity": "sha512-cjqcXepwC5M+VeIhwT6Xpi/tT4AiNzlIx8SMJ9IihduHnsSrnWNvTBfKIpmqOOCNOPqtbBx6w2JqfoLOJguo8g==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz",
+      "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "chalk": "^4.0.0",
-        "jest-message-util": "^26.6.1",
-        "jest-util": "^26.6.1",
+        "jest-message-util": "^26.6.2",
+        "jest-util": "^26.6.2",
         "slash": "^3.0.0"
       },
       "dependencies": {
@@ -792,34 +621,34 @@
       }
     },
     "@jest/core": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.1.tgz",
-      "integrity": "sha512-p4F0pgK3rKnoS9olXXXOkbus1Bsu6fd8pcvLMPsUy4CVXZ8WSeiwQ1lK5hwkCIqJ+amZOYPd778sbPha/S8Srw==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz",
+      "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==",
       "dev": true,
       "requires": {
-        "@jest/console": "^26.6.1",
-        "@jest/reporters": "^26.6.1",
-        "@jest/test-result": "^26.6.1",
-        "@jest/transform": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/console": "^26.6.2",
+        "@jest/reporters": "^26.6.2",
+        "@jest/test-result": "^26.6.2",
+        "@jest/transform": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "ansi-escapes": "^4.2.1",
         "chalk": "^4.0.0",
         "exit": "^0.1.2",
         "graceful-fs": "^4.2.4",
-        "jest-changed-files": "^26.6.1",
-        "jest-config": "^26.6.1",
-        "jest-haste-map": "^26.6.1",
-        "jest-message-util": "^26.6.1",
+        "jest-changed-files": "^26.6.2",
+        "jest-config": "^26.6.3",
+        "jest-haste-map": "^26.6.2",
+        "jest-message-util": "^26.6.2",
         "jest-regex-util": "^26.0.0",
-        "jest-resolve": "^26.6.1",
-        "jest-resolve-dependencies": "^26.6.1",
-        "jest-runner": "^26.6.1",
-        "jest-runtime": "^26.6.1",
-        "jest-snapshot": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "jest-validate": "^26.6.1",
-        "jest-watcher": "^26.6.1",
+        "jest-resolve": "^26.6.2",
+        "jest-resolve-dependencies": "^26.6.3",
+        "jest-runner": "^26.6.3",
+        "jest-runtime": "^26.6.3",
+        "jest-snapshot": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "jest-validate": "^26.6.2",
+        "jest-watcher": "^26.6.2",
         "micromatch": "^4.0.2",
         "p-each-series": "^2.1.0",
         "rimraf": "^3.0.0",
@@ -870,53 +699,53 @@
       }
     },
     "@jest/environment": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.1.tgz",
-      "integrity": "sha512-GNvHwkOFJtNgSwdzH9flUPzF9AYAZhUg124CBoQcwcZCM9s5TLz8Y3fMtiaWt4ffbigoetjGk5PU2Dd8nLrSEw==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
+      "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==",
       "dev": true,
       "requires": {
-        "@jest/fake-timers": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/fake-timers": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
-        "jest-mock": "^26.6.1"
+        "jest-mock": "^26.6.2"
       }
     },
     "@jest/fake-timers": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.1.tgz",
-      "integrity": "sha512-T/SkMLgOquenw/nIisBRD6XAYpFir0kNuclYLkse5BpzeDUukyBr+K31xgAo9M0hgjU9ORlekAYPSzc0DKfmKg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz",
+      "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@sinonjs/fake-timers": "^6.0.1",
         "@types/node": "*",
-        "jest-message-util": "^26.6.1",
-        "jest-mock": "^26.6.1",
-        "jest-util": "^26.6.1"
+        "jest-message-util": "^26.6.2",
+        "jest-mock": "^26.6.2",
+        "jest-util": "^26.6.2"
       }
     },
     "@jest/globals": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.1.tgz",
-      "integrity": "sha512-acxXsSguuLV/CeMYmBseefw6apO7NuXqpE+v5r3yD9ye2PY7h1nS20vY7Obk2w6S7eJO4OIAJeDnoGcLC/McEQ==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz",
+      "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^26.6.1",
-        "@jest/types": "^26.6.1",
-        "expect": "^26.6.1"
+        "@jest/environment": "^26.6.2",
+        "@jest/types": "^26.6.2",
+        "expect": "^26.6.2"
       }
     },
     "@jest/reporters": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.1.tgz",
-      "integrity": "sha512-J6OlXVFY3q1SXWJhjme5i7qT/BAZSikdOK2t8Ht5OS32BDo6KfG5CzIzzIFnAVd82/WWbc9Hb7SJ/jwSvVH9YA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz",
+      "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==",
       "dev": true,
       "requires": {
         "@bcoe/v8-coverage": "^0.2.3",
-        "@jest/console": "^26.6.1",
-        "@jest/test-result": "^26.6.1",
-        "@jest/transform": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/console": "^26.6.2",
+        "@jest/test-result": "^26.6.2",
+        "@jest/transform": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "chalk": "^4.0.0",
         "collect-v8-coverage": "^1.0.0",
         "exit": "^0.1.2",
@@ -927,16 +756,16 @@
         "istanbul-lib-report": "^3.0.0",
         "istanbul-lib-source-maps": "^4.0.0",
         "istanbul-reports": "^3.0.2",
-        "jest-haste-map": "^26.6.1",
-        "jest-resolve": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "jest-worker": "^26.6.1",
+        "jest-haste-map": "^26.6.2",
+        "jest-resolve": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "jest-worker": "^26.6.2",
         "node-notifier": "^8.0.0",
         "slash": "^3.0.0",
         "source-map": "^0.6.0",
         "string-length": "^4.0.1",
         "terminal-link": "^2.0.0",
-        "v8-to-istanbul": "^6.0.1"
+        "v8-to-istanbul": "^7.0.0"
       },
       "dependencies": {
         "chalk": {
@@ -997,9 +826,9 @@
       }
     },
     "@jest/source-map": {
-      "version": "26.5.0",
-      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.5.0.tgz",
-      "integrity": "sha512-jWAw9ZwYHJMe9eZq/WrsHlwF8E3hM9gynlcDpOyCb9bR8wEd9ZNBZCi7/jZyzHxC7t3thZ10gO2IDhu0bPKS5g==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
+      "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==",
       "dev": true,
       "requires": {
         "callsites": "^3.0.0",
@@ -1016,46 +845,46 @@
       }
     },
     "@jest/test-result": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.1.tgz",
-      "integrity": "sha512-wqAgIerIN2gSdT2A8WeA5+AFh9XQBqYGf8etK143yng3qYd0mF0ie2W5PVmgnjw4VDU6ammI9NdXrKgNhreawg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz",
+      "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
       "dev": true,
       "requires": {
-        "@jest/console": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/console": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/istanbul-lib-coverage": "^2.0.0",
         "collect-v8-coverage": "^1.0.0"
       }
     },
     "@jest/test-sequencer": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.1.tgz",
-      "integrity": "sha512-0csqA/XApZiNeTIPYh6koIDCACSoR6hi29T61tKJMtCZdEC+tF3PoNt7MS0oK/zKC6daBgCbqXxia5ztr/NyCQ==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz",
+      "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^26.6.1",
+        "@jest/test-result": "^26.6.2",
         "graceful-fs": "^4.2.4",
-        "jest-haste-map": "^26.6.1",
-        "jest-runner": "^26.6.1",
-        "jest-runtime": "^26.6.1"
+        "jest-haste-map": "^26.6.2",
+        "jest-runner": "^26.6.3",
+        "jest-runtime": "^26.6.3"
       }
     },
     "@jest/transform": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.1.tgz",
-      "integrity": "sha512-oNFAqVtqRxZRx6vXL3I4bPKUK0BIlEeaalkwxyQGGI8oXDQBtYQBpiMe5F7qPs4QdvvFYB42gPGIMMcxXaBBxQ==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz",
+      "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "babel-plugin-istanbul": "^6.0.0",
         "chalk": "^4.0.0",
         "convert-source-map": "^1.4.0",
         "fast-json-stable-stringify": "^2.0.0",
         "graceful-fs": "^4.2.4",
-        "jest-haste-map": "^26.6.1",
+        "jest-haste-map": "^26.6.2",
         "jest-regex-util": "^26.0.0",
-        "jest-util": "^26.6.1",
+        "jest-util": "^26.6.2",
         "micromatch": "^4.0.2",
         "pirates": "^4.0.1",
         "slash": "^3.0.0",
@@ -1097,9 +926,9 @@
       }
     },
     "@jest/types": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.1.tgz",
-      "integrity": "sha512-ywHavIKNpAVrStiRY5wiyehvcktpijpItvGiK72RAn5ctqmzvPk8OvKnvHeBqa1XdQr959CTWAJMqxI8BTibyg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
+      "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.0",
@@ -1161,146 +990,188 @@
       }
     },
     "@stryker-mutator/api": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-3.3.1.tgz",
-      "integrity": "sha512-t3TZyzxZYwZHUF1aCCpqLOQJjW0DZMZTrwGP/zGuDBUjr1/Opq+S6emeLFVjSJiDeMyqkqh9X01ZzHIWJPD+Sg==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-4.4.1.tgz",
+      "integrity": "sha512-qjkkdsOepy0NEGyxU2hvqQ70JFBaukkCO1MoWdG1e2oWpPQaTYNF+1W38fOF0QWGO0FVm50cA0wbf7Apqp5wIA==",
       "dev": true,
       "requires": {
-        "mutation-testing-report-schema": "~1.3.0",
+        "mutation-testing-report-schema": "~1.5.2",
         "surrial": "~2.0.2",
-        "tslib": "~2.0.0"
+        "tslib": "~2.1.0"
       }
     },
     "@stryker-mutator/core": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-3.3.1.tgz",
-      "integrity": "sha512-OT2X5qI+ePHhsjO8iwkWGdj70q3F8wxLGoNZYDtV6ct8PQU79Yn2ZUpBBK36RubMoaU3ld1XVcjieSAeVUJ4mg==",
-      "dev": true,
-      "requires": {
-        "@stryker-mutator/api": "^3.3.1",
-        "@stryker-mutator/util": "^3.3.1",
-        "ajv": "^6.12.0",
-        "chalk": "~4.0.0",
-        "commander": "~5.1.0",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-4.4.1.tgz",
+      "integrity": "sha512-xGH/GmKDgB4O8tqZx+N0dNhwuG7li13Yzv7Tqz/VIe3CTuTjoKFrmLq4UnsL9yA/DBbNfjgILBdY8BMNHr9kXA==",
+      "dev": true,
+      "requires": {
+        "@stryker-mutator/api": "4.4.1",
+        "@stryker-mutator/instrumenter": "4.4.1",
+        "@stryker-mutator/util": "4.4.1",
+        "ajv": "~7.0.2",
+        "chalk": "~4.1.0",
+        "commander": "~7.0.0",
+        "execa": "~5.0.0",
         "file-url": "~3.0.0",
         "get-port": "~5.0.0",
         "glob": "~7.1.2",
-        "inquirer": "~7.1.0",
-        "istanbul-lib-instrument": "~3.3.0",
-        "lodash.flatmap": "^4.5.0",
-        "lodash.groupby": "^4.6.0",
-        "log4js": "6.2.1",
+        "inquirer": "~7.3.2",
+        "lodash.flatmap": "~4.5.0",
+        "lodash.groupby": "~4.6.0",
+        "log4js": "~6.2.1",
+        "minimatch": "~3.0.4",
         "mkdirp": "~1.0.3",
-        "mutation-testing-elements": "~1.3.0",
-        "mutation-testing-metrics": "~1.3.0",
+        "mutation-testing-elements": "~1.5.2",
+        "mutation-testing-metrics": "~1.5.2",
+        "npm-run-path": "~4.0.1",
         "progress": "~2.0.0",
         "rimraf": "~3.0.0",
         "rxjs": "~6.6.0",
         "source-map": "~0.7.3",
         "surrial": "~2.0.2",
-        "tree-kill": "~1.2.0",
-        "tslib": "~2.0.0",
-        "typed-inject": "~2.2.1",
-        "typed-rest-client": "~1.7.1"
+        "tree-kill": "~1.2.2",
+        "tslib": "~2.1.0",
+        "typed-inject": "~3.0.0",
+        "typed-rest-client": "~1.8.0"
       },
       "dependencies": {
+        "ajv": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
+          "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2",
+            "uri-js": "^4.2.2"
+          }
+        },
         "chalk": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
-          "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
             "supports-color": "^7.1.0"
           }
         },
+        "cross-spawn": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+          "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+          "dev": true,
+          "requires": {
+            "path-key": "^3.1.0",
+            "shebang-command": "^2.0.0",
+            "which": "^2.0.1"
+          }
+        },
+        "execa": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz",
+          "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^7.0.3",
+            "get-stream": "^6.0.0",
+            "human-signals": "^2.1.0",
+            "is-stream": "^2.0.0",
+            "merge-stream": "^2.0.0",
+            "npm-run-path": "^4.0.1",
+            "onetime": "^5.1.2",
+            "signal-exit": "^3.0.3",
+            "strip-final-newline": "^2.0.0"
+          }
+        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
-    "@stryker-mutator/javascript-mutator": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/@stryker-mutator/javascript-mutator/-/javascript-mutator-3.3.1.tgz",
-      "integrity": "sha512-YVRw/NZjRcrsu10APeHkIEw+TEr7KMyyu36Tls3TPltXKhXh5IQKihL4nW/zg7AXP7gN1Ym6VhO00ZMs07JeAQ==",
-      "dev": true,
-      "requires": {
-        "@babel/generator": "~7.9.4",
-        "@babel/parser": "~7.9.4",
-        "@babel/traverse": "~7.9.5",
-        "@stryker-mutator/api": "^3.3.1",
-        "tslib": "~2.0.0"
-      },
-      "dependencies": {
-        "@babel/generator": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
+        "human-signals": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+          "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+          "dev": true
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true
+        },
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+          "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.9.6",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
+            "shebang-regex": "^3.0.0"
           }
         },
-        "@babel/parser": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
+        "shebang-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+          "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
           "dev": true
         },
-        "@babel/traverse": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.9.6",
-            "@babel/helper-function-name": "^7.9.5",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.9.6",
-            "@babel/types": "^7.9.6",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
+            "has-flag": "^4.0.0"
           }
         },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "isexe": "^2.0.0"
           }
-        },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
         }
       }
     },
+    "@stryker-mutator/instrumenter": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-4.4.1.tgz",
+      "integrity": "sha512-JQrEgUrUBDfofNAeBdojjnqWJbZRHw8aqX+yRO9tsR5dHX3iSkLrYQs1UTOP0JuBYqnStIeJW2pnDQnjh0z3cw==",
+      "dev": true,
+      "requires": {
+        "@babel/core": "~7.12.3",
+        "@babel/generator": "~7.12.1",
+        "@babel/parser": "~7.12.3",
+        "@babel/plugin-proposal-class-properties": "^7.12.1",
+        "@babel/plugin-proposal-decorators": "~7.12.1 ",
+        "@babel/plugin-proposal-private-methods": "^7.12.1",
+        "@babel/preset-typescript": "~7.12.1 ",
+        "@stryker-mutator/api": "4.4.1",
+        "@stryker-mutator/util": "4.4.1",
+        "angular-html-parser": "~1.7.0",
+        "weapon-regex": "~0.3.0"
+      }
+    },
     "@stryker-mutator/util": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-3.3.1.tgz",
-      "integrity": "sha512-JE9PT6/Fqo4343fQWb3YzbkGmBU4bUeuynYhsTeDmY0fhTT653oGHeyEKWeV39/kgSyKfIpY5ABb1RvJclOgkg==",
-      "dev": true
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-4.4.1.tgz",
+      "integrity": "sha512-F0IFpjU6cc4H/exn8iI08QLqa7d5yLod+p5lI0IeddzQJQCs0ztMX5g9zqLU7nTCTcEbL2XgI9S8815/YbNjDQ==",
+      "dev": true,
+      "requires": {
+        "lodash.flatmap": "~4.5.0"
+      }
     },
     "@szmarczak/http-timer": {
       "version": "1.1.2",
@@ -1312,9 +1183,9 @@
       }
     },
     "@types/babel__core": {
-      "version": "7.1.10",
-      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.10.tgz",
-      "integrity": "sha512-x8OM8XzITIMyiwl5Vmo2B1cR1S1Ipkyv4mdlbJjMa1lmuKvKY9FrBbEANIaMlnWn5Rf7uO+rC/VgYabNkE17Hw==",
+      "version": "7.1.12",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
+      "integrity": "sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==",
       "dev": true,
       "requires": {
         "@babel/parser": "^7.1.0",
@@ -1392,9 +1263,9 @@
       }
     },
     "@types/node": {
-      "version": "14.14.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz",
-      "integrity": "sha512-jeYJU2kl7hL9U5xuI/BhKPZ4vqGM/OmK6whiFAXVhlstzZhVamWhDSmHyGLIp+RVyuF9/d0dqr2P85aFj4BvJg==",
+      "version": "14.14.6",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz",
+      "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==",
       "dev": true
     },
     "@types/normalize-package-data": {
@@ -1482,6 +1353,23 @@
         "uri-js": "^4.2.2"
       }
     },
+    "angular-html-parser": {
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.7.1.tgz",
+      "integrity": "sha512-bDOeuWyKNuvggsBcN9jG7bFCuy5L3vHGoJ5+djuvo6vhQiCTu01smwOlh2WBa3ZjdttBY/vtb9XWfCoaMdKL6Q==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+          "dev": true
+        }
+      }
+    },
     "ansi-align": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
@@ -1608,9 +1496,9 @@
       "dev": true
     },
     "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
       "dev": true
     },
     "asynckit": {
@@ -1632,22 +1520,22 @@
       "dev": true
     },
     "aws4": {
-      "version": "1.10.1",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
-      "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+      "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
       "dev": true
     },
     "babel-jest": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.1.tgz",
-      "integrity": "sha512-duMWEOKrSBYRVTTNpL2SipNIWnZOjP77auOBMPQ3zXAdnDbyZQWU8r/RxNWpUf9N6cgPFecQYelYLytTVXVDtA==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
+      "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==",
       "dev": true,
       "requires": {
-        "@jest/transform": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/transform": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/babel__core": "^7.1.7",
         "babel-plugin-istanbul": "^6.0.0",
-        "babel-preset-jest": "^26.5.0",
+        "babel-preset-jest": "^26.6.2",
         "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "slash": "^3.0.0"
@@ -1720,9 +1608,9 @@
       }
     },
     "babel-plugin-jest-hoist": {
-      "version": "26.5.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.5.0.tgz",
-      "integrity": "sha512-ck17uZFD3CDfuwCLATWZxkkuGGFhMij8quP8CNhwj8ek1mqFgbFzRJ30xwC04LLscj/aKsVFfRST+b5PT7rSuw==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz",
+      "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.3.3",
@@ -1732,9 +1620,9 @@
       }
     },
     "babel-preset-current-node-syntax": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz",
-      "integrity": "sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.0.tgz",
+      "integrity": "sha512-mGkvkpocWJes1CmMKtgGUwCeeq0pOhALyymozzDWYomHTbDLwueDYG6p4TK1YOeYHCzBzYPsWkgTto10JubI1Q==",
       "dev": true,
       "requires": {
         "@babel/plugin-syntax-async-generators": "^7.8.4",
@@ -1747,17 +1635,18 @@
         "@babel/plugin-syntax-numeric-separator": "^7.8.3",
         "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
         "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
-        "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+        "@babel/plugin-syntax-top-level-await": "^7.8.3"
       }
     },
     "babel-preset-jest": {
-      "version": "26.5.0",
-      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.5.0.tgz",
-      "integrity": "sha512-F2vTluljhqkiGSJGBg/jOruA8vIIIL11YrxRcO7nviNTMbbofPSHwnm8mgP7d/wS7wRSexRoI6X1A6T74d4LQA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz",
+      "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==",
       "dev": true,
       "requires": {
-        "babel-plugin-jest-hoist": "^26.5.0",
-        "babel-preset-current-node-syntax": "^0.1.3"
+        "babel-plugin-jest-hoist": "^26.6.2",
+        "babel-preset-current-node-syntax": "^1.0.0"
       }
     },
     "balanced-match": {
@@ -1789,35 +1678,6 @@
           "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"
-          }
         }
       }
     },
@@ -1831,9 +1691,9 @@
       }
     },
     "binary-extensions": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
-      "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
       "dev": true
     },
     "boxen": {
@@ -2014,19 +1874,28 @@
       "dev": true
     },
     "chokidar": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
-      "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
+      "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
       "dev": true,
       "requires": {
         "anymatch": "~3.1.1",
         "braces": "~3.0.2",
-        "fsevents": "~2.1.2",
+        "fsevents": "~2.3.1",
         "glob-parent": "~5.1.0",
         "is-binary-path": "~2.1.0",
         "is-glob": "~4.0.1",
         "normalize-path": "~3.0.0",
         "readdirp": "~3.5.0"
+      },
+      "dependencies": {
+        "fsevents": {
+          "version": "2.3.1",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
+          "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
+          "dev": true,
+          "optional": true
+        }
       }
     },
     "ci-info": {
@@ -2036,9 +1905,9 @@
       "dev": true
     },
     "cjs-module-lexer": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.4.3.tgz",
-      "integrity": "sha512-5RLK0Qfs0PNDpEyBXIr3bIT1Muw3ojSlvpw6dAmkUcO0+uTrsBn7GuEIgx40u+OzbCBLDta7nvmud85P4EmTsQ==",
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz",
+      "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
       "dev": true
     },
     "class-utils": {
@@ -2061,6 +1930,63 @@
           "requires": {
             "is-descriptor": "^0.1.0"
           }
+        },
+        "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": {
+            "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-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": {
+            "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-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"
+          }
+        },
+        "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
         }
       }
     },
@@ -2080,9 +2006,9 @@
       }
     },
     "cli-width": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
-      "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+      "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
       "dev": true
     },
     "cliui": {
@@ -2169,9 +2095,9 @@
       }
     },
     "commander": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
-      "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz",
+      "integrity": "sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA==",
       "dev": true
     },
     "component-emitter": {
@@ -2290,9 +2216,9 @@
       "dev": true
     },
     "debug": {
-      "version": "3.2.6",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
       "dev": true,
       "requires": {
         "ms": "^2.1.1"
@@ -2366,37 +2292,6 @@
       "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": {
@@ -2412,9 +2307,9 @@
       "dev": true
     },
     "diff-sequences": {
-      "version": "26.5.0",
-      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz",
-      "integrity": "sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
+      "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
       "dev": true
     },
     "doctrine": {
@@ -2620,13 +2515,13 @@
       }
     },
     "eslint": {
-      "version": "7.12.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz",
-      "integrity": "sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA==",
+      "version": "7.18.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz",
+      "integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@eslint/eslintrc": "^0.2.0",
+        "@eslint/eslintrc": "^0.3.0",
         "ajv": "^6.10.0",
         "chalk": "^4.0.0",
         "cross-spawn": "^7.0.2",
@@ -2636,10 +2531,10 @@
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^2.1.0",
         "eslint-visitor-keys": "^2.0.0",
-        "espree": "^7.3.0",
+        "espree": "^7.3.1",
         "esquery": "^1.2.0",
         "esutils": "^2.0.2",
-        "file-entry-cache": "^5.0.1",
+        "file-entry-cache": "^6.0.0",
         "functional-red-black-tree": "^1.0.1",
         "glob-parent": "^5.0.0",
         "globals": "^12.1.0",
@@ -2650,7 +2545,7 @@
         "js-yaml": "^3.13.1",
         "json-stable-stringify-without-jsonify": "^1.0.1",
         "levn": "^0.4.1",
-        "lodash": "^4.17.19",
+        "lodash": "^4.17.20",
         "minimatch": "^3.0.4",
         "natural-compare": "^1.4.0",
         "optionator": "^0.9.1",
@@ -2659,7 +2554,7 @@
         "semver": "^7.2.1",
         "strip-ansi": "^6.0.0",
         "strip-json-comments": "^3.1.0",
-        "table": "^5.2.3",
+        "table": "^6.0.4",
         "text-table": "^0.2.0",
         "v8-compile-cache": "^2.0.3"
       },
@@ -2692,9 +2587,9 @@
           }
         },
         "debug": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
-          "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "dev": true,
           "requires": {
             "ms": "2.1.2"
@@ -2722,10 +2617,13 @@
           "dev": true
         },
         "semver": {
-          "version": "7.3.2",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
-          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
-          "dev": true
+          "version": "7.3.4",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
         },
         "shebang-command": {
           "version": "2.0.0",
@@ -2778,13 +2676,10 @@
       }
     },
     "eslint-config-prettier": {
-      "version": "6.14.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.14.0.tgz",
-      "integrity": "sha512-DbVwh0qZhAC7CNDWcq8cBdK6FcVHiMTKmCypOPWeZkp9hJ8xYwTaWSa6bb6cjfi8KOeJy0e9a8Izxyx+O4+gCQ==",
-      "dev": true,
-      "requires": {
-        "get-stdin": "^6.0.0"
-      }
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz",
+      "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==",
+      "dev": true
     },
     "eslint-plugin-es5": {
       "version": "1.5.0",
@@ -2793,9 +2688,9 @@
       "dev": true
     },
     "eslint-plugin-prettier": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz",
-      "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz",
+      "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==",
       "dev": true,
       "requires": {
         "prettier-linter-helpers": "^1.0.0"
@@ -2835,13 +2730,13 @@
       "dev": true
     },
     "espree": {
-      "version": "7.3.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
-      "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+      "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
       "dev": true,
       "requires": {
         "acorn": "^7.4.0",
-        "acorn-jsx": "^5.2.0",
+        "acorn-jsx": "^5.3.1",
         "eslint-visitor-keys": "^1.3.0"
       },
       "dependencies": {
@@ -2912,28 +2807,71 @@
       "dev": true
     },
     "execa": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
-      "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+      "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
       "dev": true,
       "requires": {
-        "cross-spawn": "^6.0.0",
-        "get-stream": "^4.0.0",
-        "is-stream": "^1.1.0",
-        "npm-run-path": "^2.0.0",
-        "p-finally": "^1.0.0",
-        "signal-exit": "^3.0.0",
-        "strip-eof": "^1.0.0"
+        "cross-spawn": "^7.0.0",
+        "get-stream": "^5.0.0",
+        "human-signals": "^1.1.1",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.0",
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2",
+        "strip-final-newline": "^2.0.0"
       },
       "dependencies": {
+        "cross-spawn": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+          "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+          "dev": true,
+          "requires": {
+            "path-key": "^3.1.0",
+            "shebang-command": "^2.0.0",
+            "which": "^2.0.1"
+          }
+        },
         "get-stream": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
-          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+          "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
           "dev": true,
           "requires": {
             "pump": "^3.0.0"
           }
+        },
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+          "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+          "dev": true,
+          "requires": {
+            "shebang-regex": "^3.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+          "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+          "dev": true
+        },
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
         }
       }
     },
@@ -2985,6 +2923,69 @@
             "is-extendable": "^0.1.0"
           }
         },
+        "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": {
+            "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-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": {
+            "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-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"
+          }
+        },
+        "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
+        },
+        "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
+        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -2994,16 +2995,16 @@
       }
     },
     "expect": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.1.tgz",
-      "integrity": "sha512-BRfxIBHagghMmr1D2MRY0Qv5d3Nc8HCqgbDwNXw/9izmM5eBb42a2YjLKSbsqle76ozGkAEPELQX4IdNHAKRNA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
+      "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "ansi-styles": "^4.0.0",
         "jest-get-type": "^26.3.0",
-        "jest-matcher-utils": "^26.6.1",
-        "jest-message-util": "^26.6.1",
+        "jest-matcher-utils": "^26.6.2",
+        "jest-message-util": "^26.6.2",
         "jest-regex-util": "^26.0.0"
       }
     },
@@ -3021,17 +3022,6 @@
       "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"
-          }
-        }
       }
     },
     "external-editor": {
@@ -3070,43 +3060,20 @@
             "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==",
+        "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-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
+            "is-extendable": "^0.1.0"
           }
+        },
+        "is-extendable": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+          "dev": true
         }
       }
     },
@@ -3168,12 +3135,12 @@
       }
     },
     "file-entry-cache": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz",
+      "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==",
       "dev": true,
       "requires": {
-        "flat-cache": "^2.0.1"
+        "flat-cache": "^3.0.4"
       }
     },
     "file-url": {
@@ -3202,24 +3169,20 @@
       }
     },
     "flat-cache": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+      "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
       "dev": true,
       "requires": {
-        "flatted": "^2.0.0",
-        "rimraf": "2.6.3",
-        "write": "1.0.3"
+        "flatted": "^3.1.0",
+        "rimraf": "^3.0.2"
       },
       "dependencies": {
-        "rimraf": {
-          "version": "2.6.3",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-          "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
+        "flatted": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz",
+          "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==",
+          "dev": true
         }
       }
     },
@@ -3298,9 +3261,9 @@
       "dev": true
     },
     "gensync": {
-      "version": "1.0.0-beta.1",
-      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
-      "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
       "dev": true
     },
     "get-caller-file": {
@@ -3332,12 +3295,6 @@
         }
       }
     },
-    "get-stdin": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
-      "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
-      "dev": true
-    },
     "get-stream": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz",
@@ -3383,12 +3340,12 @@
       }
     },
     "global-dirs": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz",
-      "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz",
+      "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==",
       "dev": true,
       "requires": {
-        "ini": "^1.3.5"
+        "ini": "1.3.7"
       }
     },
     "globals": {
@@ -3601,9 +3558,9 @@
       "dev": true
     },
     "import-fresh": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
-      "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
       "dev": true,
       "requires": {
         "parent-module": "^1.0.0",
@@ -3649,27 +3606,27 @@
       "dev": true
     },
     "ini": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
+      "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
       "dev": true
     },
     "inquirer": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
-      "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
+      "version": "7.3.3",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
+      "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^4.2.1",
-        "chalk": "^3.0.0",
+        "chalk": "^4.1.0",
         "cli-cursor": "^3.1.0",
-        "cli-width": "^2.0.0",
+        "cli-width": "^3.0.0",
         "external-editor": "^3.0.3",
         "figures": "^3.0.0",
-        "lodash": "^4.17.15",
+        "lodash": "^4.17.19",
         "mute-stream": "0.0.8",
         "run-async": "^2.4.0",
-        "rxjs": "^6.5.3",
+        "rxjs": "^6.6.0",
         "string-width": "^4.1.0",
         "strip-ansi": "^6.0.0",
         "through": "^2.3.6"
@@ -3681,6 +3638,22 @@
           "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
         },
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
         "strip-ansi": {
           "version": "6.0.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@@ -3689,6 +3662,15 @@
           "requires": {
             "ansi-regex": "^5.0.0"
           }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
         }
       }
     },
@@ -3699,23 +3681,12 @@
       "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=",
+      "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": "^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": "^6.0.0"
       }
     },
     "is-arrayish": {
@@ -3764,23 +3735,12 @@
       }
     },
     "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=",
+      "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": "^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": "^6.0.0"
       }
     },
     "is-date-object": {
@@ -3790,22 +3750,14 @@
       "dev": true
     },
     "is-descriptor": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "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": "^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-accessor-descriptor": "^1.0.0",
+        "is-data-descriptor": "^1.0.0",
+        "kind-of": "^6.0.2"
       }
     },
     "is-docker": {
@@ -3816,10 +3768,13 @@
       "optional": 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
+      "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"
+      }
     },
     "is-extglob": {
       "version": "2.1.1",
@@ -3907,9 +3862,9 @@
       }
     },
     "is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+      "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
       "dev": true
     },
     "is-symbol": {
@@ -3973,35 +3928,6 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
       "dev": true
     },
-    "istanbul-lib-coverage": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
-      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
-      "dev": true
-    },
-    "istanbul-lib-instrument": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
-      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
-      "dev": true,
-      "requires": {
-        "@babel/generator": "^7.4.0",
-        "@babel/parser": "^7.4.3",
-        "@babel/template": "^7.4.0",
-        "@babel/traverse": "^7.4.3",
-        "@babel/types": "^7.4.0",
-        "istanbul-lib-coverage": "^2.0.5",
-        "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
-        }
-      }
-    },
     "istanbul-lib-report": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
@@ -4081,14 +4007,46 @@
       }
     },
     "jest": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.1.tgz",
-      "integrity": "sha512-f+ahfqw3Ffy+9vA7sWFGpTmhtKEMsNAZiWBVXDkrpIO73zIz22iimjirnV78kh/eWlylmvLh/0WxHN6fZraZdA==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
+      "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==",
       "dev": true,
       "requires": {
-        "@jest/core": "^26.6.1",
+        "@jest/core": "^26.6.3",
         "import-local": "^3.0.2",
-        "jest-cli": "^26.6.1"
+        "jest-cli": "^26.6.3"
+      }
+    },
+    "jest-changed-files": {
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz",
+      "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==",
+      "dev": true,
+      "requires": {
+        "@jest/types": "^26.6.2",
+        "execa": "^4.0.0",
+        "throat": "^5.0.0"
+      }
+    },
+    "jest-cli": {
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz",
+      "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==",
+      "dev": true,
+      "requires": {
+        "@jest/core": "^26.6.3",
+        "@jest/test-result": "^26.6.2",
+        "@jest/types": "^26.6.2",
+        "chalk": "^4.0.0",
+        "exit": "^0.1.2",
+        "graceful-fs": "^4.2.4",
+        "import-local": "^3.0.2",
+        "is-ci": "^2.0.0",
+        "jest-config": "^26.6.3",
+        "jest-util": "^26.6.2",
+        "jest-validate": "^26.6.2",
+        "prompts": "^2.0.1",
+        "yargs": "^15.4.1"
       },
       "dependencies": {
         "chalk": {
@@ -4107,27 +4065,6 @@
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "jest-cli": {
-          "version": "26.6.1",
-          "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.1.tgz",
-          "integrity": "sha512-aPLoEjlwFrCWhiPpW5NUxQA1X1kWsAnQcQ0SO/fHsCvczL3W75iVAcH9kP6NN+BNqZcHNEvkhxT5cDmBfEAh+w==",
-          "dev": true,
-          "requires": {
-            "@jest/core": "^26.6.1",
-            "@jest/test-result": "^26.6.1",
-            "@jest/types": "^26.6.1",
-            "chalk": "^4.0.0",
-            "exit": "^0.1.2",
-            "graceful-fs": "^4.2.4",
-            "import-local": "^3.0.2",
-            "is-ci": "^2.0.0",
-            "jest-config": "^26.6.1",
-            "jest-util": "^26.6.1",
-            "jest-validate": "^26.6.1",
-            "prompts": "^2.0.1",
-            "yargs": "^15.4.1"
-          }
-        },
         "supports-color": {
           "version": "7.2.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -4139,125 +4076,30 @@
         }
       }
     },
-    "jest-changed-files": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.1.tgz",
-      "integrity": "sha512-NhSdZ5F6b/rIN5V46x1l31vrmukD/bJUXgYAY8VtP1SknYdJwjYDRxuLt7Z8QryIdqCjMIn2C0Cd98EZ4umo8Q==",
-      "dev": true,
-      "requires": {
-        "@jest/types": "^26.6.1",
-        "execa": "^4.0.0",
-        "throat": "^5.0.0"
-      },
-      "dependencies": {
-        "cross-spawn": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-          "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-          "dev": true,
-          "requires": {
-            "path-key": "^3.1.0",
-            "shebang-command": "^2.0.0",
-            "which": "^2.0.1"
-          }
-        },
-        "execa": {
-          "version": "4.0.3",
-          "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz",
-          "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==",
-          "dev": true,
-          "requires": {
-            "cross-spawn": "^7.0.0",
-            "get-stream": "^5.0.0",
-            "human-signals": "^1.1.1",
-            "is-stream": "^2.0.0",
-            "merge-stream": "^2.0.0",
-            "npm-run-path": "^4.0.0",
-            "onetime": "^5.1.0",
-            "signal-exit": "^3.0.2",
-            "strip-final-newline": "^2.0.0"
-          }
-        },
-        "get-stream": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
-          "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
-          "dev": true,
-          "requires": {
-            "pump": "^3.0.0"
-          }
-        },
-        "is-stream": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
-          "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
-          "dev": true
-        },
-        "npm-run-path": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
-          "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
-          "dev": true,
-          "requires": {
-            "path-key": "^3.0.0"
-          }
-        },
-        "path-key": {
-          "version": "3.1.1",
-          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-          "dev": true
-        },
-        "shebang-command": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-          "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-          "dev": true,
-          "requires": {
-            "shebang-regex": "^3.0.0"
-          }
-        },
-        "shebang-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-          "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-          "dev": true
-        },
-        "which": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
-        }
-      }
-    },
     "jest-config": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.1.tgz",
-      "integrity": "sha512-mtJzIynIwW1d1nMlKCNCQiSgWaqFn8cH/fOSNY97xG7Y9tBCZbCSuW2GTX0RPmceSJGO7l27JgwC18LEg0Vg+g==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz",
+      "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/test-sequencer": "^26.6.1",
-        "@jest/types": "^26.6.1",
-        "babel-jest": "^26.6.1",
+        "@jest/test-sequencer": "^26.6.3",
+        "@jest/types": "^26.6.2",
+        "babel-jest": "^26.6.3",
         "chalk": "^4.0.0",
         "deepmerge": "^4.2.2",
         "glob": "^7.1.1",
         "graceful-fs": "^4.2.4",
-        "jest-environment-jsdom": "^26.6.1",
-        "jest-environment-node": "^26.6.1",
+        "jest-environment-jsdom": "^26.6.2",
+        "jest-environment-node": "^26.6.2",
         "jest-get-type": "^26.3.0",
-        "jest-jasmine2": "^26.6.1",
+        "jest-jasmine2": "^26.6.3",
         "jest-regex-util": "^26.0.0",
-        "jest-resolve": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "jest-validate": "^26.6.1",
+        "jest-resolve": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "jest-validate": "^26.6.2",
         "micromatch": "^4.0.2",
-        "pretty-format": "^26.6.1"
+        "pretty-format": "^26.6.2"
       },
       "dependencies": {
         "chalk": {
@@ -4288,15 +4130,15 @@
       }
     },
     "jest-diff": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.1.tgz",
-      "integrity": "sha512-BBNy/zin2m4kG5In126O8chOBxLLS/XMTuuM2+YhgyHk87ewPzKTuTJcqj3lOWOi03NNgrl+DkMeV/exdvG9gg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
+      "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
       "dev": true,
       "requires": {
         "chalk": "^4.0.0",
-        "diff-sequences": "^26.5.0",
+        "diff-sequences": "^26.6.2",
         "jest-get-type": "^26.3.0",
-        "pretty-format": "^26.6.1"
+        "pretty-format": "^26.6.2"
       },
       "dependencies": {
         "chalk": {
@@ -4336,16 +4178,16 @@
       }
     },
     "jest-each": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.1.tgz",
-      "integrity": "sha512-gSn8eB3buchuq45SU7pLB7qmCGax1ZSxfaWuEFblCyNMtyokYaKFh9dRhYPujK6xYL57dLIPhLKatjmB5XWzGA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz",
+      "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "chalk": "^4.0.0",
         "jest-get-type": "^26.3.0",
-        "jest-util": "^26.6.1",
-        "pretty-format": "^26.6.1"
+        "jest-util": "^26.6.2",
+        "pretty-format": "^26.6.2"
       },
       "dependencies": {
         "chalk": {
@@ -4376,32 +4218,32 @@
       }
     },
     "jest-environment-jsdom": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.1.tgz",
-      "integrity": "sha512-A17RiXuHYNVlkM+3QNcQ6n5EZyAc6eld8ra9TW26luounGWpku4tj03uqRgHJCI1d4uHr5rJiuCH5JFRtdmrcA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz",
+      "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^26.6.1",
-        "@jest/fake-timers": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/environment": "^26.6.2",
+        "@jest/fake-timers": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
-        "jest-mock": "^26.6.1",
-        "jest-util": "^26.6.1",
+        "jest-mock": "^26.6.2",
+        "jest-util": "^26.6.2",
         "jsdom": "^16.4.0"
       }
     },
     "jest-environment-node": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.1.tgz",
-      "integrity": "sha512-YffaCp6h0j1kbcf1NVZ7umC6CPgD67YS+G1BeornfuSkx5s3xdhuwG0DCxSiHPXyT81FfJzA1L7nXvhq50OWIg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz",
+      "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^26.6.1",
-        "@jest/fake-timers": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/environment": "^26.6.2",
+        "@jest/fake-timers": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
-        "jest-mock": "^26.6.1",
-        "jest-util": "^26.6.1"
+        "jest-mock": "^26.6.2",
+        "jest-util": "^26.6.2"
       }
     },
     "jest-get-type": {
@@ -4411,12 +4253,12 @@
       "dev": true
     },
     "jest-haste-map": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.1.tgz",
-      "integrity": "sha512-9kPafkv0nX6ta1PrshnkiyhhoQoFWncrU/uUBt3/AP1r78WSCU5iLceYRTwDvJl67H3RrXqSlSVDDa/AsUB7OQ==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz",
+      "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/graceful-fs": "^4.1.2",
         "@types/node": "*",
         "anymatch": "^3.0.3",
@@ -4424,37 +4266,37 @@
         "fsevents": "^2.1.2",
         "graceful-fs": "^4.2.4",
         "jest-regex-util": "^26.0.0",
-        "jest-serializer": "^26.5.0",
-        "jest-util": "^26.6.1",
-        "jest-worker": "^26.6.1",
+        "jest-serializer": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "jest-worker": "^26.6.2",
         "micromatch": "^4.0.2",
         "sane": "^4.0.3",
         "walker": "^1.0.7"
       }
     },
     "jest-jasmine2": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.1.tgz",
-      "integrity": "sha512-2uYdT32o/ZzSxYAPduAgokO8OlAL1YdG/9oxcEY138EDNpIK5XRRJDaGzTZdIBWSxk0aR8XxN44FvfXtHB+Fiw==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz",
+      "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==",
       "dev": true,
       "requires": {
         "@babel/traverse": "^7.1.0",
-        "@jest/environment": "^26.6.1",
-        "@jest/source-map": "^26.5.0",
-        "@jest/test-result": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/environment": "^26.6.2",
+        "@jest/source-map": "^26.6.2",
+        "@jest/test-result": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "chalk": "^4.0.0",
         "co": "^4.6.0",
-        "expect": "^26.6.1",
+        "expect": "^26.6.2",
         "is-generator-fn": "^2.0.0",
-        "jest-each": "^26.6.1",
-        "jest-matcher-utils": "^26.6.1",
-        "jest-message-util": "^26.6.1",
-        "jest-runtime": "^26.6.1",
-        "jest-snapshot": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "pretty-format": "^26.6.1",
+        "jest-each": "^26.6.2",
+        "jest-matcher-utils": "^26.6.2",
+        "jest-message-util": "^26.6.2",
+        "jest-runtime": "^26.6.3",
+        "jest-snapshot": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "pretty-format": "^26.6.2",
         "throat": "^5.0.0"
       },
       "dependencies": {
@@ -4486,25 +4328,25 @@
       }
     },
     "jest-leak-detector": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.1.tgz",
-      "integrity": "sha512-j9ZOtJSJKlHjrs4aIxWjiQUjyrffPdiAQn2Iw0916w7qZE5Lk0T2KhIH6E9vfhzP6sw0Q0jtnLLb4vQ71o1HlA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz",
+      "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==",
       "dev": true,
       "requires": {
         "jest-get-type": "^26.3.0",
-        "pretty-format": "^26.6.1"
+        "pretty-format": "^26.6.2"
       }
     },
     "jest-matcher-utils": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.1.tgz",
-      "integrity": "sha512-9iu3zrsYlUnl8pByhREF9rr5eYoiEb1F7ymNKg6lJr/0qD37LWS5FSW/JcoDl8UdMX2+zAzabDs7sTO+QFKjCg==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz",
+      "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==",
       "dev": true,
       "requires": {
         "chalk": "^4.0.0",
-        "jest-diff": "^26.6.1",
+        "jest-diff": "^26.6.2",
         "jest-get-type": "^26.3.0",
-        "pretty-format": "^26.6.1"
+        "pretty-format": "^26.6.2"
       },
       "dependencies": {
         "chalk": {
@@ -4535,17 +4377,18 @@
       }
     },
     "jest-message-util": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.1.tgz",
-      "integrity": "sha512-cqM4HnqncIebBNdTKrBoWR/4ufHTll0pK/FWwX0YasK+TlBQEMqw3IEdynuuOTjDPFO3ONlFn37280X48beByw==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz",
+      "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/stack-utils": "^2.0.0",
         "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "micromatch": "^4.0.2",
+        "pretty-format": "^26.6.2",
         "slash": "^3.0.0",
         "stack-utils": "^2.0.2"
       },
@@ -4578,12 +4421,12 @@
       }
     },
     "jest-mock": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.1.tgz",
-      "integrity": "sha512-my0lPTBu1awY8iVG62sB2sx9qf8zxNDVX+5aFgoB8Vbqjb6LqIOsfyFA8P1z6H2IsqMbvOX9oCJnK67Y3yUIMA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz",
+      "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/node": "*"
       }
     },
@@ -4600,16 +4443,16 @@
       "dev": true
     },
     "jest-resolve": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.1.tgz",
-      "integrity": "sha512-hiHfQH6rrcpAmw9xCQ0vD66SDuU+7ZulOuKwc4jpbmFFsz0bQG/Ib92K+9/489u5rVw0btr/ZhiHqBpmkbCvuQ==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz",
+      "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
         "jest-pnp-resolver": "^1.2.2",
-        "jest-util": "^26.6.1",
+        "jest-util": "^26.6.2",
         "read-pkg-up": "^7.0.1",
         "resolve": "^1.18.1",
         "slash": "^3.0.0"
@@ -4631,16 +4474,6 @@
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "resolve": {
-          "version": "1.18.1",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz",
-          "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==",
-          "dev": true,
-          "requires": {
-            "is-core-module": "^2.0.0",
-            "path-parse": "^1.0.6"
-          }
-        },
         "supports-color": {
           "version": "7.2.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -4653,40 +4486,40 @@
       }
     },
     "jest-resolve-dependencies": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.1.tgz",
-      "integrity": "sha512-MN6lufbZJ3RBfTnJesZtHu3hUCBqPdHRe2+FhIt0yiqJ3fMgzWRqMRQyN/d/QwOE7KXwAG2ekZutbPhuD7s51A==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz",
+      "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "jest-regex-util": "^26.0.0",
-        "jest-snapshot": "^26.6.1"
+        "jest-snapshot": "^26.6.2"
       }
     },
     "jest-runner": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.1.tgz",
-      "integrity": "sha512-DmpNGdgsbl5s0FGkmsInmqnmqCtliCSnjWA2TFAJS1m1mL5atwfPsf+uoZ8uYQ2X0uDj4NM+nPcDnUpbNTRMBA==",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz",
+      "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==",
       "dev": true,
       "requires": {
-        "@jest/console": "^26.6.1",
-        "@jest/environment": "^26.6.1",
-        "@jest/test-result": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/console": "^26.6.2",
+        "@jest/environment": "^26.6.2",
+        "@jest/test-result": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "chalk": "^4.0.0",
         "emittery": "^0.7.1",
         "exit": "^0.1.2",
         "graceful-fs": "^4.2.4",
-        "jest-config": "^26.6.1",
+        "jest-config": "^26.6.3",
         "jest-docblock": "^26.0.0",
-        "jest-haste-map": "^26.6.1",
-        "jest-leak-detector": "^26.6.1",
-        "jest-message-util": "^26.6.1",
-        "jest-resolve": "^26.6.1",
-        "jest-runtime": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "jest-worker": "^26.6.1",
+        "jest-haste-map": "^26.6.2",
+        "jest-leak-detector": "^26.6.2",
+        "jest-message-util": "^26.6.2",
+        "jest-resolve": "^26.6.2",
+        "jest-runtime": "^26.6.3",
+        "jest-util": "^26.6.2",
+        "jest-worker": "^26.6.2",
         "source-map-support": "^0.5.6",
         "throat": "^5.0.0"
       },
@@ -4719,35 +4552,35 @@
       }
     },
     "jest-runtime": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.1.tgz",
-      "integrity": "sha512-7uOCNeezXDWgjEyzYbRN2ViY7xNZzusNVGAMmU0UHRUNXuY4j4GBHKGMqPo/cBPZA9bSYp+lwK2DRRBU5Dv6YQ==",
-      "dev": true,
-      "requires": {
-        "@jest/console": "^26.6.1",
-        "@jest/environment": "^26.6.1",
-        "@jest/fake-timers": "^26.6.1",
-        "@jest/globals": "^26.6.1",
-        "@jest/source-map": "^26.5.0",
-        "@jest/test-result": "^26.6.1",
-        "@jest/transform": "^26.6.1",
-        "@jest/types": "^26.6.1",
+      "version": "26.6.3",
+      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz",
+      "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==",
+      "dev": true,
+      "requires": {
+        "@jest/console": "^26.6.2",
+        "@jest/environment": "^26.6.2",
+        "@jest/fake-timers": "^26.6.2",
+        "@jest/globals": "^26.6.2",
+        "@jest/source-map": "^26.6.2",
+        "@jest/test-result": "^26.6.2",
+        "@jest/transform": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/yargs": "^15.0.0",
         "chalk": "^4.0.0",
-        "cjs-module-lexer": "^0.4.2",
+        "cjs-module-lexer": "^0.6.0",
         "collect-v8-coverage": "^1.0.0",
         "exit": "^0.1.2",
         "glob": "^7.1.3",
         "graceful-fs": "^4.2.4",
-        "jest-config": "^26.6.1",
-        "jest-haste-map": "^26.6.1",
-        "jest-message-util": "^26.6.1",
-        "jest-mock": "^26.6.1",
+        "jest-config": "^26.6.3",
+        "jest-haste-map": "^26.6.2",
+        "jest-message-util": "^26.6.2",
+        "jest-mock": "^26.6.2",
         "jest-regex-util": "^26.0.0",
-        "jest-resolve": "^26.6.1",
-        "jest-snapshot": "^26.6.1",
-        "jest-util": "^26.6.1",
-        "jest-validate": "^26.6.1",
+        "jest-resolve": "^26.6.2",
+        "jest-snapshot": "^26.6.2",
+        "jest-util": "^26.6.2",
+        "jest-validate": "^26.6.2",
         "slash": "^3.0.0",
         "strip-bom": "^4.0.0",
         "yargs": "^15.4.1"
@@ -4787,9 +4620,9 @@
       }
     },
     "jest-serializer": {
-      "version": "26.5.0",
-      "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.5.0.tgz",
-      "integrity": "sha512-+h3Gf5CDRlSLdgTv7y0vPIAoLgX/SI7T4v6hy+TEXMgYbv+ztzbg5PSN6mUXAT/hXYHvZRWm+MaObVfqkhCGxA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz",
+      "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -4797,26 +4630,26 @@
       }
     },
     "jest-snapshot": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.1.tgz",
-      "integrity": "sha512-JA7bZp7HRTIJYAi85pJ/OZ2eur2dqmwIToA5/6d7Mn90isGEfeF9FvuhDLLEczgKP1ihreBzrJ6Vr7zteP5JNA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz",
+      "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.0.0",
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/babel__traverse": "^7.0.4",
         "@types/prettier": "^2.0.0",
         "chalk": "^4.0.0",
-        "expect": "^26.6.1",
+        "expect": "^26.6.2",
         "graceful-fs": "^4.2.4",
-        "jest-diff": "^26.6.1",
+        "jest-diff": "^26.6.2",
         "jest-get-type": "^26.3.0",
-        "jest-haste-map": "^26.6.1",
-        "jest-matcher-utils": "^26.6.1",
-        "jest-message-util": "^26.6.1",
-        "jest-resolve": "^26.6.1",
+        "jest-haste-map": "^26.6.2",
+        "jest-matcher-utils": "^26.6.2",
+        "jest-message-util": "^26.6.2",
+        "jest-resolve": "^26.6.2",
         "natural-compare": "^1.4.0",
-        "pretty-format": "^26.6.1",
+        "pretty-format": "^26.6.2",
         "semver": "^7.3.2"
       },
       "dependencies": {
@@ -4854,12 +4687,12 @@
       }
     },
     "jest-util": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.1.tgz",
-      "integrity": "sha512-xCLZUqVoqhquyPLuDXmH7ogceGctbW8SMyQVjD9o+1+NPWI7t0vO08udcFLVPLgKWcvc+zotaUv/RuaR6l8HIA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz",
+      "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "chalk": "^4.0.0",
         "graceful-fs": "^4.2.4",
@@ -4895,23 +4728,23 @@
       }
     },
     "jest-validate": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.1.tgz",
-      "integrity": "sha512-BEFpGbylKocnNPZULcnk+TGaz1oFZQH/wcaXlaXABbu0zBwkOGczuWgdLucUouuQqn7VadHZZeTvo8VSFDLMOA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz",
+      "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "camelcase": "^6.0.0",
         "chalk": "^4.0.0",
         "jest-get-type": "^26.3.0",
         "leven": "^3.1.0",
-        "pretty-format": "^26.6.1"
+        "pretty-format": "^26.6.2"
       },
       "dependencies": {
         "camelcase": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.1.0.tgz",
-          "integrity": "sha512-WCMml9ivU60+8rEJgELlFp1gxFcEGxwYleE3bziHEDeqsqAWGHdimB7beBFGjLzVNgPGyDsfgXLQEYMpmIFnVQ==",
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
+          "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
           "dev": true
         },
         "chalk": {
@@ -4942,17 +4775,17 @@
       }
     },
     "jest-watcher": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.1.tgz",
-      "integrity": "sha512-0LBIPPncNi9CaLKK15bnxyd2E8OMl4kJg0PTiNOI+MXztXw1zVdtX/x9Pr6pXaQYps+eS/ts43O4+HByZ7yJSw==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz",
+      "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^26.6.1",
-        "@jest/types": "^26.6.1",
+        "@jest/test-result": "^26.6.2",
+        "@jest/types": "^26.6.2",
         "@types/node": "*",
         "ansi-escapes": "^4.2.1",
         "chalk": "^4.0.0",
-        "jest-util": "^26.6.1",
+        "jest-util": "^26.6.2",
         "string-length": "^4.0.1"
       },
       "dependencies": {
@@ -4984,9 +4817,9 @@
       }
     },
     "jest-worker": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.1.tgz",
-      "integrity": "sha512-R5IE3qSGz+QynJx8y+ICEkdI2OJ3RJjRQVEyCcFAd3yVhQSEtquziPO29Mlzgn07LOVE8u8jhJ1FqcwegiXWOw==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+      "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -5256,12 +5089,12 @@
       },
       "dependencies": {
         "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "ms": "2.1.2"
           }
         }
       }
@@ -5272,6 +5105,15 @@
       "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
       "dev": true
     },
+    "lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "requires": {
+        "yallist": "^4.0.0"
+      }
+    },
     "make-dir": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -5385,17 +5227,6 @@
       "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": {
@@ -5411,24 +5242,24 @@
       "dev": true
     },
     "mutation-testing-elements": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.3.1.tgz",
-      "integrity": "sha512-XXP/enxyOd8X6lK/lu4nlPGLmwH3wfMwj9eatxLp4er0zrmv0p5gGZVkj4KnuuGfp7rnlVNBI/5EZShPJgK3HA==",
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.5.2.tgz",
+      "integrity": "sha512-ugngX+MB6tnwFxirDVSFiCQdbGMLCUQ7oPqltk5QJ/pye8aCyuA90C3Gw8klHk4aRL1JR91FEupacR9CgGXC7w==",
       "dev": true
     },
     "mutation-testing-metrics": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.3.0.tgz",
-      "integrity": "sha512-T7UkUGljyCLMEWGK6YtRTjt4fxqi5+052gjDBkKBR6T5Po6DbwwIx6DAvFyBYzjBzUx6wUhXt7UaxB/wy+JyEg==",
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.5.2.tgz",
+      "integrity": "sha512-KRMBf1tRNh1snwt+5rZu4Le+dgam+GSX+39WfzJG9k55f/+isRn4hv3dhC4Vl/XdlJ29/Z0dTSe7ZFsWBTABUA==",
       "dev": true,
       "requires": {
-        "mutation-testing-report-schema": "^1.3.0"
+        "mutation-testing-report-schema": "^1.5.2"
       }
     },
     "mutation-testing-report-schema": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.3.1.tgz",
-      "integrity": "sha512-2T2A5qBg+2SZ7CtAvW5m4W95VJxZ/UsSWVwzv3VZpm7c2VoGgIWZGPiTC76a+gorxJobyCzkWv0902UNs4Wl5Q==",
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.5.2.tgz",
+      "integrity": "sha512-ad90c42vMHa0S4ZZ3e5oZOzGAWg4G8JWto9MrmDkrwInf/Dq+Q8FupCOOTqed0V9FTWqv4sl5arRlYEbedW6Ww==",
       "dev": true
     },
     "mute-stream": {
@@ -5481,9 +5312,9 @@
       "dev": true
     },
     "node-notifier": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz",
-      "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz",
+      "integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==",
       "dev": true,
       "optional": true,
       "requires": {
@@ -5496,11 +5327,14 @@
       },
       "dependencies": {
         "semver": {
-          "version": "7.3.2",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
-          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "version": "7.3.4",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
           "dev": true,
-          "optional": true
+          "optional": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
         },
         "which": {
           "version": "2.0.2",
@@ -5515,9 +5349,9 @@
       }
     },
     "nodemon": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz",
-      "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==",
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz",
+      "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==",
       "dev": true,
       "requires": {
         "chokidar": "^3.2.2",
@@ -5620,12 +5454,20 @@
       }
     },
     "npm-run-path": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
       "dev": true,
       "requires": {
-        "path-key": "^2.0.0"
+        "path-key": "^3.0.0"
+      },
+      "dependencies": {
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+          "dev": true
+        }
       }
     },
     "nwsapi": {
@@ -5657,7 +5499,44 @@
           "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
           "dev": true,
           "requires": {
-            "is-descriptor": "^0.1.0"
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "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
+            }
           }
         },
         "kind-of": {
@@ -5944,9 +5823,9 @@
       "dev": true
     },
     "prettier": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
-      "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
+      "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
       "dev": true
     },
     "prettier-linter-helpers": {
@@ -5959,12 +5838,12 @@
       }
     },
     "pretty-format": {
-      "version": "26.6.1",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.1.tgz",
-      "integrity": "sha512-MeqqsP5PYcRBbGMvwzsyBdmAJ4EFX7pWFyl7x4+dMVg5pE0ZDdBIvEH2ergvIO+Gvwv1wh64YuOY9y5LuyY/GA==",
+      "version": "26.6.2",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
+      "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
       "dev": true,
       "requires": {
-        "@jest/types": "^26.6.1",
+        "@jest/types": "^26.6.2",
         "ansi-regex": "^5.0.0",
         "ansi-styles": "^4.0.0",
         "react-is": "^17.0.1"
@@ -5985,13 +5864,13 @@
       "dev": true
     },
     "prompts": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz",
-      "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz",
+      "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==",
       "dev": true,
       "requires": {
         "kleur": "^3.0.3",
-        "sisteransi": "^1.0.4"
+        "sisteransi": "^1.0.5"
       }
     },
     "psl": {
@@ -6023,18 +5902,18 @@
       "dev": true
     },
     "pupa": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz",
-      "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
+      "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
       "dev": true,
       "requires": {
         "escape-goat": "^2.0.0"
       }
     },
     "qs": {
-      "version": "6.9.4",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
-      "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==",
+      "version": "6.9.6",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
+      "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
       "dev": true
     },
     "rc": {
@@ -6137,9 +6016,9 @@
       "dev": true
     },
     "registry-auth-token": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz",
-      "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
+      "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
       "dev": true,
       "requires": {
         "rc": "^1.2.8"
@@ -6262,6 +6141,12 @@
       "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
       "dev": true
     },
+    "require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true
+    },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -6269,11 +6154,12 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
-      "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+      "version": "1.18.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz",
+      "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==",
       "dev": true,
       "requires": {
+        "is-core-module": "^2.0.0",
         "path-parse": "^1.0.6"
       }
     },
@@ -6332,9 +6218,9 @@
       "dev": true
     },
     "rfdc": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
-      "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.2.0.tgz",
+      "integrity": "sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA==",
       "dev": true
     },
     "rimraf": {
@@ -6359,18 +6245,18 @@
       "dev": true
     },
     "rxjs": {
-      "version": "6.6.2",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
-      "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
+      "version": "6.6.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
+      "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==",
       "dev": true,
       "requires": {
         "tslib": "^1.9.0"
       },
       "dependencies": {
         "tslib": {
-          "version": "1.13.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
-          "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
           "dev": true
         }
       }
@@ -6452,6 +6338,21 @@
             }
           }
         },
+        "execa": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+          "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^6.0.0",
+            "get-stream": "^4.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
         "fill-range": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -6475,6 +6376,21 @@
             }
           }
         },
+        "get-stream": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "dev": true,
+          "requires": {
+            "pump": "^3.0.0"
+          }
+        },
+        "is-extendable": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+          "dev": true
+        },
         "is-number": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -6495,6 +6411,12 @@
             }
           }
         },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        },
         "micromatch": {
           "version": "3.1.10",
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -6525,6 +6447,15 @@
             "remove-trailing-separator": "^1.0.1"
           }
         },
+        "npm-run-path": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+          "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+          "dev": true,
+          "requires": {
+            "path-key": "^2.0.0"
+          }
+        },
         "to-regex-range": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
@@ -6601,6 +6532,12 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
+        },
+        "is-extendable": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+          "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+          "dev": true
         }
       }
     },
@@ -6651,38 +6588,20 @@
       "dev": true
     },
     "slice-ansi": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
-      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
       "dev": true,
       "requires": {
-        "ansi-styles": "^3.2.0",
-        "astral-regex": "^1.0.0",
-        "is-fullwidth-code-point": "^2.0.0"
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "dev": true,
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
           "dev": true
         }
       }
@@ -6730,6 +6649,69 @@
             "is-extendable": "^0.1.0"
           }
         },
+        "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": {
+            "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-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": {
+            "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-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"
+          }
+        },
+        "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
+        },
+        "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
+        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -6763,35 +6745,6 @@
           "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"
-          }
         }
       }
     },
@@ -6957,6 +6910,63 @@
           "requires": {
             "is-descriptor": "^0.1.0"
           }
+        },
+        "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": {
+            "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-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": {
+            "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-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"
+          }
+        },
+        "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
         }
       }
     },
@@ -6984,12 +6994,12 @@
           "dev": true
         },
         "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "ms": "2.1.2"
           }
         }
       }
@@ -7173,34 +7183,41 @@
       "dev": true
     },
     "table": {
-      "version": "5.4.6",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
-      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+      "version": "6.0.7",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
+      "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
       "dev": true,
       "requires": {
-        "ajv": "^6.10.2",
-        "lodash": "^4.17.14",
-        "slice-ansi": "^2.1.0",
-        "string-width": "^3.0.0"
+        "ajv": "^7.0.2",
+        "lodash": "^4.17.20",
+        "slice-ansi": "^4.0.0",
+        "string-width": "^4.2.0"
       },
       "dependencies": {
-        "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+        "ajv": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
+          "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
+            "fast-deep-equal": "^3.1.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2",
+            "uri-js": "^4.2.2"
           }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true
         }
       }
     },
     "term-size": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
-      "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
+      "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
       "dev": true
     },
     "terminal-link": {
@@ -7346,9 +7363,9 @@
       "dev": true
     },
     "tslib": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
-      "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+      "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
       "dev": true
     },
     "tunnel": {
@@ -7394,15 +7411,15 @@
       "dev": true
     },
     "typed-inject": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/typed-inject/-/typed-inject-2.2.1.tgz",
-      "integrity": "sha512-+PFtxIKTfrfuqba42XYmTotRCoPC8U7/cIQSu9bHhRlHLDazrbagEDzJ8mjnVVUzgrAlseFx0qKwvf6ua5Yzmg==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/typed-inject/-/typed-inject-3.0.0.tgz",
+      "integrity": "sha512-LDuyPsk6mO1R0qpe/rm/4u/6pPgT2Fob5T+u2D/wDlORxqlwtG9oWxruTaFZ6L61kzwWGzSp80soc3UUScHmaQ==",
       "dev": true
     },
     "typed-rest-client": {
-      "version": "1.7.3",
-      "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.7.3.tgz",
-      "integrity": "sha512-CwTpx/TkRHGZoHkJhBcp4X8K3/WtlzSHVQR0OIFnt10j4tgy4ypgq/SrrgVpA1s6tAL49Q6J3R5C0Cgfh2ddqA==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.0.tgz",
+      "integrity": "sha512-Nu1MrdH6ECrRW5gHoRAdubgCs4oH6q5/J76jsEC8bVDfvVoVPkigukPalhMHPwb7ZvpsZqPptd5zpt/QdtrdBw==",
       "dev": true,
       "requires": {
         "qs": "^6.9.1",
@@ -7461,6 +7478,14 @@
         "get-value": "^2.0.6",
         "is-extendable": "^0.1.1",
         "set-value": "^2.0.1"
+      },
+      "dependencies": {
+        "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
+        }
       }
     },
     "unique-string": {
@@ -7577,15 +7602,15 @@
       "optional": true
     },
     "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==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
+      "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
       "dev": true
     },
     "v8-to-istanbul": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-6.0.1.tgz",
-      "integrity": "sha512-PzM1WlqquhBvsV+Gco6WSFeg1AGdD53ccMRkFeyHRE/KRZaVacPOmQYP3EeVgDBtKD2BJ8kgynBQ5OtKiHCH+w==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz",
+      "integrity": "sha512-fLL2rFuQpMtm9r8hrAV2apXX/WqHJ6+IC4/eQVdMDGBUgH/YMV4Gv3duk3kjmyg6uiQWBAA9nJwue4iJUOkHeA==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.1",
@@ -7641,6 +7666,12 @@
         "makeerror": "1.0.x"
       }
     },
+    "weapon-regex": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-0.3.0.tgz",
+      "integrity": "sha512-IctFbNWZJ7n8mBmEqVAdirWZbLhFlv+2so3FEiZjhzlUuhs07drvKHXiU+DppO8Fz/EbYfbcTt7HGeNzinXUlw==",
+      "dev": true
+    },
     "webidl-conversions": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
@@ -7737,26 +7768,6 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     },
-    "write": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
-      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
-      "dev": true,
-      "requires": {
-        "mkdirp": "^0.5.1"
-      },
-      "dependencies": {
-        "mkdirp": {
-          "version": "0.5.5",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.5"
-          }
-        }
-      }
-    },
     "write-file-atomic": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
@@ -7794,9 +7805,9 @@
       "dev": true
     },
     "xmltest": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/xmltest/-/xmltest-1.4.0.tgz",
-      "integrity": "sha512-FOmYNFI+NhGyd3Oyxnbs4zQQX7iAesgjyzqBWedIaeCCvDv9EE2dkcHWzUFoTrT1GP10Z+vg9JY8JE9N3vdAhQ==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/xmltest/-/xmltest-1.5.0.tgz",
+      "integrity": "sha512-wfUp7JUwE+h8Njc6SZ2l7+1HrrPgIm2b1zIYTS6kyrh1CYFepgvo5Lu7kTdoq1wdeQwii39jHCVwqwYaQP9ikw==",
       "dev": true
     },
     "y18n": {
@@ -7805,6 +7816,12 @@
       "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
       "dev": true
     },
+    "yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
     "yargs": {
       "version": "15.4.1",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
diff --git a/package.json b/package.json
index 68d5d32..a755333 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "xmldom",
-  "version": "0.4.0",
+  "version": "0.5.0",
   "description": "A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.",
   "keywords": [
     "w3c",
@@ -20,7 +20,7 @@
   "main": "lib/dom-parser.js",
   "files": [
     "CHANGELOG.md",
-    "LICENSE.md",
+    "LICENSE",
     "readme.md",
     "lib"
   ],
@@ -38,19 +38,18 @@
   },
   "dependencies": {},
   "devDependencies": {
-    "@stryker-mutator/core": "^3.3.1",
-    "@stryker-mutator/javascript-mutator": "^3.3.1",
+    "@stryker-mutator/core": "^4.4.1",
     "dom-js": "0.0.9",
-    "eslint": "^7.12.0",
-    "eslint-config-prettier": "^6.14.0",
+    "eslint": "^7.18.0",
+    "eslint-config-prettier": "^7.2.0",
     "eslint-plugin-es5": "^1.5.0",
-    "eslint-plugin-prettier": "^3.1.4",
+    "eslint-plugin-prettier": "^3.3.1",
     "get-stream": "^6.0.0",
-    "jest": "^26.6.1",
-    "nodemon": "^2.0.6",
+    "jest": "^26.6.3",
+    "nodemon": "^2.0.7",
     "npm-run-all": "^4.1.5",
-    "prettier": "^2.1.2",
-    "xmltest": "^1.4.0",
+    "prettier": "^2.2.1",
+    "xmltest": "^1.5.0",
     "yauzl": "^2.10.0"
   },
   "maintainers": [
@@ -85,10 +84,15 @@
       "name": "Eric Newport",
       "email": "kethinov at gmail.com",
       "web": "https://github.com/kethinov"
+    },
+    {
+      "name": "Christian Bewernitz",
+      "email": "coder at karfau.de",
+      "web": "https://github.com/karfau"
     }
   ],
   "bugs": {
     "url": "https://github.com/xmldom/xmldom/issues"
   },
-  "license": "(LGPL-2.0 OR MIT)"
+  "license": "MIT"
 }
diff --git a/readme.md b/readme.md
index 159ff28..479c077 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,6 @@
 # XMLDOM
 
-[![license](https://img.shields.io/npm/l/xmldom?color=blue&style=flat-square)](./LICENSE.md)
+[![license](https://img.shields.io/npm/l/xmldom?color=blue&style=flat-square)](LICENSE)
 [![npm](https://img.shields.io/npm/v/xmldom?style=flat-square)](https://www.npmjs.com/package/xmldom)
 [![bug issues](https://img.shields.io/github/issues/xmldom/xmldom/bug?color=red&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
 [!["help wanted" issues](https://img.shields.io/github/issues/xmldom/xmldom/help%20wanted?color=darkgreen&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
@@ -46,7 +46,7 @@ import { DOMParser } from 'xmldom'
 API Reference
 =====
 
- * [DOMParser](https://developer.mozilla.org/en/DOMParser):
+ * [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser):
 
 	```javascript
 	parseFromString(xmlsource,mimeType)
@@ -74,7 +74,7 @@ API Reference
 		
 	```
 
- * [XMLSerializer](https://developer.mozilla.org/en/XMLSerializer)
+ * [XMLSerializer](https://developer.mozilla.org/en-US/docs/Web/API/XMLSerializer)
  
 	```javascript
 	serializeToString(node)
@@ -98,6 +98,30 @@ DOM level2 method and attribute:
 			normalize()
 			isSupported(feature, version)
 			hasAttributes()
+* [DOMException](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html)
+   The DOMException class has the following constants (and `value` of type `Number`):
+  
+  1. `DOMException.INDEX_SIZE_ERR` (`1`)
+  1. `DOMException.DOMSTRING_SIZE_ERR` (`2`)
+  1. `DOMException.HIERARCHY_REQUEST_ERR` (`3`)
+  1. `DOMException.WRONG_DOCUMENT_ERR` (`4`)
+  1. `DOMException.INVALID_CHARACTER_ERR` (`5`)
+  1. `DOMException.NO_DATA_ALLOWED_ERR` (`6`)
+  1. `DOMException.NO_MODIFICATION_ALLOWED_ERR` (`7`)
+  1. `DOMException.NOT_FOUND_ERR` (`8`)
+  1. `DOMException.NOT_SUPPORTED_ERR` (`9`)
+  1. `DOMException.INUSE_ATTRIBUTE_ERR` (`10`)
+  1. `DOMException.INVALID_STATE_ERR` (`11`)
+  1. `DOMException.SYNTAX_ERR` (`12`)
+  1. `DOMException.INVALID_MODIFICATION_ERR` (`13`)
+  1. `DOMException.NAMESPACE_ERR` (`14`)
+  1. `DOMException.INVALID_ACCESS_ERR` (`15`)
+   
+   The DOMException object has the following properties:
+   code
+   This property is of type Number.
+
+	 * extends the Error type thrown as part of DOM API:
 
  * [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490)
 		
@@ -228,7 +252,8 @@ DOM level 3 support:
 
 DOM extension by xmldom
 ---
- * [Node] Source position extension; 
+
+* [Node] Source position extension; 
 		
 		attribute:
 			//Numbered starting from '1'
diff --git a/stryker.conf.json b/stryker.conf.json
index 05059b5..5fcbb87 100644
--- a/stryker.conf.json
+++ b/stryker.conf.json
@@ -1,6 +1,5 @@
 {
   "$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
-  "mutator": "javascript",
   "packageManager": "npm",
   "reporters": [
     "html",
@@ -9,13 +8,14 @@
     "dashboard"
   ],
   "testRunner": "command",
-  "transpilers": [],
   "dashboard": {
     "project": "github.com/brodybits/xmldom",
     "version": "master"
   },
-  "coverageAnalysis": "all",
+  "coverageAnalysis": "off",
   "commandRunner": {
-    "command": "npm run test:unit"
-  }
+    "command": "npm run test:jest -- --bail --no-cache --ci --maxWorkers=1"
+  },
+  "timeoutMS_comment": "When all tests pass (mutant survives) our tests need some time. So this is configured to prevent 'timeout's",
+  "timeoutMS": 15000
 }
diff --git a/test/assert.js b/test/assert.js
deleted file mode 100644
index 5ecc5cd..0000000
--- a/test/assert.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/* eslint strict: off */
-
-var node_assert = require('assert')
-
-function isAssertionError(error) {
-	return error.name.startsWith('AssertionError')
-}
-
-/**
- * Picks the location of the assertion from the stacktrace if available.
- *
- * @param {Error} error
- */
-function locateAssertion(error) {
-	return (
-		(error &&
-			error.stack &&
-			error.stack
-				.split('\n')
-				.find((l) => l.includes(__dirname) && !l.includes(__filename))) ||
-		'[No stacktrace available]'
-	)
-}
-
-/**
- * The existing vows testsuite makes heavy use of `console.assert(actual+'' == expected, ...)`.
- * With the assumption that the equivalent call to an assertion method that can fail a test,
- * is `assert(expected == actual, ...)` (the non strict assert using loose equality)
- * this function is provided to solve:
- *
- * - `...` often contains a repetition of `actual` to have it in the test message
- * - we want to make sure `assert.isTrue` is checked to cater for any weird type coercion
- * - we would "prefer" using `assert.isEqual` for better failure message and test maintainability
- * - easy switch to this method by
- *
- * by just making both assertions :)
- * It prefixes each assertion with `(strict ===)` or `(strict ===)`, so it's clear which one fails
- *
- * @param {*} actual The the value returned by the code under test
- * @param {*} expected The expected value
- * @param {...*} messages values to use as assertion message, no need to repeat expected or actual
- * @returns {undefined} if both assertion pass
- * @throws {AssertionError} if one of the assertion fails
- *
- * @see https://nodejs.org/docs/latest-v10.x/api/assert.html#assert_class_assert_assertionerror
- * @see https://nodejs.org/docs/latest-v10.x/api/assert.html#assert_strict_mode
- * @see https://github.com/vowsjs/vows#assertistrueactual-message
- * @see https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
- */
-function assert(actual, expected, ...messages) {
-	// in case console.assert gets converted without changing == to ,: fail
-	// it makes no sense to call this method with only one boolean argument
-	if (typeof actual === 'boolean' && arguments.length === 1)
-		throw new Error('convert equal to ,')
-	let caught
-	// the assertion with the better error message comes first so we can benefit
-	try {
-		node_assert.strict.equal(actual, expected)
-	} catch (error) {
-		if (!isAssertionError(error)) throw error
-		caught = error
-	}
-	// the original assertion comes second, it has to always be executed
-	node_assert(
-		actual == expected,
-		['(loose ==)', ...messages, actual, locateAssertion(caught)].join(' ')
-	)
-	if (caught) {
-		const msg = [
-			'(strict ===) ',
-			...messages,
-			caught.message,
-			locateAssertion(caught),
-		]
-		if ((this.strictThrows || assert.strictThrows)()) {
-			caught.message = msg.join(' ')
-			throw caught
-		}
-		;(this.log || assert.log)(...msg)
-	}
-}
-
-assert.log = console.warn
-assert.strictThrows = () => process.env.XMLDOM_ASSERT_STRICT || false
-
-/**
- * This is a consistent way of skipping an assertion since it currently fails:
- * Change `assert(exp, act, ...)` to `assert.skip(exp, act, ...)`
- *
- * - it prints something to the output when the assertion fails (like `console.assert`)
- * - it fails if no assertion fails (no more need to skip it, if it's no longer needed, remove it)
- * - it fails if the reason for skipping is not provided
- *
- * @param {*} expected The expected value
- * @param {*} actual The the value returned by the code under test
- * @param {...*} messages values to use as assertion message, no need to repeat expected or actual
- * @returns {undefined} if the assertion fails
- * @throws {AssertionError} if no assertion fails
- */
-function skip(actual, expected, ...messages) {
-	try {
-		assert.apply(this, arguments)
-	} catch (error) {
-		if (!isAssertionError(error)) {
-			throw error
-		}
-		;(this.log || assert.log)(
-			'Skipped assertion fails as expected:\n  ',
-			error.message,
-			'in',
-			locateAssertion(error)
-		)
-		return
-	}
-	const error = new Error(
-		`Skipped assertion is not failing: '''${messages.join(' ')}'''\n  `
-	)
-	error.message += locateAssertion(error)
-	throw error
-}
-
-assert.skip = skip
-
-// provide access to used node assertions to avoid cumbersome duplicate imports
-// and avoid forgetting to import .strict methods
-assert.fail = node_assert.strict.fail
-assert.equal = node_assert.strict.equal
-assert.isTrue = (actual) => assert(actual, true)
-
-module.exports = assert
diff --git a/test/assert.vows.checks.js b/test/assert.vows.checks.js
deleted file mode 100644
index b134225..0000000
--- a/test/assert.vows.checks.js
+++ /dev/null
@@ -1,218 +0,0 @@
-'use strict'
-
-const vows = require('vows')
-const assert = require('assert').strict
-const a = require('./assert')
-
-const values = [
-	undefined,
-	null,
-	true,
-	false,
-	NaN,
-	0,
-	1,
-	Infinity,
-	-Infinity,
-	'',
-	'0',
-	'1',
-	'true',
-	'false',
-	'[object Object]',
-	'() => {}',
-	[],
-	{},
-	() => {},
-]
-const describe = (...args) =>
-	args
-		.map((a) => {
-			const type = typeof a
-			let str = JSON.stringify(a)
-			if (str === undefined) {
-				str = String(a)
-			}
-			return `${type} ${str}`
-		})
-		.join(', ')
-
-const suite = vows.describe('assert')
-values.forEach((actual) => {
-	values.forEach((expected) => {
-		// `NaN === NaN` and `NaN == NaN` are false so skip NaN as expected
-		if (typeof expected === 'number' && isNaN(expected)) return
-
-		if (expected == actual) {
-			// actual and expected are loose equal
-
-			if (expected !== actual) {
-				// actual and expected are loose equal but not strict equal
-				suite.addBatch({
-					[`assert(${describe(
-						actual,
-						expected
-					)}) {strictThrows: false} logs`]: () => {
-						const logs = []
-						const t = {
-							strictThrows: () => false,
-							log: (...args) => {
-								logs.push(args.join(' '))
-								// console.warn(...args)
-							},
-						}
-						a.call(t, actual, expected, 'msg1', 'msg2')
-						assert.equal(
-							logs.length,
-							1,
-							'expected 1 log entry but was ' + logs.length
-						)
-						const missing = [
-							'(strict ===)',
-							'msg1',
-							'msg2',
-							`${__filename}:`,
-						].filter((em) => !logs[0].includes(em))
-						assert(
-							missing.length === 0,
-							`Expected all of [${describe(...missing)}] in '''${logs[0]}'''.`
-						)
-					},
-					[`assert(${describe(
-						actual,
-						expected
-					)}) {strictThrows: true} throws`]: () => {
-						const t = {
-							strictThrows: () => true,
-						}
-						// assert.throws doesn't work here since the check is not triggered for AssertionError
-						let caught
-						try {
-							a.call(t, actual, expected, 'msg1', 'msg2')
-						} catch (error) {
-							caught = error
-						}
-						assert(
-							caught && caught.name.startsWith('AssertionError'),
-							'expected an AssertionError to be thrown'
-						)
-						const missing = [
-							'(strict ===)',
-							'msg1',
-							'msg2',
-							`${__filename}:`,
-						].filter((em) => !caught.message.includes(em))
-						assert(
-							missing.length === 0,
-							`Expected all of [${describe(...missing)}] in '''${
-								caught.message
-							}'''.`
-						)
-					},
-					[`assert.skip(${describe(actual, expected)}) logs`]: () => {
-						const logs = []
-						const t = {
-							strictThrows: () => true,
-							log: (...args) => {
-								logs.push(args.join(' '))
-								// console.warn(...args)
-							},
-						}
-						a.skip.call(t, actual, expected, 'msg1', 'msg2')
-						assert.equal(
-							logs.length,
-							1,
-							'expected 1 log entry but was ' + logs.length
-						)
-						const missing = [
-							'Skipped',
-							'(strict ===)',
-							'msg1',
-							'msg2',
-							`${__filename}:`,
-						].filter((em) => !logs[0].includes(em))
-						assert(
-							missing.length === 0,
-							`Expected all of [${describe(...missing)}] in '''${logs[0]}'''.`
-						)
-					},
-				})
-			} else {
-				// actual and expected are loose and strict equal
-				suite.addBatch({
-					[`assert.skip(${describe(
-						actual,
-						expected
-					)}) throws since no asssertion fails`]: () => {
-						// assert.throws doesn't work here since the check is not triggered for AssertionError
-						let caught
-						try {
-							a.skip(actual, expected, 'msg1', 'msg2')
-						} catch (error) {
-							caught = error
-						}
-						assert(caught, 'expected an nError to be thrown')
-						const missing = [
-							'Skipped',
-							'not failing',
-							'msg1',
-							'msg2',
-							`${__filename}:`,
-						].filter((em) => !caught.message.includes(em))
-						assert(
-							missing.length === 0,
-							`Expected all of [${describe(...missing)}] in '''${
-								caught.message
-							}'''.`
-						)
-					},
-				})
-			}
-		} else {
-			// actual and expected are NOT loose equal
-			suite.addBatch({
-				[`assert(${describe(actual, expected)}) loose fails`]: () => {
-					assert.throws(
-						() => a(actual, expected, 'msg1', 'msg2'),
-						(e) => {
-							const check =
-								/AssertionError/.test(e.name) &&
-								['(loose ==)', 'msg1', 'msg2'].every((em) =>
-									e.message.includes(em)
-								)
-							return check || console.error(e)
-						}
-					)
-				},
-				[`assert.skip(${describe(actual, expected)}) logs`]: () => {
-					const logs = []
-					const t = {
-						log: (...args) => {
-							logs.push(args.join(' '))
-							// console.warn(...args)
-						},
-					}
-					a.skip.call(t, actual, expected, 'msg1', 'msg2')
-					assert.equal(
-						logs.length,
-						1,
-						'expected 1 log entry but was ' + logs.length
-					)
-					const missing = [
-						'Skipped',
-						'(loose ==)',
-						'msg1',
-						'msg2',
-						`${__filename}:`,
-					].filter((em) => !logs[0].includes(em))
-					assert(
-						missing.length === 0,
-						`Expected all of [${describe(...missing)}] in '''${logs[0]}'''.`
-					)
-				},
-			})
-		}
-	})
-})
-
-suite.export(module)
diff --git a/test/dom-parser.test.js b/test/dom-parser.test.js
index b0948d5..e31aa18 100644
--- a/test/dom-parser.test.js
+++ b/test/dom-parser.test.js
@@ -15,7 +15,7 @@ describe('DOMParser', () => {
 				columnNumber: 1,
 				lineNumber: 1,
 			}
-			expect(options.locator).toEqual(expected)
+			expect(options.locator).toStrictEqual(expected)
 		})
 
 		test('should store passed options.xmlns for default mime type', () => {
@@ -25,7 +25,7 @@ describe('DOMParser', () => {
 			// TODO: is there a simpler way to test this that doesn't involve invoking parseFromString?
 			const actual = it.parseFromString('<xml/>')
 
-			expect(actual.toString()).toEqual('<xml xmlns="custom-default-ns"/>')
+			expect(actual.toString()).toBe('<xml xmlns="custom-default-ns"/>')
 		})
 
 		test('should store and modify passed options.xmlns for html mime type', () => {
@@ -35,7 +35,7 @@ describe('DOMParser', () => {
 			// TODO: is there a simpler way to test this that doesn't involve invoking parseFromString?
 			it.parseFromString('<xml/>', 'text/html')
 
-			expect(options.xmlns['']).toEqual('http://www.w3.org/1999/xhtml')
+			expect(options.xmlns['']).toBe('http://www.w3.org/1999/xhtml')
 		})
 	})
 
@@ -45,7 +45,7 @@ describe('DOMParser', () => {
 
 			const actual = new DOMParser().parseFromString(XML).toString()
 
-			expect(actual).toEqual(XML)
+			expect(actual).toBe(XML)
 		})
 
 		test('should provide access to textContent and attribute values', () => {
@@ -71,13 +71,13 @@ describe('DOMParser', () => {
 			*/
 			const textTags = document.getElementsByTagName('text')
 
-			expect(textTags.length).toEqual(3)
+			expect(textTags).toHaveLength(3)
 
 			const expectedText = ['first', 'second', 'last']
 			for (let i = 0; i < textTags.length; i++) {
 				const textTag = textTags[i]
-				expect(textTag.textContent).toEqual(expectedText[i])
-				expect(textTag.getAttribute('top')).toEqual(`${i}`)
+				expect(textTag.textContent).toBe(expectedText[i])
+				expect(textTag.getAttribute('top')).toBe(`${i}`)
 			}
 		})
 	})
diff --git a/test/dom/attr.test.js b/test/dom/attr.test.js
index ccdee40..0376672 100644
--- a/test/dom/attr.test.js
+++ b/test/dom/attr.test.js
@@ -1,71 +1,62 @@
 'use strict'
+const { DOMParser } = require('../../lib/dom-parser')
+const { DOMException } = require('../../lib/dom')
 
-var DOMParser = require('../../lib/dom-parser').DOMParser
-const assert = require('../assert')
-
-// Create a Test Suite
 describe('XML attrs', () => {
 	it('can properly set attribute', () => {
-		var root = new DOMParser().parseFromString('<xml/>', 'text/xml')
+		const root = new DOMParser().parseFromString('<xml/>', 'text/xml')
 			.documentElement
 		root.setAttribute('a', '1')
-		assert(root.attributes[0].localName, 'a')
+		expect(root.attributes[0].localName).toBe('a')
+
 		root.setAttribute('b', 2)
 		root.setAttribute('a', 1)
 		root.setAttribute('a', 1)
 		root.setAttribute('a', 1)
-		assert(root.attributes.length, 2)
-		try {
-			var c = root.ownerDocument.createElement('c')
+		expect(root.attributes.length).toBe(2)
+
+		const c = root.ownerDocument.createElement('c')
+		expect(() => {
 			c.setAttributeNode(root.attributes.item(0))
-		} catch (e) {
-			assert(e.code, 10)
-			return
-		}
-		assert.fail('expected error but none was thrown')
+		}).toThrow(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR))
 	})
 
 	it('can properly set ns attribute', () => {
-		var root = new DOMParser().parseFromString(
+		const root = new DOMParser().parseFromString(
 			"<xml xmlns:a='a' xmlns:b='b' xmlns='e'><child/></xml>",
 			'text/xml'
 		).documentElement
-		var child = root.firstChild
+
+		const child = root.firstChild
 		child.setAttributeNS('a', 'a:a', '1')
 		child.setAttributeNS('b', 'b:b', '2')
 		child.setAttributeNS('b', 'b:a', '1')
-		assert(child.attributes.length, 3, 'after adding 3', child)
+		expect(child.attributes.length).toBe(3)
 		child.setAttribute('a', 1)
 		child.setAttributeNS('b', 'b:b', '2')
-		assert(child.attributes.length, 4, 'after adding 4 and one with namespace')
-		try {
-			var c = root.ownerDocument.createElement('c')
+		expect(child.attributes.length).toBe(4)
+
+		const c = root.ownerDocument.createElement('c')
+		expect(() => {
 			c.setAttributeNodeNS(root.attributes.item(0))
-		} catch (e) {
-			assert(e.code, 10, 'wrong error code')
-			return
-		}
-		assert.fail('expected error but none was thrown')
+		}).toThrow(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR))
 	})
 
 	it('can properly override attribute', () => {
-		var root = new DOMParser().parseFromString(
+		const root = new DOMParser().parseFromString(
 			"<xml xmlns:a='a' xmlns:b='b' xmlns='e'><child/></xml>",
 			'text/xml'
 		).documentElement
 		root.setAttributeNS('a', 'a:a', '1')
-		assert(root.attributes.length, 4)
-		//not standart
-		//    	root.firstChild.setAttributeNode(root.attributes[0]);
-		//    	assert(root.attributes.length, 0);
+		expect(root.attributes.length).toBe(4)
 	})
 
 	it('properly supports attribute namespace', () => {
-		var root = new DOMParser().parseFromString(
+		const root = new DOMParser().parseFromString(
 			"<xml xmlns:a='a' xmlns:b='b' a:b='e'></xml>",
 			'text/xml'
 		).documentElement
-		assert(root.getAttributeNS('a', 'b'), 'e')
+		expect(root.getAttributeNS('a', 'b')).toBe('e')
 	})
 
 	xit('can properly override ns attribute', () => {})
diff --git a/test/dom/clone.test.js b/test/dom/clone.test.js
index 701c039..698e756 100644
--- a/test/dom/clone.test.js
+++ b/test/dom/clone.test.js
@@ -1,34 +1,31 @@
 'use strict'
 
-var XMLSerializer = require('../../lib/dom-parser').XMLSerializer
-var DOMParser = require('../../lib/dom-parser').DOMParser
-const assert = require('../assert')
+const { DOMParser, XMLSerializer } = require('../../lib/dom-parser')
 
-// Create a Test Suite
 describe('XML Namespace Parse', () => {
 	it('can properly set clone', () => {
-		var doc1 = new DOMParser().parseFromString(
+		const doc1 = new DOMParser().parseFromString(
 			"<doc1 attr1='1' attr2='a2'>text1<child>text2</child></doc1>",
 			'text/xml'
 		)
-		var doc1s = new XMLSerializer().serializeToString(doc1)
-		var n = doc1.cloneNode(true)
-		assert(n, doc1s)
+		const doc1s = new XMLSerializer().serializeToString(doc1)
+		const n = doc1.cloneNode(true)
+		expect(n.toString()).toBe(doc1s.toString())
 	})
 
 	it('can properly import', () => {
-		var doc1 = new DOMParser().parseFromString("<doc2 attr='2'/>")
-		var doc2 = new DOMParser().parseFromString(
+		const doc1 = new DOMParser().parseFromString("<doc2 attr='2'/>")
+		const doc2 = new DOMParser().parseFromString(
 			"<doc1 attr1='1' attr2='a2'>text1<child>text2</child></doc1>",
 			'text/xml'
 		)
 
-		var doc3 = new DOMParser().parseFromString(
+		const doc3 = new DOMParser().parseFromString(
 			"<doc2 attr='2'><doc1 attr1='1' attr2='a2'>text1<child>text2</child></doc1></doc2>"
 		)
-		var n = doc1.importNode(doc2.documentElement, true)
+		const n = doc1.importNode(doc2.documentElement, true)
 		doc1.documentElement.appendChild(n)
-		assert(doc1, doc3 + '')
-		assert.isTrue(doc2 != doc3 + '')
+		expect(doc1.toString()).toBe(doc3.toString())
+		expect(doc2.toString()).not.toBe(doc3.toString())
 	})
 })
diff --git a/test/dom/element.test.js b/test/dom/element.test.js
index 392a222..ad9cc41 100644
--- a/test/dom/element.test.js
+++ b/test/dom/element.test.js
@@ -1,59 +1,54 @@
 'use strict'
 
-var DOMParser = require('../../lib/dom-parser').DOMParser
-var assert = require('../assert')
-var XMLSerializer = require('../../lib/dom-parser').XMLSerializer
+const { DOMParser, XMLSerializer } = require('../../lib/dom-parser')
 
 // Create a Test Suite
 describe('XML Namespace Parse', () => {
 	// See: http://jsfiddle.net/bigeasy/ShcXP/1/
 	it('supports Document_getElementsByTagName', () => {
-		var doc = new DOMParser().parseFromString('<a><b/></a>')
-		assert(doc.getElementsByTagName('*').length, 2, 'on doc')
-		assert(
-			doc.documentElement.getElementsByTagName('*').length,
-			1,
-			'on doc.documentElement'
-		)
+		const doc = new DOMParser().parseFromString('<a><b/></a>')
+		expect(doc.getElementsByTagName('*')).toHaveLength(2)
+		expect(doc.documentElement.getElementsByTagName('*')).toHaveLength(1)
 	})
 
 	it('supports getElementsByTagName', () => {
-		var doc = new DOMParser().parseFromString(
+		const doc = new DOMParser().parseFromString(
 			'<xml xmlns="http://test.com" xmlns:t="http://test.com" xmlns:t2="http://test2.com">' +
 				'<t:test/><test/><t2:test/>' +
 				'<child attr="1"><test><child attr="2"/></test></child>' +
 				'<child attr="3"/></xml>',
 			'text/xml'
 		)
-		var childs = doc.documentElement.getElementsByTagName('child')
-		assert(childs.item(0).getAttribute('attr'), '1', childs.item(0) + '')
-		assert(childs.item(1).getAttribute('attr'), '2', childs.item(1) + '')
-		assert(childs.item(2).getAttribute('attr'), '3', childs.item(2) + '')
-		assert(childs.length, 3, 'documentElement children length')
-
-		var childs = doc.getElementsByTagName('child')
-		assert(childs.item(0).getAttribute('attr'), '1', childs.item(0) + '')
-		assert(childs.item(1).getAttribute('attr'), '2', childs.item(1) + '')
-		assert(childs.item(2).getAttribute('attr'), '3', childs.item(2) + '')
-		assert(childs.length, 3, 'doc children length')
-
-		var childs = doc.documentElement.getElementsByTagName('*')
-		for (var i = 0, buf = []; i < childs.length; i++) {
-			buf.push(childs[i].tagName)
+
+		const childs1 = doc.documentElement.getElementsByTagName('child')
+		expect(childs1.item(0).getAttribute('attr')).toBe('1')
+		expect(childs1.item(1).getAttribute('attr')).toBe('2')
+		expect(childs1.item(2).getAttribute('attr')).toBe('3')
+		expect(childs1).toHaveLength(3)
+
+		const childs2 = doc.getElementsByTagName('child')
+		expect(childs2.item(0).getAttribute('attr')).toBe('1')
+		expect(childs2.item(1).getAttribute('attr')).toBe('2')
+		expect(childs2.item(2).getAttribute('attr')).toBe('3')
+		expect(childs2).toHaveLength(3)
+
+		const childs3 = doc.documentElement.getElementsByTagName('*')
+		for (let i = 0, buf = []; i < childs3.length; i++) {
+			buf.push(childs3[i].tagName)
 		}
-		assert(childs.length, 7, buf)
+		expect(childs3).toHaveLength(7)
 
-		var feed = new DOMParser().parseFromString(
+		const feed = new DOMParser().parseFromString(
 			'<feed><entry>foo</entry></feed>'
 		)
-		var entries = feed.documentElement.getElementsByTagName('entry')
-		assert.equal(entries.length, 1, 'assert entry nodelist length ==1')
-		assert(entries[0].nodeName, 'entry')
-		assert(feed.documentElement.childNodes.item(0).nodeName, 'entry')
+		const entries = feed.documentElement.getElementsByTagName('entry')
+		expect(entries).toHaveLength(1)
+		expect(entries[0].nodeName).toBe('entry')
+		expect(feed.documentElement.childNodes.item(0).nodeName).toBe('entry')
 	})
 
 	it('supports getElementsByTagNameNS', () => {
-		var doc = new DOMParser().parseFromString(
+		const doc = new DOMParser().parseFromString(
 			'<xml xmlns="http://test.com" xmlns:t="http://test.com" xmlns:t2="http://test2.com">' +
 				'<t:test/><test/><t2:test/>' +
 				'<child attr="1"><test><child attr="2"/></test></child>' +
@@ -61,119 +56,112 @@ describe('XML Namespace Parse', () => {
 			'text/xml'
 		)
 
-		var childs = doc.documentElement.getElementsByTagNameNS(
+		const childs1 = doc.documentElement.getElementsByTagNameNS(
 			'http://test.com',
 			'*'
 		)
-		var i = 0
-		assert(childs.length, 6)
+		expect(childs1).toHaveLength(6)
 
-		var childs = doc.getElementsByTagNameNS('http://test.com', '*')
-		assert(childs.length, 7)
+		const childs2 = doc.getElementsByTagNameNS('http://test.com', '*')
+		expect(childs2).toHaveLength(7)
 
-		var childs = doc.documentElement.getElementsByTagNameNS(
+		const childs3 = doc.documentElement.getElementsByTagNameNS(
 			'http://test.com',
 			'test'
 		)
-		assert(childs.length, 3)
+		expect(childs3).toHaveLength(3)
 
-		var childs = doc.getElementsByTagNameNS('http://test.com', 'test')
-		assert(childs.length, 3)
+		const childs4 = doc.getElementsByTagNameNS('http://test.com', 'test')
+		expect(childs4).toHaveLength(3)
 
-		var childs = doc.getElementsByTagNameNS('*', 'test')
-		assert(childs.length, 4)
+		const childs5 = doc.getElementsByTagNameNS('*', 'test')
+		expect(childs5).toHaveLength(4)
 
-		var childs = doc.documentElement.getElementsByTagNameNS('*', 'test')
-		assert(childs.length, 4)
+		const childs6 = doc.documentElement.getElementsByTagNameNS('*', 'test')
+		expect(childs6).toHaveLength(4)
 	})
 
 	it('supports getElementById', () => {
-		var doc = new DOMParser().parseFromString(
+		const doc = new DOMParser().parseFromString(
 			'<xml xmlns="http://test.com" id="root">' +
 				'<child id="a1" title="1"><child id="a2"  title="2"/></child>' +
 				'<child id="a1"   title="3"/></xml>',
 			'text/xml'
 		)
-		assert.isTrue(doc.getElementById('root') != null, 'root')
-		assert(doc.getElementById('a1').getAttribute('title'), '1', 'first')
-		assert(doc.getElementById('a2').getAttribute('title'), '2', 'second')
-		assert(doc.getElementById('a2').getAttribute('title2'), '', 'empty')
+		expect(doc.getElementById('root')).not.toBeNull()
+		expect(doc.getElementById('a1').getAttribute('title')).toBe('1')
+		expect(doc.getElementById('a2').getAttribute('title')).toBe('2')
+		expect(doc.getElementById('a2').getAttribute('title2')).toBe('')
 	})
 
 	it('can properly append exist child', () => {
-		var doc = new DOMParser().parseFromString(
+		const doc = new DOMParser().parseFromString(
 			'<xml xmlns="http://test.com" id="root">' +
 				'<child1 id="a1" title="1"><child11 id="a2"  title="2"/></child1>' +
 				'<child2 id="a1"   title="3"/><child3 id="a1"   title="3"/></xml>',
 			'text/xml'
 		)
 
-		var doc1 = doc
-		var str1 = new XMLSerializer().serializeToString(doc)
-		var doc2 = doc1.cloneNode(true)
-		var doc3 = doc1.cloneNode(true)
-		var doc4 = doc1.cloneNode(true)
+		const doc1 = doc
+		const str1 = new XMLSerializer().serializeToString(doc)
+		const doc2 = doc1.cloneNode(true)
+		const doc3 = doc1.cloneNode(true)
+		const doc4 = doc1.cloneNode(true)
 
 		doc3.documentElement.appendChild(doc3.documentElement.lastChild)
 		doc4.documentElement.appendChild(doc4.documentElement.firstChild)
 
-		var str2 = new XMLSerializer().serializeToString(doc2)
-		var str3 = new XMLSerializer().serializeToString(doc3)
-		var str4 = new XMLSerializer().serializeToString(doc4)
-		assert(str1, str2, 'str1 == str2')
-		assert(str2, str3, 'str2 == str3')
-		assert.isTrue(str3 != str4, 'str4 != str3:' + str3)
-		assert(str3.length, str4.length, 'str3 and str4 have same length')
+		const str2 = new XMLSerializer().serializeToString(doc2)
+		const str3 = new XMLSerializer().serializeToString(doc3)
+		const str4 = new XMLSerializer().serializeToString(doc4)
+		expect(str1).toBe(str2)
+		expect(str2).toBe(str3)
+		expect(str3).not.toBe(str4)
+		expect(str3.length).toBe(str4.length)
 	})
 
 	it('can properly append exist other child', () => {
-		var doc = new DOMParser().parseFromString(
+		const doc = new DOMParser().parseFromString(
 			'<xml xmlns="http://test.com" id="root">' +
 				'<child1 id="a1" title="1"><child11 id="a2"  title="2"><child/></child11></child1>' +
 				'<child2 id="a1"   title="3"/><child3 id="a1"   title="3"/></xml>',
 			'text/xml'
 		)
 
-		var doc1 = doc
-		var str1 = new XMLSerializer().serializeToString(doc)
-		var doc2 = doc1.cloneNode(true)
+		const doc1 = doc
+		const str1 = new XMLSerializer().serializeToString(doc)
+		const doc2 = doc1.cloneNode(true)
 
-		assert(doc2.documentElement.lastChild.childNodes.length, 0, 'initially 0')
+		expect(doc2.documentElement.lastChild.childNodes).toHaveLength(0)
 		doc2.documentElement.appendChild(doc2.documentElement.firstChild.firstChild)
 
-		var str2 = new XMLSerializer().serializeToString(doc2)
+		const str2 = new XMLSerializer().serializeToString(doc2)
 
-		assert(
-			doc2.documentElement.lastChild.childNodes.length,
-			1,
-			'1 after adding'
-		)
-		assert.isTrue(str1 != str2, 'str1 != str2')
-		assert.isTrue(str1.length != str2.length, 'str1/length != str2.length')
-		var doc3 = new DOMParser().parseFromString(str2, 'text/xml')
+		expect(doc2.documentElement.lastChild.childNodes).toHaveLength(1)
+		expect(str1).not.toBe(str2)
+		expect(str1).not.toHaveLength(str2.length)
+		const doc3 = new DOMParser().parseFromString(str2, 'text/xml')
 		doc3.documentElement.firstChild.appendChild(doc3.documentElement.lastChild)
-		var str3 = new XMLSerializer().serializeToString(doc3)
-		assert(str1, str3, 'final assertion')
+		const str3 = new XMLSerializer().serializeToString(doc3)
+		expect(str1).toBe(str3)
 	})
 
 	it('can properly set textContent', () => {
-		var doc = new DOMParser().parseFromString('<test><a/><b><c/></b></test>')
-		var a = doc.documentElement.firstChild
-		var b = a.nextSibling
+		const doc = new DOMParser().parseFromString('<test><a/><b><c/></b></test>')
+		const a = doc.documentElement.firstChild
+		const b = a.nextSibling
 		a.textContent = 'hello'
-		assert(
-			doc.documentElement.toString(),
+		expect(doc.documentElement.toString()).toBe(
 			'<test><a>hello</a><b><c/></b></test>'
 		)
 		b.textContent = 'there'
-		assert(
-			doc.documentElement.toString(),
+		expect(doc.documentElement.toString()).toBe(
 			'<test><a>hello</a><b>there</b></test>'
 		)
 		b.textContent = ''
-		assert(doc.documentElement.toString(), '<test><a>hello</a><b/></test>')
+		expect(doc.documentElement.toString()).toBe('<test><a>hello</a><b/></test>')
 		doc.documentElement.textContent = 'bye'
-		assert(doc.documentElement.toString(), '<test>bye</test>')
+		expect(doc.documentElement.toString()).toBe('<test>bye</test>')
 	})
 
 	xit('nested append failed', () => {})
diff --git a/test/dom/fragment.test.js b/test/dom/fragment.test.js
index ed39ebb..d584fc7 100644
--- a/test/dom/fragment.test.js
+++ b/test/dom/fragment.test.js
@@ -1,16 +1,15 @@
 'use strict'
 
-var DOMParser = require('../../lib/dom-parser').DOMParser
-const assert = require('../assert')
+const { DOMParser } = require('../../lib/dom-parser')
 
 describe('DOM DocumentFragment', () => {
 	// see: http://jsfiddle.net/9Wmh2/1/
 	it('append empty fragment', () => {
-		var document = new DOMParser().parseFromString('<p id="p"/>')
-		var fragment = document.createDocumentFragment()
+		const document = new DOMParser().parseFromString('<p id="p"/>')
+		const fragment = document.createDocumentFragment()
 		document.getElementById('p').insertBefore(fragment, null)
 		fragment.appendChild(document.createTextNode('a'))
 		document.getElementById('p').insertBefore(fragment, null)
-		assert(document.toString(), '<p id="p">a</p>')
+		expect(document.toString()).toBe('<p id="p">a</p>')
 	})
 })
diff --git a/test/dom/ns-test.test.js b/test/dom/ns-test.test.js
index 8fd1809..5ad560e 100644
--- a/test/dom/ns-test.test.js
+++ b/test/dom/ns-test.test.js
@@ -1,12 +1,11 @@
 'use strict'
 
-var assert = require('../assert')
-var DOMParser = require('../../lib/dom-parser').DOMParser
+const { DOMParser } = require('../../lib/dom-parser')
 
 // Create a Test Suite
 describe('XML Namespace Parse', () => {
 	it('supports testlitecns', () => {
-		var doc = new DOMParser({
+		const doc = new DOMParser({
 			xmlns: {
 				c: 'http://www.xidea.org/lite/core',
 				'': 'http://www.w3.org/1999/xhtml',
@@ -15,55 +14,42 @@ describe('XML Namespace Parse', () => {
 			'<html><body><c:var name="a" value="${1}"/></body></html>',
 			'text/xml'
 		)
-		var el = doc.getElementsByTagName('c:var')[0]
-		assert(el.namespaceURI, 'http://www.xidea.org/lite/core')
-		assert(
-			doc,
+		const el = doc.getElementsByTagName('c:var')[0]
+		expect(el.namespaceURI).toBe('http://www.xidea.org/lite/core')
+		expect(doc.toString()).toBe(
 			'<html xmlns="http://www.w3.org/1999/xhtml"><body><c:var name="a" value="${1}" xmlns:c="http://www.xidea.org/lite/core"></c:var></body></html>'
 		)
 	})
 
 	//ignore default prefix xml attribute
 	it('test', () => {
-		var w3 = 'http://www.w3.org/1999/xhtml'
-		var n1 = 'http://www.frankston.com/public'
-		var n2 = 'http://rmf.vc/n2'
-		var hx =
+		const w3 = 'http://www.w3.org/1999/xhtml'
+		const n1 = 'http://www.frankston.com/public'
+		const n2 = 'http://rmf.vc/n2'
+		const hx =
 			'<html test="a" xmlns="' +
 			w3 +
 			'" xmlns:rmf="' +
 			n1 +
 			'"><rmf:foo hello="asdfa"/></html>'
 
-		var doc = new DOMParser().parseFromString(hx, 'text/xml')
-		var els = [].slice.call(
+		const doc = new DOMParser().parseFromString(hx, 'text/xml')
+		const els = [].slice.call(
 			doc.documentElement.getElementsByTagNameNS(n1, 'foo')
 		)
-		for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {
-			var el = els_1[_i]
+		for (let _i = 0, els_1 = els; _i < els_1.length; _i++) {
+			const el = els_1[_i]
 
-			var te = doc.createElementNS(n1, 'test')
+			const te = doc.createElementNS(n1, 'test')
 			te.setAttributeNS(n1, 'bar', 'valx')
-			var te = doc.createElementNS(n1, 'test')
-			te.setAttributeNS(n1, 'bar', 'valx')
-			assert.equal(
-				String(te),
-				'<test xmlns="' + n1 + '" bar="valx"/>',
-				`1. i ${_i}, ${el}`
-			)
+			expect(te.toString()).toBe('<test xmlns="' + n1 + '" bar="valx"/>')
 			el.appendChild(te)
-			var tx = doc.createElementNS(n2, 'test')
+			const tx = doc.createElementNS(n2, 'test')
 			tx.setAttributeNS(n2, 'bar', 'valx')
-			assert.equal(
-				String(tx),
-				'<test xmlns="' + n2 + '" bar="valx"/>',
-				`2. i ${_i}, ${el}`
-			)
+			expect(tx.toString()).toBe('<test xmlns="' + n2 + '" bar="valx"/>')
 			el.appendChild(tx)
 		}
-		var sr = String(doc)
-		assert(
-			sr,
+		expect(doc.toString()).toBe(
 			'<html test="a" xmlns="http://www.w3.org/1999/xhtml" xmlns:rmf="http://www.frankston.com/public"><rmf:foo hello="asdfa"><test xmlns="http://www.frankston.com/public" bar="valx"></test><test xmlns="http://rmf.vc/n2" bar="valx"></test></rmf:foo></html>'
 		)
 	})
diff --git a/test/dom/serializer.test.js b/test/dom/serializer.test.js
index 045b15e..7ae9f87 100644
--- a/test/dom/serializer.test.js
+++ b/test/dom/serializer.test.js
@@ -1,21 +1,19 @@
 'use strict'
 
-var DOMParser = require('../../lib/dom-parser').DOMParser
-const assert = require('../assert')
+const { DOMParser } = require('../../lib/dom-parser')
 
 describe('XML Serializer', () => {
 	it('supports text node containing "]]>"', () => {
-		var doc = new DOMParser().parseFromString('<test/>', 'text/xml')
+		const doc = new DOMParser().parseFromString('<test/>', 'text/xml')
 		doc.documentElement.appendChild(doc.createTextNode('hello ]]> there'))
-		assert(doc.documentElement.firstChild.toString(), 'hello ]]> there')
+		expect(doc.documentElement.firstChild.toString()).toBe('hello ]]> there')
 	})
 
 	it('supports <script> element with no children', () => {
-		var doc = new DOMParser({
+		const doc = new DOMParser({
 			xmlns: { xmlns: 'http://www.w3.org/1999/xhtml' },
 		}).parseFromString('<html2><script></script></html2>', 'text/html')
-		assert(
-			doc.documentElement.firstChild.toString(),
+		expect(doc.documentElement.firstChild.toString()).toBe(
 			'<script xmlns="http://www.w3.org/1999/xhtml"></script>'
 		)
 	})
diff --git a/test/error/__snapshots__/reported-levels.test.js.snap b/test/error/__snapshots__/reported-levels.test.js.snap
new file mode 100644
index 0000000..529e08d
--- /dev/null
+++ b/test/error/__snapshots__/reported-levels.test.js.snap
@@ -0,0 +1,501 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value missed!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value missed!!||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value missed!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value missed!!||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value no end '\\"' match
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value no end '\\"' match||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value no end '\\"' match
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: attribute value no end '\\"' match||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_ElementClosingNotConnected with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: elements closed character '/' and '>' must be connected to
+@#[line:1,col:6]",
+]
+`;
+
+exports[`SYNTAX_ElementClosingNotConnected with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: elements closed character '/' and '>' must be connected to||@#[line:1,col:6]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_ElementClosingNotConnected with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: elements closed character '/' and '>' must be connected to
+@#[line:1,col:6]",
+]
+`;
+
+exports[`SYNTAX_ElementClosingNotConnected with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: elements closed character '/' and '>' must be connected to||@#[line:1,col:6]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	end tag name: inner maybe not complete
+@#[line:1,col:6]",
+]
+`;
+
+exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	end tag name: inner maybe not complete||@#[line:1,col:6]
+    at parse (lib/sax.js:128)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	end tag name: inner maybe not complete||@#[line:1,col:6]||@#[line:1,col:6]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	end tag name: inner maybe not complete
+@#[line:1,col:6]",
+]
+`;
+
+exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	end tag name: inner maybe not complete||@#[line:1,col:6]
+    at parse (lib/sax.js:128)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	end tag name: inner maybe not complete||@#[line:1,col:6]||@#[line:1,col:6]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_EndTagNotComplete with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	end tag name: xml is not complete:xml
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_EndTagNotComplete with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	end tag name: xml is not complete:xml||@#[line:1,col:1]
+    at parse (lib/sax.js:124)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	end tag name: xml is not complete:xml||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_EndTagNotComplete with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	end tag name: xml is not complete:xml
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_EndTagNotComplete with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	end tag name: xml is not complete:xml||@#[line:1,col:1]
+    at parse (lib/sax.js:124)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	end tag name: xml is not complete:xml||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_InvalidAttributeName with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid attribute:123
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_InvalidAttributeName with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid attribute:123||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_InvalidAttributeName with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid attribute:123
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_InvalidAttributeName with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid attribute:123||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_InvalidTagName with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid tagName:123
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_InvalidTagName with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid tagName:123||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_InvalidTagName with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid tagName:123
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_InvalidTagName with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	element parse error: Error: invalid tagName:123||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_UnclosedComment with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	Unclosed comment
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_UnclosedComment with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	Unclosed comment||@#[line:1,col:1]
+    at parseDCC (lib/sax.js:538)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	Unclosed comment||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_UnclosedComment with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	Unclosed comment
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_UnclosedComment with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	Unclosed comment||@#[line:1,col:1]
+    at parseDCC (lib/sax.js:538)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	Unclosed comment||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	unexpected end of input
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	unexpected end of input||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:308)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	unexpected end of input||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	unexpected end of input
+@#[line:1,col:1]",
+]
+`;
+
+exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	unexpected end of input||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:308)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	unexpected end of input||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`WF_AttributeMissingQuote with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"value\\" missed quot(\\")!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingQuote with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"value\\" missed quot(\\")!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:333)",
+]
+`;
+
+exports[`WF_AttributeMissingQuote with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"value\\" missed quot(\\")!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingQuote with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"value\\" missed quot(\\")!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:333)",
+]
+`;
+
+exports[`WF_AttributeMissingQuote2 with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"&\\" missed quot(\\")!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingQuote2 with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"&\\" missed quot(\\")!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:363)",
+]
+`;
+
+exports[`WF_AttributeMissingQuote2 with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"&\\" missed quot(\\")!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingQuote2 with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"&\\" missed quot(\\")!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:363)",
+]
+`;
+
+exports[`WF_AttributeMissingStartingQuote with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed start quot(\\")!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingStartingQuote with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed start quot(\\")!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:281)",
+]
+`;
+
+exports[`WF_AttributeMissingStartingQuote with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed start quot(\\")!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingStartingQuote with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed start quot(\\")!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:281)",
+]
+`;
+
+exports[`WF_AttributeMissingValue with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingValue with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:337)",
+]
+`;
+
+exports[`WF_AttributeMissingValue with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingValue with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:337)",
+]
+`;
+
+exports[`WF_AttributeMissingValue2 with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead2!!
+@#[line:1,col:1]",
+  "[xmldom warning]	attribute \\"attr2\\" missed value!! \\"attr2\\" instead!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingValue2 with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead2!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:385)",
+]
+`;
+
+exports[`WF_AttributeMissingValue2 with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead2!!
+@#[line:1,col:1]",
+  "[xmldom warning]	attribute \\"attr2\\" missed value!! \\"attr2\\" instead!!
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeMissingValue2 with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute \\"attr\\" missed value!! \\"attr\\" instead2!!||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:385)",
+]
+`;
+
+exports[`WF_AttributeValueMustAfterEqual with mimeType text/html should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute value must after \\"=\\"
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeValueMustAfterEqual with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute value must after \\"=\\"||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:263)",
+]
+`;
+
+exports[`WF_AttributeValueMustAfterEqual with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	attribute value must after \\"=\\"
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_AttributeValueMustAfterEqual with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	attribute value must after \\"=\\"||@#[line:1,col:1]
+    at parseElementStartPart (lib/sax.js:263)",
+]
+`;
+
+exports[`WF_DuplicateAttribute with mimeType text/html should be reported as fatalError 1`] = `
+Array [
+  "[xmldom fatalError]	Attribute a redefined
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_DuplicateAttribute with mimeType text/xml should be reported as fatalError 1`] = `
+Array [
+  "[xmldom fatalError]	Attribute a redefined
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_EntityDeclared with mimeType text/html should be reported as error 1`] = `
+Array [
+  "[xmldom error]	entity not found:&e;
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_EntityDeclared with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	entity not found:&e;||@#[line:1,col:1]
+    at replace (lib/sax.js:71)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	entity not found:&e;||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`WF_EntityDeclared with mimeType text/xml should be reported as error 1`] = `
+Array [
+  "[xmldom error]	entity not found:&e;
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_EntityDeclared with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = `
+Array [
+  "[xmldom error]	entity not found:&e;||@#[line:1,col:1]
+    at replace (lib/sax.js:71)",
+  "[xmldom error]	element parse error: Error: [xmldom error]	entity not found:&e;||@#[line:1,col:1]||@#[line:1,col:1]
+    at parse (lib/sax.js:208)",
+]
+`;
+
+exports[`WF_UnclosedXmlAttribute with mimeType text/xml should be reported as warning 1`] = `
+Array [
+  "[xmldom warning]	unclosed xml attribute
+@#[line:1,col:1]",
+]
+`;
+
+exports[`WF_UnclosedXmlAttribute with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = `
+Array [
+  "[xmldom warning]	unclosed xml attribute||@#[line:1,col:1]
+    at parse (lib/sax.js:173)",
+]
+`;
diff --git a/test/error/__snapshots__/xml-error.test.js.snap b/test/error/__snapshots__/xml-error.test.js.snap
index d0a1bb1..5a9ac6e 100644
--- a/test/error/__snapshots__/xml-error.test.js.snap
+++ b/test/error/__snapshots__/xml-error.test.js.snap
@@ -4,7 +4,7 @@ exports[`html vs xml: html attribute (miss quote) 1`] = `
 Object {
   "actual": "<img attr=\\"1\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"/>",
   "warning": Array [
-    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
@@ -37,21 +37,6 @@ Object {
   ],
 }
 `;
-exports[`html vs xml: unclosed document in text/xml 1`] = `
-Object {
-  "actual": "<img/>",
-  "warning": Array [
-    "[xmldom warning]	unclosed xml attribute
-@#[line:1,col:1]",
-  ],
-}
-`;
-
-exports[`html vs xml: unclosed document in text/html 1`] = `
-Object {
-  "actual": "<img xmlns=\\"http://www.w3.org/1999/xhtml\\"/>",
-}
-`;
 
 exports[`html vs xml: text/html attribute (missing =) 1`] = `
 Object {
@@ -94,3 +79,19 @@ Object {
   ],
 }
 `;
+
+exports[`html vs xml: unclosed document in text/html 1`] = `
+Object {
+  "actual": "<img xmlns=\\"http://www.w3.org/1999/xhtml\\"/>",
+}
+`;
+
+exports[`html vs xml: unclosed document in text/xml 1`] = `
+Object {
+  "actual": "<img/>",
+  "warning": Array [
+    "[xmldom warning]	unclosed xml attribute
+@#[line:1,col:1]",
+  ],
+}
+`;
diff --git a/test/error/error-handler.test.js b/test/error/error-handler.test.js
new file mode 100644
index 0000000..8c4f50b
--- /dev/null
+++ b/test/error/error-handler.test.js
@@ -0,0 +1,51 @@
+'use strict'
+
+const { DOMParser } = require('../../lib/dom-parser')
+const { REPORTED } = require('./reported')
+
+describe('custom errorHandler', () => {
+	it('function with two args receives key and message', () => {
+		const errors = {}
+		const parser = new DOMParser({
+			// currently needs to be a `function` to make the test work,
+			// `jest.fn()` or using `() => {}` doesn't work
+			errorHandler: function (key, msg) {
+				errors[key] = msg
+			},
+		})
+
+		parser.parseFromString(REPORTED.WF_AttributeMissingQuote.source, 'text/xml')
+		expect(errors).toHaveProperty('warning')
+		parser.parseFromString(
+			REPORTED.SYNTAX_AttributeEqualMissingValue.source,
+			'text/xml'
+		)
+		expect(errors).toHaveProperty('error')
+		parser.parseFromString(REPORTED.WF_DuplicateAttribute.source, 'text/xml')
+		expect(errors).toHaveProperty('fatalError')
+	})
+
+	it('function with one argument builds list', () => {
+		const errors = []
+		const parser = new DOMParser({
+			// currently needs to be a `function` to make the test work,
+			// `jest.fn()` or using `() => {}` doesn't work
+			errorHandler: function (msg) {
+				errors.push(msg)
+			},
+		})
+
+		parser.parseFromString(REPORTED.WF_AttributeMissingQuote.source, 'text/xml')
+		parser.parseFromString(
+			REPORTED.SYNTAX_AttributeEqualMissingValue.source,
+			'text/xml'
+		)
+		parser.parseFromString(REPORTED.WF_DuplicateAttribute.source, 'text/xml')
+
+		expect(errors).toMatchObject([
+			/\[xmldom warning]/,
+			/\[xmldom error]/,
+			/\[xmldom fatalError]/,
+		])
+	})
+})
diff --git a/test/error/error.test.js b/test/error/error.test.js
deleted file mode 100644
index d92fcb4..0000000
--- a/test/error/error.test.js
+++ /dev/null
@@ -1,83 +0,0 @@
-'use strict'
-
-const { DOMParser } = require('../../lib/dom-parser')
-
-const XML_ERROR = '<html><body title="1<2"><table<;test</body></body></html>'
-const XML_ERROR_AND_WARNING = '<html disabled><1 1="2"/></body></html>'
-
-describe('errorHandler', () => {
-	it('only single function with two args builds map', () => {
-		const errors = {}
-		const parser = new DOMParser({
-			errorHandler: function (key, msg) {
-				errors[key] = msg
-			},
-		})
-
-		parser.parseFromString(XML_ERROR_AND_WARNING, 'text/xml')
-
-		expect(errors).toMatchObject({
-			warning: expect.stringMatching(/.*/),
-			error: expect.stringMatching(/.*/),
-		})
-	})
-
-	it('only one function with one argument builds list', () => {
-		const errors = []
-		const parser = new DOMParser({
-			errorHandler: function (msg) {
-				errors.push(msg)
-			},
-		})
-
-		parser.parseFromString(XML_ERROR_AND_WARNING, 'text/xml')
-
-		expect(errors).toMatchObject([/\[xmldom warning]/, /\[xmldom error]/])
-	})
-
-	it.each(['warning', 'error'])(
-		'errorHandler for only one level: %s',
-		(level) => {
-			const errors = []
-			const parser = new DOMParser({
-				errorHandler: {
-					[level]: function (msg) {
-						errors.push(msg)
-					},
-				},
-			})
-
-			parser.parseFromString(XML_ERROR_AND_WARNING, 'text/xml')
-
-			expect(errors).toHaveLength(1)
-		}
-	)
-	it.todo(
-		'errorHandler for only one level: fatalError'
-		/*
-		I was not able to create a test case for a fatalError.
-		It might need to be removed from the API, since all but one cases are in comments
-		and an error is thrown instead. The one case left I was not able to reproduce.
-		*/
-	)
-
-	it('error function throwing is not caught', () => {
-		const errors = []
-		const ERROR_MSG = 'FROM TEST'
-
-		const parser = new DOMParser({
-			locator: {}, // removing the locator makes the test fail!
-			errorHandler: {
-				error: function (msg) {
-					errors.push(msg)
-					throw new Error(ERROR_MSG)
-				},
-			},
-		})
-
-		expect(() => {
-			parser.parseFromString(XML_ERROR, 'text/html')
-		}).toThrow(ERROR_MSG)
-		expect(errors).toMatchObject([/\n@#\[line\:\d+,col\:\d+\]/])
-	})
-})
diff --git a/test/error/reported-levels.test.js b/test/error/reported-levels.test.js
new file mode 100644
index 0000000..63ba055
--- /dev/null
+++ b/test/error/reported-levels.test.js
@@ -0,0 +1,106 @@
+'use strict'
+
+const { REPORTED } = require('./reported')
+const { getTestParser } = require('../get-test-parser')
+const { ParseError } = require('../../lib/sax')
+const { DOMParser } = require('../../lib/dom-parser')
+
+describe.each(Object.entries(REPORTED))(
+	'%s',
+	(name, { source, level, match, skippedInHtml }) => {
+		describe.each(['text/xml', 'text/html'])('with mimeType %s', (mimeType) => {
+			const isHtml = mimeType === 'text/html'
+			if (isHtml && skippedInHtml) {
+				it(`should not be reported as ${level}`, () => {
+					const { errors, parser } = getTestParser()
+
+					parser.parseFromString(source, mimeType)
+
+					// if no report was triggered, the key is not present on `errors`
+					expect(errors[level]).toBeUndefined()
+				})
+			} else {
+				it(`should be reported as ${level}`, () => {
+					const { errors, parser } = getTestParser()
+
+					parser.parseFromString(source, mimeType)
+
+					const reported = errors[level]
+					// store the snapshot, so any change in message can be inspected in the git diff
+					expect(reported).toMatchSnapshot()
+					// if a match has been defined, filter messages
+					expect(
+						match ? (reported || []).filter(match) : reported
+					).toHaveLength(1)
+				})
+				if (level === 'fatalError') {
+					it(`should throw ParseError in errorHandler.fatalError`, () => {
+						const parser = new DOMParser()
+
+						expect(() => parser.parseFromString(source, mimeType)).toThrow(
+							ParseError
+						)
+					})
+				} else if (level === 'error') {
+					it(`should not catch Error thrown in errorHandler.${level}`, () => {
+						let thrown = []
+						const errorHandler = {
+							[level]: jest.fn((message) => {
+								const toThrow = new Error(message)
+								thrown.push(toThrow)
+								throw toThrow
+							}),
+						}
+						const { parser } = getTestParser({ errorHandler })
+
+						expect(() => parser.parseFromString(source, mimeType)).toThrow(
+							Error
+						)
+						expect(thrown.map(toErrorSnapshot)).toMatchSnapshot()
+						match && expect(match(thrown[0].toString())).toBe(true)
+					})
+				} else if (level === 'warning') {
+					it('should escalate Error thrown in errorHandler.warning to errorHandler.error', () => {
+						let thrown = []
+						const errorHandler = {
+							warning: jest.fn((message) => {
+								const toThrow = new Error(message)
+								thrown.push(toThrow)
+								throw toThrow
+							}),
+							error: jest.fn(),
+						}
+						const { parser } = getTestParser({ errorHandler })
+
+						parser.parseFromString(source, mimeType)
+
+						expect(errorHandler.warning).toHaveBeenCalledTimes(1)
+						expect(errorHandler.error).toHaveBeenCalledTimes(1)
+						expect(thrown.map(toErrorSnapshot)).toMatchSnapshot()
+						match && expect(match(thrown[0].message)).toBe(true)
+					})
+				}
+			}
+		})
+	}
+)
+
+/**
+ * Creates a string from an error that is easily readable in a snapshot
+ * - put's the message on one line as first line
+ * - picks the first line in the stack trace that is in `lib/sax.js`,
+ *   and strips absolute paths and character position from that stack entry
+ *   as second line
+ * @param {Error} error
+ */
+function toErrorSnapshot(error) {
+	const libSaxMatch = /\/.*\/(lib\/sax\.js)/
+	return `${error.message.replace(/([\n\r]+\s*)/g, '||')}\n${error.stack
+		.split(/[\n\r]+/)
+		// find first line that is from lib/sax.js
+		.filter((l) => libSaxMatch.test(l))[0]
+		// strip of absolute path
+		.replace(libSaxMatch, '$1')
+		// strip of position of character in line
+		.replace(/:\d+\)$/, ')')}`
+}
diff --git a/test/error/reported.js b/test/error/reported.js
new file mode 100644
index 0000000..2820684
--- /dev/null
+++ b/test/error/reported.js
@@ -0,0 +1,243 @@
+'use strict'
+
+/**
+ * @typedef ErrorReport
+ * @property {string} source the XML snippet
+ * @property {'error'|'warning'|'fatalError'} level the name of the method triggered
+ * @property {?function(msg:string):boolean} match to pick the relevant report when there are multiple
+ * @property {?boolean} skippedInHtml Is the error reported when parsing HTML?
+ */
+/**
+ * A collection of XML samples and related information that cause the XMLReader
+ * to call methods on `errorHandler`.
+ *
+ * @type {Record<string, ErrorReport>}}
+ */
+const REPORTED = {
+	/**
+	 * Entities need to be in the entityMap to be converted as part of parsing.
+	 * xmldom currently doesn't parse entities declared in DTD.
+	 *
+	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#wf-entdeclared
+	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#wf-entdeclared
+	 */
+	WF_EntityDeclared: {
+		source: '<xml>&e;</xml>',
+		level: 'error',
+		match: (msg) => /entity not found/.test(msg),
+	},
+	/**
+	 * Well-formedness constraint: Unique Att Spec
+	 *
+	 * An attribute name must not appear more than once
+	 * in the same start-tag or empty-element tag.
+	 *
+	 * In the browser:
+	 * - as XML it is reported as `error on line 1 at column 17: Attribute a redefined`
+	 * - as HTML only the first definition is considered
+	 *
+	 * In xmldom the behavior is different for namespaces (picks first)
+	 * than for other attributes (picks last),
+	 * which can be a security issue.
+	 *
+	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#uniqattspec
+	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#uniqattspec
+	 */
+	WF_DuplicateAttribute: {
+		source: '<xml a="1" a="2"></xml>',
+		level: 'fatalError',
+		match: (msg) => /Attribute .* redefined/.test(msg),
+	},
+	/**
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser it is reported as `error on line 1 at column 14: expected '>'`,
+	 * but still adds the root level element to the dom.
+	 */
+	SYNTAX_EndTagNotComplete: {
+		source: '<xml></xml',
+		level: 'error',
+		match: (msg) => /end tag name/.test(msg) && /is not complete/.test(msg),
+	},
+	/**
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser it is reported as `error on line 1 at column 21: expected '>'`,
+	 * but still adds the root level element and inner tag to the dom.
+	 */
+	SYNTAX_EndTagMaybeNotComplete: {
+		source: '<xml><inner></inner </xml>',
+		level: 'error',
+		match: (msg) => /end tag name/.test(msg) && /maybe not complete/.test(msg),
+	},
+	/**
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser it is reported as `error on line 1 at column 6: Comment not terminated`.
+	 */
+	SYNTAX_UnclosedComment: {
+		source: '<!--',
+		level: 'error',
+		match: (msg) => /Unclosed comment/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:596, caught in 208
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser:
+	 * - as XML it is reported as
+	 * `error on line 1 at column 2: StartTag: invalid element name`
+	 * - as HTML it is accepted as characters
+	 *
+	 */
+	SYNTAX_InvalidTagName: {
+		source: '<123 />',
+		level: 'error',
+		match: (msg) => /invalid tagName/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:602, caught in 208
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser:
+	 * - as XML it is reported as
+	 * `error on line 1 at column 6: error parsing attribute name`
+	 * - as HTML it is accepted as attribute name
+	 */
+	SYNTAX_InvalidAttributeName: {
+		source: '<xml 123=""/>',
+		level: 'error',
+		match: (msg) => /invalid attribute/.test(msg),
+	},
+	/**
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser it is reported as `error on line 1 at column 5: Couldn't find end of Start Tag xml`.
+	 */
+	SYNTAX_UnexpectedEndOfInput: {
+		source: '<xml',
+		level: 'error',
+		match: (msg) => /unexpected end of input/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:392, caught in 208
+	 * This sample doesn't follow the specified grammar.
+	 * In the browser:
+	 * - in XML it is reported as `error on line 1 at column 8: error parsing attribute name`
+	 * - in HTML it produces `<xml><a <="" xml=""></a></xml>` (invalid XML?)
+	 */
+	SYNTAX_ElementClosingNotConnected: {
+		source: '<xml><a/ </xml>',
+		level: 'error',
+		match: (msg) => /must be connected/.test(msg),
+	},
+	/**
+	 * In the Browser (for XML) this is reported as
+	 * `error on line 1 at column 6: Extra content at the end of the document`
+	 * for HTML it's added to the DOM without anything being reported.
+	 */
+	WF_UnclosedXmlAttribute: {
+		source: '<xml>',
+		level: 'warning',
+		skippedInHtml: true,
+		match: (msg) => /unclosed xml attribute/.test(msg),
+	},
+	/**
+	 * In the browser:
+	 * - for XML it is reported as
+	 * `error on line 1 at column 10: Specification mandates value for attribute attr`
+	 * - for HTML is uses the attribute as one with no value and adds `"value"` to the attribute name
+	 *   and is not reporting any issue.
+	 */
+	WF_AttributeValueMustAfterEqual: {
+		source: '<xml attr"value" />',
+		level: 'warning',
+		match: (msg) => /attribute value must after "="/.test(msg),
+	},
+	/**
+	 * In the browser:
+	 * - for XML it is reported as `error on line 1 at column 11: AttValue: " or ' expected`
+	 * - for HTML is wraps `value"` with quotes and is not reporting any issue.
+	 */
+	WF_AttributeMissingStartingQuote: {
+		source: '<xml attr=value" />',
+		level: 'warning',
+		match: (msg) => /missed start quot/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:264, caught in 208.
+	 * TODO: Comment indicates fatalError, change to use errorHandler.fatalError?
+	 *
+	 * In the browser:
+	 * - for XML it is reported as `error on line 1 at column 20: AttValue: ' expected`
+	 * - for HTML nothing is added to the DOM.
+	 */
+	SYNTAX_AttributeMissingEndingQuote: {
+		source: '<xml attr="value />',
+		level: 'error',
+		match: (msg) => /attribute value no end .* match/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:324
+	 * In the browser:
+	 * - for XML it is reported as `error on line 1 at column 11: AttValue: " or ' expected`
+	 * - for HTML is wraps `value/` with quotes and is not reporting any issue.
+	 */
+	WF_AttributeMissingQuote: {
+		source: '<xml attr=value/>',
+		level: 'warning',
+		match: (msg) => / missed quot/.test(msg) && /!!/.test(msg) === false,
+	},
+	/**
+	 * Triggered by lib/sax.js:354
+	 * This is the only warning reported in this sample.
+	 * For some reason the "attribute" that is reported as missing quotes
+	 * has the name `&`.
+	 * This case is also present in 2 tests in test/html/normalize.test.js
+	 *
+	 * In the browser:
+	 * - for XML it is reported as `error on line 1 at column 8: AttValue: " or ' expected`
+	 * - for HTML is yields `<xml a="&" b="&"></xml>` and is not reporting any issue.
+	 */
+	WF_AttributeMissingQuote2: {
+		source: `<xml a=& b="&"/>`,
+		level: 'warning',
+		match: (msg) => / missed quot/.test(msg) && /!!/.test(msg),
+	},
+	/**
+	 * In the browser:
+	 * - for XML it is reported as `error on line 1 at column 9: AttValue: " or ' expected`
+	 * - for HTML is yields `<doc a1></xml>` and is not reporting any issue.
+	 *
+	 * But the XML specifications does not allow that:
+	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Attribute
+	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-Attribute
+	 */
+	SYNTAX_AttributeEqualMissingValue: {
+		source: '<doc a1=></doc>',
+		level: 'error',
+		match: (msg) => /attribute value missed!!/.test(msg),
+	},
+	/**
+	 * In the browser this is not an issue at all, but just add an attribute without a value.
+	 * But the XML specifications does not allow that:
+	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Attribute
+	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-Attribute
+	 */
+	WF_AttributeMissingValue: {
+		source: '<xml attr ></xml>',
+		level: 'warning',
+		match: (msg) => /missed value/.test(msg) && /instead!!/.test(msg),
+	},
+	/**
+	 * Triggered by lib/sax.js:376
+	 * This seems to only be reached when there are two subsequent attributes with a missing value
+	 * In the browser this is not an issue at all, but just add an attribute without a value.
+	 * But the XML specifications does not allow that:
+	 * @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Attribute
+	 * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-Attribute
+	 */
+	WF_AttributeMissingValue2: {
+		source: '<xml attr attr2 ></xml>',
+		level: 'warning',
+		match: (msg) => /missed value/.test(msg) && /instead2!!/.test(msg),
+	},
+}
+
+module.exports = {
+	REPORTED,
+}
diff --git a/test/error/xml-reader-dom-handler-errors.test.js b/test/error/xml-reader-dom-handler-errors.test.js
new file mode 100644
index 0000000..cb410e6
--- /dev/null
+++ b/test/error/xml-reader-dom-handler-errors.test.js
@@ -0,0 +1,140 @@
+'use strict'
+
+const { ParseError } = require('../../lib/sax')
+const { __DOMHandler, DOMParser } = require('../../lib/dom-parser')
+
+/**
+ * All methods implemented on the DOMHandler prototype.
+ *
+ * @type {string[]}
+ */
+const DOMHandlerMethods = Object.keys(__DOMHandler.prototype).sort()
+
+/**
+ * XMLReader is currently not calling all methods "implemented" by DOMHandler (some are just empty),
+ * If this changes the first test will fail.
+ *
+ * @type {Set<string>}
+ */
+const UNCALLED_METHODS = new Set([
+	'attributeDecl',
+	'elementDecl',
+	'endEntity',
+	'externalEntityDecl',
+	'getExternalSubset',
+	'ignorableWhitespace',
+	'internalEntityDecl',
+	'notationDecl',
+	'resolveEntity',
+	'skippedEntity',
+	'startEntity',
+	'unparsedEntityDecl',
+])
+
+/**
+ * Some of the methods DOMParser/XMLReader call during parsing are not guarded by try/catch,
+ * hence an error happening in those will stop the parsing process.
+ * There is a test to verify this error handling.
+ * If it changes this list might need to be changed as well
+ *
+ * @type {Set<string>}
+ */
+const UNCAUGHT_METHODS = new Set([
+	'characters',
+	'endDocument',
+	'error',
+	'setDocumentLocator',
+	'startDocument',
+])
+
+function noop() {}
+
+/**
+ * A subclass of DOMHandler that mocks all methods for later inspection.
+ * As part of the constructor it can be told which method is supposed to throw an error
+ * and which error constructor to use.
+ *
+ * The `methods` property provides the list of all mocks.
+ */
+class StubDOMHandler extends __DOMHandler {
+	constructor(throwingMethod, ErrorClass) {
+		super()
+		this.methods = []
+		DOMHandlerMethods.forEach((method) => {
+			const impl = jest.fn(
+				method === throwingMethod
+					? () => {
+							throw new (ErrorClass || ParseError)(
+								`StubDOMHandler throwing in ${throwingMethod}`
+							)
+					  }
+					: noop
+			)
+			impl.mockName(method)
+			this[method] = impl
+			this.methods.push(impl)
+		})
+	}
+}
+/**
+ * This sample is triggering all method calls from XMLReader to DOMHandler at least once.
+ * This is verified in a test.
+ *
+ * There is of course no guarantee that it triggers all the places where XMLReader calls DOMHandler.
+ * For example not all possible warning and error cases are present in this file,
+ * but some, so that the methods are triggered.
+ * For testing all the cases of the different error levels,
+ * there are samples per case in
+ * @see REPORTED
+ */
+const ALL_METHODS = `<?xml ?>
+<!DOCTYPE name >
+<![CDATA[ raw ]]>
+<root xmlns="namespace">
+  <!-- -->
+  <element xmlns:x="http://test" x:a="" warning>
+    character
+  </element>
+  <element duplicate="" duplicate="fatal"></mismatch>
+</root>
+<!--
+`
+
+describe('methods called in DOMHandler', () => {
+	it('should call "all possible" methods when using StubDOMHandler', () => {
+		const domBuilder = new StubDOMHandler()
+		const parser = new DOMParser({ domBuilder, locator: {} })
+		expect(domBuilder.methods).toHaveLength(DOMHandlerMethods.length)
+
+		parser.parseFromString(ALL_METHODS)
+
+		const uncalledMethodNames = domBuilder.methods
+			.filter((m) => m.mock.calls.length === 0)
+			.map((m) => m.getMockName())
+		expect(uncalledMethodNames).toEqual([...UNCALLED_METHODS.values()].sort())
+	})
+	describe.each(DOMHandlerMethods.filter((m) => !UNCALLED_METHODS.has(m)))(
+		'when DOMHandler.%s throws',
+		(throwing) => {
+			it('should not catch ParserError', () => {
+				const domBuilder = new StubDOMHandler(throwing, ParseError)
+				const parser = new DOMParser({ domBuilder, locator: {} })
+
+				expect(() => parser.parseFromString(ALL_METHODS)).toThrow(ParseError)
+			})
+			const isUncaughtMethod = UNCAUGHT_METHODS.has(throwing)
+			it(`${
+				isUncaughtMethod ? 'does not' : 'should'
+			} catch other Error`, () => {
+				const domBuilder = new StubDOMHandler(throwing, Error)
+				const parser = new DOMParser({ domBuilder, locator: {} })
+
+				if (isUncaughtMethod) {
+					expect(() => parser.parseFromString(ALL_METHODS)).toThrow()
+				} else {
+					expect(() => parser.parseFromString(ALL_METHODS)).not.toThrow()
+				}
+			})
+		}
+	)
+})
diff --git a/test/html/__snapshots__/normalize.test.js.snap b/test/html/__snapshots__/normalize.test.js.snap
index 6ce329b..6835182 100644
--- a/test/html/__snapshots__/normalize.test.js.snap
+++ b/test/html/__snapshots__/normalize.test.js.snap
@@ -13,6 +13,10 @@ Object {
 exports[`html normalizer <div a=& a="&''" b/> 1`] = `
 Object {
   "actual": "<div a=\\"&''\\" b=\\"b\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></div>",
+  "fatalError": Array [
+    "[xmldom fatalError]	Attribute a redefined
+@#[line:1,col:1]",
+  ],
   "warning": Array [
     "[xmldom warning]	attribute \\"&\\" missed quot(\\")!!
 @#[line:1,col:1]",
@@ -32,7 +36,7 @@ Object {
 @#[line:1,col:1]",
     "[xmldom warning]	attribute \\"c\\" missed value!! \\"c\\" instead2!!
 @#[line:1,col:1]",
-    "[xmldom warning]	attribute \\"123&&456\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"123&&456\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
@@ -40,13 +44,13 @@ Object {
 
 exports[`html normalizer <div test="a<b&&a< c && a>d"></div> 1`] = `
 Object {
-  "actual": "<div test=\\"a<b&&a< c && a>d\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></div>",
+  "actual": "<div test=\\"a<b&&a< c && a>d\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></div>",
 }
 `;
 
 exports[`html normalizer <div test="alert('<br/>')"/> 1`] = `
 Object {
-  "actual": "<div test=\\"alert('<br/>')\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></div>",
+  "actual": "<div test=\\"alert('<br/>')\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></div>",
 }
 `;
 
@@ -86,7 +90,7 @@ Object {
 
 exports[`html normalizer <html test="a<b && a>b && '&&&'"/> 1`] = `
 Object {
-  "actual": "<html test=\\"a<b && a>b && '&&&'\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></html>",
+  "actual": "<html test=\\"a<b && a>b && '&&&'\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></html>",
 }
 `;
 
@@ -178,7 +182,7 @@ exports[`html normalizer unclosed html <html title = 1/> 1`] = `
 Object {
   "actual": "<html title=\\"1\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></html>",
   "warning": Array [
-    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
@@ -188,7 +192,7 @@ exports[`html normalizer unclosed html <html title =1/2></html> 1`] = `
 Object {
   "actual": "<html title=\\"1/2\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></html>",
   "warning": Array [
-    "[xmldom warning]	attribute \\"1/2\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"1/2\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
@@ -208,7 +212,7 @@ exports[`html normalizer unclosed html <html title= 1/> 1`] = `
 Object {
   "actual": "<html title=\\"1\\" xmlns=\\"http://www.w3.org/1999/xhtml\\"></html>",
   "warning": Array [
-    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"1\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
diff --git a/test/parse/__snapshots__/locator.test.js.snap b/test/parse/__snapshots__/locator.test.js.snap
index cc247f5..be4371f 100644
--- a/test/parse/__snapshots__/locator.test.js.snap
+++ b/test/parse/__snapshots__/locator.test.js.snap
@@ -2,7 +2,7 @@
 
 exports[`DOMLocator attribute position 1`] = `
 Object {
-  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"><table></table><;test</body></html>",
+  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"><table></table><;test</body></html>",
 }
 `;
 
diff --git a/test/parse/__snapshots__/simple.test.js.snap b/test/parse/__snapshots__/simple.test.js.snap
index 7478b6f..28e5448 100644
--- a/test/parse/__snapshots__/simple.test.js.snap
+++ b/test/parse/__snapshots__/simple.test.js.snap
@@ -12,7 +12,7 @@ Object {
 
 exports[`parse simple 1`] = `
 Object {
-  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"></body></html>",
+  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"></body></html>",
 }
 `;
 
@@ -49,6 +49,6 @@ Object {
 
 exports[`parse wrong closing tag 1`] = `
 Object {
-  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"><table></table><;test</body></html>",
+  "actual": "<html xmlns=\\"http://www.w3.org/1999/xhtml\\"><body title=\\"1<2\\"><table></table><;test</body></html>",
 }
 `;
diff --git a/test/parse/doctype.test.js b/test/parse/doctype.test.js
new file mode 100644
index 0000000..70d81f4
--- /dev/null
+++ b/test/parse/doctype.test.js
@@ -0,0 +1,27 @@
+'use strict'
+
+const { getTestParser } = require('../get-test-parser')
+describe('doctype', () => {
+	describe.each(['SYSTEM', 'PUBLIC'])('%s', (idType) => {
+		test.each([
+			['outer single', `<!DOCTYPE x ${idType} '\"'><X/>`, "'\"'"],
+			['outer double', `<!DOCTYPE x ${idType} "\'"><X/>`, '"\'"'],
+		])(
+			'should parse single line DOCTYPE with mixed quotes (%s)',
+			(_, source, idValue) => {
+				const { errors, parser } = getTestParser()
+
+				const actual = parser.parseFromString(source).firstChild
+
+				expect({
+					[idType]: idType === 'SYSTEM' ? actual.systemId : actual.publicId,
+					name: actual.name,
+					...errors,
+				}).toEqual({
+					[idType]: idValue,
+					name: 'x',
+				})
+			}
+		)
+	})
+})
diff --git a/test/parse/parse-element.test.js b/test/parse/parse-element.test.js
index 487f163..bafb25f 100644
--- a/test/parse/parse-element.test.js
+++ b/test/parse/parse-element.test.js
@@ -9,7 +9,7 @@ describe('XML Node Parse', () => {
 			const actual = new DOMParser()
 				.parseFromString(input, 'text/xml')
 				.toString()
-			expect(actual).toEqual('<xml/>')
+			expect(actual).toBe('<xml/>')
 		})
 	})
 
@@ -24,7 +24,7 @@ describe('XML Node Parse', () => {
 					.parseFromString(input, 'text/xml')
 					.toString()
 
-				expect(actual).toEqual('<xml a="1" b="2"/>')
+				expect(actual).toBe('<xml a="1" b="2"/>')
 			})
 		})
 		describe('empty b', () => {
@@ -36,7 +36,7 @@ describe('XML Node Parse', () => {
 			])('%s', (input) => {
 				expect(
 					new DOMParser().parseFromString(input, 'text/xml').toString()
-				).toEqual('<xml a="1" b=""/>')
+				).toBe('<xml a="1" b=""/>')
 			})
 		})
 
@@ -61,7 +61,7 @@ describe('XML Node Parse', () => {
 				.parseFromString(input, 'text/xml')
 				.toString()
 
-			expect(actual).toEqual('<xml xmlns="1" xmlns:a="2" a:test="3"/>')
+			expect(actual).toBe('<xml xmlns="1" xmlns:a="2" a:test="3"/>')
 		})
 
 		it('unclosed root tag will be closed', () => {
diff --git a/test/parse/parse-error.test.js b/test/parse/parse-error.test.js
new file mode 100644
index 0000000..4b10cd7
--- /dev/null
+++ b/test/parse/parse-error.test.js
@@ -0,0 +1,38 @@
+'use strict'
+const { ParseError } = require('../../lib/sax')
+
+describe('ParseError', () => {
+	it('should have name ParseError', () => {
+		expect(new ParseError('').name).toBe('ParseError')
+	})
+	it('should be an instance of Error', () => {
+		expect(new ParseError('') instanceof Error).toBe(true)
+	})
+
+	it('should be an instance of ParseError', () => {
+		expect(new ParseError('') instanceof ParseError).toBe(true)
+	})
+
+	it('should store first argument as message', () => {
+		const error = new ParseError('FROM TEST')
+		expect(error.message).toBe('FROM TEST')
+	})
+
+	it('should store second argument as locator', () => {
+		const locator = {}
+		const error = new ParseError('', locator)
+		expect(error.locator).toBe(locator)
+	})
+
+	it('should have correct StackTrace', () => {
+		const error = new ParseError('MESSAGE')
+		const stack = error.stack && error.stack.split(/[\n\r]+/)
+		expect(stack && stack.length).toBeGreaterThan(1)
+		expect(stack[0]).toBe('ParseError: MESSAGE')
+		expect(stack[1]).toContain(__filename)
+	})
+
+	it('Error should not be instanceof ParseError', () => {
+		expect(new Error() instanceof ParseError).toBe(false)
+	})
+})
diff --git a/test/xmltest/__snapshots__/not-wf.test.js.snap b/test/xmltest/__snapshots__/not-wf.test.js.snap
index 5661d2d..400dd6e 100644
--- a/test/xmltest/__snapshots__/not-wf.test.js.snap
+++ b/test/xmltest/__snapshots__/not-wf.test.js.snap
@@ -94,7 +94,7 @@ exports[`xmltest/not-wellformed standalone should match 012.xml with snapshot 1`
 Object {
   "actual": "<doc a1=\\"v1\\"/>",
   "warning": Array [
-    "[xmldom warning]	attribute \\"v1\\" missed quot(\\")!!
+    "[xmldom warning]	attribute \\"v1\\" missed quot(\\")!
 @#[line:1,col:1]",
   ],
 }
@@ -112,7 +112,7 @@ Object {
 
 exports[`xmltest/not-wellformed standalone should match 014.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc a1=\\"<foo>\\"/>",
+  "actual": "<doc a1=\\"<foo>\\"/>",
 }
 `;
 
@@ -144,7 +144,7 @@ Object {
 
 exports[`xmltest/not-wellformed standalone should match 018.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc><![CDATA [ stuff]]></doc>",
+  "actual": "<doc><![CDATA [ stuff]]></doc>",
 }
 `;
 
@@ -205,13 +205,13 @@ Object {
 
 exports[`xmltest/not-wellformed standalone should match 025.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc>]]></doc>",
+  "actual": "<doc>]]></doc>",
 }
 `;
 
 exports[`xmltest/not-wellformed standalone should match 026.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc>]]]></doc>",
+  "actual": "<doc>]]]></doc>",
 }
 `;
 
@@ -237,7 +237,7 @@ Object {
 
 exports[`xmltest/not-wellformed standalone should match 029.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc>abc]]]>def</doc>",
+  "actual": "<doc>abc]]]>def</doc>",
 }
 `;
 
@@ -300,6 +300,10 @@ Object {
 exports[`xmltest/not-wellformed standalone should match 038.xml with snapshot 1`] = `
 Object {
   "actual": "<doc x=\\"baz\\" y=\\"bar\\"/>",
+  "fatalError": Array [
+    "[xmldom fatalError]	Attribute x redefined
+@#[line:1,col:1]",
+  ],
 }
 `;
 
@@ -831,7 +835,7 @@ Object {
 exports[`xmltest/not-wellformed standalone should match 108.xml with snapshot 1`] = `
 Object {
   "actual": "<doc>
-<![CDATA [  ]]>
+<![CDATA [  ]]>
 </doc>",
 }
 `;
@@ -870,7 +874,7 @@ Object {
 exports[`xmltest/not-wellformed standalone should match 112.xml with snapshot 1`] = `
 Object {
   "actual": "<doc>
-<![cdata[data]]>
+<![cdata[data]]>
 </doc>",
 }
 `;
@@ -1354,7 +1358,7 @@ Object {
 
 exports[`xmltest/not-wellformed standalone should match 181.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc>&e;]]></doc>",
+  "actual": "<doc>&e;]]></doc>",
   "error": Array [
     "[xmldom error]	entity not found:&e;
 @#[line:1,col:1]",
diff --git a/test/xmltest/__snapshots__/valid.test.js.snap b/test/xmltest/__snapshots__/valid.test.js.snap
index fdf34ca..085aa75 100644
--- a/test/xmltest/__snapshots__/valid.test.js.snap
+++ b/test/xmltest/__snapshots__/valid.test.js.snap
@@ -293,7 +293,7 @@ Object {
 
 exports[`xmltest/valid standalone should match 040.xml with snapshot 1`] = `
 Object {
-  "actual": "<doc a1=\\""<&>'\\"/>",
+  "actual": "<doc a1=\\""<&>'\\"/>",
   "expected": "<doc a1=\\""<&>'\\"></doc>",
 }
 `;
diff --git a/test/xss.test.js b/test/xss.test.js
index 533cea9..e5fd71a 100644
--- a/test/xss.test.js
+++ b/test/xss.test.js
@@ -68,7 +68,7 @@ describe('xss test', () => {
 
 		const actual = xss(html)
 
-		expect(actual).toEqual(
+		expect(actual).toBe(
 			'<div title="32323" xmlns="http://www.w3.org/1999/xhtml"></div>'
 		)
 	})


More information about the Pkg-javascript-devel mailing list