Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/devtools/client/webconsole/test/browser/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 17 kB image not shown  

Quelle  shared-head.js   Sprache: JAVA

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */


/**
 * Helper methods for finding messages in the virtualized output of the
 * webconsole. This file can be safely required from other panel test
 * files.
 */


"use strict";

/* eslint-disable no-unused-vars */

// Assume that shared-head is always imported before this file
/* import-globals-from ../../../shared/test/shared-head.js */

/**
 * Find a message with given messageId in the output, scrolling through the
 * output from top to bottom in order to make sure the messages are actually
 * rendered.
 *
 * @param object hud
 *        The web console.
 * @param messageId
 *        A message ID to look for. This could be baked into the selector, but
 *        is provided as a convenience.
 * @return {Node} the node corresponding the found message
 */

async function findMessageVirtualizedById({ hud, messageId }) {
  if (!messageId) {
    throw new Error("messageId parameter is required");
  }

  const elements = await findMessagesVirtualized({
    hud,
    expectedCount: 1,
    messageId,
  });
  return elements.at(-1);
}

/**
 * Find the last message with given message type in the output, scrolling
 * through the output from top to bottom in order to make sure the messages are
 * actually rendered.
 *
 * @param object hud
 *        The web console.
 * @param string text
 *        A substring that can be found in the message.
 * @param string typeSelector
 *        A part of selector for the message, to specify the message type.
 * @return {Node} the node corresponding the found message
 */

async function findMessageVirtualizedByType({ hud, text, typeSelector }) {
  const elements = await findMessagesVirtualizedByType({
    hud,
    text,
    typeSelector,
    expectedCount: 1,
  });
  return elements.at(-1);
}

/**
 * Find all messages in the output, scrolling through the output from top
 * to bottom in order to make sure the messages are actually rendered.
 *
 * @param object hud
 *        The web console.
 * @return {Array} all of the message nodes in the console output. Some of
 *        these may be stale from having been scrolled out of view.
 */

async function findAllMessagesVirtualized(hud) {
  return findMessagesVirtualized({ hud });
}

// This is just a reentrancy guard. Because findMessagesVirtualized mucks
// around with the scroll position, if we do something like
//   let promise1 = findMessagesVirtualized(...);
//   let promise2 = findMessagesVirtualized(...);
//   await promise1;
//   await promise2;
// then the two calls will end up messing up each other's expected scroll
// position, at which point they could get stuck. This lets us throw an
// error when that happens.
let gInFindMessagesVirtualized = false;
// And this lets us get a little more information in the error - it just holds
// the stack of the prior call.
let gFindMessagesVirtualizedStack = null;

/**
 * Find multiple messages in the output, scrolling through the output from top
 * to bottom in order to make sure the messages are actually rendered.
 *
 * @param object options
 * @param object options.hud
 *        The web console.
 * @param options.text [optional]
 *        A substring that can be found in the message.
 * @param options.typeSelector
 *        A part of selector for the message, to specify the message type.
 * @param options.expectedCount [optional]
 *        The number of messages to get. This lets us stop scrolling early if
 *        we find that number of messages.
 * @return {Array} all of the message nodes in the console output matching the
 *        provided filters. If expectedCount is greater than 1, or equal to -1,
 *        some of these may be stale from having been scrolled out of view.
 */

async function findMessagesVirtualizedByType({
  hud,
  text,
  typeSelector,
  expectedCount,
}) {
  if (!typeSelector) {
    throw new Error("typeSelector parameter is required");
  }
  if (!typeSelector.startsWith(".")) {
    throw new Error("typeSelector should start with a dot e.g. `.result`");
  }

  return findMessagesVirtualized({
    hud,
    text,
    selector: ".message" + typeSelector,
    expectedCount,
  });
}

/**
 * Find multiple messages in the output, scrolling through the output from top
 * to bottom in order to make sure the messages are actually rendered.
 *
 * @param object options
 * @param object options.hud
 *        The web console.
 * @param options.text [optional]
 *        A substring that can be found in the message.
 * @param options.selector [optional]
 *        The selector to use in finding the message.
 * @param options.expectedCount [optional]
 *        The number of messages to get. This lets us stop scrolling early if
 *        we find that number of messages.
 * @param options.messageId [optional]
 *        A message ID to look for. This could be baked into the selector, but
 *        is provided as a convenience.
 * @return {Array} all of the message nodes in the console output matching the
 *        provided filters. If expectedCount is greater than 1, or equal to -1,
 *        some of these may be stale from having been scrolled out of view.
 */

async function findMessagesVirtualized({
  hud,
  text,
  selector,
  expectedCount,
  messageId,
}) {
  if (text === undefined) {
    text = "";
  }
  if (selector === undefined) {
    selector = ".message";
  }
  if (expectedCount === undefined) {
    expectedCount = -1;
  }

  const outputNode = hud.ui.outputNode;
  const scrollport = outputNode.querySelector(".webconsole-output");

  function getVisibleMessageIds() {
    return JSON.parse(scrollport.getAttribute("data-visible-messages"));
  }

  function getVisibleMessageMap() {
    return new Map(
      JSON.parse(scrollport.getAttribute("data-visible-messages")).map(
        (id, i) => [id, i]
      )
    );
  }

  function getMessageIndex(message) {
    return getVisibleMessageIds().indexOf(
      message.getAttribute("data-message-id")
    );
  }

  function getNextMessageId(prevMessage) {
    const visible = getVisibleMessageIds();
    let index = 0;
    if (prevMessage) {
      const lastId = prevMessage.getAttribute("data-message-id");
      index = visible.indexOf(lastId);
      if (index === -1) {
        throw new Error(
          `Tried to get next message ID for message that doesn't exist. Last seen ID: ${lastId}, all visible ids: [${visible.join(
            ", "
          )}]`
        );
      }
    }
    if (index + 1 >= visible.length) {
      return null;
    }
    return visible[index + 1];
  }

  if (gInFindMessagesVirtualized) {
    throw new Error(
      `findMessagesVirtualized was re-entered somehow. This is not allowed. Other stack: [${gFindMessagesVirtualizedStack}]`
    );
  }
  try {
    gInFindMessagesVirtualized = true;
    gFindMessagesVirtualizedStack = new Error().stack;
    // The console output will automatically scroll to the bottom of the
    // scrollport in certain circumstances. Because we need to scroll the
    // output to find all messages, we need to disable this. This attribute
    // controls that.
    scrollport.setAttribute("disable-autoscroll""");

    // This array is here purely for debugging purposes. We collect the indices
    // of every element we see in order to validate that we don't have any gaps
    // in the list.
    const allIndices = [];

    const allElements = [];
    const seenIds = new Set();
    let lastItem = null;
    while (true) {
      if (scrollport.scrollHeight > scrollport.clientHeight) {
        if (!lastItem && scrollport.scrollTop != 0) {
          // For simplicity's sake, we always start from the top of the output.
          scrollport.scrollTop = 0;
        } else if (!lastItem && scrollport.scrollTop == 0) {
          // We want to make sure that we actually change the scroll position
          // here, because we're going to wait for an update below regardless,
          // just to flush out any changes that may have just happened. If we
          // don't do this, and there were no changes before this function was
          // called, then we'll just hang on the promise below.
          scrollport.scrollTop = 1;
        } else {
          // This is the core of the loop. Scroll down to the bottom of the
          // current scrollport, wait until we see the element after the last
          // one we've seen, and then harvest the messages that are displayed.
          scrollport.scrollTop = scrollport.scrollTop + scrollport.clientHeight;
        }

        // Wait for something to happen in the output before checking for our
        // expected next message.
        await new Promise(resolve =>
          hud.ui.once("lazy-message-list-updated-or-noop", resolve)
        );

        try {
          await waitFor(async () => {
            const nextMessageId = getNextMessageId(lastItem);
            if (
              nextMessageId === undefined ||
              scrollport.querySelector(`[data-message-id="${nextMessageId}"]`)
            ) {
              return true;
            }

            // After a scroll, we typically expect to get an updated list of
            // elements. However, we have some slack at the top of the list,
            // because we draw elements above and below the actual scrollport to
            // avoid white flashes when async scrolling.
            const scrollTarget = scrollport.scrollTop + scrollport.clientHeight;
            scrollport.scrollTop = scrollTarget;
            await new Promise(resolve =>
              hud.ui.once("lazy-message-list-updated-or-noop", resolve)
            );
            return false;
          });
        } catch (e) {
          throw new Error(
            `Failed waiting for next message ID (${getNextMessageId(
              lastItem
            )}) Visible messages: [${[
              ...scrollport.querySelectorAll(".message"),
            ].map(el => el.getAttribute("data-message-id"))}]`
          );
        }
      }

      const bottomPlaceholder = scrollport.querySelector(
        ".lazy-message-list-bottom"
      );
      if (!bottomPlaceholder) {
        // When there are no messages in the output, there is also no
        // top/bottom placeholder. There's nothing more to do at this point,
        // so break and return.
        break;
      }

      lastItem = bottomPlaceholder.previousSibling;

      // This chunk is just validating that we have no gaps in our output so
      // far.
      const indices = [...scrollport.querySelectorAll("[data-message-id]")]
        .filter(
          el => el !== scrollport.firstChild && el !== scrollport.lastChild
        )
        .map(el => getMessageIndex(el));
      allIndices.push(...indices);
      allIndices.sort((lhs, rhs) => lhs - rhs);
      for (let i = 1; i < allIndices.length; i++) {
        if (
          allIndices[i] != allIndices[i - 1] &&
          allIndices[i] != allIndices[i - 1] + 1
        ) {
          throw new Error(
            `Gap detected in virtualized webconsole output between ${
              allIndices[i - 1]
            } and ${allIndices[i]}. Indices: ${allIndices.join(",")}`
          );
        }
      }

      const messages = scrollport.querySelectorAll(selector);
      const filtered = [...messages].filter(
        el =>
          // Core user filters:
          el.textContent.includes(text) &&
          (!messageId || el.getAttribute("data-message-id") === messageId) &&
          // Make sure we don't collect duplicate messages:
          !seenIds.has(el.getAttribute("data-message-id"))
      );
      allElements.push(...filtered);
      for (const message of filtered) {
        seenIds.add(message.getAttribute("data-message-id"));
      }

      if (expectedCount >= 0 && allElements.length >= expectedCount) {
        break;
      }

      // If the bottom placeholder has 0 height, it means we've scrolled to the
      // bottom and output all the items.
      if (bottomPlaceholder.getBoundingClientRect().height == 0) {
        break;
      }

      await waitForTime(0);
    }

    // Finally, we get the map of message IDs to indices within the output, and
    // sort the message nodes according to that index. They can come in out of
    // order for a number of reasons (we continue rendering any messages that
    // have been expanded, and we always render the topmost and bottommost
    // messages for a11y reasons.)
    const idsToIndices = getVisibleMessageMap();
    allElements.sort(
      (lhs, rhs) =>
        idsToIndices.get(lhs.getAttribute("data-message-id")) -
        idsToIndices.get(rhs.getAttribute("data-message-id"))
    );
    return allElements;
  } finally {
    scrollport.removeAttribute("disable-autoscroll");
    gInFindMessagesVirtualized = false;
    gFindMessagesVirtualizedStack = null;
  }
}

/**
 * Find the last message with given message type in the output.
 *
 * @param object hud
 *        The web console.
 * @param string text
 *        A substring that can be found in the message.
 * @param string typeSelector
 *        A part of selector for the message, to specify the message type.
 * @return {Node} the node corresponding the found message, otherwise undefined
 */

function findMessageByType(hud, text, typeSelector) {
  const elements = findMessagesByType(hud, text, typeSelector);
  return elements.at(-1);
}

/**
 * Find multiple messages with given message type in the output.
 *
 * @param object hud
 *        The web console.
 * @param string text
 *        A substring that can be found in the message.
 * @param string typeSelector
 *        A part of selector for the message, to specify the message type.
 * @return {Array} The nodes corresponding the found messages
 */

function findMessagesByType(hud, text, typeSelector) {
  if (!typeSelector) {
    throw new Error("typeSelector parameter is required");
  }
  if (!typeSelector.startsWith(".")) {
    throw new Error("typeSelector should start with a dot e.g. `.result`");
  }

  const selector = ".message" + typeSelector;
  const messages = hud.ui.outputNode.querySelectorAll(selector);
  const elements = Array.from(messages).filter(el =>
    el.textContent.includes(text)
  );
  return elements;
}

/**
 * Find all messages in the output.
 *
 * @param object hud
 *        The web console.
 * @return {Array} The nodes corresponding the found messages
 */

function findAllMessages(hud) {
  const messages = hud.ui.outputNode.querySelectorAll(".message");
  return Array.from(messages);
}

/**
 * Find a part of the last message with given message type in the output.
 *
 * @param object hud
 *        The web console.
 * @param object options
 *        - text : {String} A substring that can be found in the message.
 *        - typeSelector: {String} A part of selector for the message,
 *                                 to specify the message type.
 *        - partSelector: {String} A selector for the part of the message.
 * @return {Node} the node corresponding the found part, otherwise undefined
 */

function findMessagePartByType(hud, options) {
  const elements = findMessagePartsByType(hud, options);
  return elements.at(-1);
}

/**
 * Find parts of multiple messages with given message type in the output.
 *
 * @param object hud
 *        The web console.
 * @param object options
 *        - text : {String} A substring that can be found in the message.
 *        - typeSelector: {String} A part of selector for the message,
 *                                 to specify the message type.
 *        - partSelector: {String} A selector for the part of the message.
 * @return {Array} The nodes corresponding the found parts
 */

function findMessagePartsByType(hud, { text, typeSelector, partSelector }) {
  if (!typeSelector) {
    throw new Error("typeSelector parameter is required");
  }
  if (!typeSelector.startsWith(".")) {
    throw new Error("typeSelector should start with a dot e.g. `.result`");
  }
  if (!partSelector) {
    throw new Error("partSelector parameter is required");
  }

  const selector = ".message" + typeSelector + " " + partSelector;
  const parts = hud.ui.outputNode.querySelectorAll(selector);
  const elements = Array.from(parts).filter(el =>
    el.textContent.includes(text)
  );
  return elements;
}

/**
 * Type-specific wrappers for findMessageByType and findMessagesByType.
 *
 * @param object hud
 *        The web console.
 * @param string text
 *        A substring that can be found in the message.
 * @param string extraSelector [optional]
 *        An extra part of selector for the message, in addition to
 *        type-specific selector.
 * @return {Node|Array} See findMessageByType or findMessagesByType.
 */

function findEvaluationResultMessage(hud, text, extraSelector = "") {
  return findMessageByType(hud, text, ".result" + extraSelector);
}
function findEvaluationResultMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".result" + extraSelector);
}
function findErrorMessage(hud, text, extraSelector = "") {
  return findMessageByType(hud, text, ".error" + extraSelector);
}
function findErrorMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".error" + extraSelector);
}
function findWarningMessage(hud, text, extraSelector = "") {
  return findMessageByType(hud, text, ".warn" + extraSelector);
}
function findWarningMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".warn" + extraSelector);
}
function findConsoleAPIMessage(hud, text, extraSelector = "") {
  return findMessageByType(hud, text, ".console-api" + extraSelector);
}
function findConsoleAPIMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".console-api" + extraSelector);
}
function findNetworkMessage(hud, text, extraSelector = "") {
  return findMessageByType(hud, text, ".network" + extraSelector);
}
function findNetworkMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".network" + extraSelector);
}
function findTracerMessages(hud, text, extraSelector = "") {
  return findMessagesByType(hud, text, ".jstracer" + extraSelector);
}

89%


¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.