match(query, pageContent, pageIndex) {
    const hasDiacritics = this._hasDiacritics[pageIndex];

    let isUnicode = false;
    if (typeof query === "string") {
      [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);
    } else {
      // Words are sorted in reverse order to be sure that "foobar" is matched
      // before "foo" in case the query is "foobar foo".
      query = query
        .sort()
        .reverse()
        .map(q => {
          const [isUnicodePart, queryPart] = this.#convertToRegExpString(
            q,
            hasDiacritics
          );
          isUnicode ||= isUnicodePart;
          return `(${queryPart})`;
        })
        .join("|");
    }
    if (!query) {
      // The query can be empty because some chars like diacritics could have
      // been stripped out.
      return undefined;
    }

    const { caseSensitive, entireWord } = this.#state;
    const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
    query = new RegExp(query, flags);

    const matches = [];
    let match;
    while ((match = query.exec(pageContent)) !== null) {
      if (
        entireWord &&
        !this.#isEntireWord(pageContent, match.index, match[0].length)
      ) {
        continue;
      }
      matches.push({ index: match.index, length: match[0].length });
    }
    return matches;
  }
@param {string | string[]} query - The search query.
@param {string} pageContent - The text content of the page to search in.
@param {number} pageIndex - The index of the page that is being processed.
@returns {FindMatch[] | undefined} An array of matches in the provided
  page.