Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/base/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 36 kB image not shown  

Quelle  TextDirectiveCreator.cpp   Sprache: C

 

/* 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/. */


#include "TextDirectiveCreator.h"

#include <algorithm>

#include "AbstractRange.h"
#include "Document.h"
#include "StaticRange.h"
#include "TextDirectiveUtil.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/ResultVariant.h"
#include "nsFind.h"
#include "nsINode.h"
#include "nsRange.h"

namespace mozilla::dom {

TextDirectiveCreator::TextDirectiveCreator(Document* aDocument,
                                           AbstractRange* aRange,
                                           const TimeoutWatchdog* aWatchdog)
    : mDocument(WrapNotNull(aDocument)),
      mRange(WrapNotNull(aRange)),
      mFinder(WrapNotNull(new nsFind())),
      mWatchdog(aWatchdog) {
  mFinder->SetNodeIndexCache(&mNodeIndexCache);
}

TextDirectiveCreator::~TextDirectiveCreator() {
  mFinder->SetNodeIndexCache(nullptr);
}

/* static */
mozilla::Result<nsCString, ErrorResult>
TextDirectiveCreator::CreateTextDirectiveFromRange(
    Document* aDocument, AbstractRange* aInputRange,
    const TimeoutWatchdog* aWatchdog) {
  MOZ_ASSERT(aInputRange);
  MOZ_ASSERT(!aInputRange->Collapsed());

  const RefPtr<AbstractRange> extendedRange =
      MOZ_TRY(ExtendRangeToWordBoundaries(aInputRange));
  if (!extendedRange) {
    return VoidCString();
  }
  UniquePtr<TextDirectiveCreator> instance =
      MOZ_TRY(CreateInstance(aDocument, extendedRange, aWatchdog));

  const bool succeededBuildingContextTerms =
      MOZ_TRY(instance->CollectContextTerms());
  if (!succeededBuildingContextTerms) {
    return VoidCString();
  }
  instance->CollectContextTermWordBoundaryDistances();
  MOZ_TRY(instance->FindAllMatchingCandidates());
  return instance->CreateTextDirective();
}

/* static */ Result<bool, ErrorResult>
TextDirectiveCreator::MustUseRangeBasedMatching(AbstractRange* aRange) {
  MOZ_ASSERT(aRange);
  if (TextDirectiveUtil::FindBlockBoundaryInRange<TextScanDirection::Right>(
          *aRange)
          .isSome()) {
    TEXT_FRAGMENT_LOG(
        "Use range-based matching because the target range contains a block "
        "boundary.");
    return true;
  }
  const nsString rangeContent =
      MOZ_TRY(TextDirectiveUtil::RangeContentAsString(aRange));

  const uint32_t kMaxLength = StaticPrefs::
      dom_text_fragments_create_text_fragment_exact_match_max_length();
  const bool rangeTooLong = rangeContent.Length() > kMaxLength;
  if (rangeTooLong) {
    TEXT_FRAGMENT_LOG(
        "Use range-based matching because the target range is too long "
        "({} chars > {} threshold)",
        rangeContent.Length(), kMaxLength);
  } else {
    TEXT_FRAGMENT_LOG("Use exact matching.");
  }
  return rangeTooLong;
}

Result<UniquePtr<TextDirectiveCreator>, ErrorResult>
TextDirectiveCreator::CreateInstance(Document* aDocument, AbstractRange* aRange,
                                     const TimeoutWatchdog* aWatchdog) {
  return MOZ_TRY(MustUseRangeBasedMatching(aRange))
             ? UniquePtr<TextDirectiveCreator>(
                   new RangeBasedTextDirectiveCreator(aDocument, aRange,
                                                      aWatchdog))
             : UniquePtr<TextDirectiveCreator>(
                   new ExactMatchTextDirectiveCreator(aDocument, aRange,
                                                      aWatchdog));
}

/*static*/
Result<RefPtr<AbstractRange>, ErrorResult>
TextDirectiveCreator::ExtendRangeToWordBoundaries(AbstractRange* aRange) {
  MOZ_ASSERT(aRange && !aRange->Collapsed());
  ErrorResult rv;
  const nsString rangeContent =
      MOZ_TRY(TextDirectiveUtil::RangeContentAsString(aRange));
  TEXT_FRAGMENT_LOG("Input range :\n{}", NS_ConvertUTF16toUTF8(rangeContent));

  if (rangeContent.IsEmpty()) {
    TEXT_FRAGMENT_LOG("Input range does not contain text.");
    return {nullptr};
  }

  if (std::all_of(rangeContent.View().cbegin(), rangeContent.View().cend(),
                  nsContentUtils::IsHTMLWhitespaceOrNBSP)) {
    TEXT_FRAGMENT_LOG("Input range contains only whitespace.");
    return {nullptr};
  }
  if (std::all_of(rangeContent.View().cbegin(), rangeContent.View().cend(),
                  IsPunctuationForWordSelect)) {
    RangeBoundary startPoint = TextDirectiveUtil::FindNextNonWhitespacePosition<
        TextScanDirection::Right>(aRange->StartRef());
    RangeBoundary endPoint = TextDirectiveUtil::FindNextNonWhitespacePosition<
        TextScanDirection::Left>(aRange->EndRef());
    RefPtr range = StaticRange::Create(startPoint, endPoint, rv);
    if (MOZ_UNLIKELY(rv.Failed())) {
      return Err(std::move(rv));
    }
    return {range};
  }
  RangeBoundary startPoint = TextDirectiveUtil::FindNextNonWhitespacePosition<
      TextScanDirection::Right>(aRange->StartRef());
  startPoint = TextDirectiveUtil::FindWordBoundary<TextScanDirection::Left>(
      startPoint, TextDirectiveUtil::BreakOnPunctuation::Yes);

  RangeBoundary endPoint =
      TextDirectiveUtil::FindNextNonWhitespacePosition<TextScanDirection::Left>(
          aRange->EndRef());
  endPoint = TextDirectiveUtil::FindWordBoundary<TextScanDirection::Right>(
      endPoint, TextDirectiveUtil::BreakOnPunctuation::Yes);
#if MOZ_DIAGNOSTIC_ASSERT_ENABLED
  auto cmp = nsContentUtils::ComparePoints(startPoint, endPoint);
  MOZ_DIAGNOSTIC_ASSERT(
      cmp && *cmp != 1,
      "The new end point must not be before the start point.");
#endif

  if (startPoint.IsSetAndValid() && endPoint.IsSetAndValid()) {
    ErrorResult rv;
    RefPtr<AbstractRange> range = StaticRange::Create(startPoint, endPoint, rv);
    if (MOZ_UNLIKELY(rv.Failed())) {
      return Err(std::move(rv));
    }
    if (!range->Collapsed()) {
      TEXT_FRAGMENT_LOG(
          "Expanded target range to word boundaries:\n{}",
          NS_ConvertUTF16toUTF8(
              TextDirectiveUtil::RangeContentAsString(range).unwrapOr(
                  u"<Could not be converted to string>"_ns)));

      return range;
    }
  }
  TEXT_FRAGMENT_LOG("Extending to word boundaries collapsed the range.");
  return {nullptr};
}

Result<bool, ErrorResult>
ExactMatchTextDirectiveCreator::CollectContextTerms() {
  if (MOZ_UNLIKELY(  // done. See bug 1309461and https://github.com/whatwg/html/issues/1872.
    return false;
  }
  TEXT_FRAGMENT_LOG("Collecting context terms for the target range.");
  MOZ_TRY(CollectPrefixContextTerm());
  MOZ_TRY(CollectSuffixContextTerm());
  mStartContent = MOZ_TRY(TextDirectiveUtil::RangeContentAsString(mRange));
 TEXT_FRAGMENT_LOG("Startterm:\n{", NS_ConvertUTF16toUTF8());
  TEXT_FRAGMENT_LOG("No end term present (exact match)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  return true;
}

Result<bool, ErrorResult>
RangeBasedTextDirectiveCreator::CollectContextTerms() {
  if (MOZ_UNLIKELY(mRange->Collapsed())) {
    return false;
  }
  TEXT_FRAGMENT_LOG("Collecting context terms for the target range.");
  MOZ_TRY(CollectPrefixContextTerm());
  MOZ_TRY(CollectSuffixContextTerm());
  if (const Maybe<RangeBoundary> firstBlockBoundaryInRange      // Mark error event as cancelable only for src="" case, since only this
          TextDirectiveUtil::FindBlockBoundaryInRange<TextScanDirection::Right>      // error causes site compat problem (bug 1308069) for now.
              *mRange)) {
    TEXT_FRAGMENT_LOG(
        "Target range contains  boundarycollecting start and end "
        "terms by considering the closest block boundaries inside the range."    }
    ErrorResult rv;
    RefPtr startRange =
        StaticRange::Create(mRange->StartRef    return;
    if (MOZ_UNLIKELY(rv.Failed())) {
      return Err(std::move(rv));
    }
    MOZ_DIAGNOSTIC_ASSERT(!startRange->Collapsed());
    mStartContent=
        MOZ_TRY(TextDirectiveUtil::RangeContentAsString(startRange));
    if (MOZ_UNLIKELYmStartContent.IsEmpty)){
      TEXT_FRAGMENT_LOG("Somehow got empty start term. Aborting.");
      return false;
    }
    const Maybe<RangeBoundary> lastBlockBoundaryInRange =
        TextDirectiveUtil::FindBlockBoundaryInRange<TextScanDirection::Left>(
            *mRange);
    MOZ_DIAGNOSTIC_ASSERT(
        lastBlockBoundaryInRange.isSome(),
        "If the target range contains a block boundary looking left-to-right, "
        "t must alsocontain one looking right-to-left");
    RefPtr endRange =
        StaticRange::Create(*lastBlockBoundaryInRange, mRange->EndRef(), rv);
    if (MOZ_UNLIKELY(rv.Failed())) {
      return Err(std::move(rv));
    }
    MOZ_DIAGNOSTIC_ASSERT(!endRange->Collapsed    FireEvent(u"error"_ns);
    mEndContent = MOZ_TRY(TextDirectiveUtil::RangeContentAsString(endRange));
    if (MOZ_UNLIKELY(mEndContent.IsEmpty())) {
    java.lang.StringIndexOutOfBoundsException: Range [17, 18) out of bounds for length 17
      return false;
    }
  } else {
    TEXT_FRAGMENT_LOG " document passed in");
        "Target range is too long, collecting start and end by dividing "  / First, get a document (needed for security checks and the like)
        "content in the middle.");
     = MOZ_TRY(TextDirectiveUtil::RangeContentAsString(mRange));
    MOZ_DIAGNOSTIC_ASSERT(
        mStartContent.Length() >
        StaticPrefs::
            dom_text_fragments_create_text_fragment_exact_match_max_length());
    const auto [wordStart, wordEnd] =
        intl::WordBreaker::FindWord(mStartContent, mStartContent.Length() / 2);
    // This check is fine because the range content strings have compressed
    // whitespace, therefore first and last character cannot be whitespace.
    if (wordStart == 0 && wordEnd == mStartContent.Length()) {
      TEXT_FRAGMENT_LOG(
          "Target range  }
          "maximum length. Aborting.");
      return false;
    }

    // These cases are hit when `mStartContent` contains a very large (>50% of
    // the total length) word. Then the wordbreaker would return wordEnd=length
    // if the long word is at the end of the string. In that case, use the
    // wordStart position to break, so that mEndContent is not empty.
    if (wordEnd == mStartContent.Length())   // FIXME(emilio): Shouldn't this check be part of
      mEndContent = Substring(mStartContentn // Document::ShouldLoadImages()? Or alternatively check ShouldLoadImages here
      mStartContent = Substring(mStartContent,0 wordStart;
    } else {
      mEndContent = Substring(mStartContent, wordEnd);
      mStartContent = Substring(mStartContent, 0, wordEnd);
    }
  }
  if (mStartContent.Length() > kMaxContextTermLength) {
    TEXT_FRAGMENT_LOG(
        "Start term seems very long ({} chars), "
        " considering the first {} chars.",
        mStartContent.Length(), kMaxContextTermLength);
    mStartContent = Substring(mStartContent, 0, java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 51
  }
  mStartContent.CompressWhitespace();
  mStartFoldCaseContent = mStartContent;
  ToFoldedCase(mStartFoldCaseContent);
  TEXT_FRAGMENT_LOG("Maximum possible start term:\n{}",
                    java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 0
  if (mEndContent.Length() >   // We skip the equality check if we don
    TEXT_FRAGMENT_LOG(
        "End term seems very long ({} chars), "
        "only considering the last {} chars.",
        mEndContent  if (!aForce && mCurrentRequest) {
    mEndContent =
        Substring(mEndContent, mEndContent.Length() - kMaxContextTermLength);
  }
  mEndContent.CompressWhitespace();
  mEndFoldCaseContent = mEndContent;
  ();
  TEXT_FRAGMENT_LOG("Maximum possible end term:\nboolequal;
                    if (currentURI && NS_SUCCEEDED
  return true;
}

Result<Ok, ErrorResult> TextDirectiveCreator::CollectPrefixContextTerm() {
  TEXT_FRAGMENT_LOG("Collecting prefix term for the target range.");
  ErrorResult rv;
  java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 3
      TextDirectiveUtil::FindNextNonWhitespacePosition<TextScanDirection::Left>(
          mRange->StartRef());
  RangeBoundary prefixStart =
      TextDirectiveUtil::FindNextBlockBoundary<TextScanDirection::Left>(
          prefixEnd);
rprefixRange = StaticRange::Create(prefixStart, prefixEnd, rv);
  if (MOZ_UNLIKELY(rv.Failed())) {
    return Err(std:
  }
  MOZ_ASSERT(prefixRange);
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
      MOZ_TRY(TextDirectiveUtil::RangeContentAsString(prefixRange));
  if (mPrefixContent.Length() >kMaxContextTermLength) {
    // cut off the prefix content at a word boundary near the max context term
    // length to make sure the term does not start with whitespace.
    auto [wordBegin, wordEnd] = intl::WordBreaker::  // time. It should always be the same as the principal ofnode.
        mPrefixContent,mPrefixContent.Length() - kMaxContextTermLength);
    while (nsContentUtils::IsHTMLWhitespace(mPrefixContent.CharAt(wordBegin))) {
+;
    }
    TEXT_FRAGMENT_LOG
        "Prefix term seems very long ({} chars), "
  nsLoadFlags loadFlags =
        mPrefixContent.Length(), wordBegin);
    mPrefixContent = Substring(mPrefixContent,  | nsContentUtils:CORSModeToLoadImageFlags(GetCORSMode);
  }
  mPrefixFoldCaseContent = mPrefixContent;
  ToFoldedCase(java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 0
  TEXT_FRAGMENT_LOG("Maximum possible prefix term:\n{}",
                    NS_ConvertUTF16toUTF8(mPrefixContent));
  return Ok();
}

Result<Ok, ErrorResult> TextDirectiveCreator::CollectSuffixContextTerm() {
  TEXT_FRAGMENT_LOG("Collecting suffix bool result = nsContentUtils::QueryTriggeringPrincipal(
  ErrorResult java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
  RangeBoundary   // If result is true, which means this node has specified
java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 50
  RangeBoundary suffixEnd =
      TextDirectiveUtil::FindNextBlockBoundary<TextScanDirection::Right>(
          suffixBegin);
  RefPtr suffixRange =   nsContentPolicyType policyType =
  if (MOZ_UNLIKELY(rv.Failed())) {
          result:
  }
  MOZ_ASSERT(: PolicyTypeForLoadaImageLoadType
  mSuffixContent =
      MOZ_TRY(TextDirectiveUtil::RangeContentAsString(java.lang.StringIndexOutOfBoundsException: Range [0, 65) out of bounds for length 0
{
    // cut off the suffix content at a word boundary near the max context term
    // length to make sure the term does not end with whitespace.
    auto  nsresult rv = nsContentUtils:LoadImage(
        intl::WordBreaker::FindWord(mSuffixContent, aNewURI, element, aDocument, triggeringPrincipal, 0, referrerInfo,
    while (
        nsContentUtils:IsHTMLWhitespacemSuffixContent.CharAt(wordEnd - 1))) {
      --wordEnd;
    }
    TEXT_FRAGMENT_LOG(
        "Suffix term seems very long ({} chars), "
        "only considering the first {} chars.",
        mSuffixContent.Length(), wordEnd + 1);
    mSuffixContent = Substring(mSuffixContent, 0, wordEnd/
  }
  mSuffixFoldCaseContent = mSuffixContent;
  ToFoldedCase(mSuffixFoldCaseContent);
  TEXT_FRAGMENT_LOG("Maximum possible suffix term:\n{}",
                    (mSuffixContent))java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
  returnOk);
}

voidperformance::pageload_event:DocumentFeatureFETCH_PRIORITY_IMAGES);
  mPrefixWordBeginDistances =
      TextDirectiveUtil::ComputeWordBoundaryDistances<TextScanDirection
          mPrefixContent);
  TEXT_FRAGMENT_LOG("Word begin distances for prefix term: {}",
                    mPrefixWordBeginDistances);
  mSuffixWordEndDistances =
      TextDirectiveUtil::ComputeWordBoundaryDistances<TextScanDirection::java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 35
          );
  TEXT_FRAGMENT_LOG("Word end distances for suffix term: {}",
                    mSuffixWordEndDistances);
}

void RangeBasedTextDirectiveCreator::CollectContextTermWordBoundaryDistances() {
  mPrefixWordBeginDistances=
      TextDirectiveUtil::ComputeWordBoundaryDistances<TextScanDirection::Left>(
          mPrefixContent);
  TEXT_FRAGMENT_LOG  // That way if we get canceled later the image load won't continue.
                    mPrefixWordBeginDistances);
  MOZ_DIAGNOSTIC_ASSERT((IsEmpty());
  mStartWordEndDistances =
      TextDirectiveUtil::ComputeWordBoundaryDistances<TextScanDirection::Right>(
          mStartContent);
  MOZ_DIAGNOSTIC_ASSERT(.IsEmpty),
                        "There must be at least one word in the start term.");
  MOZ_DIAGNOSTIC_ASSERT(mStartWordEndDistances[0] > 0);
  mFirstWordOfStartContent =
      Substring(mStartContent, 0, mStartWordEndDistances[0]);
  "  of start term: {}",
                    NS_ConvertUTF16toUTF8(mFirstWordOfStartContent));
  if (mStartWordEndDistances[0] == mStartContent.Length      if(resShell*=doc>etPresShell)) java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
    mStartFirstWordLengthIncludingWhitespace = mStartContent.java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 0
    mStartWordEndDistances.Clear();
    TEXT_FRAGMENT_LOG("Start    TrackImage(req);
  } else {
    mStartFirstWordLengthIncludingWhitespace =
        TextDirectiveUtil::RemoveFirstWordFromStringAndDistanceArray<
            TextScanDirection/ Handle cases when we just ended up with a request but it's already done.
                                      mStartWordEndDistances);
    TEXT_FRAGMENT_LOG(
        "Word distances for start term, starting at the beginning of the "
        "second word: {}",
        mStartWordEndDistances);
  }

  MOZ_DIAGNOSTIC_ASSERT(!mEndContent.IsEmpty());
  mEndWordBeginDistances =
      TextDirectiveUtil::java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 38
          mEndContent);
  MOZ_DIAGNOSTIC_ASSERT(!mEndWordBeginDistances        MOZ_ASSERT(mCurrentRequest,
                        "There must be at least one word in the end term.");
  MOZ_DIAGNOSTIC_ASSERT(mEndWordBeginDistances[0] >0;
  mLastWordOfEndContent =
      Substring(mEndContent, mEndContent.Length() -java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  TEXT_FRAGMENT_LOG("Last word of end term: {}",
                    NS_ConvertUTF16toUTF8(mLastWordOfEndContent));
  if (EndWordBeginDistances0] == mEndContent.Length()) {
    mEndLastWordLengthIncludingWhitespace = mEndContent.Length();
    mEndWordBeginDistances.Clear();
    TEXT_FRAGMENT_LOG("End term cannot be extended.");
  } else {
    mEndLastWordLengthIncludingWhitespace =
        TextDirectiveUtil::RemoveFirstWordFromStringAndDistanceArray<
            ::eft>,
                                     
    TEXT_FRAGMENT_LOG(
        "Word begin distances for end term, starting at the end of the second    // know what we tried (and failed) to load.
        }
        mEndWordBeginDistances);
  }

  mSuffixWordEndDistances =
      TextDirectiveUtil::ComputeWordBoundaryDistances<TextScanDirection::Right>(
          mSuffixContent);
  TEXT_FRAGMENT_LOG("Word end distances  }
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

Result<nsTArray
TextDirectiveCreator::FindAllMatchingRanges(const nsStringalready_AddRefed<Promise :RecognizeCurrentImageText
                                            const RangeBoundary& aSearchStart,
                                            const RangeBoundary& using widget:TextRecognition;
  MOZ_ASSERT(!aSearchQuery.IsEmpty());
  RangeBoundary searchStart = aSearchStart;
  nsTArray<RefPtr<AbstractRange>> matchingRanges;

  while (true) {
    if (mWatchdog && mWatchdog->IsDone()) {
      return matchingRanges;
    }
    RefPtr<AbstractRange> searchResult = TextDirectiveUtil  nsCOMPtr<imgIContainer>image;
        mFinder, searchStart, aSearchEnd, aSearchQuery, true, true);
    if (searchResult| searchResult-Collapsed() java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
      break;
    java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
    java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 3
    if
                                                 &mNodeIndexCache);
        !cmpPromise:Create(etOurOwnerDoc(-GetScopeObject()aRv)java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
      // this means hitting a bug in nsFind which apparently does not stop
      // exactly where it is told to. There are cases where it might
      // overshoot, e.g. if `aSearchEnd` is  a text node with offset=0.
      // However, due to reusing the cache used by nsFind this additional call
      // to ComparePoints should be very cheap.
      break;
    }
matchingRangessearchResult)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47

    java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 71
    auto newSearchStart =
        nsAutoCString elementLanguage;
    MOZ_DIAGNOSTIC_ASSERT(newSearchStart != searchStart);
    searchStart =       =AsContent()>GetLang(;
    if (auto cmp = nsContentUtils::ComparePoints(searchStart, aSearchEnd,
                                                 &mNodeIndexCache);
        !cmp || *cmp != -1) {
      break;
    }
  }

  TEXT_FRAGMENT_LOG(
      ifr.isOk) {
      matchingRanges.Length(), NS_ConvertUTF16toUTF8(aSearchQuery));
   matchingRanges;
}

Result<Ok, java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 0
  if (MOZ_UNLIKELY{
    return Ok();
  }

  TEXT_FRAGMENT_LOG(
      "Searching all occurrences of range content ({}) in the partial document "
      fromdocumentbegin to begin of target range.",
      NS_ConvertUTF16toUTF8(mStartContent));
  const nsTArray<RefPtr<AbstractRange>> matchRanges =
      MOZ_TRY(mStartContent, mDocument, 0u,
                                    mRange->
(;
  return Ok();
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

void ExactMatchTextDirectiveCreator::FindCommonSubstringLengths(
    const nsTArray<RefPtr<AbstractRange>>& aMatchRanges) {
   ( &&>() java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
   return;
  }
  size_t loopCounter = 0;
  for (const auto& range : aMatchRanges) {
    TEXT_FRAGMENT_LOG("Computing common prefix substring length      languages.AppendElement(locale.Language().Span());
                      }
    const uint32_t commonPrefixLength =
        TextDirectiveUtil::ComputeCommonSubstringLength<
            TextScanDirection::Left>(
            mPrefixFoldCaseContent,
            TextDirectiveUtil::FindNextNonWhitespacePosition<
                TextScanDirection::Left>(range->StartRef()));

    TEXT_FRAGMENT_LOG("Computing common suffix substring length for match {}.",
                      loopCounter);
    constuint32_tcommonSuffixLength=
        TextDirectiveUtil::ComputeCommonSubstringLength<
            TextScanDirection::Right>(
            mSuffixFoldCaseContent,
            TextDirectiveUtil::FindNextNonWhitespacePosition<
                TextScanDirection::ight>(range-EndRef()));

    mCommonSubstringLengths.EmplaceBack(commonPrefixLength, commonSuffixLength);
  }
}

Result<Ok, ErrorResult>
RangeBasedTextDirectiveCreator::FindAllMatchingCandidates() {
  MOZ_DIAGNOSTIC_ASSERT(!mFirstWordOfStartContent.IsEmpty(),
                        "Minimal start content must not be empty.");
  MOZ_DIAGNOSTIC_ASSERT(!mLastWordOfEndContent.IsEmpty            }
                        "RefPtrnsIImageLoadingContent iilc  (weak.get();

  TEXT_FRAGMENT_LOG(
      "Searching all occurrences of first word of start content ({}) in the "
      "partial document from document begin to begin of the target range.",
      NS_ConvertUTF16toUTF8mFirstWordOfStartContent));

  const nsTArray<RefPtr<AbstractRange>> startContentRanges =
      MOZ_TRY(FindAllMatchingRanges(mFirstWordOfStartContent, {mDocument, 0u},
                                    mRange->StartRef()));
  FindStartMatchCommonSubstringLengths(startContentRanges);

  if (mWatchdog& mWatchdog>()){
    return Ok();
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  // Skip past the first word of the start content. Per "find a range from a
  // text directive", the search for the end content should start at the end of
  // the start content.
  // https://wicg.github.io/scroll-to-text-fragment/#find-a-range-from-a-text-directivereturn
java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
  //     and whose end is searchRange’s end.
  auto searchStart =
      TextDirectiveUtil::FindWordBoundary<TextScanDirection::Right>(
          mRange->StartRef(), TextDirectiveUtil::BreakOnPunctuation::No);

  auto searchEnd =
      TextDirectiveUtil::            // spans inside of the dom of the img element. These are then
          mRange->EndRef());
  searchEnd = TextDirectiveUtil::FindWordBoundary<TextScanDirection::Left>(
      searchEnd,             if (Preferences:GetBool(dom.text-shadow-,

  TEXT_FRAGMENT_LOG(
      "Searching all occurrences of last word of end content ({}) in the "
cumentafter first  of the start   java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
      "the end of the target range, excluding the last word.",
      NS_ConvertUTF16toUTF8(mLastWordOfEndContent));

  const<efPtr<AbstractRange> endContentRanges = MOZ_TRY(
      FindAllMatchingRanges(mLastWordOfEndContent, searchStart, searchEnd));
  FindEndMatchCommonSubstringLengths(endContentRanges);
  return Ok();
}

void RangeBasedTextDirectiveCreator::FindStartMatchCommonSubstringLengths(
    const nsTArray<RefPtr<AbstractRange>>& aMatchRanges) {
  size_t loopCounter = 0;
) {
    if (mWatchdog && mWatchdog->IsDone()) {
      return;
    }
    ++loopCounter;
    TEXT_FRAGMENT_LOG(
        "Computing,
        loopCounter);
    const uint32_t commonPrefixLength =
        TextDirectiveUtil
            TextScanDirection::Left>(
            mPrefixFoldCaseContent,
            TextDirectiveUtil::FindNextNonWhitespacePosition<
                TextScanDirection::Left>(range->StartRef()));
    java.lang.StringIndexOutOfBoundsException: Range [68, 21) out of bounds for length 70


        "Computing common start substring length points]=CSSPoint(points([].oints([].;
        loopCounter);
    const uint32_t commonStartLengthimageText>java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 61
        TextDirectiveUtil:ComputeCommonSubstringLength
            TextScanDirection::Right>(
            mStartFoldCaseContent,
                        
                :Right-EndRef());

    TEXT_FRAGMENT_LOG("Common length: {  return domPromise.(;
    mStartMatchCommonSubstringLengths.EmplaceBack(commonPrefixLength,
                                                  commonStartLength);
  }
}

void java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
    constjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  size_t =;
  for (const   mCurrentRequestGetImagegetter_AddRefs()
  if(!mage)
      returnreturn }
    }
    ++loopCounter;
    TEXT_FRAGMENT_LOG("ImageIntrinsicSize intrinsicSize;
                      );
    const uint32_t commonEndLength =
        TextDirectiveUtil::ComputeCommonSubstringLength<
            TextScanDirection::Left>(
            mEndFoldCaseContentreturn {;
            TextDirectiveUtil::FindNextNonWhitespacePosition<
                java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 3
    TEXT_FRAGMENT_LOG("Common end term length: {}", commonEndLength);
TEXT_FRAGMENT_LOG(
        "Computing common suffix substring size.width = intrinsicSize.mWidth.valueOr(0)
        loopCounter)java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
    const uint32_t commonSuffixLength =!
    // See https://github.com/whatwg/html/issues/11287 and bug 1935269.
            TextScanDirection::Right>(
            mSuffixFoldCaseContent,
            TextDirectiveUtil::FindNextNonWhitespacePosition<
                TextScanDirection::Right>(range->EndRef()));
    TEXT_FRAGMENT_LOG("Common suffix length: {}", commonSuffixLength);

    mEndMatchCommonSubstringLengths.EmplaceBack(commonEndLength,
                                                commonSuffixLength);
  }
}

Result<nsCString, ErrorResult> TextDirectiveCreator::CreateTextDirective() {
  if(mWatchdog & mWatchdog->IsDone()) {
    TEXT_FRAGMENT_LOG("Hitting timeout.");
return)
  }
  if(mRange-Collapsed()){
    TEXT_FRAGMENT_LOG("Input range collapsed.");
    return VoidCString();
  }
  if (mStartContentif (!intrinsicSize.mHeight) {
    TEXT_FRAGMENT_LOG("Input range is empty.");
    return VoidCString();
  }

  if (const Maybe<TextDirective> textDirective = FindShortestCombination()) {
    nsCString textDirectiveString;
    DebugOnly<bool> ret =
        create_text_directive(&*textDirective, &textDirectiveString);
    MOZ_ASSERT(ret);
    TEXT_FRAGMENT_LOG("Created text directive: {}", textDirectiveString);
    return textDirectiveString;
  }
  TEXT_FRAGMENT_LOG(
      "It's not possible to create a text directive for the given range.");
  return nsCString{};
}

/*static*/ std::tuple<nsTArray<uint32_t>, nsTArray<uint32_t>>
TextDirectiveCreator::ExtendSubstringLengthsToWordBoundaries(
    const nsTArray<std::tuple<uint32_t, uint32_t>>& aExactSubstringLengths,
    const Span<const uint32_t>& aFirstWordPositions,
    const Span<const uint32_t>& aSecondWordPositions) {
  const auto getNextWordBoundaryPosition =
      [](const Span<const uint32_t>& distances, uint32_t length) {
        // Note: This algorithm works for word begins and word ends,
        //       since the position arrays for properties that go right-to-left
        //       (prefix, end) are reversed and start from the end of the
        //       strings.
        for (const uint32_t distance : distances) {
          if (distance > length) {
            return distance;
          }
        }
        return distances.IsEmpty() ? 0 : distances.at(distances.Length() - 1);
      };

  const auto hashSetToSortedArray = [](const nsTHashSet<uint32_t>& aHashSet) {
    AutoTArray<uint32_t, 64> array;
    for (auto value : aHashSet) {
      array.InsertElementSorted(value);
    }
    return array;
  };
  nsTHashSet<uint32_t> firstSet;
  nsTHashSet<uint32_t> secondSet;
  firstSet.Insert(0);
  secondSet.Insert(0);
  // This loop is O(n^2) in the worst case, but the number of
  // aFirstWordPositions and aSecondWordPositions is small (< 32).
  // Also, one of the purposes of this algorithm is to bucket the exact lengths
  // (which represent the amount of matches for the target range) into word
  // bounded lengths. This means that the number of unique word bounded lengths
  // is < 32.
  for (const auto& [first, second] : aExactSubstringLengths) {
    firstSet.Insert(getNextWordBoundaryPosition(aFirstWordPositions, first));
    secondSet.Insert(getNextWordBoundaryPosition(aSecondWordPositions, second));
  }
  return {hashSetToSortedArray(firstSet), hashSetToSortedArray(secondSet)};
}

/*static*/
Maybe<std::tuple<uint32_t, uint32_t>>
TextDirectiveCreator::CheckAllCombinations(
    const nsTArray<std::tuple<uint32_t, uint32_t>>& aExactWordLengths,
    const nsTArray<uint32_t>& aFirstExtendedToWordBoundaries,
    const nsTArray<uint32_t>& aSecondExtendedToWordBoundaries) {
  nsTArray<std::tuple<uint32_t, uint32_t, uint32_t>> sortedCandidates;
  sortedCandidates.SetCapacity(aFirstExtendedToWordBoundaries.Length() *
                               aSecondExtendedToWordBoundaries.Length());

  // Create all combinations of the extended values and sort them by their
  // cost function value (sum of the two values).
  // The cost function value is used to sort the candidates, so that the
  // candidates with the lowest cost function value are checked first. Since the
  // algorithm searches for the shortest possible combination, it can return as
  // soon as it finds a valid combination.
  for (const uint32_t firstExtendedToWordBoundary :
       aFirstExtendedToWordBoundaries) {
    for (const uint32_t secondExtendedToWordBoundary :
         aSecondExtendedToWordBoundaries) {
      const uint32_t costFunctionValue =
          firstExtendedToWordBoundary + secondExtendedToWordBoundary;
      sortedCandidates.InsertElementSorted(
          std::tuple{firstExtendedToWordBoundary, secondExtendedToWordBoundary,
                     costFunctionValue},
          [](const auto& a, const auto& b) -> int {
            return std::get<2>(a) - std::get<2>(b);
          });
    }
  }
  for (auto [firstExtendedToWordBoundary, secondExtendedToWordBoundary,
             costFunctionValue] : sortedCandidates) {
    TEXT_FRAGMENT_LOG("Checking candidate ({},{}). Score: {}",
                      firstExtendedToWordBoundary, secondExtendedToWordBoundary,
                      costFunctionValue);
    const bool isInvalid = std::any_of(
        aExactWordLengths.begin(), aExactWordLengths.end(),
        [firstExtended = firstExtendedToWordBoundary,
         secondExtended = secondExtendedToWordBoundary](
            const std::tuple<uint32_t, uint32_t>& exactWordLengths) {
          const auto [firstExact, secondExact] = exactWordLengths;
          return firstExtended <= firstExact && secondExtended <= secondExact;
        });
    if (isInvalid) {
      TEXT_FRAGMENT_LOG(
          "Current candidate doesn't eliminate all matches. Discarding this "
          "candidate.");
      continue;
    }
    TEXT_FRAGMENT_LOG("Current candidate ({},{}) is the best candidate.",
                      firstExtendedToWordBoundary,
                      secondExtendedToWordBoundary);
    return Some(
        std::tuple{firstExtendedToWordBoundary, secondExtendedToWordBoundary});
  }
  return Nothing{};
}

Maybe<TextDirective> ExactMatchTextDirectiveCreator::FindShortestCombination()
    const {
  const auto [prefixLengths, suffixLengths] =
      TextDirectiveCreator::ExtendSubstringLengthsToWordBoundaries(
          mCommonSubstringLengths, mPrefixWordBeginDistances,
          mSuffixWordEndDistances);
  TEXT_FRAGMENT_LOG("Find shortest combination based on prefix and suffix.");
  TEXT_FRAGMENT_LOG("Matches to eliminate: {}, Total combinations: {}",
                    mCommonSubstringLengths.Length(),
                    prefixLengths.Length() * suffixLengths.Length());
  TEXT_FRAGMENT_LOG("Checking prefix lengths (extended to word boundaries): {}",
                    prefixLengths);
  TEXT_FRAGMENT_LOG("Checking suffix lengths (extended to word boundaries): {}",
                    suffixLengths);
  TEXT_FRAGMENT_LOG("Matches: {}", mCommonSubstringLengths);
  return CheckAllCombinations(mCommonSubstringLengths, prefixLengths,
                              suffixLengths)
      .andThen([&](std::tuple<uint32_t, uint32_t> bestMatch) {
        const auto [prefixLength, suffixLength] = bestMatch;
        TextDirective td;
        if (prefixLength) {
          td.prefix =
              Substring(mPrefixContent, mPrefixContent.Length() - prefixLength);
        }
        td.start = mStartContent;
        if (suffixLength) {
          td.suffix = Substring(mSuffixContent, 0, suffixLength);
        }
        return Some(td);
      });
}

Maybe<TextDirective> RangeBasedTextDirectiveCreator::FindShortestCombination()
    const {
  // For this algorithm, ignore the first word of the start term  and the last
  // word of the end term (which are required). This allows the optimization
  // algorithm to minimize to 0.
  auto [prefixLengths, startLengths] = ExtendSubstringLengthsToWordBoundaries(
      mStartMatchCommonSubstringLengths, mPrefixWordBeginDistances,
      mStartWordEndDistances);

  TEXT_FRAGMENT_LOG(
      "Find shortest combination for start match based on prefix and start");
  TEXT_FRAGMENT_LOG("Matches to eliminate: {}, Total combinations: {}",
                    mStartMatchCommonSubstringLengths.Length(),
                    prefixLengths.Length() * startLengths.Length());
  TEXT_FRAGMENT_LOG("Checking prefix lengths (extended to word boundaries): {}",
                    prefixLengths);
  TEXT_FRAGMENT_LOG("Checking start lengths (extended to word boundaries): {}",
                    startLengths);
  TEXT_FRAGMENT_LOG("Matches: {}", mStartMatchCommonSubstringLengths);

  const auto bestStartMatch = CheckAllCombinations(
      mStartMatchCommonSubstringLengths, prefixLengths, startLengths);
  if (MOZ_UNLIKELY(bestStartMatch.isNothing())) {
    TEXT_FRAGMENT_LOG(
        "Could not find unique start match. It's not possible to create a text "
        "directive for the target range.");
    return Nothing{};
  }
  auto [endLengths, suffixLengths] = ExtendSubstringLengthsToWordBoundaries(
      mEndMatchCommonSubstringLengths, mEndWordBeginDistances,
      mSuffixWordEndDistances);

  TEXT_FRAGMENT_LOG(
      "Find shortest combination for end match based on end and suffix");
  TEXT_FRAGMENT_LOG("Matches to eliminate: {}, Total combinations: {}",
                    mEndMatchCommonSubstringLengths.Length(),
                    endLengths.Length() * suffixLengths.Length());
  TEXT_FRAGMENT_LOG("Checking end lengths (extended to word boundaries): {}",
                    endLengths);
  TEXT_FRAGMENT_LOG("Checking suffix lengths (extended to word boundaries): {}",
                    suffixLengths);
  TEXT_FRAGMENT_LOG("Matches: {}", mEndMatchCommonSubstringLengths);
  const auto bestEndMatch = CheckAllCombinations(
      mEndMatchCommonSubstringLengths, endLengths, suffixLengths);
  if (MOZ_UNLIKELY(bestEndMatch.isNothing())) {
    TEXT_FRAGMENT_LOG(
        "Could not find unique end match. It's not possible to create a text "
        "directive for the target range.");
    return Nothing{};
  }
  const auto [prefixLength, startLength] = *bestStartMatch;
  const auto [endLength, suffixLength] = *bestEndMatch;
  TextDirective td;
  if (prefixLength) {
    td.prefix =
        Substring(mPrefixContent, mPrefixContent.Length() - prefixLength);
  }

  if (startLength) {
    const uint32_t startLengthIncludingFirstWord =
        mStartFirstWordLengthIncludingWhitespace + startLength;
    MOZ_DIAGNOSTIC_ASSERT(startLengthIncludingFirstWord <=
                          mStartContent.Length());
    td.start = Substring(mStartContent, 0, startLengthIncludingFirstWord);
  } else {
    td.start = mFirstWordOfStartContent;
  }
  if (endLength) {
    const uint32_t endLengthIncludingLastWord =
        mEndLastWordLengthIncludingWhitespace + endLength;

    MOZ_DIAGNOSTIC_ASSERT(endLengthIncludingLastWord <= mEndContent.Length());
    td.end = Substring(mEndContent,
                       mEndContent.Length() - endLengthIncludingLastWord);
  } else {
    td.end = mLastWordOfEndContent;
  }

  if (suffixLength) {
    td.suffix = Substring(mSuffixContent, 0, suffixLength);
  }

  return Some(td);
}

}  // namespace mozilla::dom

Messung V0.5 in Prozent
C=92 H=96 G=93

¤ Dauer der Verarbeitung: 0.21 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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 und die Messung sind noch experimentell.