chromium/third_party/blink/web_tests/inspector-protocol/dom/resources/dom-test-helper.js

(class DomTestHelper {
  /**
   * @param {Array<!Node>} nodes
   * @param {string} attrValue
   * @return {?Node}
   */
  static searchNodesByAttributeValue(nodes, attrValue) {
    for (let node of nodes) {
      if (node.attributes && (node.attributes.indexOf(attrValue) !== -1))
        return node;

      if (node.children) {
        const childSearch = DomTestHelper.searchNodesByAttributeValue(node.children, attrValue);
        if (childSearch)
          return childSearch;
      }
    }

    return null;
  }

  /**
   * Queries DevTools protocol for document to find body node
   *
   * @return {?Node}
   */
  static async findBodyNode(dp) {
    /** Query for depth = 3 in conventional files (specifically our resource files)
     * #document
     *  - #doctype
     *  - html
     *   - head
     *   - body
     */
    const documentMessage = await dp.DOM.getDocument({ depth: 2 });
    /** Do a breadth-first traversal to find a node where nodeName === 'BODY' */
    const toVisit = [documentMessage.result.root];
    while (toVisit.length > 0) {
      const toCheck = toVisit.shift();
      if (toCheck.nodeName === 'BODY')
        return toCheck;

      if (toCheck.children)
        toVisit.push(...toCheck.children);

    }

    return null;
  }

  /**
   * Searches an array of nodes and returns the first which has a
   * matching id.
   *
   * @param {Array<!Node>} nodes
   * @param {number} nodeId
   * @return {?Node}
   */
  static searchNodesByNodeId(nodes, nodeId) {
    return nodes.find(node => node.nodeId === nodeId) || null;
  }

  /**
   * Performs a depth first search of an array of nodes and their
   * children for the first iframe contentDocument
   *
   * @param {Array<!Node>} nodes
   * @return {?Node}
   */
  static searchNodesForContentDocument(nodes) {
    for (let node of nodes) {
      if (node.contentDocument)
        return node.contentDocument;

      if (node.children) {
        const childSearch = DomTestHelper.searchNodesForContentDocument(node.children);
        if (childSearch)
          return childSearch;
      }
    }

    return null;
  }
})