Skip to content

Commit

Permalink
#450@trivial: Continue on Range implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
capricorn86 committed Jun 8, 2022
1 parent 327eeb9 commit d212611
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 28 deletions.
14 changes: 8 additions & 6 deletions packages/happy-dom/src/nodes/node/INode.ts
Expand Up @@ -2,14 +2,16 @@ import IEventTarget from '../../event/IEventTarget';
import IDocument from '../document/IDocument';
import IElement from '../element/IElement';
import INodeList from './INodeList';
import NodeTypeEnum from './NodeTypeEnum';

export default interface INode extends IEventTarget {
readonly ELEMENT_NODE: number;
readonly TEXT_NODE: number;
readonly COMMENT_NODE: number;
readonly DOCUMENT_NODE: number;
readonly DOCUMENT_TYPE_NODE: number;
readonly DOCUMENT_FRAGMENT_NODE: number;
readonly ELEMENT_NODE: NodeTypeEnum;
readonly TEXT_NODE: NodeTypeEnum;
readonly COMMENT_NODE: NodeTypeEnum;
readonly DOCUMENT_NODE: NodeTypeEnum;
readonly DOCUMENT_TYPE_NODE: NodeTypeEnum;
readonly DOCUMENT_FRAGMENT_NODE: NodeTypeEnum;
readonly PROCESSING_INSTRUCTION_NODE: NodeTypeEnum;
readonly ownerDocument: IDocument;
readonly parentNode: INode;
readonly parentElement: IElement;
Expand Down
27 changes: 15 additions & 12 deletions packages/happy-dom/src/nodes/node/Node.ts
Expand Up @@ -10,25 +10,28 @@ import IElement from '../element/IElement';
import IHTMLBaseElement from '../html-base-element/IHTMLBaseElement';
import INodeList from './INodeList';
import NodeListFactory from './NodeListFactory';
import NodeTypeEnum from './NodeTypeEnum';

/**
* Node.
*/
export default class Node extends EventTarget implements INode {
// Public properties
public static readonly ELEMENT_NODE = 1;
public static readonly TEXT_NODE = 3;
public static readonly COMMENT_NODE = 8;
public static readonly DOCUMENT_NODE = 9;
public static readonly DOCUMENT_TYPE_NODE = 10;
public static readonly DOCUMENT_FRAGMENT_NODE = 11;
public static readonly ELEMENT_NODE = NodeTypeEnum.elementNode;
public static readonly TEXT_NODE = NodeTypeEnum.textNode;
public static readonly COMMENT_NODE = NodeTypeEnum.commentNode;
public static readonly DOCUMENT_NODE = NodeTypeEnum.documentNode;
public static readonly DOCUMENT_TYPE_NODE = NodeTypeEnum.documentTypeNode;
public static readonly DOCUMENT_FRAGMENT_NODE = NodeTypeEnum.documentFragmentNode;
public static readonly PROCESSING_INSTRUCTION_NODE = NodeTypeEnum.processingInstructionNode;
public static ownerDocument: IDocument = null;
public readonly ELEMENT_NODE = 1;
public readonly TEXT_NODE = 3;
public readonly COMMENT_NODE = 8;
public readonly DOCUMENT_NODE = 9;
public readonly DOCUMENT_TYPE_NODE = 10;
public readonly DOCUMENT_FRAGMENT_NODE = 11;
public readonly ELEMENT_NODE = NodeTypeEnum.elementNode;
public readonly TEXT_NODE = NodeTypeEnum.textNode;
public readonly COMMENT_NODE = NodeTypeEnum.commentNode;
public readonly DOCUMENT_NODE = NodeTypeEnum.documentNode;
public readonly DOCUMENT_TYPE_NODE = NodeTypeEnum.documentTypeNode;
public readonly DOCUMENT_FRAGMENT_NODE = NodeTypeEnum.documentFragmentNode;
public readonly PROCESSING_INSTRUCTION_NODE = NodeTypeEnum.processingInstructionNode;
public readonly ownerDocument: IDocument = null;
public readonly parentNode: INode = null;
public readonly nodeType: number;
Expand Down
11 changes: 11 additions & 0 deletions packages/happy-dom/src/nodes/node/NodeTypeEnum.ts
@@ -0,0 +1,11 @@
enum NodeTypeEnum {
elementNode = 1,
textNode = 3,
commentNode = 8,
documentNode = 9,
documentTypeNode = 10,
documentFragmentNode = 11,
processingInstructionNode = 7
}

export default NodeTypeEnum;
39 changes: 36 additions & 3 deletions packages/happy-dom/src/nodes/node/NodeUtility.ts
@@ -1,4 +1,7 @@
import IText from '../text/IText';
import IComment from '../comment/IComment';
import INode from './INode';
import NodeTypeEnum from './NodeTypeEnum';

/**
* Node utility.
Expand Down Expand Up @@ -32,14 +35,44 @@ export default class NodeUtility {
* @returns "true" if following.
*/
public static isFollowing(nodeA: INode, nodeB: INode): boolean {
let current: INode = nodeA.nextSibling;
if (nodeA === nodeB) {
return false;
}

let current: INode = nodeB;

while (current) {
if (current === nodeB) {
const nextSibling = current.nextSibling;

if (nextSibling === nodeA) {
return true;
}
const nextSibling = current.nextSibling;

current = nextSibling ? nextSibling : current.parentNode;
}

return false;
}

/**
* Node length.
*
* @see https://dom.spec.whatwg.org/#concept-node-length
* @param node Node.
* @returns Node length.
*/
public static getNodeLength(node: INode): number {
switch (node.nodeType) {
case NodeTypeEnum.documentTypeNode:
return 0;

case NodeTypeEnum.textNode:
case NodeTypeEnum.processingInstructionNode:
case NodeTypeEnum.commentNode:
return (<IText | IComment>node).data.length;

default:
return node.childNodes.length;
}
}
}
79 changes: 73 additions & 6 deletions packages/happy-dom/src/range/Range.ts
Expand Up @@ -6,6 +6,8 @@ import RangeHowEnum from './RangeHowEnum';
import DOMException from '../exception/DOMException';
import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum';
import RangeUtility from './RangeUtility';
import NodeTypeEnum from '../nodes/node/NodeTypeEnum';
import NodeUtility from '../nodes/node/NodeUtility';

/**
* Range.
Expand Down Expand Up @@ -161,12 +163,47 @@ export default class Range {
/**
* Returns -1, 0, or 1 depending on whether the referenceNode is before, the same as, or after the Range.
*
* @param _referenceNode Reference node.
* @param [_offset=0] Offset.
* @param referenceNode Reference node.
* @param offset Offset.
* @returns -1,0, or 1.
*/
public comparePoint(_referenceNode: INode, _offset = 0): number {
// TODO: Implement
public comparePoint(referenceNode: INode, offset): number {
if (referenceNode.ownerDocument !== this._ownerDocument) {
throw new DOMException(
`The two Ranges are not in the same tree.`,
DOMExceptionNameEnum.wrongDocumentError
);
}

if (referenceNode.nodeType === NodeTypeEnum.documentTypeNode) {
throw new DOMException(
`DocumentType Node can't be used as boundary point.`,
DOMExceptionNameEnum.invalidNodeTypeError
);
}

if (offset > NodeUtility.getNodeLength(referenceNode)) {
throw new DOMException(`'Offset out of bound.`, DOMExceptionNameEnum.indexSizeError);
}

const boundaryPoint = { node: referenceNode, offset };

if (
RangeUtility.compareBoundaryPointsPosition(boundaryPoint, {
node: this.startContainer,
offset: this.startOffset
}) === -1
) {
return -1;
} else if (
RangeUtility.compareBoundaryPointsPosition(boundaryPoint, {
node: this.endContainer,
offset: this.endOffset
}) === 1
) {
return 1;
}

return 0;
}

Expand Down Expand Up @@ -324,14 +361,29 @@ export default class Range {
);
}
if (
endNode.nodeType !== endNode.TEXT_NODE &&
endNode.nodeType !== NodeTypeEnum.textNode &&
endOffset > 0 &&
endNode.childNodes.length < endOffset
) {
throw new DOMException(
`Failed to execute 'setEnd' on 'Range': There is no child at offset ${endOffset}.`
);
}
if (
endNode.ownerDocument !== this._ownerDocument ||
RangeUtility.compareBoundaryPointsPosition(
{
node: endNode,
offset: endOffset
},
{
node: this.startContainer,
offset: this.startOffset
}
) === -1
) {
this.setStart(endNode, endOffset);
}
(<INode>this.endContainer) = endNode;
(<number>this.endOffset) = endOffset;
}
Expand All @@ -349,14 +401,29 @@ export default class Range {
);
}
if (
startNode.nodeType !== startNode.TEXT_NODE &&
startNode.nodeType !== NodeTypeEnum.textNode &&
startOffset > 0 &&
startNode.childNodes.length < startOffset
) {
throw new DOMException(
`Failed to execute 'setStart' on 'Range': There is no child at offset ${startOffset}.`
);
}
if (
startNode.ownerDocument !== this._ownerDocument ||
RangeUtility.compareBoundaryPointsPosition(
{
node: startNode,
offset: startOffset
},
{
node: this.endContainer,
offset: this.endOffset
}
) === 1
) {
this.setEnd(startNode, startOffset);
}
(<INode>this.startContainer) = startNode;
(<number>this.startOffset) = startOffset;
}
Expand Down
30 changes: 29 additions & 1 deletion packages/happy-dom/test/range/Range.test.ts
Expand Up @@ -153,7 +153,7 @@ describe('Range', () => {
range.collapse(true);

expect(range.startContainer === span.childNodes[0]).toBe(true);
expect(range.endContainer === span.childNodes[0]).toBe(true);
expect(range.endContainer === span2.childNodes[0]).toBe(true);
expect(range.startOffset).toBe(1);
expect(range.endOffset).toBe(1);
expect(range.collapsed).toBe(true);
Expand Down Expand Up @@ -223,4 +223,32 @@ describe('Range', () => {
expect(range.compareBoundaryPoints(Range.START_TO_END, sourceRange)).toBe(0);
});
});

describe('comparePoint()', () => {
it('Returns 1 when referenceNode is after range.', () => {
const container = document.createElement('div');

container.innerHTML = `
<div>This is the Range 1 Content</div>
<div>This is the Range 2 Content</div>
`;

range.selectNode(container.children[0]);

expect(range.comparePoint(container.children[1], 0)).toBe(1);
});

it('Returns -1 when referenceNode is before range.', () => {
const container = document.createElement('div');

container.innerHTML = `
<div>This is the Range 1 Content</div>
<div>This is the Range 2 Content</div>
`;

range.selectNode(container.children[1]);

expect(range.comparePoint(container.children[0], 0)).toBe(-1);
});
});
});

0 comments on commit d212611

Please sign in to comment.