diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebInspectorUI/UserInterface/RemoteObject.js | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/RemoteObject.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/RemoteObject.js | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/RemoteObject.js b/Source/WebInspectorUI/UserInterface/RemoteObject.js new file mode 100644 index 000000000..9a9a1d304 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/RemoteObject.js @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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. + */ + +/** + * @constructor + * @param {string|undefined} objectId + * @param {string} type + * @param {string|undefined} subtype + * @param {*} value + * @param {string=} description + */ +WebInspector.RemoteObject = function(objectId, type, subtype, value, description) +{ + this._type = type; + this._subtype = subtype; + if (objectId) { + // handle + this._objectId = objectId; + this._description = description; + this._hasChildren = true; + } else { + // Primitive or null object. + console.assert(type !== "object" || value === null); + this._description = description || (value + ""); + this._hasChildren = false; + this.value = value; + } +} + +/** + * @param {number|string|boolean} value + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromPrimitiveValue = function(value) +{ + return new WebInspector.RemoteObject(undefined, typeof value, undefined, value); +} + +/** + * @param {Object} value + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromLocalObject = function(value) +{ + return new WebInspector.LocalJSONObject(value); +} + +/** + * @param {WebInspector.DOMNode} node + * @param {string} objectGroup + * @param {function(?WebInspector.RemoteObject)} callback + */ +WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback) +{ + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} object + */ + function mycallback(error, object) + { + if (!callback) + return; + + if (error || !object) + callback(null); + else + callback(WebInspector.RemoteObject.fromPayload(object)); + } + DOMAgent.resolveNode(node.id, objectGroup, mycallback); +} + +/** + * @param {RuntimeAgent.RemoteObject} payload + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromPayload = function(payload) +{ + console.assert(typeof payload === "object", "Remote object payload should only be an object"); + + return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description); +} + +/** + * @param {WebInspector.RemoteObject} remoteObject + * @return {string} + */ +WebInspector.RemoteObject.type = function(remoteObject) +{ + if (remoteObject === null) + return "null"; + + var type = typeof remoteObject; + if (type !== "object" && type !== "function") + return type; + + return remoteObject.type; +} + +WebInspector.RemoteObject.prototype = { + /** @return {RuntimeAgent.RemoteObjectId} */ + get objectId() + { + return this._objectId; + }, + + /** @return {string} */ + get type() + { + return this._type; + }, + + /** @return {string|undefined} */ + get subtype() + { + return this._subtype; + }, + + /** @return {string|undefined} */ + get description() + { + return this._description; + }, + + /** @return {boolean} */ + get hasChildren() + { + return this._hasChildren; + }, + + /** + * @param {function(Array.<WebInspector.RemoteObjectProperty>)} callback + */ + getOwnProperties: function(callback) + { + this._getProperties(true, callback); + }, + + /** + * @param {function(Array.<WebInspector.RemoteObjectProperty>)} callback + */ + getAllProperties: function(callback) + { + this._getProperties(false, callback); + }, + + /** + * @param {boolean} ownProperties + * @param {function(Array.<RuntimeAgent.RemoteObject>)} callback + */ + _getProperties: function(ownProperties, callback) + { + if (!this._objectId) { + callback([]); + return; + } + + /** + * @param {?Protocol.Error} error + * @param {Array.<WebInspector.RemoteObjectProperty>} properties + */ + function remoteObjectBinder(error, properties) + { + if (error) { + callback(null); + return; + } + var result = []; + for (var i = 0; properties && i < properties.length; ++i) { + var property = properties[i]; + if (property.get || property.set) { + if (property.get) + result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property)); + if (property.set) + result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property)); + } else + result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property)); + } + callback(result); + } + RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder); + }, + + /** + * @param {string} name + * @param {string} value + * @param {function(string=)} callback + */ + setPropertyValue: function(name, value, callback) + { + if (!this._objectId) { + callback("Can't set a property of non-object."); + return; + } + + RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this)); + + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + function evaluatedCallback(error, result, wasThrown) + { + if (error || wasThrown) { + callback(error || result.description); + return; + } + + function setPropertyValue(propertyName, propertyValue) + { + this[propertyName] = propertyValue; + } + + delete result.description; // Optimize on traffic. + RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], true, undefined, propertySetCallback.bind(this)); + if (result._objectId) + RuntimeAgent.releaseObject(result._objectId); + } + + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + function propertySetCallback(error, result, wasThrown) + { + if (error || wasThrown) { + callback(error || result.description); + return; + } + callback(); + } + }, + + /** + * @param {function(DOMAgent.NodeId)} callback + */ + pushNodeToFrontend: function(callback) + { + if (this._objectId) + WebInspector.domTreeManager.pushNodeToFrontend(this._objectId, callback); + else + callback(0); + }, + + /** + * @param {string} functionDeclaration + * @param {function(?WebInspector.RemoteObject)} callback + */ + callFunction: function(functionDeclaration, args, callback) + { + function mycallback(error, result, wasThrown) + { + callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result)); + } + + RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, mycallback); + }, + + /** + * @param {string} functionDeclaration + * @param {function(*)} callback + */ + callFunctionJSON: function(functionDeclaration, args, callback) + { + function mycallback(error, result, wasThrown) + { + callback((error || wasThrown) ? null : result.value); + } + + RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, mycallback); + }, + + release: function() + { + RuntimeAgent.releaseObject(this._objectId); + }, + + /** + * @return {number} + */ + arrayLength: function() + { + if (this.subtype !== "array") + return 0; + + var matches = this._description.match(/\[([0-9]+)\]/); + if (!matches) + return 0; + return parseInt(matches[1], 10); + } +} + +/** + * @constructor + * @param {string} name + * @param {WebInspector.RemoteObject} value + * @param {Object=} descriptor + */ +WebInspector.RemoteObjectProperty = function(name, value, descriptor) +{ + this.name = name; + this.value = value; + this.enumerable = descriptor ? !!descriptor.enumerable : true; + this.writable = descriptor ? !!descriptor.writable : true; + if (descriptor && descriptor.wasThrown) + this.wasThrown = true; +} + +/** + * @param {string} name + * @param {string} value + * @return {WebInspector.RemoteObjectProperty} + */ +WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value) +{ + return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value)); +} + +// The below is a wrapper around a local object that provides an interface comaptible +// with RemoteObject, to be used by the UI code (primarily ObjectPropertiesSection). +// Note that only JSON-compliant objects are currently supported, as there's no provision +// for traversing prototypes, extracting class names via constuctor, handling properties +// or functions. + +/** + * @constructor + * @extends {WebInspector.RemoteObject} + * @param {Object} value + */ +WebInspector.LocalJSONObject = function(value) +{ + this._value = value; +} + +WebInspector.LocalJSONObject.prototype = { + /** + * @return {string} + */ + get description() + { + if (this._cachedDescription) + return this._cachedDescription; + + if (this.type === "object") { + switch (this.subtype) { + case "array": + function formatArrayItem(property) + { + return property.value.description; + } + this._cachedDescription = this._concatenate("[", "]", formatArrayItem); + break; + case "null": + this._cachedDescription = "null"; + break; + default: + function formatObjectItem(property) + { + return property.name + ":" + property.value.description; + } + this._cachedDescription = this._concatenate("{", "}", formatObjectItem); + } + } else + this._cachedDescription = String(this._value); + + return this._cachedDescription; + }, + + /** + * @param {string} prefix + * @param {string} suffix + * @return {string} + */ + _concatenate: function(prefix, suffix, formatProperty) + { + const previewChars = 100; + + var buffer = prefix; + var children = this._children(); + for (var i = 0; i < children.length; ++i) { + var itemDescription = formatProperty(children[i]); + if (buffer.length + itemDescription.length > previewChars) { + buffer += ",\u2026"; + break; + } + if (i) + buffer += ", "; + buffer += itemDescription; + } + buffer += suffix; + return buffer; + }, + + /** + * @return {string} + */ + get type() + { + return typeof this._value; + }, + + /** + * @return {string|undefined} + */ + get subtype() + { + if (this._value === null) + return "null"; + + if (this._value instanceof Array) + return "array"; + + return undefined; + }, + + /** + * @return {boolean} + */ + get hasChildren() + { + return typeof this._value === "object" && this._value !== null && !isEmptyObject(this._value); + }, + + /** + * @param {function(Array.<WebInspector.RemoteObjectProperty>)} callback + */ + getOwnProperties: function(callback) + { + callback(this._children()); + }, + + /** + * @param {function(Array.<WebInspector.RemoteObjectProperty>)} callback + */ + getAllProperties: function(callback) + { + callback(this._children()); + }, + + /** + * @return {Array.<WebInspector.RemoteObjectProperty>} + */ + _children: function() + { + if (!this.hasChildren) + return []; + + function buildProperty(propName) + { + return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName])); + } + if (!this._cachedChildren) + this._cachedChildren = Object.keys(this._value || {}).map(buildProperty.bind(this)); + return this._cachedChildren; + }, + + /** + * @return {boolean} + */ + isError: function() + { + return false; + } +} |