nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: capricorn86/happy-dom
Pull request #459 (2022-04-26 15:04:06)

#457@minor: Adds support for Window.getSelection().


Patch:
diff --git a/packages/happy-dom/src/window/IWindow.ts b/packages/happy-dom/src/window/IWindow.ts
index c40d9d87..e0eb944b 100644
--- a/packages/happy-dom/src/window/IWindow.ts
+++ b/packages/happy-dom/src/window/IWindow.ts
@@ -213,6 +213,13 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
 	 */
 	getComputedStyle(element: IHTMLElement): CSSStyleDeclaration;
 
+	/**
+	 * Returns selection.
+	 *
+	 * @returns Selection.
+	 */
+	getSelection(): Selection;
+
 	/**
 	 * Scrolls to a particular set of coordinates.
 	 *
diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts
index 83e11228..e6dd2225 100644
--- a/packages/happy-dom/src/window/Window.ts
+++ b/packages/happy-dom/src/window/Window.ts
@@ -361,6 +361,15 @@ export default class Window extends EventTarget implements IWindow {
 		return new CSSStyleDeclaration(element._attributes, element);
 	}
 
+	/**
+	 * Returns selection.
+	 *
+	 * @returns Selection.
+	 */
+	public getSelection(): Selection {
+		return this.document.getSelection();
+	}
+
 	/**
 	 * Scrolls to a particular set of coordinates.
 	 *


Test patch:
diff --git a/packages/happy-dom/test/window/Window.test.ts b/packages/happy-dom/test/window/Window.test.ts
index a19dbe54..fe547d16 100644
--- a/packages/happy-dom/test/window/Window.test.ts
+++ b/packages/happy-dom/test/window/Window.test.ts
@@ -10,6 +10,7 @@ import Navigator from '../../src/navigator/Navigator';
 import Headers from '../../src/fetch/Headers';
 import Response from '../../src/fetch/Response';
 import Request from '../../src/fetch/Request';
+import Selection from '../../src/selection/Selection';
 
 const MOCKED_NODE_FETCH = global['mockedModules']['node-fetch'];
 
@@ -422,6 +423,12 @@ describe('Window', () => {
 		});
 	}
 
+	describe('getSelection()', () => {
+		it('Returns selection.', () => {
+			expect(window.getSelection() instanceof Selection).toBe(true);
+		});
+	});
+
 	describe('addEventListener()', () => {
 		it('Triggers "load" event if no resources needs to be loaded.', (done) => {
 			let loadEvent = null;
Repository: capricorn86/happy-dom
Pull request #497 (2022-06-08 11:28:42)

#496@minor: Add toString method to DOMTokenList.
Minor fix for #496.


Patch:
diff --git a/package-lock.json b/package-lock.json
index 54890d7f..3c541db1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11830,7 +11830,7 @@
 		"node_modules/safe-regex": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-			"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+			"integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
 			"dependencies": {
 				"ret": "~0.1.10"
 			}
@@ -23215,7 +23215,7 @@
 		"safe-regex": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-			"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+			"integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
 			"requires": {
 				"ret": "~0.1.10"
 			}
diff --git a/packages/happy-dom/src/dom-token-list/DOMTokenList.ts b/packages/happy-dom/src/dom-token-list/DOMTokenList.ts
index 9c475aa5..19a02231 100644
--- a/packages/happy-dom/src/dom-token-list/DOMTokenList.ts
+++ b/packages/happy-dom/src/dom-token-list/DOMTokenList.ts
@@ -212,4 +212,11 @@ export default class DOMTokenList implements IDOMTokenList {
 
 		(<number>this.length) = list.length;
 	}
+
+	/**
+	 * Returns DOMTokenList value.
+	 */
+	public toString(): string {
+		return this.value || '';
+	}
 }
diff --git a/packages/happy-dom/src/dom-token-list/IDOMTokenList.ts b/packages/happy-dom/src/dom-token-list/IDOMTokenList.ts
index 6a7c46bc..d677cc57 100644
--- a/packages/happy-dom/src/dom-token-list/IDOMTokenList.ts
+++ b/packages/happy-dom/src/dom-token-list/IDOMTokenList.ts
@@ -16,4 +16,5 @@ export default interface IDOMTokenList {
 	entries(): IterableIterator<[number, string]>;
 	forEach(callback: (currentValue, currentIndex, listObj) => void, thisArg?: this): void;
 	keys(): IterableIterator<number>;
+	toString(): string;
 }


Test patch:
diff --git a/packages/happy-dom/test/dom-token-list/DOMTokenList.test.ts b/packages/happy-dom/test/dom-token-list/DOMTokenList.test.ts
index 327450cb..93b86467 100644
--- a/packages/happy-dom/test/dom-token-list/DOMTokenList.test.ts
+++ b/packages/happy-dom/test/dom-token-list/DOMTokenList.test.ts
@@ -203,4 +203,11 @@ describe('DOMTokenList', () => {
 			expect(Array.from(classList.keys())).toEqual([0, 1, 2]);
 		});
 	});
+
+	describe('toString()', () => {
+		it('Returns list value as string', () => {
+			element.className = 'class1 class2  class3';
+			expect(element.classList.toString()).toEqual('class1 class2  class3');
+		});
+	});
 });
Repository: capricorn86/happy-dom
Pull request #541 (2022-07-13 18:50:54)

add blob arrayBuffer()
https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer


Patch:
diff --git a/packages/happy-dom/src/file/Blob.ts b/packages/happy-dom/src/file/Blob.ts
index 7d48b800..bfcfe884 100644
--- a/packages/happy-dom/src/file/Blob.ts
+++ b/packages/happy-dom/src/file/Blob.ts
@@ -110,6 +110,20 @@ export default class Blob implements IBlob {
 		return blob;
 	}
 
+
+	/**
+	 * Returns a Promise that resolves to a ArrayBuffer.
+	 *
+	 * @returns ArrayBuffer.
+	 */
+
+	// Reference:
+	// https://github.com/web-std/io/blob/c88170bf24f064adfbb3586a21fb76650ca5a9ab/packages/blob/src/blob.js#L139-L148
+	// https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer
+	public async arrayBuffer(): Promise<ArrayBuffer> {
+		return new Uint8Array(this._buffer).buffer
+	}
+
 	/**
 	 * Returns a Promise that resolves to a text.
 	 *


Test patch:
diff --git a/packages/happy-dom/test/file/Blob.test.ts b/packages/happy-dom/test/file/Blob.test.ts
index 50f300ce..de5d205b 100644
--- a/packages/happy-dom/test/file/Blob.test.ts
+++ b/packages/happy-dom/test/file/Blob.test.ts
@@ -22,6 +22,20 @@ describe('Blob', () => {
 		});
 	});
 
+	// Reference:
+	// https://github.com/web-std/io/blob/c88170bf24f064adfbb3586a21fb76650ca5a9ab/packages/blob/test/blob.spec.js#L35-L44
+	describe('arrayBuffer()', () => {
+		it('Returns "Promise<ArrayBuffer>".', async () => {
+			const str = 'TEST';
+			const blob = new Blob([str]);
+			const buffer = await blob.arrayBuffer();
+			const result = new Uint8Array(buffer);
+			for (let i = 0; i < result.length; ++i) {
+				expect(result[i]).toBe(str[i].charCodeAt(0));
+			}
+		});
+	});
+
 	describe('toString()', () => {
 		it('Returns "[object Blob]".', () => {
 			const blob = new Blob(['TEST']);
Repository: capricorn86/happy-dom
Pull request #543 (2022-07-17 17:08:37)

#542@patch: Fix Response constructor issue.
Fixes https://github.com/capricorn86/happy-dom/issues/542


Patch:
diff --git a/packages/happy-dom/src/fetch/Response.ts b/packages/happy-dom/src/fetch/Response.ts
index 7ca26314..a368b466 100644
--- a/packages/happy-dom/src/fetch/Response.ts
+++ b/packages/happy-dom/src/fetch/Response.ts
@@ -13,9 +13,12 @@ export default class Response extends NodeFetch.Response implements IResponse {
 
 	/**
 	 * Constructor.
+	 *
+	 * @param [body] An object defining a body for the response (can be omitted)
+	 * @param [init] An options object containing any custom settings that you want to apply to the response, or an empty object (which is the default value)
 	 */
-	constructor() {
-		super();
+	constructor(body?: NodeFetch.BodyInit, init?: NodeFetch.ResponseInit) {
+		super(body, init);
 		this._ownerDocument = (<typeof Response>this.constructor)._ownerDocument;
 	}
 


Test patch:
diff --git a/packages/happy-dom/test/fetch/Response.test.ts b/packages/happy-dom/test/fetch/Response.test.ts
new file mode 100644
index 00000000..00862989
--- /dev/null
+++ b/packages/happy-dom/test/fetch/Response.test.ts
@@ -0,0 +1,22 @@
+import Response from '../../src/fetch/Response';
+import Window from '../../src/window/Window';
+
+jest.unmock('node-fetch');
+
+beforeAll(() => {
+	const window = new Window();
+	Response._ownerDocument = window.document;
+});
+
+afterAll(() => {
+	Response._ownerDocument = null;
+});
+
+describe('Response', () => {
+	it('Forwards constructor arguments to base implementation.', async () => {
+		const response = new Response('hello there', { status: 404 });
+
+		expect(response.status).toBe(404);
+		expect(await response.text()).toBe('hello there');
+	});
+});
Repository: capricorn86/happy-dom
Pull request #555 (2022-07-28 15:05:51)

#554@patch: Use current timestamp in requestAnimationFrame callback.
Use `performance.now()` to pass current timestamp and use test allowing for up to 0.1s drift between callback call and execution in test.


Patch:
diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts
index c70fadee..4f5df201 100644
--- a/packages/happy-dom/src/window/Window.ts
+++ b/packages/happy-dom/src/window/Window.ts
@@ -589,7 +589,7 @@ export default class Window extends EventTarget implements IWindow {
 	 */
 	public requestAnimationFrame(callback: (timestamp: number) => void): NodeJS.Timeout {
 		return this.setTimeout(() => {
-			callback(2);
+			callback(this.performance.now());
 		});
 	}
 


Test patch:
diff --git a/packages/happy-dom/test/window/Window.test.ts b/packages/happy-dom/test/window/Window.test.ts
index d2f02619..fceebab1 100644
--- a/packages/happy-dom/test/window/Window.test.ts
+++ b/packages/happy-dom/test/window/Window.test.ts
@@ -402,6 +402,13 @@ describe('Window', () => {
 			const timeoutId = window.requestAnimationFrame(() => done());
 			expect(timeoutId.constructor.name).toBe('Timeout');
 		});
+
+		it('Calls passed callback with current time', (done) => {
+			window.requestAnimationFrame((now) => {
+				expect(Math.abs(now - window.performance.now())).toBeLessThan(100);
+				done();
+			});
+		});
 	});
 
 	describe('cancelAnimationFrame()', () => {
Repository: capricorn86/happy-dom
Pull request #613 (2022-10-11 22:39:11)

#612@patch: Fixes issue related to sending in other types of values t…
…han string to CSSStyleDeclaration properties, causing the property parser to crash.


Patch:
diff --git a/packages/happy-dom/src/css/declaration/AbstractCSSStyleDeclaration.ts b/packages/happy-dom/src/css/declaration/AbstractCSSStyleDeclaration.ts
index 19895a36..af58ea6a 100644
--- a/packages/happy-dom/src/css/declaration/AbstractCSSStyleDeclaration.ts
+++ b/packages/happy-dom/src/css/declaration/AbstractCSSStyleDeclaration.ts
@@ -129,7 +129,9 @@ export default abstract class AbstractCSSStyleDeclaration {
 			return;
 		}
 
-		if (!value) {
+		const stringValue = String(value);
+
+		if (!stringValue) {
 			this.removeProperty(name);
 		} else if (this._ownerElement) {
 			if (!this._ownerElement['_attributes']['style']) {
@@ -139,7 +141,7 @@ export default abstract class AbstractCSSStyleDeclaration {
 			}
 
 			const style = this._elementStyle.getElementStyle();
-			style.set(name, value, !!priority);
+			style.set(name, stringValue, !!priority);
 
 			if (this._ownerElement.isConnected) {
 				this._ownerElement.ownerDocument['_cacheID']++;
@@ -147,7 +149,7 @@ export default abstract class AbstractCSSStyleDeclaration {
 
 			this._ownerElement['_attributes']['style'].value = style.toString();
 		} else {
-			this._style.set(name, value, !!priority);
+			this._style.set(name, stringValue, !!priority);
 		}
 	}
 


Test patch:
diff --git a/packages/happy-dom/test/css/declaration/CSSStyleDeclaration.test.ts b/packages/happy-dom/test/css/declaration/CSSStyleDeclaration.test.ts
index 5db6b0f4..1d3a1302 100644
--- a/packages/happy-dom/test/css/declaration/CSSStyleDeclaration.test.ts
+++ b/packages/happy-dom/test/css/declaration/CSSStyleDeclaration.test.ts
@@ -1586,6 +1586,10 @@ describe('CSSStyleDeclaration', () => {
 			element.setAttribute('style', 'top: fit-content(20em)');
 
 			expect(declaration.top).toBe('fit-content(20em)');
+
+			(<number>(<unknown>declaration.top)) = 0;
+
+			expect(declaration.top).toBe('0px');
 		});
 	});
 
@@ -2065,6 +2069,18 @@ describe('CSSStyleDeclaration', () => {
 			);
 		});
 
+		it('Handles when value is a number.', () => {
+			const declaration = new CSSStyleDeclaration(element);
+
+			declaration.setProperty('top', <string>(<unknown>1));
+
+			expect(element.getAttribute('style')).toBe('');
+
+			declaration.setProperty('top', <string>(<unknown>0));
+
+			expect(element.getAttribute('style')).toBe('top: 0px;');
+		});
+
 		it('Removes style attribute on element if empty value is sent', () => {
 			const declaration = new CSSStyleDeclaration(element);
Repository: capricorn86/happy-dom
Pull request #625 (2022-10-18 02:03:07)

#622@patch: Fix Element.matches failing when using non-matching desce…
…ndant selector on element detached from document.

Fixes second issue reported under #622


Patch:
diff --git a/packages/happy-dom/src/query-selector/QuerySelector.ts b/packages/happy-dom/src/query-selector/QuerySelector.ts
index b0c70202..7bf78ad8 100644
--- a/packages/happy-dom/src/query-selector/QuerySelector.ts
+++ b/packages/happy-dom/src/query-selector/QuerySelector.ts
@@ -106,7 +106,14 @@ export default class QuerySelector {
 		const selector = new SelectorItem(selectorParts[0]);
 		const result = selector.match(<IElement>currentNode);
 
-		if ((targetNode === currentNode || !currentNode.parentElement) && !result.matches) {
+		if (result.matches && selectorParts.length === 1) {
+			return {
+				priorityWeight: priorityWeight + result.priorityWeight,
+				matches: true
+			};
+		}
+
+		if (!currentNode.parentElement || (targetNode === currentNode && !result.matches)) {
 			return { priorityWeight: 0, matches: false };
 		}
 


Test patch:
diff --git a/packages/happy-dom/test/nodes/element/Element.test.ts b/packages/happy-dom/test/nodes/element/Element.test.ts
index 0d6b551a..f35e87e1 100644
--- a/packages/happy-dom/test/nodes/element/Element.test.ts
+++ b/packages/happy-dom/test/nodes/element/Element.test.ts
@@ -713,6 +713,19 @@ describe('Element', () => {
 			expect(element.matches('.nonexistent-class div.active')).toBe(false);
 		});
 
+		it('Checks if a detached element matches with a descendant combinator', () => {
+			const parentElement = document.createElement('div');
+			parentElement.setAttribute('role', 'status');
+
+			const element = document.createElement('div');
+			element.className = 'active';
+			parentElement.appendChild(element);
+
+			expect(element.matches('div[role="status"] div.active')).toBe(true);
+			expect(element.matches('div[role="article"] div.active')).toBe(false);
+			expect(parentElement.matches('.nonexistent-class div[role="status"]')).toBe(false);
+		});
+
 		it('Checks if the element matches with a child combinator', () => {
 			const grandparentElement = document.createElement('div');
 			grandparentElement.setAttribute('role', 'alert');
@@ -727,6 +740,7 @@ describe('Element', () => {
 
 			expect(element.matches('div[role="status"] > div.active')).toBe(true);
 			expect(element.matches('div[role="alert"] > div.active')).toBe(false);
+			expect(grandparentElement.matches('div > div[role="alert"]')).toBe(false);
 		});
 	});
Repository: capricorn86/happy-dom
Pull request #649 (2022-11-07 13:13:20)

#648@patch: OptionElement.value returns `textContent` as fallback.
Proposed fix for #648 



Patch:
diff --git a/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts b/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts
index a692e5e0..8a56a4c9 100644
--- a/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts
+++ b/packages/happy-dom/src/nodes/html-option-element/HTMLOptionElement.ts
@@ -109,7 +109,7 @@ export default class HTMLOptionElement extends HTMLElement implements IHTMLOptio
 	 * @returns Value.
 	 */
 	public get value(): string {
-		return this.getAttributeNS(null, 'value') || '';
+		return this.getAttributeNS(null, 'value') || this.textContent;
 	}
 
 	/**


Test patch:
diff --git a/packages/happy-dom/test/nodes/html-option-element/HTMLOptionElement.test.ts b/packages/happy-dom/test/nodes/html-option-element/HTMLOptionElement.test.ts
index dc876963..679435e8 100644
--- a/packages/happy-dom/test/nodes/html-option-element/HTMLOptionElement.test.ts
+++ b/packages/happy-dom/test/nodes/html-option-element/HTMLOptionElement.test.ts
@@ -25,6 +25,12 @@ describe('HTMLOptionElement', () => {
 			element.setAttribute('value', 'VALUE');
 			expect(element.value).toBe('VALUE');
 		});
+
+		it('Returns the text IDL value if no attribute is present.', () => {
+			element.removeAttribute('value');
+			element.textContent = 'TEXT VALUE';
+			expect(element.value).toBe('TEXT VALUE');
+		});
 	});
 
 	describe('set value()', () => {
Repository: capricorn86/happy-dom
Pull request #865 (2023-04-17 06:42:13)

#0@minor: Contains parameter support null.


Patch:
diff --git a/packages/happy-dom/src/nodes/node/INode.ts b/packages/happy-dom/src/nodes/node/INode.ts
index 4a514b3d..eb5e17a0 100644
--- a/packages/happy-dom/src/nodes/node/INode.ts
+++ b/packages/happy-dom/src/nodes/node/INode.ts
@@ -42,7 +42,7 @@ export default interface INode extends IEventTarget {
 	appendChild(node: INode): INode;
 	removeChild(node: INode): INode;
 	hasChildNodes(): boolean;
-	contains(otherNode: INode): boolean;
+	contains(otherNode: INode | null): boolean;
 	insertBefore(newNode: INode, referenceNode?: INode | null): INode;
 	replaceChild(newChild: INode, oldChild: INode): INode;
 	toString(): string;
diff --git a/packages/happy-dom/src/nodes/node/Node.ts b/packages/happy-dom/src/nodes/node/Node.ts
index c7a7cd8a..4f7a4633 100644
--- a/packages/happy-dom/src/nodes/node/Node.ts
+++ b/packages/happy-dom/src/nodes/node/Node.ts
@@ -250,7 +250,7 @@ export default class Node extends EventTarget implements INode {
 	 * @param otherNode Node to test with.
 	 * @returns "true" if this node contains the other node.
 	 */
-	public contains(otherNode: INode): boolean {
+	public contains(otherNode: INode | null): boolean {
 		return NodeUtility.contains(this, otherNode);
 	}
 
diff --git a/packages/happy-dom/src/nodes/node/NodeUtility.ts b/packages/happy-dom/src/nodes/node/NodeUtility.ts
index 77daf6c0..1833fbd7 100644
--- a/packages/happy-dom/src/nodes/node/NodeUtility.ts
+++ b/packages/happy-dom/src/nodes/node/NodeUtility.ts
@@ -30,7 +30,15 @@ export default class NodeUtility {
 	 * @param [includeShadowRoots = false] Include shadow roots.
 	 * @returns "true" if this node contains the other node.
 	 */
-	public static contains(rootNode: INode, otherNode: INode, includeShadowRoots = false): boolean {
+	public static contains(
+		rootNode: INode,
+		otherNode: INode | null,
+		includeShadowRoots = false
+	): boolean {
+		if (otherNode === null) {
+			return false;
+		}
+
 		if (rootNode === otherNode) {
 			return true;
 		}


Test patch:
diff --git a/packages/happy-dom/test/nodes/node/Node.test.ts b/packages/happy-dom/test/nodes/node/Node.test.ts
index 0ec7ffb1..deb2810c 100644
--- a/packages/happy-dom/test/nodes/node/Node.test.ts
+++ b/packages/happy-dom/test/nodes/node/Node.test.ts
@@ -297,6 +297,12 @@ describe('Node', () => {
 
 			expect(div.contains(text)).toBe(true);
 		});
+
+		it('Returns "false" if match node is null.', () => {
+			const div = document.createElement('div');
+
+			expect(div.contains(null)).toBe(false);
+		});
 	});
 
 	describe('getRootNode()', () => {
Repository: capricorn86/happy-dom
Pull request #879 (2023-04-29 22:24:23)

#877@patch: Adds support for using escaped characters to ID:s in quer…
…y selectors (e.g. "#\:id").


Patch:
diff --git a/packages/happy-dom/src/query-selector/SelectorParser.ts b/packages/happy-dom/src/query-selector/SelectorParser.ts
index 5923e319..e2201c8f 100644
--- a/packages/happy-dom/src/query-selector/SelectorParser.ts
+++ b/packages/happy-dom/src/query-selector/SelectorParser.ts
@@ -18,7 +18,7 @@ import DOMException from '../exception/DOMException';
  * Group 11: Combinator.
  */
 const SELECTOR_REGEXP =
-	/(\*)|([a-zA-Z0-9-]+)|#([a-zA-Z0-9-_]+)|\.((?:[a-zA-Z0-9-_]|\\.)+)|\[([a-zA-Z0-9-_]+)\]|\[([a-zA-Z0-9-_]+)([~|^$*]{0,1}) *= *["']{0,1}([^"']+)["']{0,1}\]|:([a-zA-Z-:]+)|\(([^)]+)\)|([ ,+>]*)/g;
+	/(\*)|([a-zA-Z0-9-]+)|#((?:[a-zA-Z0-9-_]|\\.)+)|\.((?:[a-zA-Z0-9-_]|\\.)+)|\[([a-zA-Z0-9-_]+)\]|\[([a-zA-Z0-9-_]+)([~|^$*]{0,1}) *= *["']{0,1}([^"']+)["']{0,1}\]|:([a-zA-Z-:]+)|\(([^)]+)\)|([ ,+>]*)/g;
 
 /**
  * Escaped Character RegExp.
@@ -85,7 +85,7 @@ export default class SelectorParser {
 				} else if (match[2]) {
 					currentSelectorItem.tagName = match[2].toUpperCase();
 				} else if (match[3]) {
-					currentSelectorItem.id = match[3];
+					currentSelectorItem.id = match[3].replace(CLASS_ESCAPED_CHARACTER_REGEXP, '');
 				} else if (match[4]) {
 					currentSelectorItem.classNames = currentSelectorItem.classNames || [];
 					currentSelectorItem.classNames.push(match[4].replace(CLASS_ESCAPED_CHARACTER_REGEXP, ''));


Test patch:
diff --git a/packages/happy-dom/test/query-selector/QuerySelector.test.ts b/packages/happy-dom/test/query-selector/QuerySelector.test.ts
index 47761118..b73a2b0f 100644
--- a/packages/happy-dom/test/query-selector/QuerySelector.test.ts
+++ b/packages/happy-dom/test/query-selector/QuerySelector.test.ts
@@ -914,7 +914,17 @@ describe('QuerySelector', () => {
 			div2.id = 'id';
 			div.appendChild(div2);
 
-			expect(div.querySelector('#id')).toEqual(div2);
+			expect(div.querySelector('#id') === div2).toBe(true);
+		});
+
+		it('Returns an element by id matching "#:id:".', () => {
+			const div = document.createElement('div');
+			const div2 = document.createElement('div');
+
+			div2.id = ':id:';
+			div.appendChild(div2);
+
+			expect(div.querySelector('#\\:id\\:') === div2).toBe(true);
 		});
 
 		it('Does not find input with selector of input:not([list])[type="search"]', () => {