/* * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ WebInspector.ObjectTreeBaseTreeElement = class ObjectTreeBaseTreeElement extends WebInspector.GeneralTreeElement { constructor(representedObject, propertyPath, property) { console.assert(representedObject); console.assert(propertyPath instanceof WebInspector.PropertyPath); console.assert(!property || property instanceof WebInspector.PropertyDescriptor); super(null, null, null, representedObject, false); this._property = property; this._propertyPath = propertyPath; this.toggleOnClick = true; this.selectable = false; this.tooltipHandledSeparately = true; } // Public get property() { return this._property; } get propertyPath() { return this._propertyPath; } // Protected oncontextmenu(event) { this._contextMenuHandler(event); } resolvedValue() { console.assert(this._property); if (this._getterValue) return this._getterValue; if (this._property.hasValue()) return this._property.value; return null; } resolvedValuePropertyPath() { console.assert(this._property); if (this._getterValue) return this._propertyPath.appendPropertyDescriptor(this._getterValue, this._property, WebInspector.PropertyPath.Type.Value); if (this._property.hasValue()) return this._propertyPath.appendPropertyDescriptor(this._property.value, this._property, WebInspector.PropertyPath.Type.Value); return null; } thisPropertyPath() { console.assert(this._property); return this._propertyPath.appendPropertyDescriptor(null, this._property, this.propertyPathType()); } hadError() { console.assert(this._property); return this._property.wasThrown || this._getterHadError; } propertyPathType() { console.assert(this._property); if (this._getterValue || this._property.hasValue()) return WebInspector.PropertyPath.Type.Value; if (this._property.hasGetter()) return WebInspector.PropertyPath.Type.Getter; if (this._property.hasSetter()) return WebInspector.PropertyPath.Type.Setter; return WebInspector.PropertyPath.Type.Value; } propertyPathString(propertyPath) { if (propertyPath.isFullPathImpossible()) return WebInspector.UIString("Unable to determine path to property from root"); return propertyPath.displayPath(this.propertyPathType()); } createGetterElement(interactive) { var getterElement = document.createElement("img"); getterElement.className = "getter"; if (!interactive) { getterElement.classList.add("disabled"); getterElement.title = WebInspector.UIString("Getter"); return getterElement; } getterElement.title = WebInspector.UIString("Invoke getter"); getterElement.addEventListener("click", function(event) { event.stopPropagation(); var lastNonPrototypeObject = this._propertyPath.lastNonPrototypeObject; var getterObject = this._property.get; lastNonPrototypeObject.invokeGetter(getterObject, function(error, result, wasThrown) { this._getterHadError = !!(error || wasThrown); this._getterValue = result; if (this.invokedGetter && typeof this.invokedGetter === "function") this.invokedGetter(); }.bind(this)); }.bind(this)); return getterElement; } createSetterElement(interactive) { var setterElement = document.createElement("img"); setterElement.className = "setter"; setterElement.title = WebInspector.UIString("Setter"); if (!interactive) setterElement.classList.add("disabled"); return setterElement; } // Private _logSymbolProperty() { var symbol = this._property.symbol; if (!symbol) return; var text = WebInspector.UIString("Selected Symbol"); WebInspector.consoleLogViewController.appendImmediateExecutionWithResult(text, symbol, true); } _logValue(value) { var resolvedValue = value || this.resolvedValue(); if (!resolvedValue) return; var propertyPath = this.resolvedValuePropertyPath(); var isImpossible = propertyPath.isFullPathImpossible(); var text = isImpossible ? WebInspector.UIString("Selected Value") : propertyPath.displayPath(this.propertyPathType()); if (!isImpossible) WebInspector.quickConsole.prompt.pushHistoryItem(text); WebInspector.consoleLogViewController.appendImmediateExecutionWithResult(text, resolvedValue, isImpossible); } _contextMenuHandler(event) { let contextMenu = WebInspector.ContextMenu.createFromEvent(event); if (typeof this.treeOutline.objectTreeElementAddContextMenuItems === "function") { this.treeOutline.objectTreeElementAddContextMenuItems(this, contextMenu); if (!contextMenu.isEmpty()) contextMenu.appendSeparator(); } let resolvedValue = this.resolvedValue(); if (!resolvedValue) return; if (this._property && this._property.symbol) contextMenu.appendItem(WebInspector.UIString("Log Symbol"), this._logSymbolProperty.bind(this)); contextMenu.appendItem(WebInspector.UIString("Log Value"), this._logValue.bind(this)); let propertyPath = this.resolvedValuePropertyPath(); if (propertyPath && !propertyPath.isFullPathImpossible()) { contextMenu.appendItem(WebInspector.UIString("Copy Path to Property"), () => { InspectorFrontendHost.copyText(propertyPath.displayPath(WebInspector.PropertyPath.Type.Value)); }); } contextMenu.appendSeparator(); this._appendMenusItemsForObject(contextMenu, resolvedValue); } _appendMenusItemsForObject(contextMenu, resolvedValue) { if (resolvedValue.type === "function") { // FIXME: We should better handle bound functions. if (!isFunctionStringNativeCode(resolvedValue.description)) { contextMenu.appendItem(WebInspector.UIString("Jump to Definition"), function() { DebuggerAgent.getFunctionDetails(resolvedValue.objectId, function(error, response) { if (error) return; let location = response.location; let sourceCode = WebInspector.debuggerManager.scriptForIdentifier(location.scriptId); if (!sourceCode) return; let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber || 0); WebInspector.showSourceCodeLocation(sourceCodeLocation); }); }); } return; } if (resolvedValue.subtype === "node") { contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), function() { resolvedValue.pushNodeToFrontend(function(nodeId) { WebInspector.domTreeManager.nodeForId(nodeId).copyNode(); }); }); contextMenu.appendItem(WebInspector.UIString("Scroll Into View"), function() { function scrollIntoView() { this.scrollIntoViewIfNeeded(true); } resolvedValue.callFunction(scrollIntoView, undefined, false, function() {}); }); contextMenu.appendSeparator(); contextMenu.appendItem(WebInspector.UIString("Reveal in DOM Tree"), function() { resolvedValue.pushNodeToFrontend(function(nodeId) { WebInspector.domTreeManager.inspectElement(nodeId); }); }); return; } } };