Skip to content

Commit

Permalink
Merge pull request #844 from capricorn86/task/840-v9-not-support-name…
Browse files Browse the repository at this point in the history
…-attr-consisting-of-pure-numbers

Task/840 v9 not support name attr consisting of pure numbers
  • Loading branch information
capricorn86 committed Apr 7, 2023
2 parents fa2d574 + 523917a commit b1f8254
Show file tree
Hide file tree
Showing 18 changed files with 198 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import INodeList from '../node/INodeList';
*/
export default class DocumentFragment extends Node implements IDocumentFragment {
public nodeType = Node.DOCUMENT_FRAGMENT_NODE;
public readonly children: IHTMLCollection<IElement, IElement> = new HTMLCollection();
public readonly children: IHTMLCollection<IElement> = new HTMLCollection();
public _rootNode: INode = this;

/**
Expand Down
20 changes: 6 additions & 14 deletions packages/happy-dom/src/nodes/document/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ export default class Document extends Node implements IDocument {
public nodeType = Node.DOCUMENT_NODE;
public adoptedStyleSheets: CSSStyleSheet[] = [];
public implementation: DOMImplementation;
public readonly children: IHTMLCollection<IElement, IElement> = new HTMLCollection<
IElement,
IElement
>();
public readonly children: IHTMLCollection<IElement> = new HTMLCollection<IElement>();
public readonly readyState = DocumentReadyStateEnum.interactive;
public readonly isConnected: boolean = true;
public readonly defaultView: IWindow;
Expand Down Expand Up @@ -421,10 +418,8 @@ export default class Document extends Node implements IDocument {
*
* @returns Scripts.
*/
public get scripts(): IHTMLCollection<IHTMLScriptElement, IHTMLScriptElement> {
return <IHTMLCollection<IHTMLScriptElement, IHTMLScriptElement>>(
this.getElementsByTagName('script')
);
public get scripts(): IHTMLCollection<IHTMLScriptElement> {
return <IHTMLCollection<IHTMLScriptElement>>this.getElementsByTagName('script');
}

/**
Expand Down Expand Up @@ -538,7 +533,7 @@ export default class Document extends Node implements IDocument {
* @param className Tag name.
* @returns Matching element.
*/
public getElementsByClassName(className: string): IHTMLCollection<IElement, IElement> {
public getElementsByClassName(className: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByClassName(this, className);
}

Expand All @@ -548,7 +543,7 @@ export default class Document extends Node implements IDocument {
* @param tagName Tag name.
* @returns Matching element.
*/
public getElementsByTagName(tagName: string): IHTMLCollection<IElement, IElement> {
public getElementsByTagName(tagName: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByTagName(this, tagName);
}

Expand All @@ -559,10 +554,7 @@ export default class Document extends Node implements IDocument {
* @param tagName Tag name.
* @returns Matching element.
*/
public getElementsByTagNameNS(
namespaceURI: string,
tagName: string
): IHTMLCollection<IElement, IElement> {
public getElementsByTagNameNS(namespaceURI: string, tagName: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByTagNameNS(this, namespaceURI, tagName);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/happy-dom/src/nodes/document/IDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default interface IDocument extends IParentNode {
readonly doctype: IDocumentType;
readonly body: IHTMLElement;
readonly head: IHTMLElement;
readonly scripts: IHTMLCollection<IHTMLScriptElement, IHTMLScriptElement>;
readonly scripts: IHTMLCollection<IHTMLScriptElement>;
readonly activeElement: IHTMLElement;
readonly styleSheets: CSSStyleSheet[];
readonly scrollingElement: IHTMLElement;
Expand Down
27 changes: 13 additions & 14 deletions packages/happy-dom/src/nodes/element/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default class Element extends Node implements IElement {

public scrollTop = 0;
public scrollLeft = 0;
public children: IHTMLCollection<IElement, IElement> = new HTMLCollection<IElement, IElement>();
public children: IHTMLCollection<IElement> = new HTMLCollection<IElement>();
public readonly namespaceURI: string = null;

// Events
Expand Down Expand Up @@ -778,7 +778,7 @@ export default class Element extends Node implements IElement {
* @param className Tag name.
* @returns Matching element.
*/
public getElementsByClassName(className: string): IHTMLCollection<IElement, IElement> {
public getElementsByClassName(className: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByClassName(this, className);
}

Expand All @@ -788,7 +788,7 @@ export default class Element extends Node implements IElement {
* @param tagName Tag name.
* @returns Matching element.
*/
public getElementsByTagName(tagName: string): IHTMLCollection<IElement, IElement> {
public getElementsByTagName(tagName: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByTagName(this, tagName);
}

Expand All @@ -799,10 +799,7 @@ export default class Element extends Node implements IElement {
* @param tagName Tag name.
* @returns Matching element.
*/
public getElementsByTagNameNS(
namespaceURI: string,
tagName: string
): IHTMLCollection<IElement, IElement> {
public getElementsByTagNameNS(namespaceURI: string, tagName: string): IHTMLCollection<IElement> {
return ParentNodeUtility.getElementsByTagNameNS(this, namespaceURI, tagName);
}

Expand Down Expand Up @@ -834,14 +831,16 @@ export default class Element extends Node implements IElement {
if (attribute.name === 'id' || attribute.name === 'name') {
if (this.parentNode && (<IElement>this.parentNode).children && attribute.value !== oldValue) {
if (oldValue) {
(<HTMLCollection<IElement, IElement>>(
(<IElement>this.parentNode).children
))._removeNamedItem(this, oldValue);
(<HTMLCollection<IElement>>(<IElement>this.parentNode).children)._removeNamedItem(
this,
oldValue
);
}
if (attribute.value) {
(<HTMLCollection<IElement, IElement>>(
(<IElement>this.parentNode).children
))._appendNamedItem(this, attribute.value);
(<HTMLCollection<IElement>>(<IElement>this.parentNode).children)._appendNamedItem(
this,
attribute.value
);
}
}
}
Expand Down Expand Up @@ -946,7 +945,7 @@ export default class Element extends Node implements IElement {

if (attribute.name === 'id' || attribute.name === 'name') {
if (this.parentNode && (<IElement>this.parentNode).children && attribute.value) {
(<HTMLCollection<IElement, IElement>>(<IElement>this.parentNode).children)._removeNamedItem(
(<HTMLCollection<IElement>>(<IElement>this.parentNode).children)._removeNamedItem(
this,
attribute.value
);
Expand Down
15 changes: 8 additions & 7 deletions packages/happy-dom/src/nodes/element/ElementUtility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ export default class ElementUtility {
if (index !== -1) {
for (const attribute of NAMED_ITEM_ATTRIBUTES) {
if ((<Element>node)._attributes[attribute]) {
(<HTMLCollection<IHTMLElement, IHTMLElement>>(
(<IElement>node.parentNode).children
))._removeNamedItem(<IHTMLElement>node, (<Element>node)._attributes[attribute].value);
(<HTMLCollection<IHTMLElement>>(<IElement>node.parentNode).children)._removeNamedItem(
<IHTMLElement>node,
(<Element>node)._attributes[attribute].value
);
}
}
(<IHTMLElement>node.parentNode).children.splice(index, 1);
Expand All @@ -40,7 +41,7 @@ export default class ElementUtility {

for (const attribute of NAMED_ITEM_ATTRIBUTES) {
if ((<Element>node)._attributes[attribute]) {
(<HTMLCollection<IHTMLElement, IHTMLElement>>parentElement.children)._appendNamedItem(
(<HTMLCollection<IHTMLElement>>parentElement.children)._appendNamedItem(
<IHTMLElement>node,
(<Element>node)._attributes[attribute].value
);
Expand All @@ -66,7 +67,7 @@ export default class ElementUtility {
if (index !== -1) {
for (const attribute of NAMED_ITEM_ATTRIBUTES) {
if ((<Element>node)._attributes[attribute]) {
(<HTMLCollection<IHTMLElement, IHTMLElement>>parentElement.children)._removeNamedItem(
(<HTMLCollection<IHTMLElement>>parentElement.children)._removeNamedItem(
<IHTMLElement>node,
(<Element>node)._attributes[attribute].value
);
Expand Down Expand Up @@ -96,7 +97,7 @@ export default class ElementUtility {
if (index !== -1) {
for (const attribute of NAMED_ITEM_ATTRIBUTES) {
if ((<Element>newNode)._attributes[attribute]) {
(<HTMLCollection<IHTMLElement, IHTMLElement>>(
(<HTMLCollection<IHTMLElement>>(
(<IElement>newNode.parentNode).children
))._removeNamedItem(
<IHTMLElement>newNode,
Expand Down Expand Up @@ -132,7 +133,7 @@ export default class ElementUtility {
if (referenceNode || referenceNode === null) {
for (const attribute of NAMED_ITEM_ATTRIBUTES) {
if ((<Element>newNode)._attributes[attribute]) {
(<HTMLCollection<IHTMLElement, IHTMLElement>>parentElement.children)._appendNamedItem(
(<HTMLCollection<IHTMLElement>>parentElement.children)._appendNamedItem(
<IHTMLElement>newNode,
(<Element>newNode)._attributes[attribute].value
);
Expand Down
31 changes: 21 additions & 10 deletions packages/happy-dom/src/nodes/element/HTMLCollection.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import IHTMLCollection from './IHTMLCollection';

/**
* Class list.
* HTML collection.
*/
export default class HTMLCollection<T, NamedItem>
extends Array
implements IHTMLCollection<T, NamedItem>
{
export default class HTMLCollection<T> extends Array implements IHTMLCollection<T> {
protected _namedItems: { [k: string]: T[] } = {};

/**
Expand All @@ -24,8 +21,10 @@ export default class HTMLCollection<T, NamedItem>
* @param name Name.
* @returns Node.
*/
public namedItem(name: string): NamedItem | null {
return this[name] || null;
public namedItem(name: string): T | null {
return this._namedItems[name] && this._namedItems[name].length
? this._namedItems[name][0]
: null;
}

/**
Expand All @@ -42,7 +41,7 @@ export default class HTMLCollection<T, NamedItem>
this._namedItems[name].push(node);
}

if (!this[name]) {
if (!this[name] && this._isValidPropertyName(name)) {
this[name] = this._namedItems[name][0];
}
}
Expand All @@ -63,11 +62,23 @@ export default class HTMLCollection<T, NamedItem>

if (this._namedItems[name].length === 0) {
delete this._namedItems[name];
delete this[name];
} else {
if (this._isValidPropertyName(name)) {
delete this[name];
}
} else if (this._isValidPropertyName(name)) {
this[name] = this._namedItems[name][0];
}
}
}
}

/**
* Returns "true" if the property name is valid.
*
* @param name Name.
* @returns True if the property name is valid.
*/
protected _isValidPropertyName(name: string): boolean {
return isNaN(Number(name)) || name.includes('.');
}
}
4 changes: 2 additions & 2 deletions packages/happy-dom/src/nodes/element/IHTMLCollection.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* HTMLCollection.
*/
export default interface IHTMLCollection<T, NamedItem> extends Array<T> {
export default interface IHTMLCollection<T> extends Array<T> {
/**
* Returns item by index.
*
Expand All @@ -15,5 +15,5 @@ export default interface IHTMLCollection<T, NamedItem> extends Array<T> {
* @param name Name.
* @returns Node.
*/
namedItem(name: string): NamedItem | null;
namedItem(name: string): T | null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,54 @@ import IHTMLFormControlsCollection from './IHTMLFormControlsCollection';
import IHTMLInputElement from '../html-input-element/IHTMLInputElement';
import IHTMLTextAreaElement from '../html-text-area-element/IHTMLTextAreaElement';
import IHTMLSelectElement from '../html-select-element/IHTMLSelectElement';
import HTMLCollection from '../element/HTMLCollection';
import RadioNodeList from './RadioNodeList';
import IHTMLButtonElement from '../html-button-element/IHTMLButtonElement';
import IRadioNodeList from './IRadioNodeList';

/**
* HTMLFormControlsCollection.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection
*/
export default class HTMLFormControlsCollection
extends HTMLCollection<
IHTMLInputElement | IHTMLTextAreaElement | IHTMLSelectElement | IHTMLButtonElement,
extends Array<IHTMLInputElement | IHTMLTextAreaElement | IHTMLSelectElement | IHTMLButtonElement>
implements IHTMLFormControlsCollection
{
public _namedItems: { [k: string]: RadioNodeList } = {};

/**
* Returns item by index.
*
* @param index Index.
*/
public item(
index: number
): IHTMLInputElement | IHTMLTextAreaElement | IHTMLSelectElement | IHTMLButtonElement | null {
return index >= 0 && this[index] ? this[index] : null;
}

/**
* Returns named item.
*
* @param name Name.
* @returns Node.
*/
public namedItem(
name: string
):
| IHTMLInputElement
| IHTMLTextAreaElement
| IHTMLSelectElement
| IHTMLButtonElement
| IRadioNodeList
>
implements IHTMLFormControlsCollection
{
public _namedItems: { [k: string]: RadioNodeList } = {};
| RadioNodeList
| null {
if (this._namedItems[name] && this._namedItems[name].length) {
if (this._namedItems[name].length === 1) {
return this._namedItems[name][0];
}
return this._namedItems[name];
}
return null;
}

/**
* Appends named item.
Expand All @@ -42,8 +68,10 @@ export default class HTMLFormControlsCollection
this._namedItems[name].push(node);
}

this[name] =
this._namedItems[name].length > 1 ? this._namedItems[name] : this._namedItems[name][0];
if (this._isValidPropertyName(name)) {
this[name] =
this._namedItems[name].length > 1 ? this._namedItems[name] : this._namedItems[name][0];
}
}
}

Expand All @@ -65,12 +93,24 @@ export default class HTMLFormControlsCollection

if (this._namedItems[name].length === 0) {
delete this._namedItems[name];
delete this[name];
} else {
if (this._isValidPropertyName(name)) {
delete this[name];
}
} else if (this._isValidPropertyName(name)) {
this[name] =
this._namedItems[name].length > 1 ? this._namedItems[name] : this._namedItems[name][0];
}
}
}
}

/**
* Returns "true" if the property name is valid.
*
* @param name Name.
* @returns True if the property name is valid.
*/
protected _isValidPropertyName(name: string): boolean {
return isNaN(Number(name)) || name.includes('.');
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import IHTMLCollection from '../element/IHTMLCollection';
import IHTMLButtonElement from '../html-button-element/IHTMLButtonElement';
import IHTMLInputElement from '../html-input-element/IHTMLInputElement';
import IHTMLSelectElement from '../html-select-element/IHTMLSelectElement';
Expand All @@ -11,13 +10,8 @@ import IRadioNodeList from './IRadioNodeList';
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection
*/
export default interface IHTMLFormControlsCollection
extends IHTMLCollection<
IHTMLInputElement | IHTMLTextAreaElement | IHTMLSelectElement | IHTMLButtonElement,
| IHTMLInputElement
| IHTMLTextAreaElement
| IHTMLSelectElement
| IHTMLButtonElement
| IRadioNodeList
extends Array<
IHTMLInputElement | IHTMLTextAreaElement | IHTMLSelectElement | IHTMLButtonElement
> {
/**
* Returns item by index.
Expand Down

0 comments on commit b1f8254

Please sign in to comment.