ITMLKit Inspector: Data Bindings / Associated Data for nodes
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Mar 2019 21:48:04 +0000 (21:48 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Mar 2019 21:48:04 +0000 (21:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195290
<rdar://problem/48304019>

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2019-03-04
Reviewed by Devin Rousso.

Source/JavaScriptCore:

* inspector/protocol/DOM.json:

Source/WebCore:

* inspector/agents/InspectorDOMAgent.h:
* inspector/agents/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::getDataBindingsForNode):
(WebCore::InspectorDOMAgent::getAssociatedDataForNode):
Stub these for web pages, they will only be used for ITMLKit right now.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
New title and empty message strings.

* UserInterface/Views/DOMNodeDetailsSidebarPanel.css:
(.sidebar > .panel.dom-node-details .details-section.dom-node-associated-data > .content .row):
* UserInterface/Views/DOMNodeDetailsSidebarPanel.js:
(WI.DOMNodeDetailsSidebarPanel.prototype.initialLayout):
(WI.DOMNodeDetailsSidebarPanel.prototype.layout):
(WI.DOMNodeDetailsSidebarPanel.prototype._refreshDataBindings):
(WI.DOMNodeDetailsSidebarPanel.prototype._refreshAssociatedData):
(WI.DOMNodeDetailsSidebarPanel.prototype._attributesChanged):
New Node sections only enabled for ITMLKit `WI.sharedApp.hasExtraDomains`.

* UserInterface/Views/ObjectTreeView.js:
(WI.ObjectTreeView):
Provide a way, like TreeElement/View to access the ObjectTreeView from an element.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242386 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/DOM.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
Source/WebCore/inspector/agents/InspectorDOMAgent.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.css
Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.js

index a8e6295..4ede916 100644 (file)
@@ -1,3 +1,13 @@
+2019-03-04  Joseph Pecoraro  <pecoraro@apple.com>
+
+        ITMLKit Inspector: Data Bindings / Associated Data for nodes
+        https://bugs.webkit.org/show_bug.cgi?id=195290
+        <rdar://problem/48304019>
+
+        Reviewed by Devin Rousso.
+
+        * inspector/protocol/DOM.json:
+
 2019-03-04  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Make Reflect lazily-allocated by dropping @Reflect references from builtin JS
index 03c437f..cade521 100644 (file)
             ]
         },
         {
+            "id": "DataBinding",
+            "type": "object",
+            "description": "Relationship between data that is associated with a node and the node itself.",
+            "properties": [
+                { "name": "binding", "type": "string", "description": "The binding key that is specified." },
+                { "name": "type", "optional": true, "type": "string", "description": "A more descriptive name for the type of binding that represents this paritcular data relationship" },
+                { "name": "value", "type": "string", "description": "The value that is resolved to with this data binding relationship." }
+            ]
+        },
+        {
             "id": "EventListener",
             "type": "object",
             "description": "A structure holding event listener properties.",
             ]
         },
         {
+            "name": "getDataBindingsForNode",
+            "description": "Returns all data binding relationships between data that is associated with the node and the node itself.",
+            "parameters": [
+                { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get data bindings for." }
+            ],
+            "returns": [
+                { "name": "dataBindings", "type": "array", "items": { "$ref": "DataBinding"}, "description": "Array of binding relationships between data and node" }
+            ]
+        },
+        {
+            "name": "getAssociatedDataForNode",
+            "description": "Returns all data that has been associated with the node and is available for data binding.",
+            "parameters": [
+                { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get associated data for." }
+            ],
+            "returns": [
+                { "name": "associatedData", "type": "string", "optional": true, "description": "Associated data bound to this node. Sent as a JSON string." }
+            ]
+        },
+        {
             "name": "getEventListenersForNode",
             "description": "Returns event listeners relevant to the node.",
             "parameters": [
index 34dd6de..49779ce 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-04  Joseph Pecoraro  <pecoraro@apple.com>
+
+        ITMLKit Inspector: Data Bindings / Associated Data for nodes
+        https://bugs.webkit.org/show_bug.cgi?id=195290
+        <rdar://problem/48304019>
+
+        Reviewed by Devin Rousso.
+
+        * inspector/agents/InspectorDOMAgent.h:
+        * inspector/agents/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::getDataBindingsForNode):
+        (WebCore::InspectorDOMAgent::getAssociatedDataForNode):
+        Stub these for web pages, they will only be used for ITMLKit right now.
+
 2019-03-04  Daniel Bates  <dabates@apple.com>
 
         [iOS] Caret x-position in empty text area does not match text field
index 0c7d769..a9ff392 100644 (file)
@@ -866,6 +866,16 @@ void InspectorDOMAgent::getSupportedEventNames(ErrorString&, RefPtr<JSON::ArrayO
 #undef DOM_EVENT_NAMES_ADD
 }
 
+void InspectorDOMAgent::getDataBindingsForNode(ErrorString& errorString, int /* nodeId */, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::DataBinding>>& /* dataBindings */)
+{
+    errorString = "Not supported"_s;
+}
+
+void InspectorDOMAgent::getAssociatedDataForNode(ErrorString& errorString, int /* nodeId */, Optional<String>& /* associatedData */)
+{
+    errorString = "Not supported"_s;
+}
+
 void InspectorDOMAgent::getEventListenersForNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray)
 {
     listenersArray = JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>::create();
index df1eedc..837b7be 100644 (file)
@@ -127,6 +127,8 @@ public:
     void insertAdjacentHTML(ErrorString&, int nodeId, const String& position, const String& html) override;
     void setNodeValue(ErrorString&, int nodeId, const String& value) override;
     void getSupportedEventNames(ErrorString&, RefPtr<JSON::ArrayOf<String>>& eventNames) override;
+    void getDataBindingsForNode(ErrorString&, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::DataBinding>>& dataArray) override;
+    void getAssociatedDataForNode(ErrorString&, int nodeId, Optional<String>& associatedData) override;
     void getEventListenersForNode(ErrorString&, int nodeId, const WTF::String* objectGroup, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray) override;
     void setEventListenerDisabled(ErrorString&, int eventListenerId, bool disabled) override;
     void setBreakpointForEventListener(ErrorString&, int eventListenerId) override;
index c21da7d..4627ff5 100644 (file)
@@ -1,3 +1,28 @@
+2019-03-04  Joseph Pecoraro  <pecoraro@apple.com>
+
+        ITMLKit Inspector: Data Bindings / Associated Data for nodes
+        https://bugs.webkit.org/show_bug.cgi?id=195290
+        <rdar://problem/48304019>
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New title and empty message strings.
+
+        * UserInterface/Views/DOMNodeDetailsSidebarPanel.css:
+        (.sidebar > .panel.dom-node-details .details-section.dom-node-associated-data > .content .row):
+        * UserInterface/Views/DOMNodeDetailsSidebarPanel.js:
+        (WI.DOMNodeDetailsSidebarPanel.prototype.initialLayout):
+        (WI.DOMNodeDetailsSidebarPanel.prototype.layout):
+        (WI.DOMNodeDetailsSidebarPanel.prototype._refreshDataBindings):
+        (WI.DOMNodeDetailsSidebarPanel.prototype._refreshAssociatedData):
+        (WI.DOMNodeDetailsSidebarPanel.prototype._attributesChanged):
+        New Node sections only enabled for ITMLKit `WI.sharedApp.hasExtraDomains`.
+
+        * UserInterface/Views/ObjectTreeView.js:
+        (WI.ObjectTreeView):
+        Provide a way, like TreeElement/View to access the ObjectTreeView from an element.
+
 2019-03-04  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Canvas: protocol error on first open
index 479c0eb..2c7fa68 100644 (file)
@@ -129,6 +129,7 @@ localizedStrings["Assertion Failed: %s"] = "Assertion Failed: %s";
 localizedStrings["Assertion Failures"] = "Assertion Failures";
 localizedStrings["Assertion with message: %s"] = "Assertion with message: %s";
 localizedStrings["Assertive"] = "Assertive";
+localizedStrings["Associated Data"] = "Associated Data";
 localizedStrings["Async audits are not supported."] = "Async audits are not supported.";
 localizedStrings["Attribute"] = "Attribute";
 localizedStrings["Attribute Modified"] = "Attribute Modified";
@@ -150,6 +151,7 @@ localizedStrings["Basic"] = "Basic";
 localizedStrings["Beacon"] = "Beacon";
 localizedStrings["Beacons"] = "Beacons";
 localizedStrings["Binary Frame"] = "Binary Frame";
+localizedStrings["Binding"] = "Binding";
 localizedStrings["Block Variables"] = "Block Variables";
 localizedStrings["Body:"] = "Body:";
 localizedStrings["Boundary"] = "Boundary";
@@ -288,6 +290,7 @@ localizedStrings["DOM Events"] = "DOM Events";
 localizedStrings["DOM Nodes:"] = "DOM Nodes:";
 localizedStrings["Damping"] = "Damping";
 localizedStrings["Data"] = "Data";
+localizedStrings["Data Bindings"] = "Data Bindings";
 localizedStrings["Data returned from the database is too large."] = "Data returned from the database is too large.";
 localizedStrings["Database"] = "Database";
 localizedStrings["Database no longer has expected version."] = "Database no longer has expected version.";
@@ -638,6 +641,7 @@ localizedStrings["Next Sibling"] = "Next Sibling";
 localizedStrings["No"] = "No";
 localizedStrings["No Accessibility Information"] = "No Accessibility Information";
 localizedStrings["No Application Cache information available"] = "No Application Cache information available";
+localizedStrings["No Associated Data"] = "No Associated Data";
 localizedStrings["No Attributes"] = "No Attributes";
 localizedStrings["No Audits"] = "No Audits";
 localizedStrings["No Box Model Information"] = "No Box Model Information";
@@ -646,6 +650,7 @@ localizedStrings["No Canvas Contexts"] = "No Canvas Contexts";
 localizedStrings["No Canvas Selected"] = "No Canvas Selected";
 localizedStrings["No Chart Available"] = "No Chart Available";
 localizedStrings["No Child Layers"] = "No Child Layers";
+localizedStrings["No Data Bindings"] = "No Data Bindings";
 localizedStrings["No Entries"] = "No Entries";
 localizedStrings["No Event Listeners"] = "No Event Listeners";
 localizedStrings["No Filter Results"] = "No Filter Results";
index d95c3a7..01c6725 100644 (file)
@@ -66,3 +66,8 @@ body[dir=rtl] .sidebar > .panel.dom-node-details .details-section.dom-node-event
         filter: brightness(1.25);
     }
 }
+
+.sidebar > .panel.dom-node-details .details-section.dom-node-associated-data > .content .row {
+    -webkit-margin-start: 6px;
+    margin-bottom: 4px;
+}
index fafa1c1..8980c0d 100644 (file)
@@ -102,6 +102,22 @@ WI.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel extends WI.DOMD
         this.contentView.element.appendChild(propertiesSection.element);
         this.contentView.element.appendChild(eventListenersSection.element);
 
+        if (WI.sharedApp.hasExtraDomains) {
+            if (InspectorBackend.domains.DOM.getDataBindingsForNode) {
+                this._dataBindingsSection = new WI.DetailsSection("dom-node-data-bindings", WI.UIString("Data Bindings"), []);
+                this.contentView.element.appendChild(this._dataBindingsSection.element);
+            }
+
+            if (InspectorBackend.domains.DOM.getAssociatedDataForNode) {
+                this._associatedDataGrid = new WI.DetailsSectionRow(WI.UIString("No Associated Data"));
+
+                let associatedDataGroup = new WI.DetailsSectionGroup([this._associatedDataGrid]);
+
+                let associatedSection = new WI.DetailsSection("dom-node-associated-data", WI.UIString("Associated Data"), [associatedDataGroup]);
+                this.contentView.element.appendChild(associatedSection.element);
+            }
+        }
+
         if (this._accessibilitySupported()) {
             this._accessibilityEmptyRow = new WI.DetailsSectionRow(WI.UIString("No Accessibility Information"));
             this._accessibilityNodeActiveDescendantRow = new WI.DetailsSectionSimpleRow(WI.UIString("Shared Focus"));
@@ -148,6 +164,8 @@ WI.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel extends WI.DOMD
         this._refreshAttributes();
         this._refreshProperties();
         this._refreshEventListeners();
+        this._refreshDataBindings();
+        this._refreshAssociatedData();
         this._refreshAccessibility();
     }
 
@@ -228,9 +246,11 @@ WI.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel extends WI.DOMD
         }
 
         let domNode = this.domNode;
-        RuntimeAgent.releaseObjectGroup(WI.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName);
 
-        WI.RemoteObject.resolveNode(domNode, WI.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName).then((object) => {
+        const objectGroup = "dom-node-details-sidebar-properties-object-group";
+        RuntimeAgent.releaseObjectGroup(objectGroup);
+
+        WI.RemoteObject.resolveNode(domNode, objectGroup).then((object) => {
             // Bail if the DOM node changed while we were waiting for the async response.
             if (this.domNode !== domNode)
                 return;
@@ -411,6 +431,89 @@ WI.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel extends WI.DOMD
         domNode.getEventListeners(eventListenersCallback.bind(this));
     }
 
+    _refreshDataBindings()
+    {
+        if (!this._dataBindingsSection)
+            return;
+
+        let domNode = this.domNode;
+        if (!domNode)
+            return;
+
+        DOMAgent.getDataBindingsForNode(this.domNode.id).then(({dataBindings}) => {
+            if (this.domNode !== domNode)
+                return;
+
+            if (!dataBindings.length) {
+                let emptyRow = new WI.DetailsSectionRow(WI.UIString("No Data Bindings"));
+                emptyRow.showEmptyMessage();
+                this._dataBindingsSection.groups = [new WI.DetailsSectionGroup([emptyRow])];
+                return;
+            }
+
+            let groups = [];
+            for (let {binding, type, value} of dataBindings) {
+                groups.push(new WI.DetailsSectionGroup([
+                    new WI.DetailsSectionSimpleRow(WI.UIString("Binding"), binding),
+                    new WI.DetailsSectionSimpleRow(WI.UIString("Type"), type),
+                    new WI.DetailsSectionSimpleRow(WI.UIString("Value"), value),
+                ]));
+            }
+            this._dataBindingsSection.groups = groups;
+        });
+    }
+
+    _refreshAssociatedData()
+    {
+        if (!this._associatedDataGrid)
+            return;
+
+        const objectGroup = "dom-node-details-sidebar-associated-data-object-group";
+        RuntimeAgent.releaseObjectGroup(objectGroup);
+
+        let domNode = this.domNode;
+        if (!domNode)
+            return;
+
+        DOMAgent.getAssociatedDataForNode(domNode.id).then(({associatedData}) => {
+            if (this.domNode !== domNode)
+                return;
+
+            if (!associatedData) {
+                this._associatedDataGrid.showEmptyMessage();
+                return;
+            }
+
+            let expression = associatedData;
+            const options = {
+                objectGroup,
+                doNotPauseOnExceptionsAndMuteConsole: true,
+            };
+            WI.runtimeManager.evaluateInInspectedWindow(expression, options, (result, wasThrown) => {
+                console.assert(!wasThrown);
+
+                if (!result) {
+                    this._associatedDataGrid.showEmptyMessage();
+                    return;
+                }
+
+                this._associatedDataGrid.hideEmptyMessage();
+
+                const propertyPath = null;
+                const forceExpanding = true;
+                let element = WI.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject(result, propertyPath, forceExpanding);
+
+                let objectTree = element.__objectTree;
+                if (objectTree) {
+                    objectTree.showOnlyProperties();
+                    objectTree.expand();
+                }
+
+                this._associatedDataGrid.element.appendChild(element);
+            });
+        });
+    }
+
     _refreshAccessibility()
     {
         if (!this._accessibilitySupported())
@@ -767,6 +870,7 @@ WI.DOMNodeDetailsSidebarPanel = class DOMNodeDetailsSidebarPanel extends WI.DOMD
             return;
         this._refreshAttributes();
         this._refreshAccessibility();
+        this._refreshDataBindings();
     }
 
     _attributeNodeValueChanged(event)
@@ -846,5 +950,3 @@ WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod = {
     Event: "event",
     Node: "node",
 };
-
-WI.DOMNodeDetailsSidebarPanel.PropertiesObjectGroupName = "dom-node-details-sidebar-properties-object-group";
index 433d041..5db1730 100644 (file)
@@ -51,6 +51,7 @@ WI.ObjectTreeView = class ObjectTreeView extends WI.Object
             forceExpanding = true;
 
         this._element = document.createElement("div");
+        this._element.__objectTree = this;
         this._element.className = "object-tree";
 
         if (this._object.preview) {