capricorn86 / happy-dom

A JavaScript implementation of a web browser without its graphical user interface
MIT License
3.1k stars 185 forks source link

TreeWalker behavior is different from Chrome and JSDOM #1172

Open konomae opened 7 months ago

konomae commented 7 months ago

Describe the bug

When running the same code, happy-dom's behavior does not match JSDOM or Chrome.

To Reproduce

Sample Code: https://stackblitz.com/edit/stackblitz-starters-7oorbw?file=jsdom.js

The basic code is below.

var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
  acceptNode: (node) => {
    console.log(node.tagName);
    return NodeFilter.FILTER_SKIP;
  },
});
walker.nextNode();

The test HTML is obtained from the following. https://github.com/capricorn86/happy-dom/blob/master/packages/happy-dom/test/tree-walker/data/TreeWalkerHTML.ts

Below is the execution result.

happy-dom

~/projects/stackblitz-starters-7oorbw
❯ node happy-dom.js
DIV
ARTICLE
BODY

JSDOM

~/projects/stackblitz-starters-7oorbw
❯ node jsdom.js
DIV
B
SPAN
ARTICLE
B

Chrome (Dev Tools)

ss

The behavior of Chrome and JSDOM is consistent.

Expected behavior

The behavior of happy-dom is the same as that of Chrome and JSDOM.

aralroca commented 4 months ago

I have the same issue with this:

function findCommentNode(htmlText: string, commentText: string) {
    return document
    .createTreeWalker(
      parser.parseFromString(htmlText, "text/html"),
      128, /* NodeFilter.SHOW_COMMENT */
      {
          acceptNode:  (node) => node.textContent === commentText 
            ? 1 /* NodeFilter.FILTER_ACCEPT */
            : 2 /* NodeFilter.FILTER_REJECT */
      }
    )
    .nextNode();
  }

In Chrome and JSDOM I'm getting the comment node, but in happy-dom is always null.

aralroca commented 4 months ago

With NodeFilter.SHOW_COMMENT is not executing any console.log inside acceptNode function.

However NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_COMMENT is returning the comments with the elements, but only NodeFilter.SHOW_COMMENT is not working!

Shadowlauch commented 1 month ago

I ran into the same issue today. Sorry it is not much, but here is a test that can be pasted into TreeWalker.test.ts to verify this behavior easily

it('Accept test', () => {
    const html: string[] = [];
    const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
        acceptNode: (node) => {
            html.push((node as Element).tagName);
            return NodeFilter.FILTER_SKIP;
        }
    });
    treeWalker.nextNode();

    expect(html).toEqual(['DIV', 'B', 'SPAN', 'ARTICLE', 'B']);
});