/* * 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. */ WI.ObjectTreeBaseTreeElement = class ObjectTreeBaseTreeElement extends WI.GeneralTreeElement { constructor(representedObject, propertyPath, property) { console.assert(representedObject); console.assert(propertyPath instanceof WI.PropertyPath); console.assert(!property || property instanceof WI.PropertyDescriptor); const classNames = null; const title = null; const subtitle = null; super(classNames, title, subtitle, representedObject); 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 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, WI.PropertyPath.Type.Value); if (this._property.hasValue()) return this._propertyPath.appendPropertyDescriptor(this._property.value, this._property, WI.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 WI.PropertyPath.Type.Value; if (this._property.hasGetter()) return WI.PropertyPath.Type.Getter; if (this._property.hasSetter()) return WI.PropertyPath.Type.Setter; return WI.PropertyPath.Type.Value; } propertyPathString(propertyPath) { if (propertyPath.isFullPathImpossible()) return WI.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 = WI.UIString("Getter"); return getterElement; } getterElement.title = WI.UIString("Invoke getter"); getterElement.addEventListener("click", (event) => { event.stopPropagation(); var lastNonPrototypeObject = this._propertyPath.lastNonPrototypeObject; var getterObject = this._property.get; lastNonPrototypeObject.invokeGetter(getterObject, (error, result, wasThrown) => { this._getterHadError = !!(error || wasThrown); this._getterValue = result; if (this.invokedGetter && typeof this.invokedGetter === "function") this.invokedGetter(); }); }); return getterElement; } createSetterElement(interactive) { var setterElement = document.createElement("img"); setterElement.className = "setter"; setterElement.title = WI.UIString("Setter"); if (!interactive) setterElement.classList.add("disabled"); return setterElement; } populateContextMenu(contextMenu, event) { if (event.__addedObjectPreviewContextMenuItems) return; if (event.__addedObjectTreeContextMenuItems) return; event.__addedObjectTreeContextMenuItems = true; 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(WI.UIString("Log Symbol"), this._logSymbolProperty.bind(this)); contextMenu.appendItem(WI.UIString("Log Value"), this._logValue.bind(this)); let propertyPath = this.resolvedValuePropertyPath(); if (propertyPath && !propertyPath.isFullPathImpossible()) { contextMenu.appendItem(WI.UIString("Copy Path to Property"), () => { InspectorFrontendHost.copyText(propertyPath.displayPath(WI.PropertyPath.Type.Value)); }); } contextMenu.appendSeparator(); this._appendMenusItemsForObject(contextMenu, resolvedValue); super.populateContextMenu(contextMenu, event); } // Private _logSymbolProperty() { var symbol = this._property.symbol; if (!symbol) return; var text = WI.UIString("Selected Symbol"); WI.consoleLogViewController.appendImmediateExecutionWithResult(text, symbol, {addSpecialUserLogClass: true}); } _logValue(value) { var resolvedValue = value || this.resolvedValue(); if (!resolvedValue) return; var propertyPath = this.resolvedValuePropertyPath(); var isImpossible = propertyPath.isFullPathImpossible(); var text = isImpossible ? WI.UIString("Selected Value") : propertyPath.displayPath(this.propertyPathType()); if (!isImpossible) WI.quickConsole.prompt.pushHistoryItem(text); WI.consoleLogViewController.appendImmediateExecutionWithResult(text, resolvedValue, {addSpecialUserLogClass: isImpossible}); } _appendMenusItemsForObject(contextMenu, resolvedValue) { if (resolvedValue.type === "function") { // FIXME: We should better handle bound functions. if (!isFunctionStringNativeCode(resolvedValue.description)) { contextMenu.appendItem(WI.UIString("Jump to Definition"), function() { resolvedValue.target.DebuggerAgent.getFunctionDetails(resolvedValue.objectId, function(error, response) { if (error) return; let location = response.location; let sourceCode = WI.debuggerManager.scriptForIdentifier(location.scriptId, resolvedValue.target); if (!sourceCode) return; let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber || 0); const options = { ignoreNetworkTab: true, ignoreSearchTab: true, }; WI.showSourceCodeLocation(sourceCodeLocation, options); }); }); } return; } } };