Diff
Modified: trunk/Source/WebCore/ChangeLog (290805 => 290806)
--- trunk/Source/WebCore/ChangeLog 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/ChangeLog 2022-03-04 01:32:11 UTC (rev 290806)
@@ -1,3 +1,37 @@
+2022-03-03 Sihui Liu <sihui_...@apple.com>
+
+ Text manipulation does not observe updated title element
+ https://bugs.webkit.org/show_bug.cgi?id=237435
+ rdar://87318842
+
+ Reviewed by Wenson Hsieh.
+
+ TextManipulationController now monitors two types of nodes (after first-time manipulation):
+ (1) manipulated nodes with content update
+ (2) non-manipulated nodes (newly displayed or newly added)
+ We should make sure title element gets added to set (1) if it's newly created, and gets added to set (2) if its
+ text content is updated.
+
+ New test: TextManipulation.CompleteTextManipulationForTitleElement
+
+ * dom/Document.cpp:
+ (WebCore::Document::setTitle):
+ * dom/Text.cpp:
+ (WebCore::Text::setDataAndUpdate):
+ * editing/TextManipulationController.cpp:
+ (WebCore::TextManipulationController::didUpdateContentForNode):
+ (WebCore::TextManipulationController::didAddOrCreateRendererForNode):
+ (WebCore::TextManipulationController::scheduleObservationUpdate):
+ (WebCore::TextManipulationController::replace):
+ (WebCore::TextManipulationController::didCreateRendererForElement): Deleted.
+ (WebCore::TextManipulationController::didUpdateContentForText): Deleted.
+ (WebCore::TextManipulationController::didCreateRendererForTextNode): Deleted.
+ * editing/TextManipulationController.h:
+ * html/HTMLTitleElement.cpp:
+ * rendering/updating/RenderTreeUpdater.cpp:
+ (WebCore::RenderTreeUpdater::createRenderer):
+ (WebCore::RenderTreeUpdater::createTextRenderer):
+
2022-03-03 Michael Saboff <msab...@apple.com>
Copy WebKit frameworks and XPC processes to Secondary Path
Modified: trunk/Source/WebCore/dom/Document.cpp (290805 => 290806)
--- trunk/Source/WebCore/dom/Document.cpp 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/dom/Document.cpp 2022-03-04 01:32:11 UTC (rev 290806)
@@ -1726,6 +1726,7 @@
if (m_titleElement)
m_titleElement->setTextContent(title);
} else if (is<HTMLElement>(element)) {
+ std::optional<String> oldTitle;
if (!m_titleElement) {
RefPtr headElement = head();
if (!headElement)
@@ -1732,10 +1733,21 @@
return;
m_titleElement = HTMLTitleElement::create(HTMLNames::titleTag, *this);
headElement->appendChild(*m_titleElement);
+ } else
+ oldTitle = m_titleElement->textContent();
+
+ // appendChild above may have run scripts which removed m_titleElement.
+ if (!m_titleElement)
+ return;
+
+ m_titleElement->setTextContent(title);
+ auto* textManipulationController = textManipulationControllerIfExists();
+ if (UNLIKELY(textManipulationController)) {
+ if (!oldTitle)
+ textManipulationController->didAddOrCreateRendererForNode(*m_titleElement);
+ else if (*oldTitle != title)
+ textManipulationController->didUpdateContentForNode(*m_titleElement);
}
- // appendChild above may have ran scripts which removed m_titleElement.
- if (m_titleElement)
- m_titleElement->setTextContent(title);
}
}
Modified: trunk/Source/WebCore/dom/Text.cpp (290805 => 290806)
--- trunk/Source/WebCore/dom/Text.cpp 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/dom/Text.cpp 2022-03-04 01:32:11 UTC (rev 290806)
@@ -269,7 +269,7 @@
if (!offsetOfReplacedData) {
auto* textManipulationController = document().textManipulationControllerIfExists();
if (UNLIKELY(textManipulationController && oldData != newData))
- textManipulationController->didUpdateContentForText(*this);
+ textManipulationController->didUpdateContentForNode(*this);
}
}
Modified: trunk/Source/WebCore/editing/TextManipulationController.cpp (290805 => 290806)
--- trunk/Source/WebCore/editing/TextManipulationController.cpp 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/editing/TextManipulationController.cpp 2022-03-04 01:32:11 UTC (rev 290806)
@@ -530,40 +530,30 @@
addItemIfPossible(std::exchange(unitsInCurrentParagraph, { }));
}
-void TextManipulationController::didCreateRendererForElement(Element& element)
+void TextManipulationController::didUpdateContentForNode(Node& node)
{
- if (m_manipulatedNodes.contains(element))
+ if (!m_manipulatedNodes.contains(node))
return;
scheduleObservationUpdate();
- if (is<PseudoElement>(element)) {
- if (auto* host = downcast<PseudoElement>(element).hostElement())
- m_elementsWithNewRenderer.add(*host);
- } else
- m_elementsWithNewRenderer.add(element);
+ m_manipulatedNodesWithNewContent.add(node);
}
-void TextManipulationController::didUpdateContentForText(Text& text)
+void TextManipulationController::didAddOrCreateRendererForNode(Node& node)
{
- if (!m_manipulatedNodes.contains(text))
+ if (m_manipulatedNodes.contains(node))
return;
scheduleObservationUpdate();
- m_manipulatedTextsWithNewContent.add(text);
+ if (is<PseudoElement>(node)) {
+ if (auto* host = downcast<PseudoElement>(node).hostElement())
+ m_addedOrNewlyRenderedNodes.add(*host);
+ } else
+ m_addedOrNewlyRenderedNodes.add(node);
}
-void TextManipulationController::didCreateRendererForTextNode(Text& text)
-{
- if (m_manipulatedNodes.contains(text))
- return;
-
- scheduleObservationUpdate();
-
- m_textNodesWithNewRenderer.add(text);
-}
-
void TextManipulationController::scheduleObservationUpdate()
{
if (m_didScheduleObservationUpdate)
@@ -582,21 +572,17 @@
controller->m_didScheduleObservationUpdate = false;
HashSet<Ref<Node>> nodesToObserve;
- for (auto& weakElement : controller->m_elementsWithNewRenderer)
- nodesToObserve.add(weakElement);
- controller->m_elementsWithNewRenderer.clear();
-
- for (auto& text : controller->m_manipulatedTextsWithNewContent) {
+ for (auto& text : controller->m_manipulatedNodesWithNewContent) {
if (!controller->m_manipulatedNodes.contains(text))
continue;
controller->m_manipulatedNodes.remove(text);
nodesToObserve.add(text);
}
- controller->m_manipulatedTextsWithNewContent.clear();
+ controller->m_manipulatedNodesWithNewContent.clear();
- for (auto& text : controller->m_textNodesWithNewRenderer)
- nodesToObserve.add(text);
- controller->m_textNodesWithNewRenderer.clear();
+ for (auto& node : controller->m_addedOrNewlyRenderedNodes)
+ nodesToObserve.add(node);
+ controller->m_addedOrNewlyRenderedNodes.clear();
if (nodesToObserve.isEmpty())
return;
@@ -615,7 +601,15 @@
commonAncestor = commonInclusiveAncestor<ComposedTree>(*commonAncestor, node.get());
}
- auto start = firstPositionInOrBeforeNode(commonAncestor.get());
+ Position start;
+ if (auto* element = downcast<Element>(commonAncestor.get())) {
+ // Ensure to include the element in the range.
+ if (canPerformTextManipulationByReplacingEntireTextContent(*element))
+ start = positionBeforeNode(commonAncestor.get());
+ }
+ if (start.isNull())
+ start = firstPositionInOrBeforeNode(commonAncestor.get());
+
auto end = lastPositionInOrAfterNode(commonAncestor.get());
controller->observeParagraphs(start, end);
@@ -781,6 +775,8 @@
downcast<HTMLInputElement>(*element).setValue(newValue.toString());
else
element->setAttribute(item.attributeName, newValue.toString());
+
+ m_manipulatedNodes.add(*element);
return std::nullopt;
}
Modified: trunk/Source/WebCore/editing/TextManipulationController.h (290805 => 290806)
--- trunk/Source/WebCore/editing/TextManipulationController.h 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/editing/TextManipulationController.h 2022-03-04 01:32:11 UTC (rev 290806)
@@ -115,9 +115,8 @@
using ManipulationItemCallback = Function<void(Document&, const Vector<ManipulationItem>&)>;
WEBCORE_EXPORT void startObservingParagraphs(ManipulationItemCallback&&, Vector<ExclusionRule>&& = { });
- void didCreateRendererForElement(Element&);
- void didCreateRendererForTextNode(Text&);
- void didUpdateContentForText(Text&);
+ void didUpdateContentForNode(Node&);
+ void didAddOrCreateRendererForNode(Node&);
void removeNode(Node&);
enum class ManipulationFailureType : uint8_t {
@@ -181,9 +180,10 @@
WeakPtr<Document> m_document;
WeakHashSet<Element> m_elementsWithNewRenderer;
- WeakHashSet<Text> m_manipulatedTextsWithNewContent;
WeakHashSet<Node> m_textNodesWithNewRenderer;
WeakHashSet<Node> m_manipulatedNodes;
+ WeakHashSet<Node> m_manipulatedNodesWithNewContent;
+ WeakHashSet<Node> m_addedOrNewlyRenderedNodes;
HashMap<String, bool> m_cachedFontFamilyExclusionResults;
Modified: trunk/Source/WebCore/html/HTMLTitleElement.cpp (290805 => 290806)
--- trunk/Source/WebCore/html/HTMLTitleElement.cpp 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/html/HTMLTitleElement.cpp 2022-03-04 01:32:11 UTC (rev 290806)
@@ -32,6 +32,7 @@
#include "StyleInheritedData.h"
#include "StyleResolver.h"
#include "Text.h"
+#include "TextManipulationController.h"
#include "TextNodeTraversal.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/Ref.h>
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (290805 => 290806)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2022-03-04 01:32:11 UTC (rev 290806)
@@ -395,7 +395,7 @@
auto* textManipulationController = m_document.textManipulationControllerIfExists();
if (UNLIKELY(textManipulationController))
- textManipulationController->didCreateRendererForElement(element);
+ textManipulationController->didAddOrCreateRendererForNode(element);
if (AXObjectCache* cache = m_document.axObjectCache())
cache->updateCacheAfterNodeIsAttached(&element);
@@ -478,7 +478,7 @@
auto* textManipulationController = m_document.textManipulationControllerIfExists();
if (UNLIKELY(textManipulationController))
- textManipulationController->didCreateRendererForTextNode(textNode);
+ textManipulationController->didAddOrCreateRendererForNode(textNode);
}
void RenderTreeUpdater::updateTextRenderer(Text& text, const Style::TextUpdate* textUpdate)
Modified: trunk/Tools/ChangeLog (290805 => 290806)
--- trunk/Tools/ChangeLog 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Tools/ChangeLog 2022-03-04 01:32:11 UTC (rev 290806)
@@ -1,3 +1,14 @@
+2022-03-03 Sihui Liu <sihui_...@apple.com>
+
+ Text manipulation does not observe updated title element
+ https://bugs.webkit.org/show_bug.cgi?id=237435
+ rdar://87318842
+
+ Reviewed by Wenson Hsieh.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
+ (TestWebKitAPI::TEST):
+
2022-03-03 Lauro Moura <lmo...@igalia.com>
[Python3] Switch a few more glib scripts to Python3
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm (290805 => 290806)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm 2022-03-04 01:26:55 UTC (rev 290805)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm 2022-03-04 01:32:11 UTC (rev 290806)
@@ -3025,6 +3025,64 @@
EXPECT_WK_STREQ("<span>Hello World Again</span><p>Hello WebKit Again</p>", [webView stringByEvaluatingJavaScript:@"document.body.innerHTML"]);
}
+TEST(TextManipulation, CompleteTextManipulationForTitleElement)
+{
+ auto delegate = adoptNS([[TextManipulationDelegate alloc] init]);
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+ [webView _setTextManipulationDelegate:delegate.get()];
+ [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html></html>"];
+
+ done = false;
+ [webView _startTextManipulationsWithConfiguration:nil completion:^{
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ auto *items = [delegate items];
+ EXPECT_EQ(items.count, 0UL);
+
+ done = false;
+ [webView stringByEvaluatingJavaScript:@"document.title = 'page title'"];
+ delegate.get().itemCallback = ^(_WKTextManipulationItem *item) {
+ if (items.count == 1)
+ done = true;
+ };
+ TestWebKitAPI::Util::run(&done);
+ EXPECT_EQ(items[0].tokens.count, 1UL);
+ EXPECT_WK_STREQ("page title", items[0].tokens[0].content);
+
+ done = false;
+ [webView _completeTextManipulationForItems:@[
+ createItem(items[0].identifier, {{ items[0].tokens[0].identifier, @"Page Title" }}).get()
+ ] completion:^(NSArray<NSError *> *errors) {
+ EXPECT_EQ(errors, nil);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ EXPECT_WK_STREQ("Page Title", [webView stringByEvaluatingJavaScript:@"document.title"]);
+ EXPECT_WK_STREQ("<head><title>Page Title</title></head><body></body>", [webView stringByEvaluatingJavaScript:@"document.documentElement.innerHTML"]);
+
+ done = false;
+ [webView stringByEvaluatingJavaScript:@"document.title = 'new page title'"];
+ delegate.get().itemCallback = ^(_WKTextManipulationItem *item) {
+ if (items.count == 2)
+ done = true;
+ };
+ TestWebKitAPI::Util::run(&done);
+ EXPECT_EQ(items[1].tokens.count, 1UL);
+ EXPECT_WK_STREQ("new page title", items[1].tokens[0].content);
+
+ done = false;
+ [webView _completeTextManipulationForItems:@[
+ createItem(items[1].identifier, {{ items[1].tokens[0].identifier, @"New Page Title" }}).get()
+ ] completion:^(NSArray<NSError *> *errors) {
+ EXPECT_EQ(errors, nil);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ EXPECT_WK_STREQ("New Page Title", [webView stringByEvaluatingJavaScript:@"document.title"]);
+ EXPECT_WK_STREQ("<head><title>New Page Title</title></head><body></body>", [webView stringByEvaluatingJavaScript:@"document.documentElement.innerHTML"]);
+}
+
TEST(TextManipulation, CompleteTextManipulationAvoidExtractingManipulatedTextAfterManipulation)
{
auto delegate = adoptNS([[TextManipulationDelegate alloc] init]);