#include "config.h"
#include "core/inspector/InspectorDOMAgent.h"
-#include "HTMLNames.h"
#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/ScriptEventListener.h"
#include "core/dom/Attr.h"
#include "core/editing/markup.h"
#include "core/fileapi/File.h"
#include "core/fileapi/FileList.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLLinkElement.h"
#include "core/html/HTMLTemplateElement.h"
+#include "core/html/imports/HTMLImportChild.h"
+#include "core/html/imports/HTMLImportLoader.h"
#include "core/inspector/DOMEditor.h"
#include "core/inspector/DOMPatchSupport.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectorHistory.h"
+#include "core/inspector/InspectorNodeIds.h"
#include "core/inspector/InspectorOverlay.h"
#include "core/inspector/InspectorPageAgent.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/DocumentLoader.h"
-#include "core/frame/Frame.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/rendering/HitTestResult.h"
return true;
}
-static Node* hoveredNodeForPoint(Frame* frame, const IntPoint& point, bool ignorePointerEventsNone)
+static Node* hoveredNodeForPoint(LocalFrame* frame, const IntPoint& point, bool ignorePointerEventsNone)
{
HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent;
if (ignorePointerEventsNone)
return node;
}
-static Node* hoveredNodeForEvent(Frame* frame, const PlatformGestureEvent& event, bool ignorePointerEventsNone)
+static Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformGestureEvent& event, bool ignorePointerEventsNone)
{
return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone);
}
-static Node* hoveredNodeForEvent(Frame* frame, const PlatformMouseEvent& event, bool ignorePointerEventsNone)
+static Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformMouseEvent& event, bool ignorePointerEventsNone)
{
return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone);
}
-static Node* hoveredNodeForEvent(Frame* frame, const PlatformTouchEvent& event, bool ignorePointerEventsNone)
+static Node* hoveredNodeForEvent(LocalFrame* frame, const PlatformTouchEvent& event, bool ignorePointerEventsNone)
{
const Vector<PlatformTouchPoint>& points = event.touchPoints();
if (!points.size())
{
m_elements.add(element);
if (!m_timer.isActive())
- m_timer.startOneShot(0);
+ m_timer.startOneShot(0, FROM_HERE);
}
void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
String InspectorDOMAgent::toErrorString(ExceptionState& exceptionState)
{
if (exceptionState.hadException())
- return DOMException::getErrorName(exceptionState.code());
+ return DOMException::getErrorName(exceptionState.code()) + " " + exceptionState.message();
return "";
}
, m_frontend(0)
, m_domListener(0)
, m_lastNodeId(1)
- , m_lastBackendNodeId(-1)
, m_searchingForNode(NotSearching)
, m_suppressAttributeModifiedEvent(false)
{
void InspectorDOMAgent::restore()
{
// Reset document to avoid early return from setDocument.
- m_document = 0;
+ m_document = nullptr;
setDocument(m_pageAgent->mainFrame()->document());
}
Vector<Document*> InspectorDOMAgent::documents()
{
Vector<Document*> result;
- for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
+ for (LocalFrame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
Document* document = frame->document();
if (!document)
continue;
void InspectorDOMAgent::reset()
{
discardFrontendBindings();
- discardBackendBindings();
- m_document = 0;
+ m_document = nullptr;
}
void InspectorDOMAgent::setDOMListener(DOMListener* listener)
unbind(element->pseudoElement(BEFORE), nodesMap);
if (element->pseudoElement(AFTER))
unbind(element->pseudoElement(AFTER), nodesMap);
+
+ if (isHTMLLinkElement(*element)) {
+ HTMLLinkElement& linkElement = toHTMLLinkElement(*element);
+ if (linkElement.isImport() && linkElement.import())
+ unbind(linkElement.import(), nodesMap);
+ }
}
nodesMap->remove(node);
child = innerNextSibling(child);
}
}
+ if (nodesMap == &m_documentNodeToIdMap)
+ m_cachedChildCount.remove(id);
}
Node* InspectorDOMAgent::assertNode(ErrorString* errorString, int nodeId)
return toElement(node);
}
+static ShadowRoot* userAgentShadowRoot(Node* node)
+{
+ if (!node || !node->isInShadowTree())
+ return 0;
+
+ Node* candidate = node;
+ while (candidate && !candidate->isShadowRoot())
+ candidate = candidate->parentOrShadowHostNode();
+ ASSERT(candidate);
+ ShadowRoot* shadowRoot = toShadowRoot(candidate);
+
+ return shadowRoot->type() == ShadowRoot::UserAgentShadowRoot ? shadowRoot : 0;
+}
+
Node* InspectorDOMAgent::assertEditableNode(ErrorString* errorString, int nodeId)
{
Node* node = assertNode(errorString, nodeId);
return 0;
if (node->isInShadowTree()) {
- *errorString = "Cannot edit nodes from shadow trees";
- return 0;
+ if (node->isShadowRoot()) {
+ *errorString = "Cannot edit shadow roots";
+ return 0;
+ }
+ if (userAgentShadowRoot(node)) {
+ *errorString = "Cannot edit nodes from user-agent shadow trees";
+ return 0;
+ }
}
if (node->isPseudoElement()) {
if (!element)
return 0;
- if (element->isInShadowTree()) {
- *errorString = "Cannot edit elements from shadow trees";
+ if (element->isInShadowTree() && userAgentShadowRoot(element)) {
+ *errorString = "Cannot edit elements from user-agent shadow trees";
return 0;
}
m_idToNode.clear();
releaseDanglingNodes();
m_childrenRequested.clear();
+ m_cachedChildCount.clear();
if (m_revalidateStyleAttrTask)
m_revalidateStyleAttrTask->reset();
}
-void InspectorDOMAgent::discardBackendBindings()
-{
- m_backendIdToNode.clear();
- m_nodeGroupToBackendIdMap.clear();
-}
-
-int InspectorDOMAgent::pushNodeToFrontend(ErrorString* errorString, int documentNodeId, Node* nodeToPush)
-{
- Document* document = assertDocument(errorString, documentNodeId);
- if (!document)
- return 0;
- if (nodeToPush->document() != document) {
- *errorString = "Node is not part of the document with given id";
- return 0;
- }
-
- return pushNodePathToFrontend(nodeToPush);
-}
-
Node* InspectorDOMAgent::nodeForId(int id)
{
if (!id)
return m_documentNodeToIdMap.get(node);
}
-BackendNodeId InspectorDOMAgent::backendNodeIdForNode(Node* node, const String& nodeGroup)
-{
- if (!node)
- return 0;
-
- if (!m_nodeGroupToBackendIdMap.contains(nodeGroup))
- m_nodeGroupToBackendIdMap.set(nodeGroup, NodeToBackendIdMap());
-
- NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
- BackendNodeId id = map.get(node);
- if (!id) {
- id = --m_lastBackendNodeId;
- map.set(node, id);
- m_backendIdToNode.set(id, std::make_pair(node, nodeGroup));
- }
-
- return id;
-}
-
-void InspectorDOMAgent::releaseBackendNodeIds(ErrorString* errorString, const String& nodeGroup)
-{
- if (m_nodeGroupToBackendIdMap.contains(nodeGroup)) {
- NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
- for (NodeToBackendIdMap::iterator it = map.begin(); it != map.end(); ++it)
- m_backendIdToNode.remove(it->value);
- m_nodeGroupToBackendIdMap.remove(nodeGroup);
- return;
- }
- *errorString = "Group name not found";
-}
-
void InspectorDOMAgent::setAttributeValue(ErrorString* errorString, int elementId, const String& name, const String& value)
{
Element* element = assertEditableElement(errorString, elementId);
bool shouldIgnoreCase = element->document().isHTMLDocument() && element->isHTMLElement();
// Not all elements can represent the context (i.e. IFRAME), hence using document.body.
if (shouldIgnoreCase && element->document().body())
- fragment->parseHTML(markup, element->document().body(), DisallowScriptingContent);
+ fragment->parseHTML(markup, element->document().body(), AllowScriptingContent);
else
- fragment->parseXML(markup, 0, DisallowScriptingContent);
+ fragment->parseXML(markup, 0, AllowScriptingContent);
Element* parsedElement = fragment->firstChild() && fragment->firstChild()->isElementNode() ? toElement(fragment->firstChild()) : 0;
if (!parsedElement) {
unsigned numAttrs = parsedElement->attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
// Add attribute pair
- const Attribute* attribute = parsedElement->attributeItem(i);
- String attributeName = attribute->name().toString();
+ const Attribute& attribute = parsedElement->attributeItem(i);
+ String attributeName = attribute.name().toString();
if (shouldIgnoreCase)
attributeName = attributeName.lower();
foundOriginalAttribute |= name && attributeName == caseAdjustedName;
- if (!m_domEditor->setAttribute(element, attributeName, attribute->value(), errorString))
+ if (!m_domEditor->setAttribute(element, attributeName, attribute.value(), errorString))
return;
}
const EventListenerVector& vector = info.eventListenerVector;
for (size_t j = 0; j < vector.size(); ++j) {
const RegisteredEventListener& listener = vector[j];
- if (listener.useCapture)
- listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.eventTarget->toNode(), objectGroup));
+ if (listener.useCapture) {
+ RefPtr<TypeBuilder::DOM::EventListener> listenerObject = buildObjectForEventListener(listener, info.eventType, info.eventTarget->toNode(), objectGroup);
+ if (listenerObject)
+ listenersArray->addItem(listenerObject);
+ }
}
}
const EventListenerVector& vector = info.eventListenerVector;
for (size_t j = 0; j < vector.size(); ++j) {
const RegisteredEventListener& listener = vector[j];
- if (!listener.useCapture)
- listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.eventTarget->toNode(), objectGroup));
+ if (!listener.useCapture) {
+ RefPtr<TypeBuilder::DOM::EventListener> listenerObject = buildObjectForEventListener(listener, info.eventType, info.eventTarget->toNode(), objectGroup);
+ if (listenerObject)
+ listenersArray->addItem(listenerObject);
+ }
}
}
}
unsigned numAttrs = element->attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
// Add attribute pair
- const Attribute* attribute = element->attributeItem(i);
- if (attribute->localName().find(whitespaceTrimmedQuery, 0, false) != kNotFound) {
+ const Attribute& attribute = element->attributeItem(i);
+ if (attribute.localName().find(whitespaceTrimmedQuery, 0, false) != kNotFound) {
resultCollector.add(node);
break;
}
- size_t foundPosition = attribute->value().find(attributeQuery, 0, false);
+ size_t foundPosition = attribute.value().find(attributeQuery, 0, false);
if (foundPosition != kNotFound) {
- if (!exactAttributeMatch || (!foundPosition && attribute->value().length() == attributeQuery.length())) {
+ if (!exactAttributeMatch || (!foundPosition && attribute.value().length() == attributeQuery.length())) {
resultCollector.add(node);
break;
}
// XPath evaluation
for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
Document* document = *it;
+ ASSERT(document);
TrackExceptionState exceptionState;
- RefPtr<XPathResult> result = DocumentXPathEvaluator::evaluate(document, whitespaceTrimmedQuery, document, 0, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, 0, exceptionState);
+ RefPtrWillBeRawPtr<XPathResult> result = DocumentXPathEvaluator::evaluate(*document, whitespaceTrimmedQuery, document, nullptr, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, 0, exceptionState);
if (exceptionState.hadException() || !result)
continue;
}
*searchId = IdentifiersFactory::createIdentifier();
- SearchResults::iterator resultsIt = m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).iterator;
+ Vector<RefPtr<Node> >* resultsIt = &m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).storedValue->value;
for (ListHashSet<Node*>::iterator it = resultCollector.begin(); it != resultCollector.end(); ++it)
- resultsIt->value.append(*it);
+ resultsIt->append(*it);
- *resultCount = resultsIt->value.size();
+ *resultCount = resultsIt->size();
}
void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<TypeBuilder::Array<int> >& nodeIds)
return false;
}
-bool InspectorDOMAgent::handleGestureEvent(Frame* frame, const PlatformGestureEvent& event)
+bool InspectorDOMAgent::handleGestureEvent(LocalFrame* frame, const PlatformGestureEvent& event)
{
if (m_searchingForNode == NotSearching || event.type() != PlatformEvent::GestureTap)
return false;
Node* node = hoveredNodeForEvent(frame, event, false);
if (node && m_inspectModeHighlightConfig) {
- m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig);
+ m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig, false);
inspect(node);
return true;
}
return false;
}
-bool InspectorDOMAgent::handleTouchEvent(Frame* frame, const PlatformTouchEvent& event)
+bool InspectorDOMAgent::handleTouchEvent(LocalFrame* frame, const PlatformTouchEvent& event)
{
if (m_searchingForNode == NotSearching)
return false;
Node* node = hoveredNodeForEvent(frame, event, false);
if (node && m_inspectModeHighlightConfig) {
- m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig);
+ m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig, false);
inspect(node);
return true;
}
return;
Node* node = inspectedNode;
- if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
- node = node->parentNode();
+ while (node && node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE)
+ node = node->parentOrShadowHostNode();
+
+ if (!node)
+ return;
int nodeId = pushNodePathToFrontend(node);
if (nodeId)
m_frontend->inspectNodeRequested(nodeId);
}
-void InspectorDOMAgent::handleMouseMove(Frame* frame, const PlatformMouseEvent& event)
+void InspectorDOMAgent::handleMouseMove(LocalFrame* frame, const PlatformMouseEvent& event)
{
if (m_searchingForNode == NotSearching)
return;
return;
Node* node = hoveredNodeForEvent(frame, event, event.shiftKey());
- while (m_searchingForNode != SearchingForShadow && node && node->isInShadowTree())
+ // Do not highlight within UA shadow root unless requested.
+ if (m_searchingForNode != SearchingForUAShadow) {
+ ShadowRoot* uaShadowRoot = userAgentShadowRoot(node);
+ if (uaShadowRoot)
+ node = uaShadowRoot->host();
+ }
+
+ // Shadow roots don't have boxes - use host element instead.
+ if (node && node->isShadowRoot())
node = node->parentOrShadowHostNode();
+ if (!node)
+ return;
+
Node* eventTarget = event.shiftKey() ? hoveredNodeForEvent(frame, event, false) : 0;
if (eventTarget == node)
eventTarget = 0;
if (node && m_inspectModeHighlightConfig)
- m_overlay->highlightNode(node, eventTarget, *m_inspectModeHighlightConfig);
+ m_overlay->highlightNode(node, eventTarget, *m_inspectModeHighlightConfig, event.ctrlKey() || event.metaKey());
}
void InspectorDOMAgent::setSearchingForNode(ErrorString* errorString, SearchMode searchMode, JSONObject* highlightInspectorObject)
return highlightConfig.release();
}
-void InspectorDOMAgent::setInspectModeEnabled(ErrorString* errorString, bool enabled, const bool* inspectShadowDOM, const RefPtr<JSONObject>* highlightConfig)
+void InspectorDOMAgent::setInspectModeEnabled(ErrorString* errorString, bool enabled, const bool* inspectUAShadowDOM, const RefPtr<JSONObject>* highlightConfig)
{
if (enabled && !pushDocumentUponHandlelessOperation(errorString))
return;
- SearchMode searchMode = enabled ? (inspectShadowDOM && *inspectShadowDOM ? SearchingForShadow : SearchingForNormal) : NotSearching;
+ SearchMode searchMode = enabled ? (inspectUAShadowDOM && *inspectUAShadowDOM ? SearchingForUAShadow : SearchingForNormal) : NotSearching;
setSearchingForNode(errorString, searchMode, highlightConfig ? highlightConfig->get() : 0);
}
if (!highlightConfig)
return;
- m_overlay->highlightNode(node, 0 /* eventTarget */, *highlightConfig);
+ m_overlay->highlightNode(node, 0 /* eventTarget */, *highlightConfig, false);
}
void InspectorDOMAgent::highlightFrame(
const RefPtr<JSONObject>* color,
const RefPtr<JSONObject>* outlineColor)
{
- Frame* frame = m_pageAgent->frameForId(frameId);
+ LocalFrame* frame = m_pageAgent->frameForId(frameId);
if (frame && frame->ownerElement()) {
OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
highlightConfig->showInfo = true; // Always show tooltips for frames.
highlightConfig->content = parseColor(color);
highlightConfig->contentOutline = parseColor(outlineColor);
- m_overlay->highlightNode(frame->ownerElement(), 0 /* eventTarget */, *highlightConfig);
+ m_overlay->highlightNode(frame->ownerElement(), 0 /* eventTarget */, *highlightConfig, false);
}
}
Node* node = assertNode(errorString, nodeId);
if (!node)
return;
- if (!node->hasTagName(inputTag) || !toHTMLInputElement(node)->isFileUpload()) {
+ if (!isHTMLInputElement(*node) || !toHTMLInputElement(*node).isFileUpload()) {
*errorString = "Node is not a file input element";
return;
}
- RefPtr<FileList> fileList = FileList::create();
+ RefPtrWillBeRawPtr<FileList> fileList = FileList::create();
for (JSONArray::const_iterator iter = files->begin(); iter != files->end(); ++iter) {
String path;
if (!(*iter)->asString(&path)) {
}
RenderObject* renderer = node->renderer();
- Frame* frame = node->document().frame();
+ LocalFrame* frame = node->document().frame();
FrameView* view = frame->view();
IntRect boundingBox = pixelSnappedIntRect(view->contentsToRootView(renderer->absoluteBoundingBoxRect()));
RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
+ RefPtr<TypeBuilder::DOM::ShapeOutsideInfo> shapeOutsideInfo = m_overlay->buildObjectForShapeOutside(node);
model = TypeBuilder::DOM::BoxModel::create()
.setContent(buildArrayForQuad(quads.at(3)))
.setMargin(buildArrayForQuad(quads.at(0)))
.setWidth(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width())
.setHeight(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height());
+ if (shapeOutsideInfo)
+ model->setShapeOutside(shapeOutsideInfo);
}
void InspectorDOMAgent::getNodeForLocation(ErrorString* errorString, int x, int y, int* nodeId)
if (node->isElementNode()) {
Element* element = toElement(node);
value->setAttributes(buildArrayForElementAttributes(element));
+
if (node->isFrameOwnerElement()) {
HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node);
- if (Frame* frame = frameOwner->contentFrame())
+ LocalFrame* frame = (frameOwner->contentFrame() && frameOwner->contentFrame()->isLocalFrame()) ? toLocalFrame(frameOwner->contentFrame()) : 0;
+ if (frame)
value->setFrameId(m_pageAgent->frameId(frame));
if (Document* doc = frameOwner->contentDocument())
value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
forcePushChildren = true;
}
- if (element->hasTagName(templateTag)) {
- value->setTemplateContent(buildObjectForNode(toHTMLTemplateElement(element)->content(), 0, nodesMap));
+ if (isHTMLLinkElement(*element)) {
+ HTMLLinkElement& linkElement = toHTMLLinkElement(*element);
+ if (linkElement.isImport() && linkElement.import() && innerParentNode(linkElement.import()) == linkElement)
+ value->setImportedDocument(buildObjectForNode(linkElement.import(), 0, nodesMap));
+ forcePushChildren = true;
+ }
+
+ if (isHTMLTemplateElement(*element)) {
+ value->setTemplateContent(buildObjectForNode(toHTMLTemplateElement(*element).content(), 0, nodesMap));
forcePushChildren = true;
}
if (node->isContainerNode()) {
int nodeCount = innerChildNodeCount(node);
value->setChildNodeCount(nodeCount);
+ if (nodesMap == &m_documentNodeToIdMap)
+ m_cachedChildCount.set(id, nodeCount);
if (forcePushChildren && !depth)
depth = 1;
RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodesMap);
unsigned numAttrs = element->attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
// Add attribute pair
- const Attribute* attribute = element->attributeItem(i);
- attributesValue->addItem(attribute->name().toString());
- attributesValue->addItem(attribute->value());
+ const Attribute& attribute = element->attributeItem(i);
+ attributesValue->addItem(attribute.name().toString());
+ attributesValue->addItem(attribute.value());
}
return attributesValue.release();
}
PassRefPtr<TypeBuilder::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
{
RefPtr<EventListener> eventListener = registeredEventListener.listener;
+ String sourceName;
+ String scriptId;
+ int lineNumber;
+ if (!eventListenerHandlerLocation(&node->document(), eventListener.get(), sourceName, scriptId, lineNumber))
+ return nullptr;
+
Document& document = node->document();
+ RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
+ .setScriptId(scriptId)
+ .setLineNumber(lineNumber);
RefPtr<TypeBuilder::DOM::EventListener> value = TypeBuilder::DOM::EventListener::create()
.setType(eventType)
.setUseCapture(registeredEventListener.useCapture)
.setIsAttribute(eventListener->isAttribute())
.setNodeId(pushNodePathToFrontend(node))
- .setHandlerBody(eventListenerHandlerBody(&document, eventListener.get()));
+ .setHandlerBody(eventListenerHandlerBody(&document, eventListener.get()))
+ .setLocation(location);
if (objectGroupId) {
ScriptValue functionValue = eventListenerHandler(&document, eventListener.get());
- if (!functionValue.hasNoValue()) {
- Frame* frame = document.frame();
+ if (!functionValue.isEmpty()) {
+ LocalFrame* frame = document.frame();
if (frame) {
ScriptState* scriptState = eventListenerHandlerScriptState(frame, eventListener.get());
if (scriptState) {
InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
- if (!injectedScript.hasNoValue()) {
+ if (!injectedScript.isEmpty()) {
RefPtr<TypeBuilder::Runtime::RemoteObject> valueJson = injectedScript.wrapObject(functionValue, *objectGroupId);
value->setHandler(valueJson);
}
}
}
}
- String sourceName;
- String scriptId;
- int lineNumber;
- if (eventListenerHandlerLocation(&node->document(), eventListener.get(), sourceName, scriptId, lineNumber)) {
- RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
- .setScriptId(scriptId)
- .setLineNumber(lineNumber);
- value->setLocation(location);
- if (!sourceName.isEmpty())
- value->setSourceName(sourceName);
- }
+ if (!sourceName.isEmpty())
+ value->setSourceName(sourceName);
return value.release();
}
PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > InspectorDOMAgent::buildArrayForPseudoElements(Element* element, NodeToIdMap* nodesMap)
{
if (!element->pseudoElement(BEFORE) && !element->pseudoElement(AFTER))
- return 0;
+ return nullptr;
RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > pseudoElements = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
if (element->pseudoElement(BEFORE))
{
if (node->isDocumentNode()) {
Document* document = toDocument(node);
+ if (HTMLImportLoader* loader = document->importLoader())
+ return loader->firstImport()->link();
return document->ownerElement();
}
return node->parentOrShadowHostNode();
return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
}
-void InspectorDOMAgent::domContentLoadedEventFired(Frame* frame)
+void InspectorDOMAgent::domContentLoadedEventFired(LocalFrame* frame)
{
if (!frame->isMainFrame())
return;
m_frontend->documentUpdated();
}
-void InspectorDOMAgent::invalidateFrameOwnerElement(Frame* frame)
+void InspectorDOMAgent::invalidateFrameOwnerElement(LocalFrame* frame)
{
Element* frameOwner = frame->document()->ownerElement();
if (!frameOwner)
m_frontend->childNodeInserted(parentId, prevId, value.release());
}
-void InspectorDOMAgent::didCommitLoad(Frame* frame, DocumentLoader* loader)
+void InspectorDOMAgent::didCommitLoad(LocalFrame* frame, DocumentLoader* loader)
{
// FIXME: If "frame" is always guarenteed to be in the same Page as loader->frame()
// then all we need to check here is loader->frame()->isMainFrame()
// and we don't need "frame" at all.
- Frame* mainFrame = frame->page()->mainFrame();
+ LocalFrame* mainFrame = frame->page()->mainFrame();
if (loader->frame() != mainFrame) {
invalidateFrameOwnerElement(loader->frame());
return;
ContainerNode* parent = node->parentNode();
if (!parent)
return;
-
int parentId = m_documentNodeToIdMap.get(parent);
// Return if parent is not mapped yet.
if (!parentId)
return;
if (!m_childrenRequested.contains(parentId)) {
- // No children are mapped yet -> only notify on changes of hasChildren.
- m_frontend->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
+ // No children are mapped yet -> only notify on changes of child count.
+ int count = m_cachedChildCount.get(parentId) + 1;
+ m_cachedChildCount.set(parentId, count);
+ m_frontend->childNodeCountUpdated(parentId, count);
} else {
// Children have been requested -> return value of a new child.
Node* prevSibling = innerPreviousSibling(node);
int parentId = m_documentNodeToIdMap.get(parent);
if (!m_childrenRequested.contains(parentId)) {
- // No children are mapped yet -> only notify on changes of hasChildren.
- if (innerChildNodeCount(parent) == 1)
- m_frontend->childNodeCountUpdated(parentId, 0);
- } else
+ // No children are mapped yet -> only notify on changes of child count.
+ int count = m_cachedChildCount.get(parentId) - 1;
+ m_cachedChildCount.set(parentId, count);
+ m_frontend->childNodeCountUpdated(parentId, count);
+ } else {
m_frontend->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
+ }
unbind(node, &m_documentNodeToIdMap);
}
m_frontend->shadowRootPopped(hostId, rootId);
}
-void InspectorDOMAgent::frameDocumentUpdated(Frame* frame)
+void InspectorDOMAgent::frameDocumentUpdated(LocalFrame* frame)
{
Document* document = frame->document();
if (!document)
m_frontend->pseudoElementRemoved(parentId, pseudoElementId);
}
+static ShadowRoot* shadowRootForNode(Node* node, const String& type)
+{
+ if (!node->isElementNode())
+ return 0;
+ if (type == "a")
+ return toElement(node)->shadowRoot();
+ if (type == "u")
+ return toElement(node)->userAgentShadowRoot();
+ return 0;
+}
+
Node* InspectorDOMAgent::nodeForPath(const String& path)
{
- // The path is of form "1,HTML,2,BODY,1,DIV"
+ // The path is of form "1,HTML,2,BODY,1,DIV" (<index> and <nodeName> interleaved).
+ // <index> may also be "a" (author shadow root) or "u" (user-agent shadow root),
+ // in which case <nodeName> MUST be "#document-fragment".
if (!m_document)
return 0;
return 0;
for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
bool success = true;
- unsigned childNumber = pathTokens[i].toUInt(&success);
- if (!success)
- return 0;
- if (childNumber >= innerChildNodeCount(node))
- return 0;
+ String& indexValue = pathTokens[i];
+ unsigned childNumber = indexValue.toUInt(&success);
+ Node* child;
+ if (!success) {
+ child = shadowRootForNode(node, indexValue);
+ } else {
+ if (childNumber >= innerChildNodeCount(node))
+ return 0;
- Node* child = innerFirstChild(node);
+ child = innerFirstChild(node);
+ }
String childName = pathTokens[i + 1];
for (size_t j = 0; child && j < childNumber; ++j)
child = innerNextSibling(child);
*errorString = "No node with given path found";
}
-void InspectorDOMAgent::pushNodeByBackendIdToFrontend(ErrorString* errorString, BackendNodeId backendNodeId, int* nodeId)
+void InspectorDOMAgent::pushNodesByBackendIdsToFrontend(ErrorString* errorString, const RefPtr<JSONArray>& backendNodeIds, RefPtr<TypeBuilder::Array<int> >& result)
{
- if (!m_backendIdToNode.contains(backendNodeId)) {
- *errorString = "No node with given backend id found";
- return;
- }
+ result = TypeBuilder::Array<int>::create();
+ for (JSONArray::const_iterator it = backendNodeIds->begin(); it != backendNodeIds->end(); ++it) {
+ int backendNodeId;
- Node* node = m_backendIdToNode.get(backendNodeId).first;
- String nodeGroup = m_backendIdToNode.get(backendNodeId).second;
- *nodeId = pushNodePathToFrontend(node);
+ if (!(*it)->asNumber(&backendNodeId)) {
+ *errorString = "Invalid argument type";
+ return;
+ }
- if (nodeGroup == "") {
- m_backendIdToNode.remove(backendNodeId);
- m_nodeGroupToBackendIdMap.find(nodeGroup)->value.remove(node);
+ Node* node = InspectorNodeIds::nodeForId(backendNodeId);
+ if (node && node->document().page() == m_pageAgent->page())
+ result->addItem(pushNodePathToFrontend(node));
+ else
+ result->addItem(0);
}
}
*errorString = "No renderer for node, perhaps orphan or hidden node";
return;
}
- while (renderer && !renderer->isRoot() && !renderer->isRelayoutBoundaryForInspector())
+ while (renderer && !renderer->isDocumentElement() && !renderer->isRelayoutBoundaryForInspector())
renderer = renderer->container();
Node* resultNode = renderer ? renderer->generatingNode() : node->ownerDocument();
*relayoutBoundaryNodeId = pushNodePathToFrontend(resultNode);
PassRefPtr<TypeBuilder::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
{
Document* document = node->isDocumentNode() ? &node->document() : node->ownerDocument();
- Frame* frame = document ? document->frame() : 0;
+ LocalFrame* frame = document ? document->frame() : 0;
if (!frame)
- return 0;
+ return nullptr;
- InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
- if (injectedScript.hasNoValue())
- return 0;
+ InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(ScriptState::forMainWorld(frame));
+ if (injectedScript.isEmpty())
+ return nullptr;
return injectedScript.wrapNode(node, objectGroup);
}