diff --git a/AUTHORS b/AUTHORS index 50edd3f6b385c2..6c9f5e768322d9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1349,6 +1349,7 @@ OpenFin Inc. <*@openfin.co> Opera Software ASA <*@opera.com> Optical Tone Ltd <*@opticaltone.com> Pengutronix e.K. <*@pengutronix.de> +Quality First Software GmbH <*@qf-software.com> Rakuten Kobo Inc. <*@kobo.com> Rakuten Kobo Inc. <*@rakuten.com> Red Hat Inc. <*@redhat.com> diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 91dbaca7659796..c42970c7d5d138 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl @@ -2259,6 +2259,13 @@ domain DOM # Enables DOM agent for the given page. command enable + parameters + # Whether to include whitespaces in the children array of returned Nodes. + experimental optional enum includeWhitespace + # Strip whitespaces from child arrays (default). + none + # Return all children including block-level whitespace nodes. + all # Focuses the given element. command focus diff --git a/third_party/blink/renderer/core/inspector/inspector_contrast.cc b/third_party/blink/renderer/core/inspector/inspector_contrast.cc index 982082e9e3f94c..695a72c8b8538f 100644 --- a/third_party/blink/renderer/core/inspector/inspector_contrast.cc +++ b/third_party/blink/renderer/core/inspector/inspector_contrast.cc @@ -145,7 +145,7 @@ void InspectorContrast::CollectNodesAndBuildRTreeIfNeeded() { } InspectorDOMAgent::CollectNodes( - document_, INT_MAX, true, + document_, INT_MAX, true, InspectorDOMAgent::IncludeWhitespaceEnum::NONE, WTF::BindRepeating(&NodeIsElementWithLayoutObject), &elements_); SortElementsByPaintOrder(elements_, document_); rtree_.Build( diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index a7078167f289d5..ac47cc77b2ae60 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc @@ -257,6 +257,9 @@ InspectorDOMAgent::InspectorDOMAgent( last_node_id_(1), suppress_attribute_modified_event_(false), enabled_(&agent_state_, /*default_value=*/false), + include_whitespace_(&agent_state_, + /*default_value=*/static_cast( + InspectorDOMAgent::IncludeWhitespaceEnum::NONE)), capture_node_stack_traces_(&agent_state_, /*default_value=*/false) {} InspectorDOMAgent::~InspectorDOMAgent() = default; @@ -319,6 +322,12 @@ bool InspectorDOMAgent::Enabled() const { return enabled_.Get(); } +InspectorDOMAgent::IncludeWhitespaceEnum InspectorDOMAgent::IncludeWhitespace() + const { + return static_cast( + include_whitespace_.Get()); +} + void InspectorDOMAgent::ReleaseDanglingNodes() { dangling_node_to_id_maps_.clear(); } @@ -371,10 +380,12 @@ void InspectorDOMAgent::Unbind(Node* node) { if (children_requested) { // Unbind subtree known to client recursively. children_requested_.erase(id); - Node* child = InnerFirstChild(node); + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + IncludeWhitespace(); + Node* child = InnerFirstChild(node, include_whitespace); while (child) { Unbind(child); - child = InnerNextSibling(child); + child = InnerNextSibling(child, include_whitespace); } } cached_child_count_.erase(id); @@ -489,15 +500,23 @@ void InspectorDOMAgent::EnableAndReset() { instrumenting_agents_->AddInspectorDOMAgent(this); } -Response InspectorDOMAgent::enable() { - if (!enabled_.Get()) +Response InspectorDOMAgent::enable(Maybe includeWhitespace) { + if (!enabled_.Get()) { EnableAndReset(); + include_whitespace_.Set(static_cast( + includeWhitespace.fromMaybe( + protocol::DOM::Enable::IncludeWhitespaceEnum::None) == + protocol::DOM::Enable::IncludeWhitespaceEnum::All + ? InspectorDOMAgent::IncludeWhitespaceEnum::ALL + : InspectorDOMAgent::IncludeWhitespaceEnum::NONE)); + } return Response::Success(); } Response InspectorDOMAgent::disable() { if (!enabled_.Get()) return Response::ServerError("DOM agent hasn't been enabled"); + include_whitespace_.Clear(); enabled_.Clear(); instrumenting_agents_->RemoveInspectorDOMAgent(this); history_.Clear(); @@ -511,7 +530,8 @@ Response InspectorDOMAgent::getDocument( Maybe pierce, std::unique_ptr* root) { // Backward compatibility. Mark agent as enabled when it requests document. - enable(); + if (!enabled_.Get()) + enable(Maybe()); if (!document_) return Response::ServerError("Document is not available"); @@ -585,7 +605,7 @@ Response InspectorDOMAgent::getNodesForSubtreeByStyle( HeapVector> nodes; CollectNodes( - root_node, INT_MAX, pierce.fromMaybe(false), + root_node, INT_MAX, pierce.fromMaybe(false), IncludeWhitespace(), WTF::BindRepeating(&NodeHasMatchingStyles, WTF::Unretained(&properties)), &nodes); @@ -638,7 +658,10 @@ void InspectorDOMAgent::PushChildNodesToFrontend(int node_id, depth--; - for (node = InnerFirstChild(node); node; node = InnerNextSibling(node)) { + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + IncludeWhitespace(); + for (node = InnerFirstChild(node, include_whitespace); node; + node = InnerNextSibling(node, include_whitespace)) { int child_node_id = node_map->at(node); DCHECK(child_node_id); PushChildNodesToFrontend(child_node_id, depth, pierce); @@ -1798,7 +1821,7 @@ std::unique_ptr InspectorDOMAgent::BuildObjectForNode( } if (node->IsContainerNode()) { - int node_count = InnerChildNodeCount(node); + int node_count = InnerChildNodeCount(node, IncludeWhitespace()); value->setChildNodeCount(node_count); if (nodes_map == document_node_to_id_map_) cached_child_count_.Set(id, node_count); @@ -1856,7 +1879,9 @@ InspectorDOMAgent::BuildArrayForContainerChildren( return children; } - Node* child = InnerFirstChild(container); + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + IncludeWhitespace(); + Node* child = InnerFirstChild(container, include_whitespace); depth--; if (nodes_map) children_requested_.insert(Bind(container, nodes_map)); @@ -1872,7 +1897,7 @@ InspectorDOMAgent::BuildArrayForContainerChildren( } if (nodes_map) children_requested_.insert(Bind(container, nodes_map)); - child = InnerNextSibling(child); + child = InnerNextSibling(child, include_whitespace); } return children; } @@ -1905,7 +1930,7 @@ InspectorDOMAgent::BuildDistributedNodesForSlot(HTMLSlotElement* slot_element) { auto distributed_nodes = std::make_unique>(); for (auto& node : slot_element->AssignedNodes()) { - if (IsWhitespace(node)) + if (ShouldSkipNode(node, IncludeWhitespace())) continue; std::unique_ptr backend_node = @@ -1920,36 +1945,44 @@ InspectorDOMAgent::BuildDistributedNodesForSlot(HTMLSlotElement* slot_element) { } // static -Node* InspectorDOMAgent::InnerFirstChild(Node* node) { +Node* InspectorDOMAgent::InnerFirstChild( + Node* node, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace) { node = node->firstChild(); - while (IsWhitespace(node)) + while (ShouldSkipNode(node, include_whitespace)) node = node->nextSibling(); return node; } // static -Node* InspectorDOMAgent::InnerNextSibling(Node* node) { +Node* InspectorDOMAgent::InnerNextSibling( + Node* node, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace) { do { node = node->nextSibling(); - } while (IsWhitespace(node)); + } while (ShouldSkipNode(node, include_whitespace)); return node; } // static -Node* InspectorDOMAgent::InnerPreviousSibling(Node* node) { +Node* InspectorDOMAgent::InnerPreviousSibling( + Node* node, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace) { do { node = node->previousSibling(); - } while (IsWhitespace(node)); + } while (ShouldSkipNode(node, include_whitespace)); return node; } // static -unsigned InspectorDOMAgent::InnerChildNodeCount(Node* node) { +unsigned InspectorDOMAgent::InnerChildNodeCount( + Node* node, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace) { unsigned count = 0; - Node* child = InnerFirstChild(node); + Node* child = InnerFirstChild(node, include_whitespace); while (child) { count++; - child = InnerNextSibling(child); + child = InnerNextSibling(child, include_whitespace); } return count; } @@ -1963,10 +1996,16 @@ Node* InspectorDOMAgent::InnerParentNode(Node* node) { } // static -bool InspectorDOMAgent::IsWhitespace(Node* node) { - // TODO: pull ignoreWhitespace setting from the frontend and use here. - return node && node->getNodeType() == Node::kTextNode && - node->nodeValue().StripWhiteSpace().length() == 0; +bool InspectorDOMAgent::ShouldSkipNode( + Node* node, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace) { + if (include_whitespace == InspectorDOMAgent::IncludeWhitespaceEnum::ALL) + return false; + + bool is_whitespace = node && node->getNodeType() == Node::kTextNode && + node->nodeValue().StripWhiteSpace().length() == 0; + + return is_whitespace; } // static @@ -1974,6 +2013,7 @@ void InspectorDOMAgent::CollectNodes( Node* node, int depth, bool pierce, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace, base::RepeatingCallback filter, HeapVector>* result) { if (filter && filter.Run(node)) @@ -1987,18 +2027,18 @@ void InspectorDOMAgent::CollectNodes( if (frame_owner->ContentFrame() && frame_owner->ContentFrame()->IsLocalFrame()) { if (Document* doc = frame_owner->contentDocument()) - CollectNodes(doc, depth, pierce, filter, result); + CollectNodes(doc, depth, pierce, include_whitespace, filter, result); } } ShadowRoot* root = element->GetShadowRoot(); if (pierce && root) - CollectNodes(root, depth, pierce, filter, result); + CollectNodes(root, depth, pierce, include_whitespace, filter, result); } - for (Node* child = InnerFirstChild(node); child; - child = InnerNextSibling(child)) { - CollectNodes(child, depth, pierce, filter, result); + for (Node* child = InnerFirstChild(node, include_whitespace); child; + child = InnerNextSibling(child, include_whitespace)) { + CollectNodes(child, depth, pierce, include_whitespace, filter, result); } } @@ -2028,7 +2068,8 @@ void InspectorDOMAgent::InvalidateFrameOwnerElement( std::unique_ptr value = BuildObjectForNode(frame_owner, 0, false, document_node_to_id_map_.Get()); - Node* previous_sibling = InnerPreviousSibling(frame_owner); + Node* previous_sibling = + InnerPreviousSibling(frame_owner, IncludeWhitespace()); int prev_id = previous_sibling ? BoundNodeId(previous_sibling) : 0; GetFrontend()->childNodeInserted(parent_id, prev_id, std::move(value)); } @@ -2061,7 +2102,9 @@ void InspectorDOMAgent::DidRestoreFromBackForwardCache(LocalFrame* frame) { } void InspectorDOMAgent::DidInsertDOMNode(Node* node) { - if (IsWhitespace(node)) + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + IncludeWhitespace(); + if (ShouldSkipNode(node, include_whitespace)) return; // We could be attaching existing subtree. Forget the bindings. @@ -2083,7 +2126,7 @@ void InspectorDOMAgent::DidInsertDOMNode(Node* node) { GetFrontend()->childNodeCountUpdated(parent_id, count); } else { // Children have been requested -> return value of a new child. - Node* prev_sibling = InnerPreviousSibling(node); + Node* prev_sibling = InnerPreviousSibling(node, include_whitespace); int prev_id = prev_sibling ? BoundNodeId(prev_sibling) : 0; std::unique_ptr value = BuildObjectForNode(node, 0, false, document_node_to_id_map_.Get()); @@ -2092,7 +2135,7 @@ void InspectorDOMAgent::DidInsertDOMNode(Node* node) { } void InspectorDOMAgent::WillRemoveDOMNode(Node* node) { - if (IsWhitespace(node)) + if (ShouldSkipNode(node, IncludeWhitespace())) return; DOMNodeRemoved(node); } @@ -2170,7 +2213,7 @@ void InspectorDOMAgent::StyleAttributeInvalidated( void InspectorDOMAgent::CharacterDataModified(CharacterData* character_data) { int id = BoundNodeId(character_data); - if (id && IsWhitespace(character_data)) { + if (id && ShouldSkipNode(character_data, IncludeWhitespace())) { DOMNodeRemoved(character_data); return; } @@ -2328,6 +2371,8 @@ Node* InspectorDOMAgent::NodeForPath(const String& path) { if (!path_tokens.size()) return nullptr; + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + IncludeWhitespace(); for (wtf_size_t i = 0; i < path_tokens.size() - 1; i += 2) { bool success = true; String& index_value = path_tokens[i]; @@ -2336,14 +2381,14 @@ Node* InspectorDOMAgent::NodeForPath(const String& path) { if (!success) { child = ShadowRootForNode(node, index_value); } else { - if (child_number >= InnerChildNodeCount(node)) + if (child_number >= InnerChildNodeCount(node, include_whitespace)) return nullptr; - child = InnerFirstChild(node); + child = InnerFirstChild(node, include_whitespace); } String child_name = path_tokens[i + 1]; for (wtf_size_t j = 0; child && j < child_number; ++j) - child = InnerNextSibling(child); + child = InnerNextSibling(child, include_whitespace); if (!child || child->nodeName() != child_name) return nullptr; diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h index 0b6f2898a39a23..d42c4acb8384f9 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h @@ -78,6 +78,8 @@ class CORE_EXPORT InspectorDOMAgent final virtual void DidModifyDOMAttr(Element*) = 0; }; + enum class IncludeWhitespaceEnum : int32_t { NONE = 0, ALL = 2 }; + class CORE_EXPORT InspectorSourceLocation final : public GarbageCollected { public: @@ -113,7 +115,7 @@ class CORE_EXPORT InspectorDOMAgent final void Reset(); // Methods called from the frontend for DOM nodes inspection. - protocol::Response enable() override; + protocol::Response enable(protocol::Maybe includeWhitespace) override; protocol::Response disable() override; protocol::Response getDocument( protocol::Maybe depth, @@ -266,6 +268,7 @@ class CORE_EXPORT InspectorDOMAgent final Element* container); bool Enabled() const; + IncludeWhitespaceEnum IncludeWhitespace() const; void ReleaseDanglingNodes(); // Methods called from the InspectorInstrumentation. @@ -310,15 +313,19 @@ class CORE_EXPORT InspectorDOMAgent final // We represent embedded doms as a part of the same hierarchy. Hence we treat // children of frame owners differently. We also skip whitespace text nodes // conditionally. Following methods encapsulate these specifics. - static Node* InnerFirstChild(Node*); - static Node* InnerNextSibling(Node*); - static Node* InnerPreviousSibling(Node*); - static unsigned InnerChildNodeCount(Node*); + static Node* InnerFirstChild(Node*, IncludeWhitespaceEnum include_whitespace); + static Node* InnerNextSibling(Node*, + IncludeWhitespaceEnum include_whitespace); + static Node* InnerPreviousSibling(Node*, + IncludeWhitespaceEnum include_whitespace); + static unsigned InnerChildNodeCount(Node*, + IncludeWhitespaceEnum include_whitespace); static Node* InnerParentNode(Node*); - static bool IsWhitespace(Node*); + static bool ShouldSkipNode(Node*, IncludeWhitespaceEnum include_whitespace); static void CollectNodes(Node* root, int depth, bool pierce, + IncludeWhitespaceEnum include_whitespace, base::RepeatingCallback, HeapVector>* result); @@ -410,6 +417,7 @@ class CORE_EXPORT InspectorDOMAgent final Member dom_editor_; bool suppress_attribute_modified_event_; InspectorAgentState::Boolean enabled_; + InspectorAgentState::Integer include_whitespace_; InspectorAgentState::Boolean capture_node_stack_traces_; }; diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc index dbf02dd81eb538..10ab8f527f96d9 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc @@ -152,7 +152,8 @@ void InspectorDOMDebuggerAgent::EventListenersInfoForTarget( v8::Local value, V8EventListenerInfoList* event_information) { InspectorDOMDebuggerAgent::EventListenersInfoForTarget( - isolate, value, 1, false, event_information); + isolate, value, 1, false, InspectorDOMAgent::IncludeWhitespaceEnum::NONE, + event_information); } static bool FilterNodesWithListeners(Node* node) { @@ -171,6 +172,7 @@ void InspectorDOMDebuggerAgent::EventListenersInfoForTarget( v8::Local value, int depth, bool pierce, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace, V8EventListenerInfoList* event_information) { // Special-case nodes, respect depth and pierce parameters in case of nodes. Node* node = V8Node::ToImplWithTypeCheck(isolate, value); @@ -179,8 +181,8 @@ void InspectorDOMDebuggerAgent::EventListenersInfoForTarget( depth = INT_MAX; HeapVector> nodes; InspectorDOMAgent::CollectNodes( - node, depth, pierce, WTF::BindRepeating(&FilterNodesWithListeners), - &nodes); + node, depth, pierce, include_whitespace, + WTF::BindRepeating(&FilterNodesWithListeners), &nodes); for (Node* n : nodes) { // We are only interested in listeners from the current context. CollectEventListeners(isolate, n, v8::Local(), n, pierce, @@ -301,15 +303,20 @@ void InspectorDOMDebuggerAgent::DidRemoveDOMNode(Node* node) { if (dom_breakpoints_.size()) { // Remove subtree breakpoints. dom_breakpoints_.erase(node); - HeapVector> stack(1, InspectorDOMAgent::InnerFirstChild(node)); + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + dom_agent_->IncludeWhitespace(); + HeapVector> stack( + 1, InspectorDOMAgent::InnerFirstChild(node, include_whitespace)); do { Node* child_node = stack.back(); stack.pop_back(); if (!child_node) continue; dom_breakpoints_.erase(child_node); - stack.push_back(InspectorDOMAgent::InnerFirstChild(child_node)); - stack.push_back(InspectorDOMAgent::InnerNextSibling(child_node)); + stack.push_back( + InspectorDOMAgent::InnerFirstChild(child_node, include_whitespace)); + stack.push_back( + InspectorDOMAgent::InnerNextSibling(child_node, include_whitespace)); } while (!stack.IsEmpty()); } } @@ -393,8 +400,12 @@ Response InspectorDOMDebuggerAgent::setDOMBreakpoint( uint32_t root_bit = 1 << type; dom_breakpoints_.Set(node, FindBreakpointMask(node) | root_bit); if (root_bit & inheritableDOMBreakpointTypesMask) { - for (Node* child = InspectorDOMAgent::InnerFirstChild(node); child; - child = InspectorDOMAgent::InnerNextSibling(child)) + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + dom_agent_->IncludeWhitespace(); + for (Node* child = + InspectorDOMAgent::InnerFirstChild(node, include_whitespace); + child; + child = InspectorDOMAgent::InnerNextSibling(child, include_whitespace)) UpdateSubtreeBreakpoints(child, root_bit, true); } DidAddBreakpoint(); @@ -423,8 +434,12 @@ Response InspectorDOMDebuggerAgent::removeDOMBreakpoint( if ((root_bit & inheritableDOMBreakpointTypesMask) && !(mask & (root_bit << domBreakpointDerivedTypeShift))) { - for (Node* child = InspectorDOMAgent::InnerFirstChild(node); child; - child = InspectorDOMAgent::InnerNextSibling(child)) + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + dom_agent_->IncludeWhitespace(); + for (Node* child = + InspectorDOMAgent::InnerFirstChild(node, include_whitespace); + child; + child = InspectorDOMAgent::InnerNextSibling(child, include_whitespace)) UpdateSubtreeBreakpoints(child, root_bit, false); } DidRemoveBreakpoint(); @@ -450,7 +465,8 @@ Response InspectorDOMDebuggerAgent::getEventListeners( V8EventListenerInfoList event_information; InspectorDOMDebuggerAgent::EventListenersInfoForTarget( context->GetIsolate(), object, depth.fromMaybe(1), - pierce.fromMaybe(false), &event_information); + pierce.fromMaybe(false), dom_agent_->IncludeWhitespace(), + &event_information); *listeners_array = BuildObjectsForEventListeners(event_information, context, object_group->string()); return Response::Success(); @@ -618,8 +634,12 @@ void InspectorDOMDebuggerAgent::UpdateSubtreeBreakpoints(Node* node, if (!new_root_mask) return; - for (Node* child = InspectorDOMAgent::InnerFirstChild(node); child; - child = InspectorDOMAgent::InnerNextSibling(child)) + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace = + dom_agent_->IncludeWhitespace(); + for (Node* child = + InspectorDOMAgent::InnerFirstChild(node, include_whitespace); + child; + child = InspectorDOMAgent::InnerNextSibling(child, include_whitespace)) UpdateSubtreeBreakpoints(child, new_root_mask, set); } diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h index fba925c654c948..9cc462f3e649e8 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h @@ -143,11 +143,13 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final private: String MatchXHRBreakpoints(const String& url) const; - static void EventListenersInfoForTarget(v8::Isolate*, - v8::Local, - int depth, - bool pierce, - V8EventListenerInfoList* listeners); + static void EventListenersInfoForTarget( + v8::Isolate*, + v8::Local, + int depth, + bool pierce, + InspectorDOMAgent::IncludeWhitespaceEnum include_whitespace, + V8EventListenerInfoList* listeners); void AllowNativeBreakpoint(const String& breakpoint_name, const String* target_name, bool sync); diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace-expected.txt new file mode 100644 index 00000000000000..e4737f84294544 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace-expected.txt @@ -0,0 +1,15 @@ +Tests that DOM debugging with DOM.enable(includeWhitespace:"all") works +Testing with includeWhitespace: all + FirstChild tag name: #text + Listeners: 1 + DOMNodeRemoved + Removing first child... + Debugger paused on node-removed + nodeId is correct + Done removing first child. +Testing with includeWhitespace: none + FirstChild tag name: SPAN + Listeners: 0 + Removing first child... + Done removing first child. + diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace.js b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace.js new file mode 100644 index 00000000000000..0aa7fd9c1b0797 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-debug-with-included-whitespace.js @@ -0,0 +1,75 @@ +(async function(testRunner) { + // The test page contains a DIV with one child node + // The function "addWhitespaceNode" inserts a whitespace node as first child which has a DOMNodeRemoved event listener attached. + const {dp} = await testRunner.startHTML(`
Inner
+ `, 'Tests that DOM debugging with DOM.enable(includeWhitespace:"all") works'); + + async function testDomDebuggingWithWhitespaceText(includeWhitespace) { + let result; + + testRunner.log("Testing with includeWhitespace: " + includeWhitespace) + + // add a whitespace text node as firstChild of DIV: + await dp.Runtime.evaluate({expression:"addWhitespaceNode()"}) + await dp.DOM.enable({includeWhitespace}); + await dp.Debugger.enable(); + + result = (await dp.DOM.getDocument({depth:-1})).result; + + const root = result.root; + const div = root.children[0].children[1].children[0]; + const firstChild = div.children[0]; + testRunner.log(" FirstChild tag name: " + firstChild.nodeName) + + // check that the event listener on the whitespace node can be retreived + result = (await dp.DOM.resolveNode({nodeId:div.nodeId})).result; + const objectId = result.object.objectId; + + // get all listeners on the outer div, including all listeners on child nodes + result = (await dp.DOMDebugger.getEventListeners({objectId,depth:-1})).result; + const listeners = result.listeners; + + testRunner.log(" Listeners: " + listeners.length); + for (const listener of listeners) { + testRunner.log(" " + listener.type); + } + + // check that the DOMBreakpoint is triggered + const nodeId = firstChild.nodeId; + await dp.DOMDebugger.setDOMBreakpoint({nodeId, type: "node-removed"}); + + dp.Debugger.oncePaused().then(function(messageObject) { + testRunner.log(" Debugger paused on " + messageObject.params.data.type); + + // check if nodeId is correct: + const isFirstChild = (messageObject.params.data.nodeId == nodeId); + testRunner.log(" nodeId is " + (isFirstChild ? "" : "not ") + "correct"); + + dp.Debugger.resume(); + }); + + testRunner.log(" Removing first child..."); + result = (await dp.Runtime.evaluate({expression: "removeFirstChild()"})); + testRunner.log(" Done removing first child."); + + await dp.DOM.disable(); + }; + + // With includeWhitespace:"all", event listeners are reported and it is possible to register a DOMBreakpoint + await testDomDebuggingWithWhitespaceText("all"); + + // With includeWhitespace:"none" (default), event listeners on whitespace nodes are ignored + await testDomDebuggingWithWhitespaceText("none"); + + testRunner.completeTest(); +}) diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace-expected.txt new file mode 100644 index 00000000000000..83144730d83301 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace-expected.txt @@ -0,0 +1,6 @@ +Tests that DOM.enable(includeWhitespace) works +includeWhitespace:all - childNodeCount: 5, children: 5 +includeWhitespace:none - childNodeCount: 2, children: 2 +includeWhitespace default - childNodeCount: 2, children: 2 +implicit - childNodeCount: 2, children: 2 + diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace.js b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace.js new file mode 100644 index 00000000000000..65a372761853a2 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/dom-include-whitespace.js @@ -0,0 +1,42 @@ +(async function(testRunner) { + let result; + + // The Test page contains a DIV with 5 childNodes: whitespace (linebreak), SPAN, whitespace, SPAN, whitespace + const {page, session, dp} = await testRunner.startHTML(`
+ First + Second +
`, 'Tests that DOM.enable(includeWhitespace) works'); + + function dumpOuterChildCount(prefix, root) { + const div = root.children[0].children[1].children[0]; + testRunner.log(prefix + " - childNodeCount: " + div.childNodeCount + ", children: " + div.children.length); + } + + // With includeWhitespace:all + await dp.DOM.enable({includeWhitespace:"all"}); + result = (await dp.DOM.getDocument({depth:-1})).result; + + dumpOuterChildCount("includeWhitespace:all", result.root); + + // With includeWhitespace:none + await dp.DOM.disable(); + await dp.DOM.enable({includeWhitespace:"none"}); + result = (await dp.DOM.getDocument({depth:-1})).result; + + dumpOuterChildCount("includeWhitespace:none", result.root); + + // With ignoreWhitespaces default ("none") + await dp.DOM.disable(); + await dp.DOM.enable(); + result = (await dp.DOM.getDocument({depth:-1})).result; + + dumpOuterChildCount("includeWhitespace default", result.root); + + // With implicit enable from getDocument (= default) + await dp.DOM.disable(); + result = (await dp.DOM.getDocument({depth:-1})).result; + + dumpOuterChildCount("implicit", result.root) + + testRunner.completeTest(); +}) \ No newline at end of file