Changeset 262601 in webkit


Ignore:
Timestamp:
Jun 4, 2020 11:13:30 PM (4 years ago)
Author:
sihui_liu@apple.com
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):

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r262599 r262601  
     12020-06-04  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Text manipulation: first and last unit in a paragraph should not contain only excluded tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=212759
     5
     6        Reviewed by Wenson Hsieh.
     7
     8        In r262398, we literally made text of one Node as the minimum unit for text manipulation. This patches introduce
     9        a struct ManipulationUnit for that. Now a paragraph can be represented as multiple ManipulationUnits. When all
     10        tokens in a ManipulationUnit are excluded, it means the ManipulationUnit is excluded and should not be
     11        manipulated. To record ManipulationUnits in a paragraph based on our current implementation, we need to keep the
     12        excluded ManipulationUnits surrounded by non-excluded ManipulationUnits, but we can safely remove the leading
     13        and trailing excluded ManipulationUnits. In this case, we can limit the range of paragraph further and thus less
     14        text replacement work.
     15
     16        Covered by existing test.
     17
     18        * editing/TextManipulationController.cpp:
     19        (WebCore::TextManipulationController::parse):
     20        (WebCore::TextManipulationController::addItemIfPossible):
     21        (WebCore::TextManipulationController::observeParagraphs):
     22        * editing/TextManipulationController.h:
     23
    1242020-06-04  Peng Liu  <peng.liu6@apple.com>
    225
  • trunk/Source/WebCore/editing/TextManipulationController.cpp

    r262587 r262601  
    295295}
    296296
    297 TextManipulationController::ManipulationTokens TextManipulationController::parse(StringView text, Node* textNode)
     297TextManipulationController::ManipulationUnit TextManipulationController::parse(StringView text, Node* textNode)
    298298{
    299299    Vector<ManipulationToken> tokens;
     
    301301    size_t positionOfLastNonHTMLSpace = WTF::notFound;
    302302    size_t startPositionOfCurrentToken = 0;
     303    bool isNodeExcluded = exclusionRuleMatcher.isExcluded(textNode);
    303304    bool containsOnlyHTMLSpace = true;
    304305    bool containsLineBreak = false;
     
    316317            if (positionOfLastNonHTMLSpace != WTF::notFound && startPositionOfCurrentToken <= positionOfLastNonHTMLSpace) {
    317318                auto tokenString = text.substring(startPositionOfCurrentToken, positionOfLastNonHTMLSpace + 1 - startPositionOfCurrentToken).toString();
    318                 tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), exclusionRuleMatcher.isExcluded(textNode) });
     319                tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), isNodeExcluded });
    319320                startPositionOfCurrentToken = positionOfLastNonHTMLSpace + 1;
    320321            }
     
    338339    if (startPositionOfCurrentToken < text.length()) {
    339340        auto tokenString = text.substring(startPositionOfCurrentToken, index + 1 - startPositionOfCurrentToken).toString();
    340         tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), exclusionRuleMatcher.isExcluded(textNode) });
     341        tokens.append(ManipulationToken { m_tokenIdentifier.generate(), tokenString, tokenInfo(textNode), isNodeExcluded });
    341342        lastTokenContainsLineBreak = false;
    342343    }
    343344
    344     return { WTFMove(tokens), containsOnlyHTMLSpace, containsLineBreak, firstTokenContainsLineBreak, lastTokenContainsLineBreak };
     345    return { WTFMove(tokens), *textNode, containsOnlyHTMLSpace || isNodeExcluded, containsLineBreak, firstTokenContainsLineBreak, lastTokenContainsLineBreak };
     346}
     347
     348void TextManipulationController::addItemIfPossible(Vector<ManipulationUnit>&& units)
     349{
     350    if (units.isEmpty())
     351        return;
     352
     353    size_t index = 0;
     354    size_t end = units.size();
     355    while (index < units.size() && units[index].areAllTokensExcluded)
     356        ++index;
     357
     358    while (end > 0 && units[end - 1].areAllTokensExcluded)
     359        --end;
     360
     361    if (index == end)
     362        return;
     363
     364    auto startPosition = firstPositionInOrBeforeNode(units.first().node.ptr());
     365    auto endPosition = positionAfterNode(units.last().node.ptr());
     366    Vector<ManipulationToken> tokens;
     367    for (; index < end; ++index)
     368        tokens.appendVector(WTFMove(units[index].tokens));
     369
     370    addItem(ManipulationItemData { startPosition, endPosition, nullptr, nullQName(), WTFMove(tokens) });
    345371}
    346372
     
    352378    auto document = makeRefPtr(start.document());
    353379    ASSERT(document);
    354     ParagraphContentIterator iterator { start, end };
    355380    // TextIterator's constructor may have updated the layout and executed arbitrary scripts.
    356381    if (document != start.document() || document != end.document())
    357382        return;
    358383
    359     Vector<ManipulationToken> tokensInCurrentParagraph;
    360     Position startOfCurrentParagraph;
    361     Position endOfCurrentParagraph;
     384    Vector<ManipulationUnit> unitsInCurrentParagraph;
    362385    RefPtr<Element> enclosingItemBoundaryElement;
    363 
     386    ParagraphContentIterator iterator { start, end };
    364387    for (; !iterator.atEnd(); iterator.advance()) {
    365388        auto content = iterator.currentContent();
     
    368391
    369392        if (enclosingItemBoundaryElement && !enclosingItemBoundaryElement->contains(contentNode)) {
    370             if (!tokensInCurrentParagraph.isEmpty())
    371                 addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
     393            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
    372394            enclosingItemBoundaryElement = nullptr;
    373395        }
     
    402424
    403425        if (content.isReplacedContent) {
    404             if (!tokensInCurrentParagraph.isEmpty()) {
    405                 tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), "[]", tokenInfo(content.node.get()), true });
    406                 endOfCurrentParagraph = positionAfterNode(contentNode);
    407             }
     426            if (!unitsInCurrentParagraph.isEmpty())
     427                unitsInCurrentParagraph.append(ManipulationUnit { { ManipulationToken { m_tokenIdentifier.generate(), "[]", tokenInfo(content.node.get()), true } }, *contentNode });
    408428            continue;
    409429        }
     
    412432            continue;
    413433
    414         auto tokensInCurrentNode = parse(content.text, contentNode);
    415         if (!tokensInCurrentParagraph.isEmpty() && tokensInCurrentNode.firstTokenContainsLineBreak)
    416             addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
    417 
    418         if (tokensInCurrentParagraph.isEmpty()) {
    419             if (tokensInCurrentNode.containsOnlyHTMLSpace)
     434        auto unitsInCurrentNode = parse(content.text, contentNode);
     435        if (unitsInCurrentNode.firstTokenContainsLineBreak)
     436            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
     437
     438        if (unitsInCurrentParagraph.isEmpty() && unitsInCurrentNode.areAllTokensExcluded)
    420439                continue;
    421             startOfCurrentParagraph = firstPositionInOrBeforeNode(contentNode);
    422         }
    423 
    424         tokensInCurrentParagraph.appendVector(tokensInCurrentNode.tokens);
    425         endOfCurrentParagraph = positionAfterNode(contentNode);
    426 
    427         if (!tokensInCurrentParagraph.isEmpty() && tokensInCurrentNode.lastTokenContainsLineBreak) {
    428             ASSERT(!tokensInCurrentParagraph.isEmpty());
    429             addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
    430         }
    431     }
    432 
    433     if (!tokensInCurrentParagraph.isEmpty())
    434         addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), WTFMove(tokensInCurrentParagraph) });
     440
     441        unitsInCurrentParagraph.append(WTFMove(unitsInCurrentNode));
     442
     443        if (unitsInCurrentNode.lastTokenContainsLineBreak)
     444            addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
     445    }
     446
     447    addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
    435448}
    436449
  • trunk/Source/WebCore/editing/TextManipulationController.h

    r262398 r262601  
    151151    };
    152152
    153     struct ManipulationTokens {
     153    struct ManipulationUnit {
    154154        Vector<ManipulationToken> tokens;
    155         bool containsOnlyHTMLSpace { true };
     155        Ref<Node> node;
     156        bool areAllTokensExcluded { true };
    156157        bool containsLineBreak { false };
    157158        bool firstTokenContainsLineBreak { false };
    158159        bool lastTokenContainsLineBreak { false };
    159160    };
    160     ManipulationTokens parse(StringView, Node*);
     161    ManipulationUnit parse(StringView, Node*);
    161162
    162163    void addItem(ManipulationItemData&&);
     164    void addItemIfPossible(Vector<ManipulationUnit>&&);
    163165    void flushPendingItemsForCallback();
    164166
  • trunk/Tools/ChangeLog

    r262588 r262601  
     12020-06-04  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Text manipulation: first and last unit in a paragraph should not contain only excluded tokens
     4        https://bugs.webkit.org/show_bug.cgi?id=212759
     5
     6        Reviewed by Wenson Hsieh.
     7
     8        Modify existing test for changed behavior that leading and trailing excluded units are not included in paragraph
     9        now.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
     12        (TestWebKitAPI::TEST):
     13
    1142020-06-04  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm

    r262587 r262601  
    244244    EXPECT_FALSE(items[2].tokens[0].isExcluded);
    245245
    246     EXPECT_EQ(items[3].tokens.count, 2UL);
     246    EXPECT_EQ(items[3].tokens.count, 1UL);
    247247    EXPECT_STREQ("hello", items[3].tokens[0].content.UTF8String);
    248248    EXPECT_FALSE(items[3].tokens[0].isExcluded);
    249     EXPECT_STREQ("[]", items[3].tokens[1].content.UTF8String);
    250     EXPECT_TRUE(items[3].tokens[1].isExcluded);
    251249}
    252250
     
    452450    auto *items = [delegate items];
    453451    EXPECT_EQ(items.count, 1UL);
    454     EXPECT_EQ(items[0].tokens.count, 2UL);
    455     EXPECT_STREQ("hello, ", items[0].tokens[0].content.UTF8String);
    456     EXPECT_TRUE(items[0].tokens[0].isExcluded);
    457     EXPECT_STREQ("world", items[0].tokens[1].content.UTF8String);
    458     EXPECT_FALSE(items[0].tokens[1].isExcluded);
     452    EXPECT_EQ(items[0].tokens.count, 1UL);
     453    EXPECT_STREQ("world", items[0].tokens[0].content.UTF8String);
     454    EXPECT_FALSE(items[0].tokens[0].isExcluded);
    459455}
    460456
     
    466462
    467463    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html>"
    468         "<html><body><span class='someClass exclude'>Message: <b>hello, </b><span>world</span></span></body></html>"];
     464        "<html><body>Message: <span class='someClass exclude'><b>hello, </b><span>world</span></span></body></html>"];
    469465
    470466    auto configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     
    481477    auto *items = [delegate items];
    482478    EXPECT_EQ(items.count, 1UL);
    483     EXPECT_EQ(items[0].tokens.count, 3UL);
     479    EXPECT_EQ(items[0].tokens.count, 1UL);
    484480    EXPECT_STREQ("Message: ", items[0].tokens[0].content.UTF8String);
    485     EXPECT_TRUE(items[0].tokens[0].isExcluded);
    486     EXPECT_STREQ("hello, ", items[0].tokens[1].content.UTF8String);
    487     EXPECT_TRUE(items[0].tokens[1].isExcluded);
    488     EXPECT_STREQ("world", items[0].tokens[2].content.UTF8String);
    489     EXPECT_TRUE(items[0].tokens[2].isExcluded);
     481    EXPECT_FALSE(items[0].tokens[0].isExcluded);
    490482}
    491483
     
    514506    auto *items = [delegate items];
    515507    EXPECT_EQ(items.count, 1UL);
    516     EXPECT_EQ(items[0].tokens.count, 3UL);
    517     EXPECT_STREQ("Message: ", items[0].tokens[0].content.UTF8String);
    518     EXPECT_TRUE(items[0].tokens[0].isExcluded);
    519     EXPECT_STREQ("hello, ", items[0].tokens[1].content.UTF8String);
    520     EXPECT_FALSE(items[0].tokens[1].isExcluded);
    521     EXPECT_STREQ("world", items[0].tokens[2].content.UTF8String);
    522     EXPECT_TRUE(items[0].tokens[2].isExcluded);
     508    EXPECT_EQ(items[0].tokens.count, 1UL);
     509    EXPECT_STREQ("hello, ", items[0].tokens[0].content.UTF8String);
     510    EXPECT_FALSE(items[0].tokens[0].isExcluded);
    523511}
    524512
     
    12941282
    12951283    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body>"
    1296     "<section><div style=\"display: inline-block;\">hello</div>"
    1297     "<div style=\"display: inline-block;\"><span style=\"display: inline-flex;\">"
    1298     "<svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg>"
    1299     "</span></div></section><p>world</p></body></html>"];
     1284    "<section><div style=\"display: inline-block;\">hello"
     1285    "<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>"
     1286    "webkit</div></section>"
     1287    "<p>world</p></body></html>"];
    13001288
    13011289    done = false;
     
    13081296    EXPECT_EQ(items.count, 2UL);
    13091297    auto *tokens = items[0].tokens;
    1310     EXPECT_EQ(tokens.count, 2UL);
     1298    EXPECT_EQ(tokens.count, 3UL);
    13111299    EXPECT_STREQ("hello", tokens[0].content.UTF8String);
    13121300    EXPECT_FALSE(tokens[0].isExcluded);
    13131301    EXPECT_STREQ("[]", tokens[1].content.UTF8String);
    13141302    EXPECT_TRUE(tokens[1].isExcluded);
     1303    EXPECT_STREQ("webkit", tokens[2].content.UTF8String);
     1304    EXPECT_FALSE(tokens[2].isExcluded);
    13151305   
    13161306    EXPECT_EQ(items[1].tokens.count, 1UL);
     
    13221312        { tokens[0].identifier, @"hey" },
    13231313        { tokens[1].identifier, nil },
     1314        { tokens[2].identifier, @"WebKit" },
    13241315    })] completion:^(NSArray<NSError *> *errors) {
    13251316        EXPECT_EQ(errors, nil);
     
    13271318    }];
    13281319    TestWebKitAPI::Util::run(&done);
    1329     EXPECT_WK_STREQ("<section><div style=\"display: inline-block;\">hey</div>"
    1330     "<div style=\"display: inline-block;\"><span style=\"display: inline-flex;\">"
    1331     "<svg viewBox=\"0 0 20 20\" width=\"20\" height=\"20\"><rect width=\"20\" height=\"20\" fill=\"#06f\"></rect></svg>"
    1332     "</span></div></section><p>world</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
     1320    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"]);
    13331321}
    13341322
     
    13961384    EXPECT_STREQ("fruit", items[2].tokens[0].content.UTF8String);
    13971385
    1398     EXPECT_EQ(items[3].tokens.count, 2UL);
     1386    EXPECT_EQ(items[3].tokens.count, 1UL);
    13991387    EXPECT_STREQ("hello", items[3].tokens[0].content.UTF8String);
    1400     EXPECT_STREQ("[]", items[3].tokens[1].content.UTF8String);
    14011388
    14021389    done = false;
     
    14761463    EXPECT_EQ(items[3].tokens.count, 1UL);
    14771464    EXPECT_EQ(items[4].tokens.count, 1UL);
    1478     EXPECT_EQ(items[5].tokens.count, 2UL);
     1465    EXPECT_EQ(items[5].tokens.count, 1UL);
    14791466    EXPECT_WK_STREQ("This is a test", items[0].tokens[0].content);
    14801467    EXPECT_WK_STREQ("Hello world", items[1].tokens[0].content);
     
    14831470    EXPECT_WK_STREQ("image", items[4].tokens[0].content);
    14841471    EXPECT_WK_STREQ("Text", items[5].tokens[0].content);
    1485     EXPECT_WK_STREQ("[]", items[5].tokens[1].content);
    14861472
    14871473    auto replacementItems = retainPtr(@[
     
    19261912
    19271913    [webView synchronouslyLoadTestPageNamed:@"simple"];
    1928     [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em></p>'"];
     1914    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em> bye</p>'"];
    19291915
    19301916    RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     
    19411927    auto *items = [delegate items];
    19421928    EXPECT_EQ(items.count, 1UL);
    1943     EXPECT_EQ(items[0].tokens.count, 2UL);
     1929    EXPECT_EQ(items[0].tokens.count, 3UL);
    19441930    EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
    19451931    EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
     1932    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
    19461933
    19471934    done = false;
     
    19491936        { items[0].tokens[0].identifier, @"Hello," },
    19501937        { items[0].tokens[1].identifier, @"WebKit" },
     1938        { items[0].tokens[2].identifier, @"Bye" },
    19511939    });
    19521940    [webView _completeTextManipulationForItems:@[item.get()] completion:^(NSArray<NSError *> *errors) {
     
    19591947
    19601948    TestWebKitAPI::Util::run(&done);
    1961     EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
     1949    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em> bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
    19621950}
    19631951
     
    19691957
    19701958    [webView synchronouslyLoadTestPageNamed:@"simple"];
    1971     [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em></p>'"];
     1959    [webView stringByEvaluatingJavaScript:@"document.body.innerHTML = '<p>hi, <em>WebKitten</em> bye</p>'"];
    19721960
    19731961    RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     
    19841972    auto *items = [delegate items];
    19851973    EXPECT_EQ(items.count, 1UL);
    1986     EXPECT_EQ(items[0].tokens.count, 2UL);
     1974    EXPECT_EQ(items[0].tokens.count, 3UL);
    19871975    EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
    19881976    EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
     1977    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
    19891978
    19901979    done = false;
     
    19931982        { items[0].tokens[0].identifier, @"Hello," },
    19941983        { items[0].tokens[1].identifier, nil },
     1984        { items[0].tokens[2].identifier, @"Bye" },
    19951985    });
    19961986    [webView _completeTextManipulationForItems:@[item.get()] completion:^(NSArray<NSError *> *errors) {
     
    20031993
    20041994    TestWebKitAPI::Util::run(&done);
    2005     EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
     1995    EXPECT_WK_STREQ("<p>hi, <em>WebKitten</em> bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
    20061996}
    20071997
     
    20122002    [webView _setTextManipulationDelegate:delegate.get()];
    20132003
    2014     [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body><p>hi, <em>WebKitten</em></p></body></html>"];
     2004    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body><p>hi, <em>WebKitten</em> bye</p></body></html>"];
    20152005
    20162006    RetainPtr<_WKTextManipulationConfiguration> configuration = adoptNS([[_WKTextManipulationConfiguration alloc] init]);
     
    20272017    auto *items = [delegate items];
    20282018    EXPECT_EQ(items.count, 1UL);
    2029     EXPECT_EQ(items[0].tokens.count, 2UL);
     2019    EXPECT_EQ(items[0].tokens.count, 3UL);
    20302020    EXPECT_STREQ("hi, ", items[0].tokens[0].content.UTF8String);
    20312021    EXPECT_STREQ("WebKitten", items[0].tokens[1].content.UTF8String);
     2022    EXPECT_STREQ(" bye", items[0].tokens[2].content.UTF8String);
    20322023
    20332024    done = false;
     
    20352026        { items[0].tokens[0].identifier, @"Hello, " },
    20362027        { items[0].tokens[1].identifier, nil },
     2028        { items[0].tokens[2].identifier, @" Bye" },
    20372029    })] completion:^(NSArray<NSError *> *errors) {
    20382030        EXPECT_EQ(errors, nil);
     
    20412033
    20422034    TestWebKitAPI::Util::run(&done);
    2043     EXPECT_WK_STREQ("<p>Hello, <em>WebKitten</em></p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
     2035    EXPECT_WK_STREQ("<p>Hello, <em>WebKitten</em> Bye</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
    20442036}
    20452037
Note: See TracChangeset for help on using the changeset viewer.