Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: capricorn86/happy-dom
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v10.10.4
Choose a base ref
...
head repository: capricorn86/happy-dom
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v10.11.0
Choose a head ref
  • 8 commits
  • 25 files changed
  • 2 contributors

Commits on Jul 2, 2023

  1. Copy the full SHA
    82e3ead View commit details

Commits on Jul 6, 2023

  1. Copy the full SHA
    23267c2 View commit details

Commits on Aug 22, 2023

  1. Copy the full SHA
    5203972 View commit details
  2. Copy the full SHA
    5d90360 View commit details
  3. Copy the full SHA
    3b120c0 View commit details
  4. #960@trivial: Fix introduced bug in ElementUtility.appendChild() and …

    …ElementUtility.insertBefore().
    capricorn86 committed Aug 22, 2023
    Copy the full SHA
    0b31097 View commit details
  5. Copy the full SHA
    28f9b72 View commit details
  6. Merge pull request #961 from edoardocavazza/master

    #960@minor: Implement childNodes and children as getters.
    capricorn86 authored Aug 22, 2023
    Copy the full SHA
    1f59807 View commit details
Showing with 326 additions and 222 deletions.
  1. +9 −7 packages/happy-dom/src/dom-parser/DOMParser.ts
  2. +10 −12 packages/happy-dom/src/nodes/child-node/ChildNodeUtility.ts
  3. +16 −9 packages/happy-dom/src/nodes/document-fragment/DocumentFragment.ts
  4. +29 −22 packages/happy-dom/src/nodes/document/Document.ts
  5. +23 −12 packages/happy-dom/src/nodes/element/Element.ts
  6. +5 −5 packages/happy-dom/src/nodes/element/ElementNamedNodeMap.ts
  7. +44 −43 packages/happy-dom/src/nodes/element/ElementUtility.ts
  8. +2 −2 packages/happy-dom/src/nodes/html-element/HTMLElement.ts
  9. +3 −3 packages/happy-dom/src/nodes/html-slot-element/HTMLSlotElement.ts
  10. +3 −2 packages/happy-dom/src/nodes/html-template-element/HTMLTemplateElement.ts
  11. +11 −11 packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts
  12. +30 −21 packages/happy-dom/src/nodes/node/Node.ts
  13. +21 −17 packages/happy-dom/src/nodes/node/NodeUtility.ts
  14. +10 −10 packages/happy-dom/src/nodes/parent-node/ParentNodeUtility.ts
  15. +2 −2 packages/happy-dom/src/nodes/shadow-root/ShadowRoot.ts
  16. +24 −8 packages/happy-dom/src/query-selector/QuerySelector.ts
  17. +15 −14 packages/happy-dom/src/query-selector/SelectorItem.ts
  18. +13 −12 packages/happy-dom/src/range/Range.ts
  19. +2 −1 packages/happy-dom/src/range/RangeUtility.ts
  20. +4 −4 packages/happy-dom/src/tree-walker/TreeWalker.ts
  21. +6 −4 packages/happy-dom/src/xml-serializer/XMLSerializer.ts
  22. +6 −0 packages/happy-dom/test/nodes/document-fragment/DocumentFragment.test.ts
  23. +7 −0 packages/happy-dom/test/nodes/document/Document.test.ts
  24. +8 −1 packages/happy-dom/test/nodes/element/Element.test.ts
  25. +23 −0 packages/happy-dom/test/nodes/node/Node.test.ts
16 changes: 9 additions & 7 deletions packages/happy-dom/src/dom-parser/DOMParser.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@ import HTMLDocument from '../nodes/html-document/HTMLDocument.js';
import XMLDocument from '../nodes/xml-document/XMLDocument.js';
import SVGDocument from '../nodes/svg-document/SVGDocument.js';
import IWindow from '../window/IWindow.js';
import Document from '../nodes/document/Document.js';
import DocumentFragment from '../nodes/document-fragment/DocumentFragment.js';

/**
* DOM parser.
@@ -38,17 +40,17 @@ export default class DOMParser {
}

const ownerDocument = this._ownerDocument;
const newDocument = this._createDocument(mimeType);
const newDocument = <Document>this._createDocument(mimeType);

(<IWindow>newDocument.defaultView) = ownerDocument.defaultView;
newDocument.childNodes.length = 0;
newDocument.children.length = 0;
newDocument._childNodes.length = 0;
newDocument._children.length = 0;

const root = XMLParser.parse(newDocument, string, { evaluateScripts: true });
const root = <DocumentFragment>XMLParser.parse(newDocument, string, { evaluateScripts: true });
let documentElement = null;
let documentTypeNode = null;

for (const node of root.childNodes) {
for (const node of root._childNodes) {
if (node['tagName'] === 'HTML') {
documentElement = node;
} else if (node.nodeType === Node.DOCUMENT_TYPE_NODE) {
@@ -67,7 +69,7 @@ export default class DOMParser {
newDocument.appendChild(documentElement);
const body = newDocument.body;
if (body) {
for (const child of root.childNodes.slice()) {
for (const child of root._childNodes.slice()) {
body.appendChild(child);
}
}
@@ -80,7 +82,7 @@ export default class DOMParser {
documentElement.appendChild(bodyElement);
newDocument.appendChild(documentElement);

for (const node of root.childNodes.slice()) {
for (const node of root._childNodes.slice()) {
bodyElement.appendChild(node);
}
}
22 changes: 10 additions & 12 deletions packages/happy-dom/src/nodes/child-node/ChildNodeUtility.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import DOMException from '../../exception/DOMException.js';
import XMLParser from '../../xml-parser/XMLParser.js';
import DocumentFragment from '../document-fragment/DocumentFragment.js';
import Document from '../document/Document.js';
import INode from '../node/INode.js';
import IParentNode from '../parent-node/IParentNode.js';
@@ -35,10 +36,9 @@ export default class ChildNodeUtility {

for (const node of nodes) {
if (typeof node === 'string') {
const newChildNodes = XMLParser.parse(
<Document>childNode.ownerDocument,
node
).childNodes.slice();
const newChildNodes = (<DocumentFragment>(
XMLParser.parse(<Document>childNode.ownerDocument, node)
))._childNodes.slice();
for (const newChildNode of newChildNodes) {
parent.insertBefore(newChildNode, childNode);
}
@@ -65,10 +65,9 @@ export default class ChildNodeUtility {

for (const node of nodes) {
if (typeof node === 'string') {
const newChildNodes = XMLParser.parse(
<Document>childNode.ownerDocument,
node
).childNodes.slice();
const newChildNodes = (<DocumentFragment>(
XMLParser.parse(<Document>childNode.ownerDocument, node)
))._childNodes.slice();
for (const newChildNode of newChildNodes) {
parent.insertBefore(newChildNode, childNode);
}
@@ -95,10 +94,9 @@ export default class ChildNodeUtility {

for (const node of nodes) {
if (typeof node === 'string') {
const newChildNodes = XMLParser.parse(
<Document>childNode.ownerDocument,
node
).childNodes.slice();
const newChildNodes = (<DocumentFragment>(
XMLParser.parse(<Document>childNode.ownerDocument, node)
))._childNodes.slice();
for (const newChildNode of newChildNodes) {
if (!nextSibling) {
parent.appendChild(newChildNode);
25 changes: 16 additions & 9 deletions packages/happy-dom/src/nodes/document-fragment/DocumentFragment.ts
Original file line number Diff line number Diff line change
@@ -14,16 +14,23 @@ import INodeList from '../node/INodeList.js';
*/
export default class DocumentFragment extends Node implements IDocumentFragment {
public nodeType = Node.DOCUMENT_FRAGMENT_NODE;
public readonly children: IHTMLCollection<IElement> = new HTMLCollection();
public readonly _children: IHTMLCollection<IElement> = new HTMLCollection();
public _rootNode: INode = this;

/**
* Returns the document fragment children.
*/
public get children(): IHTMLCollection<IElement> {
return this._children;
}

/**
* Last element child.
*
* @returns Element.
*/
public get childElementCount(): number {
return this.children.length;
return this._children.length;
}

/**
@@ -32,7 +39,7 @@ export default class DocumentFragment extends Node implements IDocumentFragment
* @returns Element.
*/
public get firstElementChild(): IElement {
return this.children ? this.children[0] || null : null;
return this._children[0] ?? null;
}

/**
@@ -41,7 +48,7 @@ export default class DocumentFragment extends Node implements IDocumentFragment
* @returns Element.
*/
public get lastElementChild(): IElement {
return this.children ? this.children[this.children.length - 1] || null : null;
return this._children[this._children.length - 1] ?? null;
}

/**
@@ -51,7 +58,7 @@ export default class DocumentFragment extends Node implements IDocumentFragment
*/
public get textContent(): string {
let result = '';
for (const childNode of this.childNodes) {
for (const childNode of this._childNodes) {
if (childNode.nodeType === Node.ELEMENT_NODE || childNode.nodeType === Node.TEXT_NODE) {
result += childNode.textContent;
}
@@ -65,7 +72,7 @@ export default class DocumentFragment extends Node implements IDocumentFragment
* @param textContent Text content.
*/
public set textContent(textContent: string) {
for (const child of this.childNodes.slice()) {
for (const child of this._childNodes.slice()) {
this.removeChild(child);
}
if (textContent) {
@@ -138,12 +145,12 @@ export default class DocumentFragment extends Node implements IDocumentFragment
* @returns Cloned node.
*/
public cloneNode(deep = false): IDocumentFragment {
const clone = <IDocumentFragment>super.cloneNode(deep);
const clone = <DocumentFragment>super.cloneNode(deep);

if (deep) {
for (const node of clone.childNodes) {
for (const node of clone._childNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
clone.children.push(<IElement>node);
clone._children.push(<IElement>node);
}
}
}
51 changes: 29 additions & 22 deletions packages/happy-dom/src/nodes/document/Document.ts
Original file line number Diff line number Diff line change
@@ -60,12 +60,12 @@ export default class Document extends Node implements IDocument {
public nodeType = Node.DOCUMENT_NODE;
public adoptedStyleSheets: CSSStyleSheet[] = [];
public implementation: DOMImplementation;
public readonly children: IHTMLCollection<IElement> = new HTMLCollection<IElement>();
public readonly readyState = DocumentReadyStateEnum.interactive;
public readonly isConnected: boolean = true;
public readonly defaultView: IWindow;
public readonly _windowClass: {} | null = null;
public readonly _readyStateManager: DocumentReadyStateManager;
public readonly _children: IHTMLCollection<IElement> = new HTMLCollection<IElement>();
public _activeElement: IHTMLElement = null;

// Used as an unique identifier which is updated whenever the DOM gets modified.
@@ -215,6 +215,13 @@ export default class Document extends Node implements IDocument {
documentElement.appendChild(bodyElement);
}

/**
* Returns document children.
*/
public get children(): IHTMLCollection<IElement> {
return this._children;
}

/**
* Returns character set.
*
@@ -276,7 +283,7 @@ export default class Document extends Node implements IDocument {
* @returns Element.
*/
public get childElementCount(): number {
return this.children.length;
return this._children.length;
}

/**
@@ -285,7 +292,7 @@ export default class Document extends Node implements IDocument {
* @returns Element.
*/
public get firstElementChild(): IElement {
return this.children ? this.children[0] || null : null;
return this._children[0] ?? null;
}

/**
@@ -294,7 +301,7 @@ export default class Document extends Node implements IDocument {
* @returns Element.
*/
public get lastElementChild(): IElement {
return this.children ? this.children[this.children.length - 1] || null : null;
return this._children[this._children.length - 1] ?? null;
}

/**
@@ -339,7 +346,7 @@ export default class Document extends Node implements IDocument {
* @returns Document type.
*/
public get doctype(): IDocumentType {
for (const node of this.childNodes) {
for (const node of this._childNodes) {
if (node instanceof DocumentType) {
return node;
}
@@ -588,22 +595,22 @@ export default class Document extends Node implements IDocument {
* @param name
*/
public getElementsByName(name: string): INodeList<IElement> {
const _getElementsByName = (
_parentNode: IElement | IDocumentFragment | IDocument,
_name: string
const getElementsByName = (
parentNode: IElement | IDocumentFragment | IDocument,
name: string
): INodeList<IElement> => {
const matches = new NodeList<IElement>();
for (const child of _parentNode.children) {
if (child.getAttributeNS(null, 'name') === _name) {
for (const child of (<Element | Document>parentNode)._children) {
if (child.getAttributeNS(null, 'name') === name) {
matches.push(child);
}
for (const match of _getElementsByName(<IElement>child, _name)) {
for (const match of getElementsByName(<IElement>child, name)) {
matches.push(match);
}
}
return matches;
};
return _getElementsByName(this, name);
return getElementsByName(this, name);
}

/**
@@ -619,9 +626,9 @@ export default class Document extends Node implements IDocument {
const clone = <Document>super.cloneNode(deep);

if (deep) {
for (const node of clone.childNodes) {
for (const node of clone._childNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
clone.children.push(<IElement>node);
clone._children.push(<IElement>node);
}
}
}
@@ -665,7 +672,7 @@ export default class Document extends Node implements IDocument {
* @param html HTML.
*/
public write(html: string): void {
const root = XMLParser.parse(this, html, { evaluateScripts: true });
const root = <DocumentFragment>XMLParser.parse(this, html, { evaluateScripts: true });

if (this._isFirstWrite || this._isFirstWriteAfterOpen) {
if (this._isFirstWrite) {
@@ -680,7 +687,7 @@ export default class Document extends Node implements IDocument {
let documentElement = null;
let documentTypeNode = null;

for (const node of root.childNodes) {
for (const node of root._childNodes) {
if (node['tagName'] === 'HTML') {
documentElement = node;
} else if (node.nodeType === NodeTypeEnum.documentTypeNode) {
@@ -700,10 +707,10 @@ export default class Document extends Node implements IDocument {

this.appendChild(documentElement);
} else {
const rootBody = ParentNodeUtility.getElementByTagName(root, 'body');
const rootBody = <Element>ParentNodeUtility.getElementByTagName(root, 'body');
const body = ParentNodeUtility.getElementByTagName(this, 'body');
if (rootBody && body) {
for (const child of rootBody.childNodes.slice()) {
for (const child of rootBody._childNodes.slice()) {
body.appendChild(child);
}
}
@@ -712,7 +719,7 @@ export default class Document extends Node implements IDocument {
// Remaining nodes outside the <html> element are added to the <body> element.
const body = ParentNodeUtility.getElementByTagName(this, 'body');
if (body) {
for (const child of root.childNodes.slice()) {
for (const child of root._childNodes.slice()) {
if (child['tagName'] !== 'HTML' && child.nodeType !== NodeTypeEnum.documentTypeNode) {
body.appendChild(child);
}
@@ -723,7 +730,7 @@ export default class Document extends Node implements IDocument {
const bodyElement = this.createElement('body');
const headElement = this.createElement('head');

for (const child of root.childNodes.slice()) {
for (const child of root._childNodes.slice()) {
bodyElement.appendChild(child);
}

@@ -735,7 +742,7 @@ export default class Document extends Node implements IDocument {
} else {
const bodyNode = ParentNodeUtility.getElementByTagName(root, 'body');
const body = ParentNodeUtility.getElementByTagName(this, 'body');
for (const child of (bodyNode || root).childNodes.slice()) {
for (const child of (<Element>(bodyNode || root))._childNodes.slice()) {
body.appendChild(child);
}
}
@@ -758,7 +765,7 @@ export default class Document extends Node implements IDocument {
}
}

for (const child of this.childNodes.slice()) {
for (const child of this._childNodes.slice()) {
this.removeChild(child);
}

Loading