Repository: capricorn86/happy-dom
Pull request #760 (2023-02-16 19:12:54)

#759@patch: Spurious HTML comments in embedded scripts.
Solves #759, added test case in `DOMParser.test.ts`.


Patch:
diff --git a/packages/happy-dom/src/config/PlainTextElements.ts b/packages/happy-dom/src/config/PlainTextElements.ts
new file mode 100644
index 00000000..dc5606eb
--- /dev/null
+++ b/packages/happy-dom/src/config/PlainTextElements.ts
@@ -0,0 +1,1 @@
+export default ['style', 'script'];
diff --git a/packages/happy-dom/src/xml-parser/XMLParser.ts b/packages/happy-dom/src/xml-parser/XMLParser.ts
index 9cb8e787..fc704af0 100755
--- a/packages/happy-dom/src/xml-parser/XMLParser.ts
+++ b/packages/happy-dom/src/xml-parser/XMLParser.ts
@@ -11,6 +11,7 @@ import INode from '../nodes/node/INode';
 import IElement from '../nodes/element/IElement';
 import HTMLLinkElement from '../nodes/html-link-element/HTMLLinkElement';
 import IDocumentFragment from '../nodes/document-fragment/IDocumentFragment';
+import PlainTextElements from '../config/PlainTextElements';
 
 const MARKUP_REGEXP = /<(\/?)([a-z][-.0-9_a-z]*)\s*([^<>]*?)(\/?)>/gi;
 const COMMENT_REGEXP = /<!--(.*?)-->|<([!?])([^>]*)>/gi;
@@ -38,6 +39,7 @@ export default class XMLParser {
 		const stack: Array<IElement | IDocumentFragment> = [root];
 		const markupRegexp = new RegExp(MARKUP_REGEXP, 'gi');
 		let parent: IDocumentFragment | IElement = root;
+		let parentTagName = null;
 		let parentUnnestableTagName = null;
 		let lastTextIndex = 0;
 		let match: RegExpExecArray;
@@ -51,7 +53,11 @@ export default class XMLParser {
 
 				if (parent && match.index !== lastTextIndex) {
 					const text = data.substring(lastTextIndex, match.index);
-					this.appendTextAndCommentNodes(document, parent, text);
+					if (parentTagName && PlainTextElements.includes(parentTagName)) {
+						parent.appendChild(document.createTextNode(text));
+					} else {
+						this.appendTextAndCommentNodes(document, parent, text);
+					}
 				}
 
 				if (isStartTag) {
@@ -84,6 +90,7 @@ export default class XMLParser {
 						}
 
 						parent = <Element>parent.appendChild(newElement);
+						parentTagName = tagName;
 						parentUnnestableTagName = this.getUnnestableTagName(parent);
 						stack.push(parent);
 					} else {
@@ -105,6 +112,9 @@ export default class XMLParser {
 				} else {
 					stack.pop();
 					parent = stack[stack.length - 1] || root;
+					parentTagName = (<IElement>parent).tagName
+						? (<IElement>parent).tagName.toLowerCase()
+						: null;
 					parentUnnestableTagName = this.getUnnestableTagName(parent);
 
 					lastTextIndex = markupRegexp.lastIndex;


Test patch:
diff --git a/packages/happy-dom/test/dom-parser/DOMParser.test.ts b/packages/happy-dom/test/dom-parser/DOMParser.test.ts
index e662a789..213697b9 100644
--- a/packages/happy-dom/test/dom-parser/DOMParser.test.ts
+++ b/packages/happy-dom/test/dom-parser/DOMParser.test.ts
@@ -7,7 +7,14 @@ describe('DOMParser', () => {
 	let window;
 
 	beforeEach(() => {
-		window = new Window();
+		window = new Window({
+			settings: {
+				disableJavaScriptFileLoading: true,
+				disableJavaScriptEvaluation: true,
+				disableCSSFileLoading: true,
+				enableFileSystemHttpRequests: false
+			}
+		});
 		domParser = new window.DOMParser();
 	});
 
@@ -55,5 +62,28 @@ describe('DOMParser', () => {
 				`.replace(/[\s]/gm, '')
 			);
 		});
+
+		it('Correctly parses JS script w/ `<!` in it', () => {
+			const newDocument = domParser.parseFromString(
+				`<html>
+					<body>
+						<script>
+							var test = {className:"meta",begin:/<![a-z]/,end:/>/,contains:[t,i,l,c]};
+						</script>
+					</body>
+				</html>`,
+				'text/html'
+			);
+			// Spurious comment `<!--[a-z]/,end:/-->` should be solved
+			expect(new XMLSerializer().serializeToString(newDocument).replace(/\s{1,}/, ' ')).toBe(
+				`<html>
+					<body>
+						<script>
+							var test = {className:"meta",begin:/<![a-z]/,end:/>/,contains:[t,i,l,c]};
+						</script>
+					</body>
+				</html>`.replace(/\s{1,}/, ' ')
+			);
+		});
 	});
 });