Title: [262601] trunk
Revision
262601
Author
sihui_...@apple.com
Date
2020-06-04 23:13:30 -0700 (Thu, 04 Jun 2020)

Log Message

Text manipulation: first and last unit in a paragraph should not contain only excluded tokens
https://bugs.webkit.org/show_bug.cgi?id=212759

Reviewed by Wenson Hsieh.

Source/WebCore:

In r262398, we literally made text of one Node as the minimum unit for text manipulation. This patches introduce
a struct ManipulationUnit for that. Now a paragraph can be represented as multiple ManipulationUnits. When all
tokens in a ManipulationUnit are excluded, it means the ManipulationUnit is excluded and should not be
manipulated. To record ManipulationUnits in a paragraph based on our current implementation, we need to keep the
excluded ManipulationUnits surrounded by non-excluded ManipulationUnits, but we can safely remove the leading
and trailing excluded ManipulationUnits. In this case, we can limit the range of paragraph further and thus less
text replacement work.

Covered by existing test.

* editing/TextManipulationController.cpp:
(WebCore::TextManipulationController::parse):
(WebCore::TextManipulationController::addItemIfPossible):
(WebCore::TextManipulationController::observeParagraphs):
* editing/TextManipulationController.h:

Tools:

Modify existing test for changed behavior that leading and trailing excluded units are not included in paragraph
now.

* TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (262600 => 262601)


--- trunk/Source/WebCore/ChangeLog	2020-06-05 05:58:55 UTC (rev 262600)
+++ trunk/Source/WebCore/ChangeLog	2020-06-05 06:13:30 UTC (rev 262601)
@@ -1,3 +1,26 @@
+2020-06-04  Sihui Liu  <sihui_...@apple.com>
+
+        Text manipulation: first and last unit in a paragraph should not contain only excluded tokens
+        https://bugs.webkit.org/show_bug.cgi?id=212759
+
+        Reviewed by Wenson Hsieh.
+
+        In r262398, we literally made text of one Node as the minimum unit for text manipulation. This patches introduce
+        a struct ManipulationUnit for that. Now a paragraph can be represented as multiple ManipulationUnits. When all 
+        tokens in a ManipulationUnit are excluded, it means the ManipulationUnit is excluded and should not be 
+        manipulated. To record ManipulationUnits in a paragraph based on our current implementation, we need to keep the
+        excluded ManipulationUnits surrounded by non-excluded ManipulationUnits, but we can safely remove the leading 
+        and trailing excluded ManipulationUnits. In this case, we can limit the range of paragraph further and thus less
+        text replacement work.
+
+        Covered by existing test.
+
+        * editing/TextManipulationController.cpp:
+        (WebCore::TextManipulationController::parse):
+        (WebCore::TextManipulationController::addItemIfPossible):
+        (WebCore::TextManipulationController::observeParagraphs):
+        * editing/TextManipulationController.h:
+
 2020-06-04  Peng Liu  <peng.l...@apple.com>
 
         A YouTube video gets stuck after rapidly tapping on touchbar’s PIP button

Modified: trunk/Source/WebCore/editing/TextManipulationController.cpp (262600 => 262601)


--- trunk/Source/WebCore/editing/TextManipulationController.cpp	2020-06-05 05:58:55 UTC (rev 262600)
+++ trunk/Source/WebCore/editing/TextManipulationController.cpp	2020-06-05 06:13:30 UTC (rev 262601)
@@ -294,12 +294,13 @@
     return false;
 }
 
-TextManipulationController::ManipulationTokens TextManipulationController::parse(StringView text, Node* textNode)
+TextManipulationController::ManipulationUnit TextManipulationController::parse(StringView text, Node* textNode)
 {
     Vector<ManipulationToken> tokens;
     ExclusionRuleMatcher exclusionRuleMatcher(m_exclusionRules);
     size_t positionOfLastNonHTMLSpace = WTF::notFound;
     size_t startPositionOfCurrentToken = 0;
+    bool isNodeExcluded = exclusionRuleMatcher.isExcluded(textNode);
     bool containsOnlyHTMLSpace = true;
     bool containsLineBreak = false;
     bool firstTokenContainsLineBreak = false;
@@ -315,7 +316,7 @@
             containsLineBreak = true;
             if (positionOfLastNonHTMLSpace != WTF::notFound && startPositionOfCurrentToken <= positionOfLastNonHTMLSpace) {
                 auto tokenString = text.substring(startPositionOfCurrentToken, positionOfLastNonHTMLSpace + 1 - startPositionOfCurrentToken).toString();
-                tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), exclusionRuleMatcher.isExcluded(textNode) });
+                tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), isNodeExcluded });
                 startPositionOfCurrentToken = positionOfLastNonHTMLSpace + 1;
             }
 
@@ -337,13 +338,38 @@
 
     if (startPositionOfCurrentToken < text.length()) {
         auto tokenString = text.substring(startPositionOfCurrentToken, index + 1 - startPositionOfCurrentToken).toString();
-        tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), exclusionRuleMatcher.isExcluded(textNode) });
+        tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), isNodeExcluded });
         lastTokenContainsLineBreak = false;
     }
 
-    return { WTFMove(tokens), containsOnlyHTMLSpace, containsLineBreak, firstTokenContainsLineBreak, lastTokenContainsLineBreak };
+    return { WTFMove(tokens), *textNode, containsOnlyHTMLSpace || isNodeExcluded, containsLineBreak, firstTokenContainsLineBreak, lastTokenContainsLineBreak };
 }
 
+void TextManipulationController::addItemIfPossible(Vector<ManipulationUnit>&& units)
+{
+    if (units.isEmpty())
+        return;
+
+    size_t index = 0;
+    size_t end = units.size();
+    while (index < units.size() && units[index].areAllTokensExcluded)
+        ++index;
+
+    while (end > 0 && units[end - 1].areAllTokensExcluded)
+        --end;
+
+    if (index == end)
+        return;
+
+    auto startPosition = firstPositionInOrBeforeNode(units.first().node.ptr());
+    auto endPosition = positionAfterNode(units.last().node.ptr());
+    Vector<ManipulationToken> tokens;
+    for (; index < end; ++index)
+        tokens.appendVector(WTFMove(units[index].tokens));
+
+    addItem(ManipulationItemData { startPosition, endPosition, nullptr, nullQName(), WTFMove(tokens) });
+}
+
 void TextManipulationController::observeParagraphs(const Position& start, const Position& end)
 {
     if (start.isNull() || end.isNull())
@@ -351,16 +377,13 @@
 
     auto document = makeRefPtr(start.document());
     ASSERT(document);
-    ParagraphContentIterator iterator { start, end };
     // TextIterator's constructor may have updated the layout and executed arbitrary scripts.
     if (document != start.document() || document != end.document())
         return;
 
-    Vector<ManipulationToken> tokensInCurrentParagraph;
-    Position startOfCurrentParagraph;
-    Position endOfCurrentParagraph;
+    Vector<ManipulationUnit> unitsInCurrentParagraph;
     RefPtr<Element> enclosingItemBoundaryElement;
-
+    ParagraphContentIterator iterator { start, end };
     for (; !iterator.atEnd(); iterator.advance()) {
         auto content = iterator.currentContent();
         auto* contentNode = content.node.get();
@@ -367,8 +390,7 @@
         ASSERT(contentNode);
 
         if (enclosingItemBoundaryElement && !enclosingItemBoundaryElement->contains(contentNode)) {
-            if (!tokensInCurrentParagraph.isEmpty())
-                addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
+            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
             enclosingItemBoundaryElement = nullptr;
         }
 
@@ -401,10 +423,8 @@
         }
 
         if (content.isReplacedContent) {
-            if (!tokensInCurrentParagraph.isEmpty()) {
-                tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), "[]", tokenInfo(content.node.get()), true });
-                endOfCurrentParagraph = positionAfterNode(contentNode);
-            }
+            if (!unitsInCurrentParagraph.isEmpty())
+                unitsInCurrentParagraph.append(ManipulationUnit { { ManipulationToken { m_tokenIdentifier.generate(), "[]", tokenInfo(content.node.get()), true } }, *contentNode });
             continue;
         }
 
@@ -411,27 +431,20 @@
         if (!content.isTextContent)
             continue;
 
-        auto tokensInCurrentNode = parse(content.text, contentNode);
-        if (!tokensInCurrentParagraph.isEmpty() && tokensInCurrentNode.firstTokenContainsLineBreak)
-            addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
+        auto unitsInCurrentNode = parse(content.text, contentNode);
+        if (unitsInCurrentNode.firstTokenContainsLineBreak)
+            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
 
-        if (tokensInCurrentParagraph.isEmpty()) {
-            if (tokensInCurrentNode.containsOnlyHTMLSpace)
+        if (unitsInCurrentParagraph.isEmpty() && unitsInCurrentNode.areAllTokensExcluded)
                 continue;
-            startOfCurrentParagraph = firstPositionInOrBeforeNode(contentNode);
-        }
 
-        tokensInCurrentParagraph.appendVector(tokensInCurrentNode.tokens);
-        endOfCurrentParagraph = positionAfterNode(contentNode);
+        unitsInCurrentParagraph.append(WTFMove(unitsInCurrentNode));
 
-        if (!tokensInCurrentParagraph.isEmpty() && tokensInCurrentNode.lastTokenContainsLineBreak) {
-            ASSERT(!tokensInCurrentParagraph.isEmpty());
-            addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
-        }
+        if (unitsInCurrentNode.lastTokenContainsLineBreak)
+            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
     }
 
-    if (!tokensInCurrentParagraph.isEmpty())
-        addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), WTFMove(tokensInCurrentParagraph) });
+    addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
 }
 
 void TextManipulationController::didCreateRendererForElement(Element& element)

Modified: trunk/Source/WebCore/editing/TextManipulationController.h (262600 => 262601)


--- trunk/Source/WebCore/editing/TextManipulationController.h	2020-06-05 05:58:55 UTC (rev 262600)
+++ trunk/Source/WebCore/editing/TextManipulationController.h	2020-06-05 06:13:30 UTC (rev 262601)
@@ -150,16 +150,18 @@
         Vector<ManipulationToken> tokens;
     };
 
-    struct ManipulationTokens {
+    struct ManipulationUnit {
         Vector<ManipulationToken> tokens;
-        bool containsOnlyHTMLSpace { true };
+        Ref<Node> node;
+        bool areAllTokensExcluded { true };
         bool containsLineBreak { false };
         bool firstTokenContainsLineBreak { false };
         bool lastTokenContainsLineBreak { false };
     };
-    ManipulationTokens parse(StringView, Node*);
+    ManipulationUnit parse(StringView, Node*);
 
     void addItem(ManipulationItemData&&);
+    void addItemIfPossible(Vector<ManipulationUnit>&&);
     void flushPendingItemsForCallback();
 
     struct NodeInsertion {

Modified: trunk/Tools/ChangeLog (262600 => 262601)


--- trunk/Tools/ChangeLog	2020-06-05 05:58:55 UTC (rev 262600)
+++ trunk/Tools/ChangeLog	2020-06-05 06:13:30 UTC (rev 262601)
@@ -1,3 +1,16 @@
+2020-06-04  Sihui Liu  <sihui_...@apple.com>
+
+        Text manipulation: first and last unit in a paragraph should not contain only excluded tokens
+        https://bugs.webkit.org/show_bug.cgi?id=212759
+
+        Reviewed by Wenson Hsieh.
+
+        Modify existing test for changed behavior that leading and trailing excluded units are not included in paragraph
+        now.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
+        (TestWebKitAPI::TEST):
+
 2020-06-04  Chris Dumez  <cdu...@apple.com>
 
         UIProcess may crash after its prewarmed WebProcess gets terminated

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm (262600 => 262601)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm	2020-06-05 05:58:55 UTC (rev 262600)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm	2020-06-05 06:13:30 UTC (rev 262601)
@@ -243,11 +243,9 @@
     EXPECT_STREQ("fruit", items[2].tokens[0].content.UTF8String);
     EXPECT_FALSE(items[2].tokens[0].isExcluded);
 
-    EXPECT_EQ(items[3].tokens.count, 2UL);
+    EXPECT_EQ(items[3].tokens.count, 1UL);
     EXPECT_STREQ("hello", items[3].tokens[0].content.UTF8String);
     EXPECT_FALSE(items[3].tokens[0].isExcluded);
-    EXPECT_STREQ("[]", items[3].tokens[1].content.UTF8String);
-    EXPECT_TRUE(items[3].tokens[1].isExcluded);
 }
 
 TEST(TextManipulation, StartTextManipulationSupportsLegacyDelegateCallback)
@@ -451,11 +449,9 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 2UL);
-    EXPECT_STREQ("hello, ", items[0].tokens[0].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[0].isExcluded);
-    EXPECT_STREQ("world", items[0].tokens[1].content.UTF8String);
-    EXPECT_FALSE(items[0].tokens[1].isExcluded);
+    EXPECT_EQ(items[0].tokens.count, 1UL);
+    EXPECT_STREQ("world", items[0].tokens[0].content.UTF8String);
+    EXPECT_FALSE(items[0].tokens[0].isExcluded);
 }
 
 TEST(TextManipulation, StartTextManipulationApplyInclusionExclusionRulesForClass)
@@ -465,7 +461,7 @@
     [webView _setTextManipulationDelegate:delegate.get()];
 
     [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html>"
-        "<html><body><span class='someClass exclude'>Message: <b>hello, </b><span>world</span></span></body></html>"];
+        "<html><body>Message: <span class='someClass exclude'><b>hello, </b><span>world</span></span></body></html>"];
 
     auto configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     [configuration setExclusionRules:@[
@@ -480,13 +476,9 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 3UL);
+    EXPECT_EQ(items[0].tokens.count, 1UL);
     EXPECT_STREQ("Message: ", items[0].tokens[0].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[0].isExcluded);
-    EXPECT_STREQ("hello, ", items[0].tokens[1].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[1].isExcluded);
-    EXPECT_STREQ("world", items[0].tokens[2].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[2].isExcluded);
+    EXPECT_FALSE(items[0].tokens[0].isExcluded);
 }
 
 TEST(TextManipulation, StartTextManipulationApplyInclusionExclusionRulesForClassAndAttribute)
@@ -513,13 +505,9 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 3UL);
-    EXPECT_STREQ("Message: ", items[0].tokens[0].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[0].isExcluded);
-    EXPECT_STREQ("hello, ", items[0].tokens[1].content.UTF8String);
-    EXPECT_FALSE(items[0].tokens[1].isExcluded);
-    EXPECT_STREQ("world", items[0].tokens[2].content.UTF8String);
-    EXPECT_TRUE(items[0].tokens[2].isExcluded);
+    EXPECT_EQ(items[0].tokens.count, 1UL);
+    EXPECT_STREQ("hello, ", items[0].tokens[0].content.UTF8String);
+    EXPECT_FALSE(items[0].tokens[0].isExcluded);
 }
 
 TEST(TextManipulation, StartTextManipulationBreaksParagraphInBetweenListItems)
@@ -1293,10 +1281,10 @@
     [webView _setTextManipulationDelegate:delegate.get()];
 
     [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body>"
-    "<section><div style=\"display: inline-block;\">hello</div>"
-    "<div style=\"display: inline-block;\"><span style=\"display: inline-flex;\">"
-    "<svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg>"
-    "</span></div></section><p>world</p></body></html>"];
+    "<section><div style=\"display: inline-block;\">hello"
+    "<span style=\"display: inline-flex;\"><svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg></span>"
+    "webkit</div></section>"
+    "<p>world</p></body></html>"];
 
     done = false;
     [webView _startTextManipulationsWithConfiguration:nil completion:^{
@@ -1307,11 +1295,13 @@
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 2UL);
     auto *tokens = items[0].tokens;
-    EXPECT_EQ(tokens.count, 2UL);
+    EXPECT_EQ(tokens.count, 3UL);
     EXPECT_STREQ("hello", tokens[0].content.UTF8String);
     EXPECT_FALSE(tokens[0].isExcluded);
     EXPECT_STREQ("[]", tokens[1].content.UTF8String);
     EXPECT_TRUE(tokens[1].isExcluded);
+    EXPECT_STREQ("webkit", tokens[2].content.UTF8String);
+    EXPECT_FALSE(tokens[2].isExcluded);
     
     EXPECT_EQ(items[1].tokens.count, 1UL);
     EXPECT_STREQ("world", items[1].tokens[0].content.UTF8String);
@@ -1321,15 +1311,13 @@
     [webView _completeTextManipulationForItems:@[(_WKTextManipulationItem *)createItem(items[0].identifier, {
         { tokens[0].identifier, @"hey" },
         { tokens[1].identifier, nil },
+        { tokens[2].identifier, @"WebKit" },
     })] completion:^(NSArray<NSError *> *errors) {
         EXPECT_EQ(errors, nil);
         done = true;
     }];
     TestWebKitAPI::Util::run(&done);
-    EXPECT_WK_STREQ("<section><div style=\"display: inline-block;\">hey</div>"
-    "<div style=\"display: inline-block;\"><span style=\"display: inline-flex;\">"
-    "<svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg>"
-    "</span></div></section><p>world</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
+    EXPECT_WK_STREQ("<section><div style=\"display: inline-block;\">hey<span style=\"display: inline-flex;\"><svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg></span>WebKit</div></section><p>world</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
 }
 
 TEST(TextManipulation, CompleteTextManipulationShouldPreserveOrderOfBlockImage)
@@ -1395,9 +1383,8 @@
     EXPECT_EQ(items[2].tokens.count, 1UL);
     EXPECT_STREQ("fruit", items[2].tokens[0].content.UTF8String);
 
-    EXPECT_EQ(items[3].tokens.count, 2UL);
+    EXPECT_EQ(items[3].tokens.count, 1UL);
     EXPECT_STREQ("hello", items[3].tokens[0].content.UTF8String);
-    EXPECT_STREQ("[]", items[3].tokens[1].content.UTF8String);
 
     done = false;
     [webView _completeTextManipulationForItems:@[
@@ -1475,7 +1462,7 @@
     EXPECT_EQ(items[2].tokens.count, 1UL);
     EXPECT_EQ(items[3].tokens.count, 1UL);
     EXPECT_EQ(items[4].tokens.count, 1UL);
-    EXPECT_EQ(items[5].tokens.count, 2UL);
+    EXPECT_EQ(items[5].tokens.count, 1UL);
     EXPECT_WK_STREQ("This is a test", items[0].tokens[0].content);
     EXPECT_WK_STREQ("Hello world", items[1].tokens[0].content);
     EXPECT_WK_STREQ("Should not be replaced", items[2].tokens[0].content);
@@ -1482,7 +1469,6 @@
     EXPECT_WK_STREQ("label", items[3].tokens[0].content);
     EXPECT_WK_STREQ("image", items[4].tokens[0].content);
     EXPECT_WK_STREQ("Text", items[5].tokens[0].content);
-    EXPECT_WK_STREQ("[]", items[5].tokens[1].content);
 
     auto replacementItems = retainPtr(@[
         createItem(items[0].identifier, { { items[0].tokens[0].identifier, @"Replacement" }, { items[0].tokens[0].identifier, @"title" } }).autorelease(),
@@ -1925,7 +1911,7 @@
     [webView _setTextManipulationDelegate:delegate.get()];
 
     [webView synchronouslyLoadTestPageNamed:@"simple"];
-    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em></p>'"];
+    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em> bye</p>'"];
 
     RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     [configuration setExclusionRules:@[
@@ -1940,14 +1926,16 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 2UL);
+    EXPECT_EQ(items[0].tokens.count, 3UL);
     EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
     EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
+    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
 
     done = false;
     __block auto item = createItem(items[0].identifier, {
         { items[0].tokens[0].identifier, @"Hello," },
         { items[0].tokens[1].identifier, @"WebKit" },
+        { items[0].tokens[2].identifier, @"Bye" },
     });
     [webView _completeTextManipulationForItems:@[item.get()] completion:^(NSArray<NSError *> *errors) {
         EXPECT_EQ(errors.count, 1UL);
@@ -1958,7 +1946,7 @@
     }];
 
     TestWebKitAPI::Util::run(&done);
-    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
+    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em> bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
 }
 
 TEST(TextManipulation, CompleteTextManipulationFailWhenExcludedContentAppearsMoreThanOnce)
@@ -1968,7 +1956,7 @@
     [webView _setTextManipulationDelegate:delegate.get()];
 
     [webView synchronouslyLoadTestPageNamed:@"simple"];
-    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em></p>'"];
+    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em> bye</p>'"];
 
     RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     [configuration setExclusionRules:@[
@@ -1983,9 +1971,10 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 2UL);
+    EXPECT_EQ(items[0].tokens.count, 3UL);
     EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
     EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
+    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
 
     done = false;
     __block auto item = createItem(items[0].identifier, {
@@ -1992,6 +1981,7 @@
         { items[0].tokens[1].identifier, nil },
         { items[0].tokens[0].identifier, @"Hello," },
         { items[0].tokens[1].identifier, nil },
+        { items[0].tokens[2].identifier, @"Bye" },
     });
     [webView _completeTextManipulationForItems:@[item.get()] completion:^(NSArray<NSError *> *errors) {
         EXPECT_EQ(errors.count, 1UL);
@@ -2002,7 +1992,7 @@
     }];
 
     TestWebKitAPI::Util::run(&done);
-    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
+    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em> bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
 }
 
 TEST(TextManipulation, CompleteTextManipulationPreservesExcludedContent)
@@ -2011,7 +2001,7 @@
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
     [webView _setTextManipulationDelegate:delegate.get()];
 
-    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body><p>hi, <em>WebKitten</em></p></body></html>"];
+    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body><p>hi, <em>WebKitten</em> bye</p></body></html>"];
 
     RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     [configuration setExclusionRules:@[
@@ -2026,14 +2016,16 @@
 
     auto *items = [delegate items];
     EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 2UL);
+    EXPECT_EQ(items[0].tokens.count, 3UL);
     EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
     EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
+    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
 
     done = false;
     [webView _completeTextManipulationForItems:@[(_WKTextManipulationItem *)createItem(items[0].identifier, {
         { items[0].tokens[0].identifier, @"Hello, " },
         { items[0].tokens[1].identifier, nil },
+        { items[0].tokens[2].identifier, @" Bye" },
     })] completion:^(NSArray<NSError *> *errors) {
         EXPECT_EQ(errors, nil);
         done = true;
@@ -2040,7 +2032,7 @@
     }];
 
     TestWebKitAPI::Util::run(&done);
-    EXPECT_WK_STREQ("<p>Hello, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
+    EXPECT_WK_STREQ("<p>Hello, <em>WebKitten</em> Bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
 }
 
 TEST(TextManipulation, CompleteTextManipulationDoesNotCreateMoreTextManipulationItems)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to