From aa1cb4645a5a891e7a76cbd812fc112ac3e0d91c Mon Sep 17 00:00:00 2001 From: Thanos Date: Sat, 10 Apr 2021 17:31:37 +0200 Subject: [PATCH 1/3] treewalker implementation --- .gitignore | 1 + src/dom/document.ts | 12 ++- src/dom/node-filter.ts | 26 ++++++ src/dom/node.ts | 10 +-- src/dom/traverser.ts | 41 +++++++++ src/dom/treewalker.ts | 196 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 278 insertions(+), 8 deletions(-) create mode 100644 src/dom/node-filter.ts create mode 100644 src/dom/traverser.ts create mode 100644 src/dom/treewalker.ts diff --git a/.gitignore b/.gitignore index a690cc0..25f09b5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules /target *~ /.vim +/.vscode diff --git a/src/dom/document.ts b/src/dom/document.ts index e432f96..35b9b75 100644 --- a/src/dom/document.ts +++ b/src/dom/document.ts @@ -1,7 +1,9 @@ import { setLock, getLock } from "../constructor-lock.ts"; import { Node, NodeType, Text, Comment } from "./node.ts"; import { NodeList, nodeListMutatorSym } from "./node-list.ts"; +import { Filter } from "./node-filter.ts"; import { Element } from "./element.ts"; +import { TreeWalker } from "./treewalker.ts" import { DOM as NWAPI } from "./nwsapi-types.ts"; export class DOMImplementation { @@ -165,6 +167,10 @@ export class Document extends Node { return child; } + createComment(data?: string): Comment { + return new Comment(data); + } + createElement(tagName: string, options?: ElementCreationOptions): Element { tagName = tagName.toUpperCase(); @@ -191,8 +197,8 @@ export class Document extends Node { return new Text(data); } - createComment(data?: string): Comment { - return new Comment(data); + createTreeWalker(root: Node, whatToShow?: number, filter?: Filter): TreeWalker { + return new TreeWalker(root, whatToShow, filter); } querySelector(selectors: string): Element | null { @@ -289,7 +295,7 @@ export class Document extends Node { export class HTMLDocument extends Document { constructor() { - let lock = getLock(); + const lock = getLock(); super(); if (lock) { diff --git a/src/dom/node-filter.ts b/src/dom/node-filter.ts new file mode 100644 index 0000000..fb9de63 --- /dev/null +++ b/src/dom/node-filter.ts @@ -0,0 +1,26 @@ +import { Node } from "./node.ts"; + +export abstract class NodeFilter { + static FILTER_ACCEPT = 1; + static FILTER_REJECT = 2; + static FILTER_SKIP = 3; + + // staticants for whatToShow + static SHOW_ALL = 0xFFFFFFFF; + static SHOW_ELEMENT = 0x1; + static SHOW_ATTRIBUTE = 0x2; + static SHOW_TEXT = 0x4; + static SHOW_CDATA_SECTION = 0x8; + static SHOW_ENTITY_REFERENCE = 0x10; // legacy + static SHOW_ENTITY = 0x20; // legacy + static SHOW_PROCESSING_INSTRUCTION = 0x40; + static SHOW_COMMENT = 0x80; + static SHOW_DOCUMENT = 0x100; + static SHOW_DOCUMENT_TYPE = 0x200; + static SHOW_DOCUMENT_FRAGMENT = 0x400; + static SHOW_NOTATION = 0x800; // legacy +} + +export interface Filter { + acceptNode(node: Node): number; +} diff --git a/src/dom/node.ts b/src/dom/node.ts index 18dfca8..8bc73aa 100644 --- a/src/dom/node.ts +++ b/src/dom/node.ts @@ -102,7 +102,7 @@ export class Node extends EventTarget { this._setOwnerDocument(newParent.#ownerDocument); // Add parent chain to ancestors - let parent: Node | null = newParent; + const parent: Node | null = newParent; this._ancestors = new Set(newParent._ancestors); this._ancestors.add(newParent); } else { @@ -287,7 +287,7 @@ export class Node extends EventTarget { } const index = parent._getChildNodesMutator().indexOf(this); - let next: Node | null = this.childNodes[index + 1] || null; + const next: Node | null = this.childNodes[index + 1] || null; return next; } @@ -300,7 +300,7 @@ export class Node extends EventTarget { } const index = parent._getChildNodesMutator().indexOf(this); - let prev: Node | null = this.childNodes[index - 1] || null; + const prev: Node | null = this.childNodes[index - 1] || null; return prev; } @@ -337,7 +337,7 @@ export class Text extends CharacterData { constructor( text: string = "", ) { - let oldLock = getLock(); + const oldLock = getLock(); setLock(false); super( text, @@ -359,7 +359,7 @@ export class Comment extends CharacterData { constructor( text: string = "", ) { - let oldLock = getLock(); + const oldLock = getLock(); setLock(false); super( text, diff --git a/src/dom/traverser.ts b/src/dom/traverser.ts new file mode 100644 index 0000000..24f3c18 --- /dev/null +++ b/src/dom/traverser.ts @@ -0,0 +1,41 @@ +import { NodeFilter, Filter } from "./node-filter.ts"; +import { Node } from "./node.ts"; + +export abstract class Traverser { + public readonly root: Node; + public readonly whatToShow: number; + public readonly filter: Filter | undefined; + private activeFlag = false; + + protected constructor(root: Node, whatToShow?: number, filter?: Filter) { + this.root = root; + this.whatToShow = whatToShow || -1; + this.filter = filter; + } + + protected accept(node: Node): number { + if (this.activeFlag) { + throw new Error("DOMException: InvalidStateError") + } + + if(!((1 << (node.nodeType-1)) & this.whatToShow)) { + return NodeFilter.FILTER_SKIP + } + + if(!this.filter) { + return NodeFilter.FILTER_ACCEPT + } + + this.activeFlag = true; + let result: number; + try { + result = this.filter.acceptNode(node); + } catch (error) { + this.activeFlag = false; + throw error + } + + this.activeFlag = false; + return result; + } +} \ No newline at end of file diff --git a/src/dom/treewalker.ts b/src/dom/treewalker.ts new file mode 100644 index 0000000..d3eebc9 --- /dev/null +++ b/src/dom/treewalker.ts @@ -0,0 +1,196 @@ +import { Node } from "./node.ts"; +import { NodeFilter, Filter } from "./node-filter.ts"; +import { Traverser } from "./traverser.ts"; + + +export class TreeWalker extends Traverser { + public currentNode: Node; + + constructor(root: Node, whatToShow?: number, filter?: Filter) { + super(root, whatToShow, filter); + this.currentNode = root; + } + + parentNode(): Node | null { + let node: Node | null = this.currentNode; + while(node && node != this.root) { + node = node.parentNode + if(node && this.accept(node) == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + } + + return null; + } + + firstChild(): Node | null { + return this.traverseChildren(new Forwards()); + } + + lastChild(): Node | null { + return this.traverseChildren(new Backwards()); + } + + previousSibling(): Node | null { + return this.traverseSiblings(new Backwards()); + } + + nextSibling(): Node | null { + return this.traverseSiblings(new Forwards()); + } + + previousNode(): Node | null { + let node: Node = this.currentNode; + let tmp: Node | null; + while(node != this.root) { + while(tmp = node.previousSibling) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_REJECT) { + continue; + } + while(tmp = node.lastChild) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_REJECT) { + break; + } + } + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + } + if(node == this.root) { + return null; + } + if(tmp = node.parentNode) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + } + } + + return null; + } + + nextNode(): Node | null { + let tmp: Node | null; + let node: Node = this.currentNode; + loop: while(true) { + while(tmp = node.firstChild) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if(result == NodeFilter.FILTER_REJECT) { + break; + } + } + while(tmp = node.nextSibling) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if(result == NodeFilter.FILTER_SKIP) { + continue loop; + } + } + break + } + + return null; + } + + private traverseChildren(strategy: Strategy): Node | null { + let node: Node; + let tmp: Node | null = strategy.first(this.currentNode); + + while(tmp) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if(result == NodeFilter.FILTER_SKIP && (tmp = strategy.first(node))) { + continue; + } + do { + if(tmp = strategy.next(node)) { + break + } + tmp = node.parentNode; + if(!tmp || tmp == this.root || tmp == this.currentNode) { + return null; + } + node = tmp; + } while(tmp); + } + + return null; + } + + private traverseSiblings(strategy: Strategy): Node | null { + let node: Node = this.currentNode; + + if(node == this.root) { + return null; + } + + let tmp: Node | null; + while(true) { + while(tmp = strategy.next(node)) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if(!(tmp = strategy.first(tmp)) || (result == NodeFilter.FILTER_REJECT)) { + tmp = strategy.next(node); + } + } + if((tmp = node.parentNode) && (tmp != this.root)) { + node = tmp; + const result = this.accept(node); + if(result == NodeFilter.FILTER_ACCEPT) { + return null; + } + } else { + return null; + } + } + } +} + +interface Strategy { + next(node: Node): Node | null; + first(node: Node): Node | null; +} + +class Forwards implements Strategy { + next(node: Node): Node | null { + return node.nextSibling; + } + first(node: Node): Node | null { + return node.firstChild; + } +} + +class Backwards implements Strategy { + next(node: Node): Node | null { + return node.previousSibling; + } + first(node: Node): Node | null { + return node.lastChild; + } +} \ No newline at end of file From 260807c21f2cda85b4b5637cc7e853aabf0e1fe3 Mon Sep 17 00:00:00 2001 From: Thanos Date: Sat, 10 Apr 2021 20:48:45 +0200 Subject: [PATCH 2/3] unittests --- test/units.ts | 6 ++++-- test/wpt-runner.ts | 2 +- test/wpt.ts | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/units.ts b/test/units.ts index 6965ec3..4e5d8b4 100644 --- a/test/units.ts +++ b/test/units.ts @@ -1,6 +1,9 @@ import { dirname, join } from "https://deno.land/std@0.85.0/path/mod.ts"; -const unitDir = join(dirname(new URL(import.meta.url).pathname), "units"); +let unitDir = join(dirname(new URL(import.meta.url).pathname), "units"); +if(Deno.build.os == 'windows') { + unitDir = unitDir.slice(1); +} const units = Array.from(Deno.readDirSync(unitDir)) .filter(file => file.isFile && file.name.endsWith(".ts")) .map(file => join("units", file.name)); @@ -12,4 +15,3 @@ Deno.chdir(unitDir); for (const file of units) { await import("./" + file); } - diff --git a/test/wpt-runner.ts b/test/wpt-runner.ts index 811e4bf..e8f940f 100644 --- a/test/wpt-runner.ts +++ b/test/wpt-runner.ts @@ -9,7 +9,7 @@ export type Backend = "wasm" | "native"; export async function run(path: string, root: string, backend: Backend) { const html = await Deno.readTextFile(path); const doc = parser.parseFromString(html, "text/html")!; - let scripts = Array.from(doc.querySelectorAll("script")).map(scriptNode => { + const scripts = Array.from(doc.querySelectorAll("script")).map(scriptNode => { const scriptElement = scriptNode as Element; let script = scriptElement.getAttribute("src")!; let scriptContents: string; diff --git a/test/wpt.ts b/test/wpt.ts index e49ac36..fad3a3a 100644 --- a/test/wpt.ts +++ b/test/wpt.ts @@ -17,11 +17,11 @@ const include = new RegExp([ "Node-", "ParentNode-", "Text-", + "TreeWalker" ].join("|")); const exclude = new RegExp([ "-namespace", - "TreeWalker", "ProcessingInstruction", "CDATA", // TODO: maybe implement CDATA support "createEvent", @@ -39,7 +39,7 @@ export function test(backend: Backend) { const limit = Infinity; let count = 0; - for (const testDir of [wptNodeTests]) { + for (const testDir of [wptTraversalTests, wptNodeTests]) { for (const entry of walkSync(testDir)) { const { path } = entry; From adcda4e98fbcbc0f4ffe63e8f1820852c7fb1171 Mon Sep 17 00:00:00 2001 From: Thanos Date: Sat, 10 Apr 2021 22:37:18 +0200 Subject: [PATCH 3/3] codestyle adjustments --- src/dom/node-filter.ts | 38 ++--- src/dom/traverser.ts | 64 ++++---- src/dom/treewalker.ts | 326 ++++++++++++++++++++--------------------- test/units.ts | 2 +- test/wpt.ts | 2 +- 5 files changed, 216 insertions(+), 216 deletions(-) diff --git a/src/dom/node-filter.ts b/src/dom/node-filter.ts index fb9de63..3daf1f2 100644 --- a/src/dom/node-filter.ts +++ b/src/dom/node-filter.ts @@ -1,26 +1,26 @@ import { Node } from "./node.ts"; -export abstract class NodeFilter { - static FILTER_ACCEPT = 1; - static FILTER_REJECT = 2; - static FILTER_SKIP = 3; +export enum NodeFilter { + FILTER_ACCEPT = 1, + FILTER_REJECT, + FILTER_SKIP, - // staticants for whatToShow - static SHOW_ALL = 0xFFFFFFFF; - static SHOW_ELEMENT = 0x1; - static SHOW_ATTRIBUTE = 0x2; - static SHOW_TEXT = 0x4; - static SHOW_CDATA_SECTION = 0x8; - static SHOW_ENTITY_REFERENCE = 0x10; // legacy - static SHOW_ENTITY = 0x20; // legacy - static SHOW_PROCESSING_INSTRUCTION = 0x40; - static SHOW_COMMENT = 0x80; - static SHOW_DOCUMENT = 0x100; - static SHOW_DOCUMENT_TYPE = 0x200; - static SHOW_DOCUMENT_FRAGMENT = 0x400; - static SHOW_NOTATION = 0x800; // legacy + // staticants for whatToShow + SHOW_ALL = -1, + SHOW_ELEMENT = 0x1, + SHOW_ATTRIBUTE = 0x2, + SHOW_TEXT = 0x4, + SHOW_CDATA_SECTION = 0x8, + SHOW_ENTITY_REFERENCE = 0x10, // legacy + SHOW_ENTITY = 0x20, // legacy + SHOW_PROCESSING_INSTRUCTION = 0x40, + SHOW_COMMENT = 0x80, + SHOW_DOCUMENT = 0x100, + SHOW_DOCUMENT_TYPE = 0x200, + SHOW_DOCUMENT_FRAGMENT = 0x400, + SHOW_NOTATION = 0x800, // legacy } export interface Filter { - acceptNode(node: Node): number; + acceptNode(node: Node): number; } diff --git a/src/dom/traverser.ts b/src/dom/traverser.ts index 24f3c18..a3bc007 100644 --- a/src/dom/traverser.ts +++ b/src/dom/traverser.ts @@ -2,40 +2,40 @@ import { NodeFilter, Filter } from "./node-filter.ts"; import { Node } from "./node.ts"; export abstract class Traverser { - public readonly root: Node; - public readonly whatToShow: number; - public readonly filter: Filter | undefined; - private activeFlag = false; - - protected constructor(root: Node, whatToShow?: number, filter?: Filter) { - this.root = root; - this.whatToShow = whatToShow || -1; - this.filter = filter; - } + public readonly root: Node; + public readonly whatToShow: number; + public readonly filter: Filter | undefined; + private activeFlag = false; + + protected constructor(root: Node, whatToShow?: number, filter?: Filter) { + this.root = root; + this.whatToShow = whatToShow || -1; + this.filter = filter; + } - protected accept(node: Node): number { - if (this.activeFlag) { - throw new Error("DOMException: InvalidStateError") - } - - if(!((1 << (node.nodeType-1)) & this.whatToShow)) { - return NodeFilter.FILTER_SKIP - } - - if(!this.filter) { - return NodeFilter.FILTER_ACCEPT - } + protected accept(node: Node): number { + if (this.activeFlag) { + throw new Error("DOMException: InvalidStateError"); + } - this.activeFlag = true; - let result: number; - try { - result = this.filter.acceptNode(node); - } catch (error) { - this.activeFlag = false; - throw error - } + if (!((1 << (node.nodeType-1)) & this.whatToShow)) { + return NodeFilter.FILTER_SKIP; + } + + if (!this.filter) { + return NodeFilter.FILTER_ACCEPT; + } - this.activeFlag = false; - return result; + this.activeFlag = true; + let result: number; + try { + result = this.filter.acceptNode(node); + } catch (error) { + this.activeFlag = false; + throw error; } + + this.activeFlag = false; + return result; + } } \ No newline at end of file diff --git a/src/dom/treewalker.ts b/src/dom/treewalker.ts index d3eebc9..9cd5000 100644 --- a/src/dom/treewalker.ts +++ b/src/dom/treewalker.ts @@ -4,193 +4,193 @@ import { Traverser } from "./traverser.ts"; export class TreeWalker extends Traverser { - public currentNode: Node; + public currentNode: Node; - constructor(root: Node, whatToShow?: number, filter?: Filter) { - super(root, whatToShow, filter); - this.currentNode = root; + constructor(root: Node, whatToShow?: number, filter?: Filter) { + super(root, whatToShow, filter); + this.currentNode = root; + } + + parentNode(): Node | null { + let node: Node | null = this.currentNode; + while (node && node != this.root) { + node = node.parentNode; + if (node && this.accept(node) === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } } - parentNode(): Node | null { - let node: Node | null = this.currentNode; - while(node && node != this.root) { - node = node.parentNode - if(node && this.accept(node) == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - } + return null; + } - return null; - } - - firstChild(): Node | null { - return this.traverseChildren(new Forwards()); - } - - lastChild(): Node | null { - return this.traverseChildren(new Backwards()); - } - - previousSibling(): Node | null { - return this.traverseSiblings(new Backwards()); - } - - nextSibling(): Node | null { - return this.traverseSiblings(new Forwards()); - } - - previousNode(): Node | null { - let node: Node = this.currentNode; - let tmp: Node | null; - while(node != this.root) { - while(tmp = node.previousSibling) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_REJECT) { - continue; - } - while(tmp = node.lastChild) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_REJECT) { - break; - } - } - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - } - if(node == this.root) { - return null; - } - if(tmp = node.parentNode) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - } - } + firstChild(): Node | null { + return this.traverseChildren(new Forwards()); + } - return null; - } - - nextNode(): Node | null { - let tmp: Node | null; - let node: Node = this.currentNode; - loop: while(true) { - while(tmp = node.firstChild) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - if(result == NodeFilter.FILTER_REJECT) { - break; - } - } - while(tmp = node.nextSibling) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - if(result == NodeFilter.FILTER_SKIP) { - continue loop; - } - } - break - } + lastChild(): Node | null { + return this.traverseChildren(new Backwards()); + } + + previousSibling(): Node | null { + return this.traverseSiblings(new Backwards()); + } + + nextSibling(): Node | null { + return this.traverseSiblings(new Forwards()); + } + previousNode(): Node | null { + let node: Node = this.currentNode; + let tmp: Node | null; + while (node != this.root) { + while (tmp = node.previousSibling) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_REJECT) { + continue; + } + while (tmp = node.lastChild) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_REJECT) { + break; + } + } + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + } + if (node === this.root) { return null; + } + if (tmp = node.parentNode) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + } } - private traverseChildren(strategy: Strategy): Node | null { - let node: Node; - let tmp: Node | null = strategy.first(this.currentNode); - - while(tmp) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - if(result == NodeFilter.FILTER_SKIP && (tmp = strategy.first(node))) { - continue; - } - do { - if(tmp = strategy.next(node)) { - break - } - tmp = node.parentNode; - if(!tmp || tmp == this.root || tmp == this.currentNode) { - return null; - } - node = tmp; - } while(tmp); + return null; + } + + nextNode(): Node | null { + let tmp: Node | null; + let node: Node = this.currentNode; + loop: while (true) { + while (tmp = node.firstChild) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if (result === NodeFilter.FILTER_REJECT) { + break; + } + } + while (tmp = node.nextSibling) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; } + if (result === NodeFilter.FILTER_SKIP) { + continue loop; + } + } + break; + } - return null; + return null; + } + + private traverseChildren(strategy: Strategy): Node | null { + let node: Node; + let tmp: Node | null = strategy.first(this.currentNode); + + while (tmp) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if (result === NodeFilter.FILTER_SKIP && (tmp = strategy.first(node))) { + continue; + } + do { + if (tmp = strategy.next(node)) { + break; + } + tmp = node.parentNode; + if (!tmp || tmp === this.root || tmp === this.currentNode) { + return null; + } + node = tmp; + } while (tmp); } - private traverseSiblings(strategy: Strategy): Node | null { - let node: Node = this.currentNode; + return null; + } - if(node == this.root) { - return null; + private traverseSiblings(strategy: Strategy): Node | null { + let node: Node = this.currentNode; + + if (node === this.root) { + return null; + } + + let tmp: Node | null; + while (true) { + while (tmp = strategy.next(node)) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + this.currentNode = node; + return node; + } + if (!(tmp = strategy.first(tmp)) || (result === NodeFilter.FILTER_REJECT)) { + tmp = strategy.next(node); + } } - - let tmp: Node | null; - while(true) { - while(tmp = strategy.next(node)) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - this.currentNode = node; - return node; - } - if(!(tmp = strategy.first(tmp)) || (result == NodeFilter.FILTER_REJECT)) { - tmp = strategy.next(node); - } - } - if((tmp = node.parentNode) && (tmp != this.root)) { - node = tmp; - const result = this.accept(node); - if(result == NodeFilter.FILTER_ACCEPT) { - return null; - } - } else { - return null; - } + if ((tmp = node.parentNode) && (tmp != this.root)) { + node = tmp; + const result = this.accept(node); + if (result === NodeFilter.FILTER_ACCEPT) { + return null; + } + } else { + return null; } } + } } interface Strategy { - next(node: Node): Node | null; - first(node: Node): Node | null; + next(node: Node): Node | null; + first(node: Node): Node | null; } class Forwards implements Strategy { - next(node: Node): Node | null { - return node.nextSibling; - } - first(node: Node): Node | null { - return node.firstChild; - } + next(node: Node): Node | null { + return node.nextSibling; + } + first(node: Node): Node | null { + return node.firstChild; + } } class Backwards implements Strategy { - next(node: Node): Node | null { - return node.previousSibling; - } - first(node: Node): Node | null { - return node.lastChild; - } + next(node: Node): Node | null { + return node.previousSibling; + } + first(node: Node): Node | null { + return node.lastChild; + } } \ No newline at end of file diff --git a/test/units.ts b/test/units.ts index 4e5d8b4..d6a7130 100644 --- a/test/units.ts +++ b/test/units.ts @@ -1,7 +1,7 @@ import { dirname, join } from "https://deno.land/std@0.85.0/path/mod.ts"; let unitDir = join(dirname(new URL(import.meta.url).pathname), "units"); -if(Deno.build.os == 'windows') { +if (Deno.build.os === "windows") { unitDir = unitDir.slice(1); } const units = Array.from(Deno.readDirSync(unitDir)) diff --git a/test/wpt.ts b/test/wpt.ts index fad3a3a..75dcaf6 100644 --- a/test/wpt.ts +++ b/test/wpt.ts @@ -17,7 +17,7 @@ const include = new RegExp([ "Node-", "ParentNode-", "Text-", - "TreeWalker" + "TreeWalker", ].join("|")); const exclude = new RegExp([