Repository: FontoXML/fontoxpath
Pull request #617 (2023-11-01 09:37:22)

Bump concurrently from 8.2.1 to 8.2.2
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 8.2.1 to 8.2.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/open-cli-tools/concurrently/releases">concurrently's releases</a>.</em></p>
<blockquote>
<h2>v8.2.2</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(suggestion): prefixColors API type to embrace string type by <a href="https://github.com/SeiwonPark"><code>@​SeiwonPark</code></a> in <a href="https://redirect.github.com/open-cli-tools/concurrently/pull/439">open-cli-tools/concurrently#439</a></li>
<li>Update dependencies by <a href="https://github.com/paescuj"><code>@​paescuj</code></a> in <a href="https://redirect.github.com/open-cli-tools/concurrently/pull/441">open-cli-tools/concurrently#441</a></li>
<li>Test against Node.js v20 instead of v19 by <a href="https://github.com/paescuj"><code>@​paescuj</code></a> in <a href="https://redirect.github.com/open-cli-tools/concurrently/pull/442">open-cli-tools/concurrently#442</a></li>
<li>Update dependencies by <a href="https://github.com/paescuj"><code>@​paescuj</code></a> in <a href="https://redirect.github.com/open-cli-tools/concurrently/pull/449">open-cli-tools/concurrently#449</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/SeiwonPark"><code>@​SeiwonPark</code></a> made their first contribution in <a href="https://redirect.github.com/open-cli-tools/concurrently/pull/439">open-cli-tools/concurrently#439</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/open-cli-tools/concurrently/compare/v8.2.1...v8.2.2">https://github.com/open-cli-tools/concurrently/compare/v8.2.1...v8.2.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/5a45482cbbc8bef74aef92770fc47e69abedcc54"><code>5a45482</code></a> 8.2.2</li>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/e06501b0beaaaefe7a10011a1003956c4a62cb5f"><code>e06501b</code></a> Update dependencies (<a href="https://redirect.github.com/open-cli-tools/concurrently/issues/449">#449</a>)</li>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/ac668c7ae7f56c0ffb8eb69d61a11a9e70c6391a"><code>ac668c7</code></a> logger: use subscribeSpyTo in tests</li>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/a61ef39468c82b66ebb247a5a5e2cf479a0c4def"><code>a61ef39</code></a> Test against Node.js v20 instead of v19 (<a href="https://redirect.github.com/open-cli-tools/concurrently/issues/442">#442</a>)</li>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/565e0b1684e40e83a1a8ce6088c8d16ccc796692"><code>565e0b1</code></a> Update dependencies (<a href="https://redirect.github.com/open-cli-tools/concurrently/issues/441">#441</a>)</li>
<li><a href="https://github.com/open-cli-tools/concurrently/commit/81529a97be1d5fb3577004bf538af43c97b5b164"><code>81529a9</code></a> fix(suggestion): prefixColors API type to embrace string type (<a href="https://redirect.github.com/open-cli-tools/concurrently/issues/439">#439</a>)</li>
<li>See full diff in <a href="https://github.com/open-cli-tools/concurrently/compare/v8.2.1...v8.2.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=concurrently&package-manager=npm_and_yarn&previous-version=8.2.1&new-version=8.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

> **Note**
> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.


bundlemon[bot]: <!-- bundlemon -->
## BundleMon

  
  
  
  
  
  
  
<details>
<summary>Unchanged files (2)</summary>

Status | Path | Size | Limits
:------------: | ------------ | :------------: | :------------:
:white_check_mark: | fontoxpath.esm.js<br/> | 77.61KB | -
:white_check_mark: | fontoxpath.js<br/> | 77.52KB | -
</details>



No change in files bundle size

Final result: :white_check_mark:

[View report in BundleMon website ➡️](https://app.bundlemon.dev/projects/6437c8f89a7cb205c434db8d/reports/65421d8641eab786eb4d0eaf)

---
<p align="center"><a href="https://app.bundlemon.dev/projects/6437c8f89a7cb205c434db8d/reports?branch=dependabot%2Fnpm_and_yarn%2Fconcurrently-8.2.2&resolution=all" target="_blank" rel="noreferrer noopener">Current branch size history</a> | <a href="https://app.bundlemon.dev/projects/6437c8f89a7cb205c434db8d/reports?branch=master&resolution=days" target="_blank" rel="noreferrer noopener">Target branch size history</a></p>
coveralls: 
[![Coverage Status](https://coveralls.io/builds/63677770/badge)](https://coveralls.io/builds/63677770)

coverage: 91.58%. remained the same when pulling **3a5a10d044527c2b6f03b6e7b529913aa98711ae on dependabot/npm_and_yarn/concurrently-8.2.2** into **dd07d62fd1dea7c171d208f63ac0aa9d38b70719 on master**.


Patch:
diff --git a/LICENSE.md b/LICENSE.md
index 6c89137c..fd39b98f 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2017 Fonto Group BV
+Copyright (c) 2017 Fonto Group BV, Martin Middel
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/package-lock.json b/package-lock.json
index c4ab928c..a20e78eb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
 	"name": "fontoxpath",
-	"version": "3.30.2",
+	"version": "3.32.0",
 	"lockfileVersion": 2,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "fontoxpath",
-			"version": "3.30.2",
+			"version": "3.32.0",
 			"license": "MIT",
 			"dependencies": {
 				"prsc": "4.0.0",
@@ -212,12 +212,12 @@
 			}
 		},
 		"node_modules/@babel/generator": {
-			"version": "7.22.15",
-			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
-			"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+			"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
 			"dev": true,
 			"dependencies": {
-				"@babel/types": "^7.22.15",
+				"@babel/types": "^7.23.0",
 				"@jridgewell/gen-mapping": "^0.3.2",
 				"@jridgewell/trace-mapping": "^0.3.17",
 				"jsesc": "^2.5.1"
@@ -273,13 +273,13 @@
 			}
 		},
 		"node_modules/@babel/helper-function-name": {
-			"version": "7.22.5",
-			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
-			"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+			"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
 			"dev": true,
 			"dependencies": {
-				"@babel/template": "^7.22.5",
-				"@babel/types": "^7.22.5"
+				"@babel/template": "^7.22.15",
+				"@babel/types": "^7.23.0"
 			},
 			"engines": {
 				"node": ">=6.9.0"
@@ -479,9 +479,9 @@
 			}
 		},
 		"node_modules/@babel/parser": {
-			"version": "7.22.16",
-			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
-			"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+			"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
 			"dev": true,
 			"bin": {
 				"parser": "bin/babel-parser.js"
@@ -517,19 +517,19 @@
 			}
 		},
 		"node_modules/@babel/traverse": {
-			"version": "7.22.20",
-			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz",
-			"integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==",
+			"version": "7.23.2",
+			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+			"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
 			"dev": true,
 			"dependencies": {
 				"@babel/code-frame": "^7.22.13",
-				"@babel/generator": "^7.22.15",
+				"@babel/generator": "^7.23.0",
 				"@babel/helper-environment-visitor": "^7.22.20",
-				"@babel/helper-function-name": "^7.22.5",
+				"@babel/helper-function-name": "^7.23.0",
 				"@babel/helper-hoist-variables": "^7.22.5",
 				"@babel/helper-split-export-declaration": "^7.22.6",
-				"@babel/parser": "^7.22.16",
-				"@babel/types": "^7.22.19",
+				"@babel/parser": "^7.23.0",
+				"@babel/types": "^7.23.0",
 				"debug": "^4.1.0",
 				"globals": "^11.1.0"
 			},
@@ -547,13 +547,13 @@
 			}
 		},
 		"node_modules/@babel/types": {
-			"version": "7.22.19",
-			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz",
-			"integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+			"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
 			"dev": true,
 			"dependencies": {
 				"@babel/helper-string-parser": "^7.22.5",
-				"@babel/helper-validator-identifier": "^7.22.19",
+				"@babel/helper-validator-identifier": "^7.22.20",
 				"to-fast-properties": "^2.0.0"
 			},
 			"engines": {
@@ -1528,16 +1528,16 @@
 			"dev": true
 		},
 		"node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz",
-			"integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz",
+			"integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==",
 			"dev": true,
 			"dependencies": {
 				"@eslint-community/regexpp": "^4.5.1",
-				"@typescript-eslint/scope-manager": "6.7.2",
-				"@typescript-eslint/type-utils": "6.7.2",
-				"@typescript-eslint/utils": "6.7.2",
-				"@typescript-eslint/visitor-keys": "6.7.2",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/type-utils": "6.16.0",
+				"@typescript-eslint/utils": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
 				"debug": "^4.3.4",
 				"graphemer": "^1.4.0",
 				"ignore": "^5.2.4",
@@ -1583,16 +1583,140 @@
 				"typescript": "*"
 			}
 		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+			"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+			"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+			"dev": true,
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+			"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
+				"is-glob": "^4.0.3",
+				"minimatch": "9.0.3",
+				"semver": "^7.5.4",
+				"ts-api-utils": "^1.0.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz",
+			"integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==",
+			"dev": true,
+			"dependencies": {
+				"@eslint-community/eslint-utils": "^4.4.0",
+				"@types/json-schema": "^7.0.12",
+				"@types/semver": "^7.5.0",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"semver": "^7.5.4"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^7.0.0 || ^8.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+			"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"eslint-visitor-keys": "^3.4.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+			"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+			"dev": true,
+			"dependencies": {
+				"balanced-match": "^1.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": {
+			"version": "9.0.3",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+			"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+			"dev": true,
+			"dependencies": {
+				"brace-expansion": "^2.0.1"
+			},
+			"engines": {
+				"node": ">=16 || 14 >=14.17"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
 		"node_modules/@typescript-eslint/parser": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz",
-			"integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz",
+			"integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "6.7.2",
-				"@typescript-eslint/types": "6.7.2",
-				"@typescript-eslint/typescript-estree": "6.7.2",
-				"@typescript-eslint/visitor-keys": "6.7.2",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
 				"debug": "^4.3.4"
 			},
 			"engines": {
@@ -1611,6 +1735,105 @@
 				}
 			}
 		},
+		"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+			"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+			"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+			"dev": true,
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+			"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
+				"is-glob": "^4.0.3",
+				"minimatch": "9.0.3",
+				"semver": "^7.5.4",
+				"ts-api-utils": "^1.0.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+			"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"eslint-visitor-keys": "^3.4.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+			"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+			"dev": true,
+			"dependencies": {
+				"balanced-match": "^1.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/parser/node_modules/minimatch": {
+			"version": "9.0.3",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+			"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+			"dev": true,
+			"dependencies": {
+				"brace-expansion": "^2.0.1"
+			},
+			"engines": {
+				"node": ">=16 || 14 >=14.17"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
 		"node_modules/@typescript-eslint/scope-manager": {
 			"version": "6.7.2",
 			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz",
@@ -1629,13 +1852,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/type-utils": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz",
-			"integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz",
+			"integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/typescript-estree": "6.7.2",
-				"@typescript-eslint/utils": "6.7.2",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"@typescript-eslint/utils": "6.16.0",
 				"debug": "^4.3.4",
 				"ts-api-utils": "^1.0.1"
 			},
@@ -1655,6 +1878,130 @@
 				}
 			}
 		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+			"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+			"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+			"dev": true,
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+			"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
+				"is-glob": "^4.0.3",
+				"minimatch": "9.0.3",
+				"semver": "^7.5.4",
+				"ts-api-utils": "^1.0.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz",
+			"integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==",
+			"dev": true,
+			"dependencies": {
+				"@eslint-community/eslint-utils": "^4.4.0",
+				"@types/json-schema": "^7.0.12",
+				"@types/semver": "^7.5.0",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"semver": "^7.5.4"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^7.0.0 || ^8.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+			"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "6.16.0",
+				"eslint-visitor-keys": "^3.4.1"
+			},
+			"engines": {
+				"node": "^16.0.0 || >=18.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+			"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+			"dev": true,
+			"dependencies": {
+				"balanced-match": "^1.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils/node_modules/minimatch": {
+			"version": "9.0.3",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+			"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+			"dev": true,
+			"dependencies": {
+				"brace-expansion": "^2.0.1"
+			},
+			"engines": {
+				"node": ">=16 || 14 >=14.17"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
 		"node_modules/@typescript-eslint/types": {
 			"version": "6.7.2",
 			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz",
@@ -2271,12 +2618,12 @@
 			}
 		},
 		"node_modules/braces": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+			"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
 			"dev": true,
 			"dependencies": {
-				"fill-range": "^7.0.1"
+				"fill-range": "^7.1.1"
 			},
 			"engines": {
 				"node": ">=8"
@@ -2828,9 +3175,9 @@
 			"dev": true
 		},
 		"node_modules/concurrently": {
-			"version": "8.2.1",
-			"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz",
-			"integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==",
+			"version": "8.2.2",
+			"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
+			"integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
 			"dev": true,
 			"dependencies": {
 				"chalk": "^4.1.2",
@@ -4160,9 +4507,9 @@
 			}
 		},
 		"node_modules/fill-range": {
-			"version": "7.0.1",
-			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"version": "7.1.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+			"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
 			"dev": true,
 			"dependencies": {
 				"to-regex-range": "^5.0.1"
@@ -4325,9 +4672,9 @@
 			}
 		},
 		"node_modules/follow-redirects": {
-			"version": "1.15.3",
-			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
-			"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
+			"version": "1.15.4",
+			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+			"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
 			"dev": true,
 			"funding": [
 				{
@@ -10343,12 +10690,12 @@
 			}
 		},
 		"@babel/generator": {
-			"version": "7.22.15",
-			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
-			"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+			"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
 			"dev": true,
 			"requires": {
-				"@babel/types": "^7.22.15",
+				"@babel/types": "^7.23.0",
 				"@jridgewell/gen-mapping": "^0.3.2",
 				"@jridgewell/trace-mapping": "^0.3.17",
 				"jsesc": "^2.5.1"
@@ -10390,13 +10737,13 @@
 			"dev": true
 		},
 		"@babel/helper-function-name": {
-			"version": "7.22.5",
-			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
-			"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+			"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
 			"dev": true,
 			"requires": {
-				"@babel/template": "^7.22.5",
-				"@babel/types": "^7.22.5"
+				"@babel/template": "^7.22.15",
+				"@babel/types": "^7.23.0"
 			}
 		},
 		"@babel/helper-hoist-variables": {
@@ -10547,9 +10894,9 @@
 			}
 		},
 		"@babel/parser": {
-			"version": "7.22.16",
-			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
-			"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+			"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
 			"dev": true
 		},
 		"@babel/runtime": {
@@ -10573,19 +10920,19 @@
 			}
 		},
 		"@babel/traverse": {
-			"version": "7.22.20",
-			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz",
-			"integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==",
+			"version": "7.23.2",
+			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+			"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
 			"dev": true,
 			"requires": {
 				"@babel/code-frame": "^7.22.13",
-				"@babel/generator": "^7.22.15",
+				"@babel/generator": "^7.23.0",
 				"@babel/helper-environment-visitor": "^7.22.20",
-				"@babel/helper-function-name": "^7.22.5",
+				"@babel/helper-function-name": "^7.23.0",
 				"@babel/helper-hoist-variables": "^7.22.5",
 				"@babel/helper-split-export-declaration": "^7.22.6",
-				"@babel/parser": "^7.22.16",
-				"@babel/types": "^7.22.19",
+				"@babel/parser": "^7.23.0",
+				"@babel/types": "^7.23.0",
 				"debug": "^4.1.0",
 				"globals": "^11.1.0"
 			},
@@ -10599,13 +10946,13 @@
 			}
 		},
 		"@babel/types": {
-			"version": "7.22.19",
-			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz",
-			"integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==",
+			"version": "7.23.0",
+			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+			"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
 			"dev": true,
 			"requires": {
 				"@babel/helper-string-parser": "^7.22.5",
-				"@babel/helper-validator-identifier": "^7.22.19",
+				"@babel/helper-validator-identifier": "^7.22.20",
 				"to-fast-properties": "^2.0.0"
 			}
 		},
@@ -11409,22 +11756,99 @@
 			"dev": true
 		},
 		"@typescript-eslint/eslint-plugin": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz",
-			"integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz",
+			"integrity": "sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==",
 			"dev": true,
 			"requires": {
 				"@eslint-community/regexpp": "^4.5.1",
-				"@typescript-eslint/scope-manager": "6.7.2",
-				"@typescript-eslint/type-utils": "6.7.2",
-				"@typescript-eslint/utils": "6.7.2",
-				"@typescript-eslint/visitor-keys": "6.7.2",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/type-utils": "6.16.0",
+				"@typescript-eslint/utils": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
 				"debug": "^4.3.4",
 				"graphemer": "^1.4.0",
 				"ignore": "^5.2.4",
 				"natural-compare": "^1.4.0",
 				"semver": "^7.5.4",
 				"ts-api-utils": "^1.0.1"
+			},
+			"dependencies": {
+				"@typescript-eslint/scope-manager": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+					"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0"
+					}
+				},
+				"@typescript-eslint/types": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+					"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+					"dev": true
+				},
+				"@typescript-eslint/typescript-estree": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+					"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0",
+						"debug": "^4.3.4",
+						"globby": "^11.1.0",
+						"is-glob": "^4.0.3",
+						"minimatch": "9.0.3",
+						"semver": "^7.5.4",
+						"ts-api-utils": "^1.0.1"
+					}
+				},
+				"@typescript-eslint/utils": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz",
+					"integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==",
+					"dev": true,
+					"requires": {
+						"@eslint-community/eslint-utils": "^4.4.0",
+						"@types/json-schema": "^7.0.12",
+						"@types/semver": "^7.5.0",
+						"@typescript-eslint/scope-manager": "6.16.0",
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/typescript-estree": "6.16.0",
+						"semver": "^7.5.4"
+					}
+				},
+				"@typescript-eslint/visitor-keys": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+					"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"eslint-visitor-keys": "^3.4.1"
+					}
+				},
+				"brace-expansion": {
+					"version": "2.0.1",
+					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+					"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+					"dev": true,
+					"requires": {
+						"balanced-match": "^1.0.0"
+					}
+				},
+				"minimatch": {
+					"version": "9.0.3",
+					"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+					"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+					"dev": true,
+					"requires": {
+						"brace-expansion": "^2.0.1"
+					}
+				}
 			}
 		},
 		"@typescript-eslint/eslint-plugin-tslint": {
@@ -11437,16 +11861,78 @@
 			}
 		},
 		"@typescript-eslint/parser": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz",
-			"integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz",
+			"integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/scope-manager": "6.7.2",
-				"@typescript-eslint/types": "6.7.2",
-				"@typescript-eslint/typescript-estree": "6.7.2",
-				"@typescript-eslint/visitor-keys": "6.7.2",
+				"@typescript-eslint/scope-manager": "6.16.0",
+				"@typescript-eslint/types": "6.16.0",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"@typescript-eslint/visitor-keys": "6.16.0",
 				"debug": "^4.3.4"
+			},
+			"dependencies": {
+				"@typescript-eslint/scope-manager": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+					"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0"
+					}
+				},
+				"@typescript-eslint/types": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+					"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+					"dev": true
+				},
+				"@typescript-eslint/typescript-estree": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+					"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0",
+						"debug": "^4.3.4",
+						"globby": "^11.1.0",
+						"is-glob": "^4.0.3",
+						"minimatch": "9.0.3",
+						"semver": "^7.5.4",
+						"ts-api-utils": "^1.0.1"
+					}
+				},
+				"@typescript-eslint/visitor-keys": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+					"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"eslint-visitor-keys": "^3.4.1"
+					}
+				},
+				"brace-expansion": {
+					"version": "2.0.1",
+					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+					"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+					"dev": true,
+					"requires": {
+						"balanced-match": "^1.0.0"
+					}
+				},
+				"minimatch": {
+					"version": "9.0.3",
+					"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+					"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+					"dev": true,
+					"requires": {
+						"brace-expansion": "^2.0.1"
+					}
+				}
 			}
 		},
 		"@typescript-eslint/scope-manager": {
@@ -11460,15 +11946,92 @@
 			}
 		},
 		"@typescript-eslint/type-utils": {
-			"version": "6.7.2",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz",
-			"integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==",
+			"version": "6.16.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz",
+			"integrity": "sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/typescript-estree": "6.7.2",
-				"@typescript-eslint/utils": "6.7.2",
+				"@typescript-eslint/typescript-estree": "6.16.0",
+				"@typescript-eslint/utils": "6.16.0",
 				"debug": "^4.3.4",
 				"ts-api-utils": "^1.0.1"
+			},
+			"dependencies": {
+				"@typescript-eslint/scope-manager": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
+					"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0"
+					}
+				},
+				"@typescript-eslint/types": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
+					"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
+					"dev": true
+				},
+				"@typescript-eslint/typescript-estree": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
+					"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/visitor-keys": "6.16.0",
+						"debug": "^4.3.4",
+						"globby": "^11.1.0",
+						"is-glob": "^4.0.3",
+						"minimatch": "9.0.3",
+						"semver": "^7.5.4",
+						"ts-api-utils": "^1.0.1"
+					}
+				},
+				"@typescript-eslint/utils": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz",
+					"integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==",
+					"dev": true,
+					"requires": {
+						"@eslint-community/eslint-utils": "^4.4.0",
+						"@types/json-schema": "^7.0.12",
+						"@types/semver": "^7.5.0",
+						"@typescript-eslint/scope-manager": "6.16.0",
+						"@typescript-eslint/types": "6.16.0",
+						"@typescript-eslint/typescript-estree": "6.16.0",
+						"semver": "^7.5.4"
+					}
+				},
+				"@typescript-eslint/visitor-keys": {
+					"version": "6.16.0",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
+					"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
+					"dev": true,
+					"requires": {
+						"@typescript-eslint/types": "6.16.0",
+						"eslint-visitor-keys": "^3.4.1"
+					}
+				},
+				"brace-expansion": {
+					"version": "2.0.1",
+					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+					"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+					"dev": true,
+					"requires": {
+						"balanced-match": "^1.0.0"
+					}
+				},
+				"minimatch": {
+					"version": "9.0.3",
+					"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+					"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+					"dev": true,
+					"requires": {
+						"brace-expansion": "^2.0.1"
+					}
+				}
 			}
 		},
 		"@typescript-eslint/types": {
@@ -11920,12 +12483,12 @@
 			}
 		},
 		"braces": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+			"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
 			"dev": true,
 			"requires": {
-				"fill-range": "^7.0.1"
+				"fill-range": "^7.1.1"
 			}
 		},
 		"brotli-size": {
@@ -12307,9 +12870,9 @@
 			"dev": true
 		},
 		"concurrently": {
-			"version": "8.2.1",
-			"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz",
-			"integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==",
+			"version": "8.2.2",
+			"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
+			"integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
 			"dev": true,
 			"requires": {
 				"chalk": "^4.1.2",
@@ -13340,9 +13903,9 @@
 			}
 		},
 		"fill-range": {
-			"version": "7.0.1",
-			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"version": "7.1.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+			"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
 			"dev": true,
 			"requires": {
 				"to-regex-range": "^5.0.1"
@@ -13482,9 +14045,9 @@
 			}
 		},
 		"follow-redirects": {
-			"version": "1.15.3",
-			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
-			"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
+			"version": "1.15.4",
+			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+			"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
 			"dev": true
 		},
 		"for-each": {
diff --git a/package.json b/package.json
index 00bf11ae..0005dd57 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "fontoxpath",
-	"version": "3.30.2",
+	"version": "3.32.0",
 	"description": "A minimalistic XPath 3.1 engine in JavaScript",
 	"main": "dist/fontoxpath.js",
 	"module": "dist/fontoxpath.esm.js",
diff --git a/src/domFacade/ConcreteNode.ts b/src/domFacade/ConcreteNode.ts
index 8f84393e..7ed11174 100644
--- a/src/domFacade/ConcreteNode.ts
+++ b/src/domFacade/ConcreteNode.ts
@@ -28,6 +28,9 @@ export type ConcreteCDATASectionNode = CDATASection & { nodeType: NODE_TYPES.CDA
 export type ConcreteDocumentTypeNode = DocumentType & { nodeType: NODE_TYPES.DOCUMENT_TYPE_NODE };
 export type ConcreteAttributeNode = Attr & { nodeType: NODE_TYPES.ATTRIBUTE_NODE };
 export type ConcreteDocumentNode = Document & { nodeType: NODE_TYPES.DOCUMENT_NODE };
+export type ConcreteDocumentFragmentNode = DocumentFragment & {
+	nodeType: NODE_TYPES.DOCUMENT_FRAGMENT_NODE;
+};
 export type ConcreteProcessingInstructionNode = ProcessingInstruction & {
 	nodeType: NODE_TYPES.PROCESSING_INSTRUCTION_NODE;
 };
@@ -47,4 +50,5 @@ export type ConcreteNode =
 	| ConcreteChildNode
 	| ConcreteParentNode
 	| ConcreteAttributeNode
-	| ConcreteDocumentTypeNode;
+	| ConcreteDocumentTypeNode
+	| ConcreteDocumentFragmentNode;
diff --git a/src/expressions/dataTypes/Value.ts b/src/expressions/dataTypes/Value.ts
index 857fb6a6..311b94c3 100644
--- a/src/expressions/dataTypes/Value.ts
+++ b/src/expressions/dataTypes/Value.ts
@@ -81,10 +81,11 @@ export const enum ValueType {
 }
 
 /**
- * Handles the occurances in the XPath specs.
- * Zero or one matches to '?';
- * One or more matches to '+';
- * Zero or more matches to '*'
+ * Handles the occurences in the XPath specs.
+ *
+ * * Zero or one matches to '?';
+ * * One or more matches to '+';
+ * * Zero or more matches to '*';
  *
  * @private
  */
diff --git a/src/expressions/dataTypes/atomize.ts b/src/expressions/dataTypes/atomize.ts
index b5bb53c3..77ecbdb2 100644
--- a/src/expressions/dataTypes/atomize.ts
+++ b/src/expressions/dataTypes/atomize.ts
@@ -79,7 +79,11 @@ export function atomizeSingleValue(
 				);
 				return;
 			}
-			if (aNodeType === NODE_TYPES.ELEMENT_NODE || aNodeType === NODE_TYPES.DOCUMENT_NODE) {
+			if (
+				aNodeType === NODE_TYPES.ELEMENT_NODE ||
+				aNodeType === NODE_TYPES.DOCUMENT_NODE ||
+				aNodeType === NODE_TYPES.DOCUMENT_FRAGMENT_NODE
+			) {
 				const children = domFacade.getChildNodes(
 					aNode as ConcreteParentNode | TinyParentNode,
 				);
diff --git a/src/expressions/functions/builtInFunctions_node.ts b/src/expressions/functions/builtInFunctions_node.ts
index 23235f0c..42006831 100644
--- a/src/expressions/functions/builtInFunctions_node.ts
+++ b/src/expressions/functions/builtInFunctions_node.ts
@@ -30,7 +30,7 @@ import { errXPDY0002 } from '../XPathErrors';
 import { BuiltinDeclarationType } from './builtInFunctions';
 import builtinStringFunctions from './builtInFunctions_string';
 import FunctionDefinitionType from './FunctionDefinitionType';
-
+import generateId from './generateId';
 const fnString = builtinStringFunctions.functions.string;
 
 function contextItemAsFirstArgument(
@@ -123,6 +123,23 @@ const fnData: FunctionDefinitionType = (
 	return atomize(sequence, executionParameters);
 };
 
+const fnGenerateId: FunctionDefinitionType = (
+	dynamicContext,
+	executionParameters,
+	_staticContext,
+	nodeValue,
+) => {
+	if (nodeValue.isEmpty()) {
+		return sequenceFactory.singleton(createAtomicValue('', ValueType.XSSTRING));
+	}
+	if (!isSubtypeOf(nodeValue.first().type, ValueType.NODE)) {
+		throw new Error('XPTY0004: The context item must be a node.');
+	}
+	const node = nodeValue.first().value as NodePointer;
+
+	return sequenceFactory.singleton(createAtomicValue(generateId(node), ValueType.XSSTRING));
+};
+
 const fnHasChildren: FunctionDefinitionType = (
 	_dynamicContext,
 	executionParameters,
@@ -165,6 +182,78 @@ function areSameNode(
 	return true;
 }
 
+/**
+ * Test if a string should match the xml:lang attribute string of a node.
+ */
+function langMatchString(truth: string, test: string): boolean {
+	truth = truth.toLowerCase();
+	test = test.toLowerCase();
+	if (truth === test) {
+		return true;
+	} else {
+		return truth.length < 5 || !truth.startsWith(test)
+			? false
+			: /* Strip the least specific part and test again */
+			  langMatchString(truth.replace(/-[a-z0-9]+$/, ''), test);
+	}
+}
+
+/**
+ * Starting at a given node, test the xml:lang attribute to see if it
+   matches a test. Move up the tree until the test passes or fails.
+ */
+function langMatchNode(node: NodePointer, domFacade: DomFacade, test: string): ISequence {
+	let toTest = node;
+	while (toTest) {
+		if (domFacade.getNodeType(toTest) !== NODE_TYPES.ELEMENT_NODE) {
+			toTest = domFacade.getParentNodePointer(toTest as AttributeNodePointer);
+		} else if (domFacade.getNodeType(toTest) === NODE_TYPES.ELEMENT_NODE) {
+			const attrValue = domFacade.getAttribute(toTest as ElementNodePointer, 'xml:lang');
+			if (attrValue) {
+				return langMatchString(attrValue, test)
+					? sequenceFactory.singletonTrueSequence()
+					: sequenceFactory.singletonFalseSequence();
+			} else {
+				toTest = domFacade.getParentNodePointer(toTest as ElementNodePointer);
+			}
+		}
+	}
+	return sequenceFactory.singletonFalseSequence();
+}
+
+const fnLang: FunctionDefinitionType = (
+	dynamicContext,
+	executionParameters,
+	_staticContext,
+	langTestValue,
+	nodeValue,
+) => {
+	const domFacade = executionParameters.domFacade;
+	let langTest;
+	if (langTestValue.isEmpty()) {
+		langTest = '';
+	} else if (!isSubtypeOf(langTestValue.first().type, ValueType.XSSTRING)) {
+		throw new Error('XPTY0004: The first argument of lang must be a string.');
+	} else {
+		langTest = langTestValue.first().value;
+	}
+	let node;
+	if (!nodeValue) {
+		if (!dynamicContext || !dynamicContext.contextItem) {
+			throw errXPDY0002(
+				`The function lang depends on dynamic context if a node is not passed as the second argument.`,
+			);
+		}
+		if (!isSubtypeOf(dynamicContext.contextItem.type, ValueType.NODE)) {
+			throw new Error('XPTY0004: The context item must be a node.');
+		}
+		node = dynamicContext.contextItem.value;
+	} else {
+		node = nodeValue.first().value;
+	}
+	return langMatchNode(node, domFacade, langTest);
+};
+
 const fnPath: FunctionDefinitionType = (
 	_dynamicContext,
 	executionParameters,
@@ -545,6 +634,38 @@ const declarations: BuiltinDeclarationType[] = [
 		namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
 		returnType: { type: ValueType.XSANYATOMICTYPE, mult: SequenceMultiplicity.ZERO_OR_MORE },
 	},
+
+	{
+		argumentTypes: [{ type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE }],
+		callFunction: fnLang,
+		localName: 'lang',
+		namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
+		returnType: { type: ValueType.XSBOOLEAN, mult: SequenceMultiplicity.EXACTLY_ONE },
+	},
+	{
+		argumentTypes: [
+			{ type: ValueType.XSSTRING, mult: SequenceMultiplicity.ZERO_OR_ONE },
+			{ type: ValueType.NODE, mult: SequenceMultiplicity.EXACTLY_ONE },
+		],
+		callFunction: fnLang,
+		localName: 'lang',
+		namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
+		returnType: { type: ValueType.XSBOOLEAN, mult: SequenceMultiplicity.EXACTLY_ONE },
+	},
+	{
+		argumentTypes: [],
+		callFunction: contextItemAsFirstArgument.bind(null, 'generate-id', fnGenerateId),
+		localName: 'generate-id',
+		namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
+		returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
+	},
+	{
+		argumentTypes: [{ type: ValueType.NODE, mult: SequenceMultiplicity.ZERO_OR_ONE }],
+		callFunction: fnGenerateId,
+		localName: 'generate-id',
+		namespaceURI: BUILT_IN_NAMESPACE_URIS.FUNCTIONS_NAMESPACE_URI,
+		returnType: { type: ValueType.XSSTRING, mult: SequenceMultiplicity.EXACTLY_ONE },
+	},
 ];
 
 export default {
diff --git a/src/expressions/functions/builtInFunctions_string.ts b/src/expressions/functions/builtInFunctions_string.ts
index f347b16d..291c775b 100644
--- a/src/expressions/functions/builtInFunctions_string.ts
+++ b/src/expressions/functions/builtInFunctions_string.ts
@@ -355,11 +355,25 @@ const fnTokenize: FunctionDefinitionType = (
 	const patternString: string = pattern.first().value;
 
 	const regex = compileJSRegex(patternString);
+	regex.lastIndex = 0;
+	const results = [];
+	let result = regex.exec(inputString);
+
+	let index = 0;
+
+	// Repeatedly execute the regex to get all the outputs
+	// TODO: with this approach it should not be too difficult to actually use XSPattern here.
+	while (result) {
+		results.push(inputString.slice(index, result.index));
+		index = regex.lastIndex;
+		result = regex.exec(inputString);
+	}
+
+	// Don't forget the last split part!
+	results.push(inputString.slice(index));
 
 	return sequenceFactory.create(
-		inputString
-			.split(regex)
-			.map((token: string) => createAtomicValue(token, ValueType.XSSTRING)),
+		results.map((token: string) => createAtomicValue(token, ValueType.XSSTRING)),
 	);
 };
 
diff --git a/src/expressions/functions/generateId.ts b/src/expressions/functions/generateId.ts
new file mode 100644
index 00000000..c92b2344
--- /dev/null
+++ b/src/expressions/functions/generateId.ts
@@ -0,0 +1,15 @@
+import { ConcreteNode } from '../../domFacade/ConcreteNode';
+import { NodePointer, TinyNode } from '../../domClone/Pointer';
+
+const generateIdMap: WeakMap<TinyNode | ConcreteNode, string> = new WeakMap();
+let generateIdCounter = 0;
+
+function generateId(ptr: NodePointer): string {
+	const node = ptr.node;
+	if (!generateIdMap.has(node)) {
+		generateIdMap.set(node, `id${++generateIdCounter}`);
+	}
+	return generateIdMap.get(node);
+}
+
+export default generateId;
diff --git a/src/expressions/xquery/SwitchExpression.ts b/src/expressions/xquery/SwitchExpression.ts
new file mode 100644
index 00000000..fb77e6f8
--- /dev/null
+++ b/src/expressions/xquery/SwitchExpression.ts
@@ -0,0 +1,135 @@
+import ISequence from '../dataTypes/ISequence';
+import sequenceFactory from '../dataTypes/sequenceFactory';
+import { SequenceType } from '../dataTypes/Value';
+import DynamicContext from '../DynamicContext';
+import ExecutionParameters from '../ExecutionParameters';
+import Expression, { RESULT_ORDERINGS } from '../Expression';
+import sequenceDeepEqual, {
+	itemDeepEqual,
+} from '../functions/builtInFunctions_sequences_deepEqual';
+import PossiblyUpdatingExpression, { SequenceCallbacks } from '../PossiblyUpdatingExpression';
+import Specificity from '../Specificity';
+import StaticContext from '../StaticContext';
+import atomizeSequence from '../util/atomizeSequence';
+import { IterationHint } from '../util/iterators';
+import { errXUST0001 } from '../xquery-update/XQueryUpdateFacilityErrors';
+import { errXPTY0004 } from './XQueryErrors';
+
+export type SwitchExpressionClause = {
+	caseClauseExpression: PossiblyUpdatingExpression;
+	tests: Expression[];
+};
+
+class SwitchExpression extends PossiblyUpdatingExpression {
+	private _amountOfCases: number;
+	private _argExpression: Expression;
+	private _testsByCase: Expression[][];
+
+	constructor(
+		argExpression: Expression,
+		caseClauses: SwitchExpressionClause[],
+		defaultExpression: PossiblyUpdatingExpression,
+		type: SequenceType,
+	) {
+		const specificity = new Specificity({});
+		super(
+			specificity,
+			[
+				argExpression,
+				defaultExpression,
+				...caseClauses.map((clause) => clause.caseClauseExpression),
+			].concat(...caseClauses.map((clause) => clause.tests.map((test) => test))),
+			{
+				canBeStaticallyEvaluated: false,
+				peer: false,
+				resultOrder: RESULT_ORDERINGS.UNSORTED,
+				subtree: false,
+			},
+			type,
+		);
+		this._argExpression = argExpression;
+		this._amountOfCases = caseClauses.length;
+		this._testsByCase = caseClauses.map((clause) => clause.tests);
+	}
+
+	public performFunctionalEvaluation(
+		dynamicContext: DynamicContext,
+		executionParameters: ExecutionParameters,
+		sequenceCallbacks: ((dynamicContext: DynamicContext) => ISequence)[],
+	) {
+		// Pick the argumentExpression.
+		const evaluatedExpression = atomizeSequence(
+			sequenceCallbacks[0](dynamicContext),
+			executionParameters,
+		);
+		const [
+			_argSequenceCallback,
+			defaultSequenceCallback,
+			...caseClauseAndTestSequenceCallbacks
+		] = sequenceCallbacks;
+		// Map over all values the type test, and return the result.
+		return evaluatedExpression.switchCases({
+			multiple: () => {
+				throw errXPTY0004(
+					'The operand for a switch expression should result in zero or one item',
+				);
+			},
+			default: () => {
+				const singleValue = evaluatedExpression.first();
+				const isEmpty = !singleValue;
+
+				for (let i = 0; i < this._amountOfCases; i++) {
+					const results = this._testsByCase[i].map((x) =>
+						x.evaluateMaybeStatically(dynamicContext, executionParameters),
+					);
+
+					for (const result of results) {
+						const atomizedResult = atomizeSequence(result, executionParameters);
+						if (atomizedResult.isEmpty()) {
+							if (isEmpty) {
+								return caseClauseAndTestSequenceCallbacks[i](dynamicContext);
+							}
+							continue;
+						}
+
+						if (!atomizedResult.isSingleton()) {
+							throw errXPTY0004(
+								'The operand for a switch case should result in zero or one item',
+							);
+						}
+
+						if (isEmpty) {
+							continue;
+						}
+
+						const first = atomizedResult.first();
+
+						if (
+							itemDeepEqual(
+								dynamicContext,
+								executionParameters,
+								null,
+								singleValue,
+								first,
+							).next(IterationHint.NONE).value
+						) {
+							return caseClauseAndTestSequenceCallbacks[i](dynamicContext);
+						}
+					}
+				}
+
+				return defaultSequenceCallback(dynamicContext);
+			},
+		});
+	}
+
+	public performStaticEvaluation(staticContext: StaticContext) {
+		super.performStaticEvaluation(staticContext);
+
+		if (this._argExpression.isUpdating) {
+			throw errXUST0001();
+		}
+	}
+}
+
+export default SwitchExpression;
diff --git a/src/parsing/compileAstToExpression.ts b/src/parsing/compileAstToExpression.ts
index babe7aec..39fb3c10 100644
--- a/src/parsing/compileAstToExpression.ts
+++ b/src/parsing/compileAstToExpression.ts
@@ -68,6 +68,7 @@ import ElementConstructor from '../expressions/xquery/ElementConstructor';
 import PIConstructor from '../expressions/xquery/PIConstructor';
 import TextConstructor from '../expressions/xquery/TextConstructor';
 import TypeSwitchExpression from '../expressions/xquery/TypeSwitchExpression';
+import SwitchExpression from '../expressions/xquery/SwitchExpression';
 import astHelper, { IAST } from './astHelper';
 
 const COMPILATION_OPTIONS = {
@@ -204,6 +205,8 @@ function compile(ast: IAST, compilationOptions: CompilationOptions): Expression
 
 		case 'typeswitchExpr':
 			return typeswitchExpr(ast, compilationOptions);
+		case 'switchExpr':
+			return switchExpr(ast, compilationOptions);
 
 		// XQuery node constructors
 		case 'elementConstructor':
@@ -1481,7 +1484,7 @@ function typeswitchExpr(ast: IAST, compilationOptions: CompilationOptions) {
 	const caseClause = astHelper.getChildren(ast, 'typeswitchExprCaseClause');
 
 	const caseClauseExpressions = caseClause.map((caseClauseExpression) => {
-		const sequenceTypesAstNodes: IAST[] =
+		const caseNodes: IAST[] =
 			astHelper.getChildren(caseClauseExpression, 'sequenceTypeUnion').length === 0
 				? [astHelper.getFirstChild(caseClauseExpression, 'sequenceType')]
 				: astHelper.getChildren(
@@ -1496,7 +1499,7 @@ function typeswitchExpr(ast: IAST, compilationOptions: CompilationOptions) {
 
 		return {
 			caseClauseExpression: resultExpression,
-			typeTests: sequenceTypesAstNodes.map((sequenceTypeAstNode: IAST) => {
+			typeTests: caseNodes.map((sequenceTypeAstNode: IAST) => {
 				const occurrenceIndicator = astHelper.getFirstChild(
 					sequenceTypeAstNode,
 					'occurrenceIndicator',
@@ -1522,6 +1525,44 @@ function typeswitchExpr(ast: IAST, compilationOptions: CompilationOptions) {
 	return new TypeSwitchExpression(argExpr, caseClauseExpressions, defaultExpression, type);
 }
 
+function switchExpr(ast: IAST, compilationOptions: CompilationOptions) {
+	if (!compilationOptions.allowXQuery) {
+		throw new Error('XPST0003: Use of XQuery functionality is not allowed in XPath context');
+	}
+
+	const type = astHelper.getAttribute(ast, 'type');
+
+	const argExpr = compile(
+		astHelper.getFirstChild(astHelper.getFirstChild(ast, 'argExpr'), '*'),
+		compilationOptions,
+	);
+
+	const caseClauses = astHelper.getChildren(ast, 'switchExprCaseClause');
+
+	const caseClauseExpressions = caseClauses.map((caseClauseExpression) => {
+		const caseNodes: IAST[] = astHelper.getChildren(caseClauseExpression, 'switchCaseExpr');
+
+		const resultExpression = compile(
+			astHelper.followPath(caseClauseExpression, ['resultExpr', '*']),
+			compilationOptions,
+		) as PossiblyUpdatingExpression;
+
+		return {
+			caseClauseExpression: resultExpression,
+			tests: caseNodes.map((caseNode) =>
+				compile(astHelper.getFirstChild(caseNode, '*'), compilationOptions),
+			),
+		};
+	});
+
+	const defaultExpression = compile(
+		astHelper.followPath(ast, ['switchExprDefaultClause', 'resultExpr', '*']),
+		compilationOptions,
+	) as PossiblyUpdatingExpression;
+
+	return new SwitchExpression(argExpr, caseClauseExpressions, defaultExpression, type);
+}
+
 export default function (xPathAst: IAST, compilationOptions: CompilationOptions): Expression {
 	return compile(xPathAst, compilationOptions);
 }
diff --git a/src/parsing/prscParser.ts b/src/parsing/prscParser.ts
index 1287f7a3..7f62f52f 100644
--- a/src/parsing/prscParser.ts
+++ b/src/parsing/prscParser.ts
@@ -1813,25 +1813,33 @@ function generateParser(options: { outputDebugInfo: boolean; xquery: boolean }):
 
 	const switchCaseClause: Parser<IAST> = then(
 		plus(
-			map(precededMultiple([tokens.CASE, whitespacePlus], switchCaseOperand), (x) => [
-				'switchCaseExpr',
-				x,
-			]),
+			then(
+				map(
+					precededMultiple([tokens.CASE, whitespacePlus], cut(switchCaseOperand)),
+					(x) => ['switchCaseExpr', x],
+				),
+				cut(whitespacePlus),
+				(x, _) => x,
+			),
 		),
-		precededMultiple([whitespacePlus, tokens.RETURN, whitespacePlus], exprSingle),
+		cut(precededMultiple([tokens.RETURN, whitespacePlus], cut(exprSingle))),
 		(operands, exprPart) =>
 			['switchExprCaseClause', ...operands, ['resultExpr', exprPart]] as IAST,
 	);
 
 	const switchExpr: Parser<IAST> = then3(
-		precededMultiple([tokens.SWITCH, whitespace, tokens.BRACE_OPEN], expr),
-		precededMultiple(
-			[whitespace, tokens.BRACE_CLOSE, whitespace],
-			plus(followed(switchCaseClause, whitespace)),
+		precededMultiple([tokens.SWITCH, whitespace, tokens.BRACE_OPEN], cut(expr)),
+		cut(
+			precededMultiple(
+				[whitespace, tokens.BRACE_CLOSE, cut(whitespace)],
+				plus(followed(switchCaseClause, whitespace)),
+			),
 		),
-		precededMultiple(
-			[tokens.DEFAULT, whitespacePlus, tokens.RETURN, whitespacePlus],
-			exprSingle,
+		cut(
+			precededMultiple(
+				[tokens.DEFAULT, whitespacePlus, tokens.RETURN, whitespacePlus],
+				exprSingle,
+			),
 		),
 		(exprPart, clauses, resultExpr) => [
 			'switchExpr',
diff --git a/src/registerXQueryModule.ts b/src/registerXQueryModule.ts
index 25004bba..d0c7055b 100644
--- a/src/registerXQueryModule.ts
+++ b/src/registerXQueryModule.ts
@@ -49,10 +49,15 @@ export default function registerXQueryModule(
 	moduleString: string,
 	options: { debug: boolean } = { debug: false },
 ): string {
-	const parsedModule = parseExpression(moduleString, {
-		allowXQuery: true,
-		debug: options['debug'],
-	});
+	let parsedModule;
+	try {
+		parsedModule = parseExpression(moduleString, {
+			allowXQuery: true,
+			debug: options['debug'],
+		});
+	} catch (error) {
+		printAndRethrowError(moduleString, error);
+	}
 
 	annotateAst(parsedModule, new AnnotationContext(undefined));
 


Test patch:
diff --git a/test/assets/failingXQueryXTestNames.csv b/test/assets/failingXQueryXTestNames.csv
index 91e30755..049247f6 100644
--- a/test/assets/failingXQueryXTestNames.csv
+++ b/test/assets/failingXQueryXTestNames.csv
@@ -2670,8 +2670,6 @@ string-constructor-026,Parse error
 string-constructor-910,Parse error
 string-constructor-911,Parse error
 string-constructor-912,Parse error
-switch-004,Parse error
-switch-005,Parse error
 try-001,Parse error
 try-002,Parse error
 try-003,Parse error
diff --git a/test/assets/runnableTestSets.csv b/test/assets/runnableTestSets.csv
index 09794f25..f864b73d 100644
--- a/test/assets/runnableTestSets.csv
+++ b/test/assets/runnableTestSets.csv
@@ -111,7 +111,7 @@ fn-insert-before,true
 fn-iri-to-uri,true
 fn-json-doc,false
 fn-json-to-xml,false
-fn-lang,false
+fn-lang,true
 fn-last,true
 fn-load-xquery-module,false
 fn-local-name,false
@@ -408,7 +408,7 @@ prod-SequenceType,true
 prod-SquareArrayConstructor,true
 prod-StepExpr,true
 prod-StringConstructor,true
-prod-SwitchExpr,false
+prod-SwitchExpr,true
 prod-TreatExpr,false
 prod-TryCatchExpr,false
 prod-TypeswitchExpr,true
diff --git a/test/assets/unrunnableTestCases.csv b/test/assets/unrunnableTestCases.csv
index 013e0a8e..79a5f487 100644
--- a/test/assets/unrunnableTestCases.csv
+++ b/test/assets/unrunnableTestCases.csv
@@ -607,10 +607,6 @@ fn-function-lookup-259,AssertionError: Expected XPath exists(function-lookup(fn:
 fn-function-lookup-260,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
 fn-function-lookup-261,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'in-scope-prefixes'), 1)) to resolve to true: expected false to be true
 fn-function-lookup-262,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
-fn-function-lookup-275,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'lang'), 1)) to resolve to true: expected false to be true
-fn-function-lookup-276,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
-fn-function-lookup-277,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'lang'), 2)) to resolve to true: expected false to be true
-fn-function-lookup-278,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
 fn-function-lookup-318,Error: FOCH0002: No collations are supported
 fn-function-lookup-320,Error: XPTY0004: eqOp not available for xs:integer and xs:string
 fn-function-lookup-322,Error: FOCH0002: No collations are supported
@@ -621,10 +617,6 @@ fn-function-lookup-353,AssertionError: Expected XPath exists(function-lookup(fn:
 fn-function-lookup-354,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
 fn-function-lookup-355,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'element-with-id'), 2)) to resolve to true: expected false to be true
 fn-function-lookup-356,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
-fn-function-lookup-361,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'generate-id'), 0)) to resolve to true: expected false to be true
-fn-function-lookup-362,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
-fn-function-lookup-363,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'generate-id'), 1)) to resolve to true: expected false to be true
-fn-function-lookup-364,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
 fn-function-lookup-365,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'doc'), 1)) to resolve to true: expected false to be true
 fn-function-lookup-366,Error: XPTY0004: Expected base expression of a function call to evaluate to a sequence of single function item
 fn-function-lookup-367,AssertionError: Expected XPath exists(function-lookup(fn:QName('http://www.w3.org/2005/xpath-functions', 'doc-available'), 1)) to resolve to true: expected false to be true
@@ -727,33 +719,13 @@ fn-function-name-014,AssertionError: Expected executing the XPath "fn:function-n
 fn-function-name-018,AssertionError: Expected executing the XPath "fn:function-name( concat#340282366920938463463374607431768211456 )" to resolve to one of the expected results, but got AssertionError: expected [Function] to throw error matching /FOAR0002/ but got 'Invalid array length', RangeError: Invalid array length.
 fn-function-name-023,Error: 1: ( 2: 	declare function local:add($arg1, $arg2, $arg3)    	        ^ 3:         { 4:            $arg1 + $arg2 + $arg3  Error: XPST0003: Failed to parse script. Expected -,+,validate,(#,(,#,parent::,ancestor::,preceding-sibling::,preceding::,ancestor-or-self::,..,child::,descendant::,attribute::,self::,descendant-or-self::,following-sibling::,following::,document-node(,element,attribute,schema-element,schema-attribute(,processing-instruction(,processing-instruction(),comment(),text(),namespace-node(),node(),:*,Q,[A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD],[\uD800-\uDB7F],/,//   at <>:2:10 - 2:11
 fn-function-name-024,Error: No selector counterpart for: typedFunctionTest.
-generate-id-000,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-001,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-002,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-003,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-004,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-005,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-006,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-008,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
-generate-id-009,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
-generate-id-010,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
 generate-id-012,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}collection with arity of 0 not registered. No similar functions found.
 generate-id-013,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}collection with arity of 0 not registered. No similar functions found.
 generate-id-014,Error: No selector counterpart for: computedDocumentConstructor.
 generate-id-015,Error: No selector counterpart for: computedDocumentConstructor.
 generate-id-016,Error: No selector counterpart for: computedDocumentConstructor.
 generate-id-017,Error: No selector counterpart for: computedDocumentConstructor.
-generate-id-018,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-019,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
-generate-id-020,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-021,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-022,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-023,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-generate-id-901,AssertionError: expected [Function] to throw error matching /XPDY0002/ but got 'XPST0017: Function Q{http://www.w3.or…'
-generate-id-902,AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'XPST0017: Function Q{http://www.w3.or…'
-generate-id-903,AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'XPST0017: Function Q{http://www.w3.or…'
-generate-id-904,AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'XPST0017: Function Q{http://www.w3.or…'
-generate-id-905,AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'XPST0017: Function Q{http://www.w3.or…'
+generate-id-018,Error: XPTY0004: Multiplicity of function argument of type node()? for generate-id is incorrect. Expected "?", but got "+".
 fn-has-children-007,AssertionError: Expected executing the XPath "(1)[fn:has-children()]" to resolve to one of the expected results, but got AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'Cannot read properties of undefined (…'.
 fn-has-children-008,AssertionError: Expected executing the XPath "(fn:concat#2)[fn:has-children()]" to resolve to one of the expected results, but got AssertionError: expected [Function] to throw error matching /XPTY0004/ but got 'Cannot read properties of undefined (…'.
 fn-has-children-012,AssertionError: expected [Function] to throw an error
@@ -804,6 +776,8 @@ K-SeqInsertBeforeFunc-17,Error: No selector counterpart for: treatExpr.
 K-SeqInsertBeforeFunc-18,Error: No selector counterpart for: treatExpr.
 K-SeqInsertBeforeFunc-19,Error: No selector counterpart for: treatExpr.
 K-SeqInsertBeforeFunc-20,Error: No selector counterpart for: treatExpr.
+fn-lang-31,AssertionError: Expected XPath let $l := /langs/para[4]!fn:lang#1 return /langs/para[1]!$l('en') to resolve to false: expected true to be false
+fn-lang-32,AssertionError: Expected XPath let $l := /langs/para[4]!fn:lang#1 return /langs/para[1]!$l('de') to resolve to true: expected false to be true
 K-ContextLastFunc-5,Error: No selector counterpart for: treatExpr.
 K-ContextLastFunc-24,Error: No selector counterpart for: treatExpr.
 K-ContextLastFunc-25,Error: No selector counterpart for: treatExpr.
@@ -1625,7 +1599,6 @@ cbcl-timezone-from-date-007,Error: XPST0017: Function Q{http://www.w3.org/2005/x
 fn-tokenize-2,AssertionError: expected [Function] to throw error matching /FORX0001/ but got 'Not implemented: Using flags in token…'
 fn-tokenize-5,Error: Not implemented: Using flags in tokenize is not supported
 fn-tokenize-6,Error: Not implemented: Using flags in tokenize is not supported
-fn-tokenize-9,AssertionError: string-join(fn:tokenize("abracadabra", "(ab)|(a)"), '#'): expected '#ab##r##a#c##a#d#ab##r##a#' to equal '#r#c#d#r#'
 fn-tokenize-31,Error: Not implemented: Using flags in tokenize is not supported
 fn-tokenize-32,Error: Not implemented: Using flags in tokenize is not supported
 fn-tokenize-35,Error: Not implemented: Using flags in tokenize is not supported
@@ -2984,7 +2957,6 @@ K-FunctionCallExpr-5,AssertionError: expected [Function] to throw error matching
 K-FunctionCallExpr-15a,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}format-number with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}format-integer (xs:integer?, xs:string)"?
 K-FunctionCallExpr-16a,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}format-time with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}current-time ()" or "Q{http://www.w3.org/2005/xpath-functions}format-integer (xs:integer?, xs:string)"?
 K-FunctionCallExpr-17a,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}format-time with arity of 5 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}current-time ()" or "Q{http://www.w3.org/2005/xpath-functions}format-integer (xs:integer?, xs:string)"?
-K-FunctionCallExpr-25a,Error: XPST0017: Function generate-id with arity of 1 not registered. No similar functions found.
 function-call-reserved-function-names-034,AssertionError: expected [Function] to throw error matching /XPST0017/ but got '1: \n2: \tnamespace-node(1)\n   \t   …'
 function-declaration-017,Error: XPST0008, The variable v is not in scope.
 function-declaration-022,AssertionError: expected [Function] to throw error matching /XQST0034/ but got 'XQST0049: The function or variable "Q…'
@@ -3161,10 +3133,6 @@ function-literal-259,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-fu
 function-literal-260,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}namespace-uri-for-prefix with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}namespace-uri-from-QName (xs:QName?)", "Q{http://www.w3.org/2005/xpath-functions}namespace-uri (node())" or "Q{http://www.w3.org/2005/xpath-functions}namespace-uri ()"?
 function-literal-261,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}in-scope-prefixes with arity of 1 not registered. No similar functions found.
 function-literal-262,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}in-scope-prefixes with arity of 1 not registered. No similar functions found.
-function-literal-275,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-function-literal-276,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-function-literal-277,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-function-literal-278,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
 function-literal-318,Error: FOCH0002: No collations are supported
 function-literal-320,Error: XPTY0004: eqOp not available for xs:integer and xs:string
 function-literal-322,Error: FOCH0002: No collations are supported
@@ -3175,10 +3143,6 @@ function-literal-353,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-fu
 function-literal-354,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}element-with-id with arity of 1 not registered. No similar functions found.
 function-literal-355,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}element-with-id with arity of 2 not registered. No similar functions found.
 function-literal-356,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}element-with-id with arity of 2 not registered. No similar functions found.
-function-literal-361,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
-function-literal-362,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 0 not registered. No similar functions found.
-function-literal-363,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
-function-literal-364,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}generate-id with arity of 1 not registered. No similar functions found.
 function-literal-365,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}doc with arity of 1 not registered. No similar functions found.
 function-literal-366,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}doc with arity of 1 not registered. No similar functions found.
 function-literal-367,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}doc-available with arity of 1 not registered. No similar functions found.
@@ -3443,6 +3407,7 @@ string-constructor-028,Error: 1: ( 2:         declare variable $n external := <e
 string-constructor-910,AssertionError: expected [Function] to throw error matching /FOTY0013/ but got '1: \n2:         declare variable $n e…'
 string-constructor-911,AssertionError: expected [Function] to throw error matching /FOTY0013/ but got '1: \n2:         declare variable $n e…'
 string-constructor-912,Error: 1:  2:         declare variable $n as xs:integer external := 10;  3:         ``[There were `{1 to $n}` green bottles]``            ^ 4:        = "There were 1 2 3 4 5 6 7 8 9 10 green bottles"  Error: XPST0003: Failed to parse script. Expected -,+,validate,(#,(,#,parent::,ancestor::,preceding-sibling::,preceding::,ancestor-or-self::,..,child::,descendant::,attribute::,self::,descendant-or-self::,following-sibling::,following::,document-node(,element,attribute,schema-element,schema-attribute(,processing-instruction(,processing-instruction(),comment(),text(),namespace-node(),node(),:*,Q,[A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD],[\uD800-\uDB7F],/,//   at <>:3:9 - 3:10
+switch-018,AssertionError: Expected XPath            let $v := xs:time('00:00:00Z')          return switch($v)          case xs:time('24:00:00Z') return 1          default return 2        to resolve to 1: expected false to be true
 typeswitchhc16,Error: XPST0008, The variable i is not in scope.
 typeswitchhc20,Error: XPST0008, The variable i is not in scope.
 K-sequenceExprTypeswitch-6,Error: No selector counterpart for: voidSequenceType.
@@ -3784,13 +3749,6 @@ functx-fn-escape-html-uri-2,Error: XPST0017: Function Q{http://www.w3.org/2005/x
 functx-fn-escape-html-uri-all,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}escape-html-uri with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}encode-for-uri (xs:string?)"?
 functx-fn-index-of-5,Error: XPTY0004: eqOp not available for xs:integer and xs:string
 functx-fn-index-of-all,Error: XPTY0004: eqOp not available for xs:integer and xs:string
-functx-fn-lang-1,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-2,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-3,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-4,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-5,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-6,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
-functx-fn-lang-all,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 1 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
 functx-fn-matches-10,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}matches with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}matches (xs:string?, xs:string)"?
 functx-fn-matches-12,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}matches with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}matches (xs:string?, xs:string)"?
 functx-fn-matches-14,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}matches with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}matches (xs:string?, xs:string)"?
@@ -3838,8 +3796,6 @@ functx-functx-dynamic-path-all,Error: No selector counterpart for: computedDocum
 functx-functx-get-matches-1,AssertionError: declare namespace functx = "http://www.example.com/";                     (:~ : Splits a string into matching and non-matching regions : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches-and-non-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches-and-non-matches ( $string as xs:string? , $regex as xs:string ) as element()* { let $iomf := functx:index-of-match-first($string, $regex) return if (empty($iomf)) then <non-match>{$string}</non-match> else if ($iomf > 1) then (<non-match>{substring($string,1,$iomf - 1)}</non-match>, functx:get-matches-and-non-matches( substring($string,$iomf),$regex)) else let $length := string-length($string) - string-length(functx:replace-first($string, $regex,'')) return (<match>{substring($string,1,$length)}</match>, if (string-length($string) > $length) then functx:get-matches-and-non-matches( substring($string,$length + 1),$regex) else ()) } ;                     (:~ : Return the matching regions of a string : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches ( $string as xs:string? , $regex as xs:string ) as xs:string* { functx:get-matches-and-non-matches($string,$regex)/ string(self::match) } ;                     (:~ : The first position of a matching substring : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_index-of-match-first.html : @param $arg the string : @param $pattern the pattern to match :)          declare function functx:index-of-match-first ( $arg as xs:string? , $pattern as xs:string ) as xs:integer? { if (matches($arg,$pattern)) then string-length(tokenize($arg, $pattern)[1]) + 1 else () } ;                     (:~ : Replaces the first match of a pattern : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_replace-first.html : @param $arg the entire string to change : @param $pattern the pattern of characters to replace : @param $replacement the replacement string :)          declare function functx:replace-first ( $arg as xs:string? , $pattern as xs:string , $replacement as xs:string ) as xs:string { replace($arg, concat('(^.*?)', $pattern), concat('$1',$replacement)) } ;                     (functx:get-matches( 'abc123def', '\d+')): expected '123  ' to equal ' 123 '
 functx-functx-get-matches-2,AssertionError: declare namespace functx = "http://www.example.com/";                     (:~ : Splits a string into matching and non-matching regions : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches-and-non-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches-and-non-matches ( $string as xs:string? , $regex as xs:string ) as element()* { let $iomf := functx:index-of-match-first($string, $regex) return if (empty($iomf)) then <non-match>{$string}</non-match> else if ($iomf > 1) then (<non-match>{substring($string,1,$iomf - 1)}</non-match>, functx:get-matches-and-non-matches( substring($string,$iomf),$regex)) else let $length := string-length($string) - string-length(functx:replace-first($string, $regex,'')) return (<match>{substring($string,1,$length)}</match>, if (string-length($string) > $length) then functx:get-matches-and-non-matches( substring($string,$length + 1),$regex) else ()) } ;                     (:~ : Return the matching regions of a string : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches ( $string as xs:string? , $regex as xs:string ) as xs:string* { functx:get-matches-and-non-matches($string,$regex)/ string(self::match) } ;                     (:~ : The first position of a matching substring : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_index-of-match-first.html : @param $arg the string : @param $pattern the pattern to match :)          declare function functx:index-of-match-first ( $arg as xs:string? , $pattern as xs:string ) as xs:integer? { if (matches($arg,$pattern)) then string-length(tokenize($arg, $pattern)[1]) + 1 else () } ;                     (:~ : Replaces the first match of a pattern : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_replace-first.html : @param $arg the entire string to change : @param $pattern the pattern of characters to replace : @param $replacement the replacement string :)          declare function functx:replace-first ( $arg as xs:string? , $pattern as xs:string , $replacement as xs:string ) as xs:string { replace($arg, concat('(^.*?)', $pattern), concat('$1',$replacement)) } ;                     (functx:get-matches( 'abc123def', '\d')): expected ' 1 3  2' to equal ' 1 2 3 '
 functx-functx-get-matches-all,AssertionError: declare namespace functx = "http://www.example.com/";                     (:~ : Splits a string into matching and non-matching regions : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches-and-non-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches-and-non-matches ( $string as xs:string? , $regex as xs:string ) as element()* { let $iomf := functx:index-of-match-first($string, $regex) return if (empty($iomf)) then <non-match>{$string}</non-match> else if ($iomf > 1) then (<non-match>{substring($string,1,$iomf - 1)}</non-match>, functx:get-matches-and-non-matches( substring($string,$iomf),$regex)) else let $length := string-length($string) - string-length(functx:replace-first($string, $regex,'')) return (<match>{substring($string,1,$length)}</match>, if (string-length($string) > $length) then functx:get-matches-and-non-matches( substring($string,$length + 1),$regex) else ()) } ;                     (:~ : Return the matching regions of a string : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_get-matches.html : @param $string the string to split : @param $regex the pattern :)          declare function functx:get-matches ( $string as xs:string? , $regex as xs:string ) as xs:string* { functx:get-matches-and-non-matches($string,$regex)/ string(self::match) } ;                     (:~ : The first position of a matching substring : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_index-of-match-first.html : @param $arg the string : @param $pattern the pattern to match :)          declare function functx:index-of-match-first ( $arg as xs:string? , $pattern as xs:string ) as xs:integer? { if (matches($arg,$pattern)) then string-length(tokenize($arg, $pattern)[1]) + 1 else () } ;                     (:~ : Replaces the first match of a pattern : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_replace-first.html : @param $arg the entire string to change : @param $pattern the pattern of characters to replace : @param $replacement the replacement string :)          declare function functx:replace-first ( $arg as xs:string? , $pattern as xs:string , $replacement as xs:string ) as xs:string { replace($arg, concat('(^.*?)', $pattern), concat('$1',$replacement)) } ;                     (functx:get-matches( 'abc123def', '\d+'), functx:get-matches( 'abc123def', '\d'), functx:get-matches( 'abc123def', '[a-z]{2}')): expected '123    1 3  2 ab  de ' to equal ' 123   1 2 3  ab  de '
-functx-functx-line-count-2,AssertionError: Expected XPath declare namespace functx = "http://www.example.com/";                     (:~ : The number of lines : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_line-count.html : @param $arg the string to test :)          declare function functx:line-count ( $arg as xs:string? ) as xs:integer { count(functx:lines($arg)) } ;                     (:~ : Split a string into separate lines : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_lines.html : @param $arg the string to split :)          declare function functx:lines ( $arg as xs:string? ) as xs:string* { tokenize($arg, '(\r\n?|\n\r?)') } ;          let $lines := 'a              value              on              many              lines' return (functx:line-count($lines))        to resolve to 5: expected false to be true
-functx-functx-line-count-all,AssertionError: declare namespace functx = "http://www.example.com/";                     (:~ : The number of lines : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_line-count.html : @param $arg the string to test :)          declare function functx:line-count ( $arg as xs:string? ) as xs:integer { count(functx:lines($arg)) } ;                     (:~ : Split a string into separate lines : : @author Priscilla Walmsley, Datypic : @version 1.0 : @see http://www.xqueryfunctions.com/xq/functx_lines.html : @param $arg the string to split :)          declare function functx:lines ( $arg as xs:string? ) as xs:string* { tokenize($arg, '(\r\n?|\n\r?)') } ;          let $lines := 'a                      value                      on                      many                      lines'           return (functx:line-count('a value'), functx:line-count($lines)): expected '1 9' to equal '1 5'
 functx-functx-next-day-1,Error: Not implemented: adding durations to xs:date
 functx-functx-next-day-2,Error: Not implemented: adding durations to xs:date
 functx-functx-next-day-all,Error: Not implemented: adding durations to xs:date
@@ -3876,7 +3832,6 @@ UseCaseR31-002,Error: Not implemented: groupByClause is not implemented yet.
 UseCaseR31-003,Error: Not implemented: groupByClause is not implemented yet.
 UseCaseR31-004,Error: 1: let $result := (        ^ 2:         declare namespace map="http://www.w3.org/2005/xpath-functions/map"; 3:   Error: XPST0003: Failed to parse script. Expected end of input   at <>:1:5 - 1:6
 UseCaseR31-009,Error: 1: let $result := (        ^ 2:       declare namespace map="http://www.w3.org/2005/xpath-functions/map"; 3:       declare variable $book:= (<book>  Error: XPST0003: Failed to parse script. Expected end of input   at <>:1:5 - 1:6
-UseCaseR31-012,Error: No selector counterpart for: switchExpr.
 UseCaseR31-015,Error: Not implemented: groupByClause is not implemented yet.
 UseCaseR31-016,Error: 1: deep-equal((              ^ 2:               declare variable $s :=[['A', 'DT'], ['bride', 'NN'], [',', ','], ['you', 'PRP'], ['know', 'VBP'], [',', ','], ['must', 'MD'], 3:  ['appear', 'VB'], ['like', 'IN'], ['a', 'DT'], ['bride', 'NN'], [',', ','], ['but', 'CC'], ['my', 'PRP$'],  Error: XPST0003: Failed to parse script. Expected end of input   at <>:1:11 - 1:12
 UseCaseR31-017,Error: 1: deep-equal((              ^ 2:               declare variable $s :=[['A', 'DT'], ['bride', 'NN'], [',', ','], ['you', 'PRP'], ['know', 'VBP'], [',', ','], ['must', 'MD'], 3:  ['appear', 'VB'], ['like', 'IN'], ['a', 'DT'], ['bride', 'NN'], [',', ','], ['but', 'CC'], ['my', 'PRP$'],  Error: XPST0003: Failed to parse script. Expected end of input   at <>:1:11 - 1:12
@@ -4131,7 +4086,6 @@ fo-test-fn-idref-001,Error: No selector counterpart for: validateExpr.
 fo-test-fn-idref-002,Error: No selector counterpart for: validateExpr.
 fo-test-fn-serialize-001,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}serialize with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}serialize (item()*)"?
 fo-test-fn-serialize-002,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}serialize with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions}serialize (item()*)"?
-fo-test-fn-filter-002,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}lang with arity of 2 not registered. Did you mean "Q{http://www.w3.org/2001/XMLSchema}long (xs:anyAtomicType?)"?
 fo-test-fn-for-each-pair-001,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}for-each-pair with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions/array}for-each-pair (array(*), array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/array}for-each (array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/map}for-each (map(*), item()*)" or "Q{http://www.w3.org/2005/xpath-functions}for-each (item()*, function(*))"?
 fo-test-fn-for-each-pair-002,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}for-each-pair with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions/array}for-each-pair (array(*), array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/array}for-each (array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/map}for-each (map(*), item()*)" or "Q{http://www.w3.org/2005/xpath-functions}for-each (item()*, function(*))"?
 fo-test-fn-for-each-pair-003,Error: XPST0017: Function Q{http://www.w3.org/2005/xpath-functions}for-each-pair with arity of 3 not registered. Did you mean "Q{http://www.w3.org/2005/xpath-functions/array}for-each-pair (array(*), array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/array}for-each (array(*), function(*))", "Q{http://www.w3.org/2005/xpath-functions/map}for-each (map(*), item()*)" or "Q{http://www.w3.org/2005/xpath-functions}for-each (item()*, function(*))"?
diff --git a/test/specs/parsing/functions/functions.node.tests.ts b/test/specs/parsing/functions/functions.node.tests.ts
index bdd9f877..520a8444 100644
--- a/test/specs/parsing/functions/functions.node.tests.ts
+++ b/test/specs/parsing/functions/functions.node.tests.ts
@@ -16,6 +16,113 @@ beforeEach(() => {
 });
 
 describe('functions over nodes', () => {
+	describe('generate-id()', () => {
+		it('returns the same value for the same node', () => {
+			jsonMlMapper.parse(['someElement'], documentNode);
+			chai.assert.isTrue(
+				evaluateXPathToBoolean('generate-id(/) = generate-id(/)', documentNode),
+			);
+		});
+
+		it('returns the empty string for the empty sequence', () => {
+			jsonMlMapper.parse(['someElement'], documentNode);
+			chai.assert.isTrue(evaluateXPathToBoolean('generate-id(()) = ""', documentNode));
+		});
+
+		it('throws the correct error when the context item is not a node', () => {
+			chai.assert.throws(
+				() => evaluateXPathToBoolean('"not a node" ! generate-id()'),
+				'XPTY0004',
+			);
+		});
+
+		it('returns the same value for subsequent calls', () => {
+			jsonMlMapper.parse(['someElement'], documentNode);
+			const id = evaluateXPathToString('generate-id(/)', documentNode);
+			chai.assert.equal(evaluateXPathToString('generate-id(/)', documentNode), id);
+		});
+	});
+
+	describe('lang()', () => {
+		it('returns true when the node has the right lang', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'en' }], documentNode);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en", .)', documentNode.firstChild),
+				true,
+			);
+		});
+
+		it('returns false when the node has the wrong lang', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'en' }], documentNode);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("es", .)', documentNode.firstChild),
+				false,
+			);
+		});
+
+		it('returns true when the node has the right lang, but capitalized', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'EN' }], documentNode);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en", .)', documentNode.firstChild),
+				true,
+			);
+		});
+
+		it('returns true when the node has the right lang, but more specific', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'en-gb' }], documentNode);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en", .)', documentNode.firstChild),
+				true,
+			);
+		});
+
+		it('returns false when the node has the right lang, but not specific enough', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'en' }], documentNode);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en-gb", .)', documentNode.firstChild),
+				false,
+			);
+		});
+
+		it('returns true for implied context', () => {
+			jsonMlMapper.parse(['someElement', { 'xml:lang': 'en' }], documentNode);
+			chai.assert.equal(evaluateXPathToBoolean('lang("en")', documentNode.firstChild), true);
+		});
+
+		it('returns true when the parent is true', () => {
+			jsonMlMapper.parse(
+				['someElement', { 'xml:lang': 'en' }, ['child', 'Hello']],
+				documentNode,
+			);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en")', documentNode.firstChild.firstChild),
+				true,
+			);
+		});
+
+		it('returns false even if the parent is true', () => {
+			jsonMlMapper.parse(
+				['someElement', { 'xml:lang': 'en' }, ['child', { 'xml:lang': 'de' }, 'Hello']],
+				documentNode,
+			);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en")', documentNode.firstChild.firstChild),
+				false,
+			);
+		});
+
+		it('returns true even if the parent is false', () => {
+			jsonMlMapper.parse(
+				['someElement', { 'xml:lang': 'de' }, ['child', { 'xml:lang': 'en' }, 'Hello']],
+				documentNode,
+			);
+			chai.assert.equal(
+				evaluateXPathToBoolean('lang("en")', documentNode.firstChild.firstChild),
+				true,
+			);
+		});
+	});
+
 	describe('node-name()', () => {
 		it('returns an empty sequence if $arg is an empty sequence', () =>
 			chai.assert.isEmpty(evaluateXPathToStrings('node-name(())', documentNode)));
diff --git a/test/specs/parsing/functions/functions.string.tests.ts b/test/specs/parsing/functions/functions.string.tests.ts
index da3f5f9d..a3135c4a 100644
--- a/test/specs/parsing/functions/functions.string.tests.ts
+++ b/test/specs/parsing/functions/functions.string.tests.ts
@@ -95,6 +95,13 @@ describe('functions over strings', () => {
 			));
 	});
 
+	it('tokenize("abracadabra", "(ab)|(a)") returns ("","r","c","d","r","")', () => {
+		chai.assert.sameOrderedMembers(
+			evaluateXPathToStrings('fn:tokenize("abracadabra", "(ab)|(a)")'),
+			['', 'r', 'c', 'd', 'r', ''],
+		);
+	});
+
 	describe('normalize-space()', () => {
 		it('Returns the value of $arg with whitespace normalized by stripping leading and trailing whitespace and replacing sequences of one or more than one whitespace character with a single space, #x20.', () =>
 			chai.assert.equal(
@@ -223,6 +230,19 @@ describe('functions over strings', () => {
 			chai.assert.equal(evaluateXPathToString('string()', document), 'Some <CDATA>');
 		});
 
+		it('regards documentFragment nodes as normal parents', () => {
+			const document = new slimdom.Document();
+			const f = document.createDocumentFragment();
+			const foo = f.appendChild(document.createElement('foo'));
+			f.firstChild.appendChild(document.createTextNode('Test'));
+			f.appendChild(foo.cloneNode(true));
+			chai.assert.equal(
+				evaluateXPathToString('string($f)', undefined, undefined, { f }),
+				'TestTest',
+			);
+			chai.assert.equal(evaluateXPathToString('string(.)', f, undefined), 'TestTest');
+		});
+
 		it('If $arg is the empty sequence, the function returns the zero-length string.', () =>
 			chai.assert.equal(evaluateXPathToString('string(())', documentNode), ''));
 
diff --git a/test/specs/parsing/registerXQueryModule.tests.ts b/test/specs/parsing/registerXQueryModule.tests.ts
index be06d1c1..f4834560 100644
--- a/test/specs/parsing/registerXQueryModule.tests.ts
+++ b/test/specs/parsing/registerXQueryModule.tests.ts
@@ -345,4 +345,13 @@ declare function bar:baz() {
 			'XPST0017',
 		);
 	});
+
+	it('throws a proper error for parse errors', () => {
+		chai.expect(() => {
+			registerXQueryModule(
+				`declare function local:one() { 1 }(:missing semicolon:)
+				declare function local:two() { 2 };`,
+			);
+		}).to.throw('XPST0003: Failed to parse script. Expected ;');
+	});
 });
diff --git a/test/specs/parsing/xquery/SwitchExpression.tests.ts b/test/specs/parsing/xquery/SwitchExpression.tests.ts
new file mode 100644
index 00000000..dcc6ad0c
--- /dev/null
+++ b/test/specs/parsing/xquery/SwitchExpression.tests.ts
@@ -0,0 +1,102 @@
+import * as chai from 'chai';
+
+import { evaluateXPath, evaluateXPathToNumber } from 'fontoxpath';
+
+describe('Switch', () => {
+	it('works', () =>
+		chai.assert.equal(
+			evaluateXPathToNumber(
+				`
+switch (1)
+case 1 return 1
+default return 0`,
+
+				null,
+				null,
+				null,
+				{
+					debug: true,
+					language: evaluateXPath.XQUERY_3_1_LANGUAGE,
+				},
+			),
+			1,
+		));
+
+	it('works hitting the default case', () =>
+		chai.assert.equal(
+			evaluateXPathToNumber(
+				`
+switch (0)
+case 1 return 1
+default return 0`,
+
+				null,
+				null,
+				null,
+				{
+					debug: true,
+					language: evaluateXPath.XQUERY_3_1_LANGUAGE,
+				},
+			),
+			0,
+		));
+
+	it('works hitting the empty sequence case', () =>
+		chai.assert.equal(
+			evaluateXPathToNumber(
+				`
+switch (())
+case () return 1
+default return 0`,
+
+				null,
+				null,
+				null,
+				{
+					debug: true,
+					language: evaluateXPath.XQUERY_3_1_LANGUAGE,
+				},
+			),
+			1,
+		));
+
+	it('works hitting the empty sequence case as a default', () =>
+		chai.assert.equal(
+			evaluateXPathToNumber(
+				`
+switch (())
+case 1 return 1
+default return 0`,
+
+				null,
+				null,
+				null,
+				{
+					debug: true,
+					language: evaluateXPath.XQUERY_3_1_LANGUAGE,
+				},
+			),
+			0,
+		));
+
+	it('works hitting overload cases', () =>
+		chai.assert.equal(
+			evaluateXPathToNumber(
+				`
+switch (1)
+case ()
+case 1 return 1
+
+default return 0`,
+
+				null,
+				null,
+				null,
+				{
+					debug: true,
+					language: evaluateXPath.XQUERY_3_1_LANGUAGE,
+				},
+			),
+			1,
+		));
+});