OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | 31 * @unrestricted |
33 * @extends {WebInspector.PopoverHelper} | |
34 * @param {!Element} panelElement | |
35 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnchor | |
36 * @param {function(!Element, function(!WebInspector.RemoteObject, boolean, !Ele
ment=):undefined, string):undefined} queryObject | |
37 * @param {function()=} onHide | |
38 * @param {boolean=} disableOnClick | |
39 */ | 32 */ |
40 WebInspector.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject
, onHide, disableOnClick) | 33 WebInspector.ObjectPopoverHelper = class extends WebInspector.PopoverHelper { |
41 { | 34 /** |
42 WebInspector.PopoverHelper.call(this, panelElement, disableOnClick); | 35 * @param {!Element} panelElement |
| 36 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnch
or |
| 37 * @param {function(!Element, function(!WebInspector.RemoteObject, boolean, !E
lement=):undefined, string):undefined} queryObject |
| 38 * @param {function()=} onHide |
| 39 * @param {boolean=} disableOnClick |
| 40 */ |
| 41 constructor(panelElement, getAnchor, queryObject, onHide, disableOnClick) { |
| 42 super(panelElement, disableOnClick); |
43 this.initializeCallbacks(getAnchor, this._showObjectPopover.bind(this), this
._onHideObjectPopover.bind(this)); | 43 this.initializeCallbacks(getAnchor, this._showObjectPopover.bind(this), this
._onHideObjectPopover.bind(this)); |
44 this._queryObject = queryObject; | 44 this._queryObject = queryObject; |
45 this._onHideCallback = onHide; | 45 this._onHideCallback = onHide; |
46 this._popoverObjectGroup = "popover"; | 46 this._popoverObjectGroup = 'popover'; |
47 panelElement.addEventListener("scroll", this.hidePopover.bind(this), true); | 47 panelElement.addEventListener('scroll', this.hidePopover.bind(this), true); |
| 48 } |
| 49 |
| 50 /** |
| 51 * @param {!Element} element |
| 52 * @param {!WebInspector.Popover} popover |
| 53 */ |
| 54 _showObjectPopover(element, popover) { |
| 55 /** |
| 56 * @param {!WebInspector.RemoteObject} funcObject |
| 57 * @param {!Element} popoverContentElement |
| 58 * @param {!Element} popoverValueElement |
| 59 * @param {!Element} anchorElement |
| 60 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| 61 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| 62 * @this {WebInspector.ObjectPopoverHelper} |
| 63 */ |
| 64 function didGetFunctionProperties( |
| 65 funcObject, popoverContentElement, popoverValueElement, anchorElement, p
roperties, internalProperties) { |
| 66 if (internalProperties) { |
| 67 for (var i = 0; i < internalProperties.length; i++) { |
| 68 if (internalProperties[i].name === '[[TargetFunction]]') { |
| 69 funcObject = internalProperties[i].value; |
| 70 break; |
| 71 } |
| 72 } |
| 73 } |
| 74 WebInspector.ObjectPropertiesSection.formatObjectAsFunction(funcObject, po
poverValueElement, true); |
| 75 funcObject.debuggerModel() |
| 76 .functionDetailsPromise(funcObject) |
| 77 .then(didGetFunctionDetails.bind(this, popoverContentElement, anchorEl
ement)); |
| 78 } |
| 79 |
| 80 /** |
| 81 * @param {!Element} popoverContentElement |
| 82 * @param {!Element} anchorElement |
| 83 * @param {?WebInspector.DebuggerModel.FunctionDetails} response |
| 84 * @this {WebInspector.ObjectPopoverHelper} |
| 85 */ |
| 86 function didGetFunctionDetails(popoverContentElement, anchorElement, respons
e) { |
| 87 if (!response || popover.disposed) |
| 88 return; |
| 89 |
| 90 var container = createElementWithClass('div', 'object-popover-container'); |
| 91 var title = container.createChild('div', 'function-popover-title source-co
de'); |
| 92 var functionName = title.createChild('span', 'function-name'); |
| 93 functionName.textContent = WebInspector.beautifyFunctionName(response.func
tionName); |
| 94 |
| 95 var rawLocation = response.location; |
| 96 var linkContainer = title.createChild('div', 'function-title-link-containe
r'); |
| 97 if (rawLocation && Runtime.experiments.isEnabled('continueToFirstInvocatio
n')) { |
| 98 var sectionToolbar = new WebInspector.Toolbar('function-location-step-in
to', linkContainer); |
| 99 var stepInto = new WebInspector.ToolbarButton( |
| 100 WebInspector.UIString('Continue to first invocation'), 'step-in-tool
bar-item'); |
| 101 stepInto.addEventListener('click', () => rawLocation.continueToLocation(
)); |
| 102 sectionToolbar.appendToolbarItem(stepInto); |
| 103 } |
| 104 var sourceURL = rawLocation && rawLocation.script() ? rawLocation.script()
.sourceURL : null; |
| 105 if (rawLocation && sourceURL) |
| 106 linkContainer.appendChild(this._lazyLinkifier().linkifyRawLocation(rawLo
cation, sourceURL)); |
| 107 container.appendChild(popoverContentElement); |
| 108 popover.showForAnchor(container, anchorElement); |
| 109 } |
| 110 |
| 111 /** |
| 112 * @param {!WebInspector.RemoteObject} result |
| 113 * @param {boolean} wasThrown |
| 114 * @param {!Element=} anchorOverride |
| 115 * @this {WebInspector.ObjectPopoverHelper} |
| 116 */ |
| 117 function didQueryObject(result, wasThrown, anchorOverride) { |
| 118 if (popover.disposed) |
| 119 return; |
| 120 if (wasThrown) { |
| 121 this.hidePopover(); |
| 122 return; |
| 123 } |
| 124 this._objectTarget = result.target(); |
| 125 var anchorElement = anchorOverride || element; |
| 126 var description = result.description.trimEnd(WebInspector.ObjectPopoverHel
per.MaxPopoverTextLength); |
| 127 var popoverContentElement = null; |
| 128 if (result.type !== 'object') { |
| 129 popoverContentElement = createElement('span'); |
| 130 WebInspector.appendStyle(popoverContentElement, 'components/objectValue.
css'); |
| 131 var valueElement = popoverContentElement.createChild('span', 'monospace
object-value-' + result.type); |
| 132 valueElement.style.whiteSpace = 'pre'; |
| 133 |
| 134 if (result.type === 'string') |
| 135 valueElement.createTextChildren('"', description, '"'); |
| 136 else if (result.type !== 'function') |
| 137 valueElement.textContent = description; |
| 138 |
| 139 if (result.type === 'function') { |
| 140 result.getOwnProperties( |
| 141 didGetFunctionProperties.bind(this, result, popoverContentElement,
valueElement, anchorElement)); |
| 142 return; |
| 143 } |
| 144 popover.showForAnchor(popoverContentElement, anchorElement); |
| 145 } else { |
| 146 if (result.subtype === 'node') { |
| 147 WebInspector.DOMModel.highlightObjectAsDOMNode(result); |
| 148 this._resultHighlightedAsDOM = true; |
| 149 } |
| 150 |
| 151 if (result.customPreview()) { |
| 152 var customPreviewComponent = new WebInspector.CustomPreviewComponent(r
esult); |
| 153 customPreviewComponent.expandIfPossible(); |
| 154 popoverContentElement = customPreviewComponent.element; |
| 155 } else { |
| 156 popoverContentElement = createElement('div'); |
| 157 this._titleElement = popoverContentElement.createChild('div', 'monospa
ce'); |
| 158 this._titleElement.createChild('span', 'source-frame-popover-title').t
extContent = description; |
| 159 var section = new WebInspector.ObjectPropertiesSection(result, '', thi
s._lazyLinkifier()); |
| 160 section.element.classList.add('source-frame-popover-tree'); |
| 161 section.titleLessMode(); |
| 162 popoverContentElement.appendChild(section.element); |
| 163 } |
| 164 var popoverWidth = 300; |
| 165 var popoverHeight = 250; |
| 166 popover.showForAnchor(popoverContentElement, anchorElement, popoverWidth
, popoverHeight); |
| 167 } |
| 168 } |
| 169 this._queryObject(element, didQueryObject.bind(this), this._popoverObjectGro
up); |
| 170 } |
| 171 |
| 172 _onHideObjectPopover() { |
| 173 if (this._resultHighlightedAsDOM) { |
| 174 WebInspector.DOMModel.hideDOMNodeHighlight(); |
| 175 delete this._resultHighlightedAsDOM; |
| 176 } |
| 177 if (this._linkifier) { |
| 178 this._linkifier.dispose(); |
| 179 delete this._linkifier; |
| 180 } |
| 181 if (this._onHideCallback) |
| 182 this._onHideCallback(); |
| 183 if (this._objectTarget) { |
| 184 this._objectTarget.runtimeAgent().releaseObjectGroup(this._popoverObjectGr
oup); |
| 185 delete this._objectTarget; |
| 186 } |
| 187 } |
| 188 |
| 189 /** |
| 190 * @return {!WebInspector.Linkifier} |
| 191 */ |
| 192 _lazyLinkifier() { |
| 193 if (!this._linkifier) |
| 194 this._linkifier = new WebInspector.Linkifier(); |
| 195 return this._linkifier; |
| 196 } |
48 }; | 197 }; |
49 | 198 |
50 WebInspector.ObjectPopoverHelper.MaxPopoverTextLength = 10000; | 199 WebInspector.ObjectPopoverHelper.MaxPopoverTextLength = 10000; |
51 | |
52 WebInspector.ObjectPopoverHelper.prototype = { | |
53 /** | |
54 * @param {!Element} element | |
55 * @param {!WebInspector.Popover} popover | |
56 */ | |
57 _showObjectPopover: function(element, popover) | |
58 { | |
59 /** | |
60 * @param {!WebInspector.RemoteObject} funcObject | |
61 * @param {!Element} popoverContentElement | |
62 * @param {!Element} popoverValueElement | |
63 * @param {!Element} anchorElement | |
64 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties | |
65 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperti
es | |
66 * @this {WebInspector.ObjectPopoverHelper} | |
67 */ | |
68 function didGetFunctionProperties(funcObject, popoverContentElement, pop
overValueElement, anchorElement, properties, internalProperties) | |
69 { | |
70 if (internalProperties) { | |
71 for (var i = 0; i < internalProperties.length; i++) { | |
72 if (internalProperties[i].name === "[[TargetFunction]]") { | |
73 funcObject = internalProperties[i].value; | |
74 break; | |
75 } | |
76 } | |
77 } | |
78 WebInspector.ObjectPropertiesSection.formatObjectAsFunction(funcObje
ct, popoverValueElement, true); | |
79 funcObject.debuggerModel().functionDetailsPromise(funcObject).then(d
idGetFunctionDetails.bind(this, popoverContentElement, anchorElement)); | |
80 } | |
81 | |
82 /** | |
83 * @param {!Element} popoverContentElement | |
84 * @param {!Element} anchorElement | |
85 * @param {?WebInspector.DebuggerModel.FunctionDetails} response | |
86 * @this {WebInspector.ObjectPopoverHelper} | |
87 */ | |
88 function didGetFunctionDetails(popoverContentElement, anchorElement, res
ponse) | |
89 { | |
90 if (!response || popover.disposed) | |
91 return; | |
92 | |
93 var container = createElementWithClass("div", "object-popover-contai
ner"); | |
94 var title = container.createChild("div", "function-popover-title sou
rce-code"); | |
95 var functionName = title.createChild("span", "function-name"); | |
96 functionName.textContent = WebInspector.beautifyFunctionName(respons
e.functionName); | |
97 | |
98 var rawLocation = response.location; | |
99 var linkContainer = title.createChild("div", "function-title-link-co
ntainer"); | |
100 if (rawLocation && Runtime.experiments.isEnabled("continueToFirstInv
ocation")) { | |
101 var sectionToolbar = new WebInspector.Toolbar("function-location
-step-into", linkContainer); | |
102 var stepInto = new WebInspector.ToolbarButton(WebInspector.UIStr
ing("Continue to first invocation"), "step-in-toolbar-item"); | |
103 stepInto.addEventListener("click", () => rawLocation.continueToL
ocation()); | |
104 sectionToolbar.appendToolbarItem(stepInto); | |
105 } | |
106 var sourceURL = rawLocation && rawLocation.script() ? rawLocation.sc
ript().sourceURL : null; | |
107 if (rawLocation && sourceURL) | |
108 linkContainer.appendChild(this._lazyLinkifier().linkifyRawLocati
on(rawLocation, sourceURL)); | |
109 container.appendChild(popoverContentElement); | |
110 popover.showForAnchor(container, anchorElement); | |
111 } | |
112 | |
113 /** | |
114 * @param {!WebInspector.RemoteObject} result | |
115 * @param {boolean} wasThrown | |
116 * @param {!Element=} anchorOverride | |
117 * @this {WebInspector.ObjectPopoverHelper} | |
118 */ | |
119 function didQueryObject(result, wasThrown, anchorOverride) | |
120 { | |
121 if (popover.disposed) | |
122 return; | |
123 if (wasThrown) { | |
124 this.hidePopover(); | |
125 return; | |
126 } | |
127 this._objectTarget = result.target(); | |
128 var anchorElement = anchorOverride || element; | |
129 var description = result.description.trimEnd(WebInspector.ObjectPopo
verHelper.MaxPopoverTextLength); | |
130 var popoverContentElement = null; | |
131 if (result.type !== "object") { | |
132 popoverContentElement = createElement("span"); | |
133 WebInspector.appendStyle(popoverContentElement, "components/obje
ctValue.css"); | |
134 var valueElement = popoverContentElement.createChild("span", "mo
nospace object-value-" + result.type); | |
135 valueElement.style.whiteSpace = "pre"; | |
136 | |
137 if (result.type === "string") | |
138 valueElement.createTextChildren("\"", description, "\""); | |
139 else if (result.type !== "function") | |
140 valueElement.textContent = description; | |
141 | |
142 if (result.type === "function") { | |
143 result.getOwnProperties(didGetFunctionProperties.bind(this,
result, popoverContentElement, valueElement, anchorElement)); | |
144 return; | |
145 } | |
146 popover.showForAnchor(popoverContentElement, anchorElement); | |
147 } else { | |
148 if (result.subtype === "node") { | |
149 WebInspector.DOMModel.highlightObjectAsDOMNode(result); | |
150 this._resultHighlightedAsDOM = true; | |
151 } | |
152 | |
153 if (result.customPreview()) { | |
154 var customPreviewComponent = new WebInspector.CustomPreviewC
omponent(result); | |
155 customPreviewComponent.expandIfPossible(); | |
156 popoverContentElement = customPreviewComponent.element; | |
157 } else { | |
158 popoverContentElement = createElement("div"); | |
159 this._titleElement = popoverContentElement.createChild("div"
, "monospace"); | |
160 this._titleElement.createChild("span", "source-frame-popover
-title").textContent = description; | |
161 var section = new WebInspector.ObjectPropertiesSection(resul
t, "", this._lazyLinkifier()); | |
162 section.element.classList.add("source-frame-popover-tree"); | |
163 section.titleLessMode(); | |
164 popoverContentElement.appendChild(section.element); | |
165 } | |
166 var popoverWidth = 300; | |
167 var popoverHeight = 250; | |
168 popover.showForAnchor(popoverContentElement, anchorElement, popo
verWidth, popoverHeight); | |
169 } | |
170 } | |
171 this._queryObject(element, didQueryObject.bind(this), this._popoverObjec
tGroup); | |
172 }, | |
173 | |
174 _onHideObjectPopover: function() | |
175 { | |
176 if (this._resultHighlightedAsDOM) { | |
177 WebInspector.DOMModel.hideDOMNodeHighlight(); | |
178 delete this._resultHighlightedAsDOM; | |
179 } | |
180 if (this._linkifier) { | |
181 this._linkifier.dispose(); | |
182 delete this._linkifier; | |
183 } | |
184 if (this._onHideCallback) | |
185 this._onHideCallback(); | |
186 if (this._objectTarget) { | |
187 this._objectTarget.runtimeAgent().releaseObjectGroup(this._popoverOb
jectGroup); | |
188 delete this._objectTarget; | |
189 } | |
190 }, | |
191 | |
192 /** | |
193 * @return {!WebInspector.Linkifier} | |
194 */ | |
195 _lazyLinkifier: function() | |
196 { | |
197 if (!this._linkifier) | |
198 this._linkifier = new WebInspector.Linkifier(); | |
199 return this._linkifier; | |
200 }, | |
201 | |
202 __proto__: WebInspector.PopoverHelper.prototype | |
203 }; | |
OLD | NEW |