blob: 5f59ed9f8e54c19c2903c44f0ad306afe10e43e0 [file] [log] [blame]
/*
* 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, 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, 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;
}
if (resolvedValue.subtype === "node") {
contextMenu.appendItem(WI.UIString("Copy as HTML"), function() {
resolvedValue.pushNodeToFrontend(function(nodeId) {
WI.domTreeManager.nodeForId(nodeId).copyNode();
});
});
contextMenu.appendItem(WI.UIString("Scroll Into View"), function() {
function scrollIntoView() { this.scrollIntoViewIfNeeded(true); }
resolvedValue.callFunction(scrollIntoView, undefined, false, function() {});
});
contextMenu.appendSeparator();
contextMenu.appendItem(WI.UIString("Reveal in DOM Tree"), function() {
resolvedValue.pushNodeToFrontend(function(nodeId) {
WI.domTreeManager.inspectElement(nodeId);
});
});
return;
}
}
};