Repository: FontoXML/fontoxpath
Pull request #642 (2024-06-16 09:52:44)

Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/micromatch/braces/commit/74b2db2938fad48a2ea54a9c8bf27a37a62c350d"><code>74b2db2</code></a> 3.0.3</li>
<li><a href="https://github.com/micromatch/braces/commit/88f1429a0f47e1dd3813de35211fc97ffda27f9e"><code>88f1429</code></a> update eslint. lint, fix unit tests.</li>
<li><a href="https://github.com/micromatch/braces/commit/415d660c3002d1ab7e63dbf490c9851da80596ff"><code>415d660</code></a> Snyk js braces 6838727 (<a href="https://redirect.github.com/micromatch/braces/issues/40">#40</a>)</li>
<li><a href="https://github.com/micromatch/braces/commit/190510f79db1adf21d92798b0bb6fccc1f72c9d6"><code>190510f</code></a> fix tests, skip 1 test in test/braces.expand</li>
<li><a href="https://github.com/micromatch/braces/commit/716eb9f12d820b145a831ad678618731927e8856"><code>716eb9f</code></a> readme bump</li>
<li><a href="https://github.com/micromatch/braces/commit/a5851e57f45c3431a94d83fc565754bc10f5bbc3"><code>a5851e5</code></a> Merge pull request <a href="https://redirect.github.com/micromatch/braces/issues/37">#37</a> from coderaiser/fix/vulnerability</li>
<li><a href="https://github.com/micromatch/braces/commit/2092bd1fb108d2c59bd62e243b70ad98db961538"><code>2092bd1</code></a> feature: braces: add maxSymbols (<a href="https://github.com/micromatch/braces/issues/">https://github.com/micromatch/braces/issues/</a>...</li>
<li><a href="https://github.com/micromatch/braces/commit/9f5b4cf47329351bcb64287223ffb6ecc9a5e6d3"><code>9f5b4cf</code></a> fix: vulnerability (<a href="https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727">https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727</a>)</li>
<li><a href="https://github.com/micromatch/braces/commit/98414f9f1fabe021736e26836d8306d5de747e0d"><code>98414f9</code></a> remove funding file</li>
<li><a href="https://github.com/micromatch/braces/commit/665ab5d561c017a38ba7aafd92cc6655b91d8c14"><code>665ab5d</code></a> update keepEscaping doc (<a href="https://redirect.github.com/micromatch/braces/issues/27">#27</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/micromatch/braces/compare/3.0.2...3.0.3">compare view</a></li>
</ul>
</details>
<br />


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

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually 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)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/FontoXML/fontoxpath/network/alerts).

</details>

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

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

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



No change in files bundle size

Final result: :white_check_mark:

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

---
<p align="center"><a href="https://app.bundlemon.dev/projects/6437c8f89a7cb205c434db8d/reports?branch=dependabot%2Fnpm_and_yarn%2Fbraces-3.0.3&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/68109396/badge)](https://coveralls.io/builds/68109396)

coverage: 91.556%. remained the same
when pulling **8d54cf626e8f37d002150a10805bf59578bf44d2 on dependabot/npm_and_yarn/braces-3.0.3**
into **35d0da50bcbd81f905382c5731d28ff2522968c7 on master**.


Patch:
diff --git a/package-lock.json b/package-lock.json
index b2c8779a..3eee694b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2618,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"
@@ -4507,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"
@@ -12483,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": {
@@ -13903,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"
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/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 b564426d..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,
@@ -635,6 +652,20 @@ const declarations: BuiltinDeclarationType[] = [
 		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/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;


Test patch:
diff --git a/test/assets/unrunnableTestCases.csv b/test/assets/unrunnableTestCases.csv
index ee69fcab..79a5f487 100644
--- a/test/assets/unrunnableTestCases.csv
+++ b/test/assets/unrunnableTestCases.csv
@@ -617,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
@@ -723,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
@@ -2981,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…'
@@ -3168,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.
diff --git a/test/specs/parsing/functions/functions.node.tests.ts b/test/specs/parsing/functions/functions.node.tests.ts
index 52462689..520a8444 100644
--- a/test/specs/parsing/functions/functions.node.tests.ts
+++ b/test/specs/parsing/functions/functions.node.tests.ts
@@ -16,6 +16,33 @@ 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);
diff --git a/test/specs/parsing/functions/functions.string.tests.ts b/test/specs/parsing/functions/functions.string.tests.ts
index ac20624b..a3135c4a 100644
--- a/test/specs/parsing/functions/functions.string.tests.ts
+++ b/test/specs/parsing/functions/functions.string.tests.ts
@@ -230,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), ''));