static void findGrammaticalErrors(TextCheckerClient& client, StringView text, Vector<TextCheckingResult>& results) { for (unsigned checkLocation = 0; checkLocation < text.length(); ) { int badGrammarLocation = -1; int badGrammarLength = 0; Vector<GrammarDetail> badGrammarDetails; client.checkGrammarOfString(text.substring(checkLocation), badGrammarDetails, &badGrammarLocation, &badGrammarLength); if (!badGrammarLength) break; ASSERT(badGrammarLocation >= 0); ASSERT(static_cast<unsigned>(badGrammarLocation) <= text.length() - checkLocation); ASSERT(badGrammarLength > 0); ASSERT(static_cast<unsigned>(badGrammarLength) <= text.length() - checkLocation - badGrammarLocation); TextCheckingResult badGrammar; badGrammar.type = TextCheckingTypeGrammar; badGrammar.location = checkLocation + badGrammarLocation; badGrammar.length = badGrammarLength; badGrammar.details = WTFMove(badGrammarDetails); results.append(badGrammar); checkLocation += badGrammarLocation + badGrammarLength; } }
// https://wicg.github.io/entries-api/#valid-path static bool isValidVirtualPath(StringView virtualPath) { if (virtualPath.isEmpty()) return true; if (virtualPath[0] == '/') { // An absolute path is a string consisting of '/' (U+002F SOLIDUS) followed by one or more path segments joined by '/' (U+002F SOLIDUS). return isZeroOrMorePathSegmentsSeparatedBySlashes(virtualPath.substring(1)); } return isValidRelativeVirtualPath(virtualPath); }
Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool) { UNUSED_PARAM(insertionPoint); Vector<TextCheckingResult> paragraphCheckingResult; #if ENABLE(SPELLCHECK) if (checkingTypes & TextCheckingTypeSpelling) { TextBreakIterator* textIterator = wordBreakIterator(text); if (!textIterator) return paragraphCheckingResult; // Omit the word separators at the beginning/end of the text to don't unnecessarily // involve the client to check spelling for them. unsigned offset = nextWordOffset(text, 0); unsigned lengthStrip = text.length(); while (lengthStrip > 0 && isTextBreak(textIterator, lengthStrip - 1)) --lengthStrip; while (offset < lengthStrip) { int32_t misspellingLocation = -1; int32_t misspellingLength = 0; checkSpellingOfString(spellDocumentTag, text.substring(offset, lengthStrip - offset), misspellingLocation, misspellingLength); if (!misspellingLength) break; TextCheckingResult misspellingResult; misspellingResult.type = TextCheckingTypeSpelling; misspellingResult.location = offset + misspellingLocation; misspellingResult.length = misspellingLength; paragraphCheckingResult.append(misspellingResult); offset += misspellingLocation + misspellingLength; // Generally, we end up checking at the word separator, move to the adjacent word. offset = nextWordOffset(text.substring(0, lengthStrip), offset); } } #else UNUSED_PARAM(spellDocumentTag); UNUSED_PARAM(text); UNUSED_PARAM(insertionPoint); UNUSED_PARAM(checkingTypes); #endif return paragraphCheckingResult; }
String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange) { WordAwareIterator it(*m_range); firstMisspellingOffset = 0; String firstMisspelling; int currentChunkOffset = 0; while (!it.atEnd()) { StringView text = it.text(); int textLength = text.length(); // Skip some work for one-space-char hunks if (textLength == 1 && text[0] == ' ') { int misspellingLocation = -1; int misspellingLength = 0; m_client->textChecker()->checkSpellingOfString(text, &misspellingLocation, &misspellingLength); // 5490627 shows that there was some code path here where the String constructor below crashes. // We don't know exactly what combination of bad input caused this, so we're making this much // more robust against bad input on release builds. ASSERT(misspellingLength >= 0); ASSERT(misspellingLocation >= -1); ASSERT(!misspellingLength || misspellingLocation >= 0); ASSERT(misspellingLocation < textLength); ASSERT(misspellingLength <= textLength); ASSERT(misspellingLocation + misspellingLength <= textLength); if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < textLength && misspellingLength <= textLength && misspellingLocation + misspellingLength <= textLength) { // Compute range of misspelled word RefPtr<Range> misspellingRange = TextIterator::subrange(m_range.get(), currentChunkOffset + misspellingLocation, misspellingLength); // Remember first-encountered misspelling and its offset. if (!firstMisspelling) { firstMisspellingOffset = currentChunkOffset + misspellingLocation; firstMisspelling = text.substring(misspellingLocation, misspellingLength).toString(); firstMisspellingRange = misspellingRange; } // Store marker for misspelled word. misspellingRange->startContainer()->document().markers().addMarker(misspellingRange.get(), DocumentMarker::Spelling); // Bail out if we're marking only the first misspelling, and not all instances. if (!markAll) break; } } currentChunkOffset += textLength; it.advance(); } return firstMisspelling; }
IDBKeyPathLexer::TokenType IDBKeyPathLexer::lex(String& element) { if (m_remainingText.isEmpty()) return TokenEnd; if (m_remainingText[0] == '.') { m_remainingText = m_remainingText.substring(1); return TokenDot; } return lexIdentifier(element); }
// https://wicg.github.io/entries-api/#resolve-a-relative-path static String resolveRelativeVirtualPath(StringView baseVirtualPath, StringView relativeVirtualPath) { ASSERT(baseVirtualPath[0] == '/'); if (!relativeVirtualPath.isEmpty() && relativeVirtualPath[0] == '/') return relativeVirtualPath.length() == 1 ? relativeVirtualPath.toString() : resolveRelativeVirtualPath("/", relativeVirtualPath.substring(1)); Vector<StringView> virtualPathSegments; for (auto segment : baseVirtualPath.split('/')) virtualPathSegments.append(segment); for (auto segment : relativeVirtualPath.split('/')) { ASSERT(!segment.isEmpty()); if (segment == ".") continue; if (segment == "..") { if (!virtualPathSegments.isEmpty()) virtualPathSegments.removeLast(); continue; } virtualPathSegments.append(segment); } if (virtualPathSegments.isEmpty()) return "/"_s; StringBuilder builder; for (auto& segment : virtualPathSegments) { builder.append('/'); builder.append(segment); } return builder.toString(); }