| /* |
| * 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. |
| */ |
| |
| /** |
| * @typedef {{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} |
| */ |
| WebInspector.CallFunctionResult; |
| |
| /** |
| * This may not be an interface due to "instanceof WebInspector.RemoteObject" checks in the code. |
| * |
| * @constructor |
| */ |
| WebInspector.RemoteObject = function() { } |
| |
| WebInspector.RemoteObject.prototype = { |
| |
| /** |
| * @return {?RuntimeAgent.CustomPreview} |
| */ |
| customPreview: function() |
| { |
| return null; |
| }, |
| |
| /** @return {string} */ |
| get type() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** @return {string|undefined} */ |
| get subtype() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** @return {string|undefined} */ |
| get description() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** @return {boolean} */ |
| get hasChildren() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @return {number} |
| */ |
| arrayLength: function() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getOwnProperties: function(callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @return {!Promise<!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>}>} |
| */ |
| getOwnPropertiesPromise: function() |
| { |
| return new Promise(promiseConstructor.bind(this)); |
| |
| /** |
| * @param {function(!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>})} success |
| * @this {WebInspector.RemoteObject} |
| */ |
| function promiseConstructor(success) |
| { |
| this.getOwnProperties(getOwnPropertiesCallback.bind(null, success)); |
| } |
| |
| /** |
| * @param {function(!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>})} callback |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| */ |
| function getOwnPropertiesCallback(callback, properties, internalProperties) |
| { |
| callback({ |
| properties: properties, |
| internalProperties: internalProperties |
| }); |
| } |
| }, |
| |
| /** |
| * @param {boolean} accessorPropertiesOnly |
| * @param {function(?Array<!WebInspector.RemoteObjectProperty>, ?Array<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getAllProperties: function(accessorPropertiesOnly, callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {boolean} accessorPropertiesOnly |
| * @return {!Promise<!{properties: ?Array<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array<!WebInspector.RemoteObjectProperty>}>} |
| */ |
| getAllPropertiesPromise: function(accessorPropertiesOnly) |
| { |
| return new Promise(promiseConstructor.bind(this)); |
| |
| /** |
| * @param {function(!{properties: ?Array<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>})} success |
| * @this {WebInspector.RemoteObject} |
| */ |
| function promiseConstructor(success) |
| { |
| this.getAllProperties(accessorPropertiesOnly, getAllPropertiesCallback.bind(null, success)); |
| } |
| |
| /** |
| * @param {function(!{properties: ?Array<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array<!WebInspector.RemoteObjectProperty>})} callback |
| * @param {?Array<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array<!WebInspector.RemoteObjectProperty>} internalProperties |
| */ |
| function getAllPropertiesCallback(callback, properties, internalProperties) |
| { |
| callback({ |
| properties: properties, |
| internalProperties: internalProperties |
| }); |
| } |
| }, |
| |
| /** |
| * @return {!Promise<?Array<!WebInspector.EventListener>>} |
| */ |
| eventListeners: function() |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {!RuntimeAgent.CallArgument} name |
| * @param {function(string=)} callback |
| */ |
| deleteProperty: function(name, callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {string|!RuntimeAgent.CallArgument} name |
| * @param {string} value |
| * @param {function(string=)} callback |
| */ |
| setPropertyValue: function(name, value, callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {function(this:Object, ...)} functionDeclaration |
| * @param {!Array<!RuntimeAgent.CallArgument>=} args |
| * @param {function(?WebInspector.RemoteObject, boolean=)=} callback |
| */ |
| callFunction: function(functionDeclaration, args, callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {function(this:Object, ...)} functionDeclaration |
| * @param {!Array<!RuntimeAgent.CallArgument>=} args |
| * @return {!Promise<!WebInspector.CallFunctionResult>} |
| */ |
| callFunctionPromise: function(functionDeclaration, args) |
| { |
| return new Promise(promiseConstructor.bind(this)); |
| |
| /** |
| * @param {function(!WebInspector.CallFunctionResult)} success |
| * @this {WebInspector.RemoteObject} |
| */ |
| function promiseConstructor(success) |
| { |
| this.callFunction(functionDeclaration, args, callFunctionCallback.bind(null, success)); |
| } |
| |
| /** |
| * @param {function(!WebInspector.CallFunctionResult)} callback |
| * @param {?WebInspector.RemoteObject} object |
| * @param {boolean=} wasThrown |
| */ |
| function callFunctionCallback(callback, object, wasThrown) |
| { |
| callback({ |
| object: object, |
| wasThrown: wasThrown |
| }); |
| } |
| }, |
| |
| /** |
| * @param {function(this:Object, ...)} functionDeclaration |
| * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args |
| * @param {function(*)} callback |
| */ |
| callFunctionJSON: function(functionDeclaration, args, callback) |
| { |
| throw "Not implemented"; |
| }, |
| |
| /** |
| * @param {function(this:Object, ...):T} functionDeclaration |
| * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args |
| * @return {!Promise<T>} |
| * @template T |
| */ |
| callFunctionJSONPromise: function(functionDeclaration, args) |
| { |
| return new Promise(promiseConstructor.bind(this)); |
| |
| /** |
| * @this {WebInspector.RemoteObject} |
| */ |
| function promiseConstructor(success) |
| { |
| this.callFunctionJSON(functionDeclaration, args, success); |
| } |
| }, |
| |
| /** |
| * @return {!WebInspector.Target} |
| */ |
| target: function() |
| { |
| throw new Error("Target-less object"); |
| }, |
| |
| /** |
| * @return {?WebInspector.DebuggerModel} |
| */ |
| debuggerModel: function() |
| { |
| throw new Error("DebuggerModel-less object"); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| isNode: function() |
| { |
| return false; |
| }, |
| |
| /** |
| * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback |
| */ |
| functionDetails: function(callback) |
| { |
| callback(null); |
| }, |
| |
| /** |
| * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} |
| */ |
| functionDetailsPromise: function() |
| { |
| return new Promise(promiseConstructor.bind(this)); |
| |
| /** |
| * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} success |
| * @this {WebInspector.RemoteObject} |
| */ |
| function promiseConstructor(success) |
| { |
| this.functionDetails(success); |
| } |
| }, |
| |
| /** |
| * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback |
| */ |
| generatorObjectDetails: function(callback) |
| { |
| callback(null); |
| }, |
| |
| /** |
| * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback |
| */ |
| collectionEntries: function(callback) |
| { |
| callback(null); |
| } |
| } |
| |
| /** |
| * @param {*} value |
| * @return {!WebInspector.RemoteObject} |
| */ |
| WebInspector.RemoteObject.fromLocalObject = function(value) |
| { |
| return new WebInspector.LocalJSONObject(value); |
| } |
| |
| /** |
| * @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; |
| } |
| |
| /** |
| * @param {!WebInspector.RemoteObject|!RuntimeAgent.RemoteObject|!RuntimeAgent.ObjectPreview} object |
| * @return {number} |
| */ |
| WebInspector.RemoteObject.arrayLength = function(object) |
| { |
| if (object.subtype !== "array") |
| return 0; |
| var matches = object.description.match(/\[([0-9]+)\]/); |
| if (!matches) |
| return 0; |
| return parseInt(matches[1], 10); |
| } |
| |
| /** |
| * @param {!RuntimeAgent.RemoteObject|!WebInspector.RemoteObject|number|string|boolean|undefined|null} object |
| * @return {!RuntimeAgent.CallArgument} |
| */ |
| WebInspector.RemoteObject.toCallArgument = function(object) |
| { |
| var type = typeof object; |
| var value = object; |
| var objectId = undefined; |
| var description = String(object); |
| |
| if (type === "number" && value === 0 && 1 / value < 0) |
| description = "-0"; |
| |
| switch (type) { |
| case "number": |
| case "string": |
| case "boolean": |
| case "undefined": |
| break; |
| default: |
| if (object) { |
| type = object.type; |
| value = object.value; |
| objectId = object.objectId; |
| description = object.description; |
| } |
| break; |
| } |
| |
| // Handle special numbers: NaN, Infinity, -Infinity, -0. |
| if (type === "number") { |
| switch (description) { |
| case "NaN": |
| case "Infinity": |
| case "-Infinity": |
| case "-0": |
| value = description; |
| break; |
| } |
| } |
| |
| return { |
| value: value, |
| objectId: objectId, |
| type: /** @type {!RuntimeAgent.CallArgumentType.<string>} */ (type) |
| }; |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.RemoteObject} |
| * @param {!WebInspector.Target} target |
| * @param {string|undefined} objectId |
| * @param {string} type |
| * @param {string|undefined} subtype |
| * @param {*} value |
| * @param {string=} description |
| * @param {!RuntimeAgent.ObjectPreview=} preview |
| * @param {!RuntimeAgent.CustomPreview=} customPreview |
| */ |
| WebInspector.RemoteObjectImpl = function(target, objectId, type, subtype, value, description, preview, customPreview) |
| { |
| WebInspector.RemoteObject.call(this); |
| |
| this._target = target; |
| this._runtimeAgent = target.runtimeAgent(); |
| this._debuggerModel = WebInspector.DebuggerModel.fromTarget(target); |
| |
| this._type = type; |
| this._subtype = subtype; |
| if (objectId) { |
| // handle |
| this._objectId = objectId; |
| this._description = description; |
| this._hasChildren = (type !== "symbol"); |
| this._preview = preview; |
| } else { |
| // Primitive or null object. |
| this._description = description || (value + ""); |
| this._hasChildren = false; |
| // Handle special numbers: NaN, Infinity, -Infinity, -0. |
| if (type === "number" && typeof value !== "number") |
| this.value = Number(value); |
| else |
| this.value = value; |
| } |
| this._customPreview = customPreview || null; |
| } |
| |
| WebInspector.RemoteObjectImpl.prototype = { |
| |
| /** |
| * @override |
| * @return {?RuntimeAgent.CustomPreview} |
| */ |
| customPreview: function() |
| { |
| return this._customPreview; |
| }, |
| |
| /** @return {!RuntimeAgent.RemoteObjectId} */ |
| get objectId() |
| { |
| return this._objectId; |
| }, |
| |
| /** |
| * @override |
| * @return {string} |
| */ |
| get type() |
| { |
| return this._type; |
| }, |
| |
| /** |
| * @override |
| * @return {string|undefined} |
| */ |
| get subtype() |
| { |
| return this._subtype; |
| }, |
| |
| /** |
| * @override |
| * @return {string|undefined} |
| */ |
| get description() |
| { |
| return this._description; |
| }, |
| |
| /** |
| * @override |
| * @return {boolean} |
| */ |
| get hasChildren() |
| { |
| return this._hasChildren; |
| }, |
| |
| /** |
| * @return {!RuntimeAgent.ObjectPreview|undefined} |
| */ |
| get preview() |
| { |
| return this._preview; |
| }, |
| |
| /** |
| * @override |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getOwnProperties: function(callback) |
| { |
| this.doGetProperties(true, false, false, callback); |
| }, |
| |
| /** |
| * @override |
| * @param {boolean} accessorPropertiesOnly |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getAllProperties: function(accessorPropertiesOnly, callback) |
| { |
| this.doGetProperties(false, accessorPropertiesOnly, false, callback); |
| }, |
| |
| /** |
| * @override |
| * @return {!Promise<?Array<!WebInspector.EventListener>>} |
| */ |
| eventListeners: function() |
| { |
| return new Promise(eventListeners.bind(this)); |
| /** |
| * @param {function(?)} fulfill |
| * @param {function(*)} reject |
| * @this {WebInspector.RemoteObject} |
| */ |
| function eventListeners(fulfill, reject) |
| { |
| if (!this.target().isPage()) { |
| // TODO(kozyatinskiy): figure out how this should work for |window| when there is no DOMDebugger. |
| fulfill([]); |
| return; |
| } |
| |
| if (!this._objectId) { |
| reject(null); |
| return; |
| } |
| |
| /** @type {?WebInspector.RemoteObject} */ |
| var removeFunction = null; |
| |
| this.callFunctionPromise(nodeRemoveEventListener).then(storeRemoveFunction.bind(this)); |
| |
| /** |
| * @param {!WebInspector.CallFunctionResult} result |
| * @this {WebInspector.RemoteObject} |
| */ |
| function storeRemoveFunction(result) |
| { |
| if (!result.wasThrown && result.object) |
| removeFunction = result.object; |
| this.target().domdebuggerAgent().getEventListeners(this._objectId, mycallback.bind(this)); |
| } |
| |
| /** |
| * @this {!WebInspector.RemoteObject} |
| * @param {?Protocol.Error} error |
| * @param {!Array<!DOMDebuggerAgent.EventListener>} payloads |
| */ |
| function mycallback(error, payloads) |
| { |
| if (error) { |
| reject(null); |
| return; |
| } |
| fulfill(payloads.map(createEventListener.bind(this))); |
| } |
| |
| /** |
| * @suppressReceiverCheck |
| * @this {Node} |
| * @return {function(this:Node, string, function(), boolean=): undefined} |
| */ |
| function nodeRemoveEventListener() |
| { |
| return removeEventListenerWrapper.bind(this); |
| /** |
| * @param {string} type |
| * @param {function()} handler |
| * @param {boolean=} useCapture |
| * @this {Node} |
| */ |
| function removeEventListenerWrapper(type, handler, useCapture) |
| { |
| this.removeEventListener(type, handler, useCapture); |
| if (this["on" + type]) |
| this["on" + type] = null; |
| } |
| } |
| |
| /** |
| * @this {!WebInspector.RemoteObject} |
| * @param {!DOMDebuggerAgent.EventListener} payload |
| */ |
| function createEventListener(payload) |
| { |
| return new WebInspector.EventListener(this._target, |
| payload.type, |
| payload.useCapture, |
| payload.handler ? this.target().runtimeModel.createRemoteObject(payload.handler) : null, |
| payload.originalHandler ? this.target().runtimeModel.createRemoteObject(payload.originalHandler) : null, |
| WebInspector.DebuggerModel.Location.fromPayload(this._debuggerModel, payload.location), |
| removeFunction); |
| } |
| } |
| }, |
| |
| /** |
| * @param {!Array.<string>} propertyPath |
| * @param {function(?WebInspector.RemoteObject, boolean=)} callback |
| */ |
| getProperty: function(propertyPath, callback) |
| { |
| /** |
| * @param {string} arrayStr |
| * @suppressReceiverCheck |
| * @this {Object} |
| */ |
| function remoteFunction(arrayStr) |
| { |
| var result = this; |
| var properties = JSON.parse(arrayStr); |
| for (var i = 0, n = properties.length; i < n; ++i) |
| result = result[properties[i]]; |
| return result; |
| } |
| |
| var args = [{ value: JSON.stringify(propertyPath) }]; |
| this.callFunction(remoteFunction, args, callback); |
| }, |
| |
| /** |
| * @param {boolean} ownProperties |
| * @param {boolean} accessorPropertiesOnly |
| * @param {boolean} generatePreview |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| doGetProperties: function(ownProperties, accessorPropertiesOnly, generatePreview, callback) |
| { |
| if (!this._objectId) { |
| callback(null, null); |
| return; |
| } |
| |
| /** |
| * @param {?Protocol.Error} error |
| * @param {!Array.<!RuntimeAgent.PropertyDescriptor>} properties |
| * @param {!Array.<!RuntimeAgent.InternalPropertyDescriptor>=} internalProperties |
| * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails |
| * @this {WebInspector.RemoteObjectImpl} |
| */ |
| function remoteObjectBinder(error, properties, internalProperties, exceptionDetails) |
| { |
| if (error) { |
| callback(null, null); |
| return; |
| } |
| if (exceptionDetails) { |
| var msg = new WebInspector.ConsoleMessage(this._target, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageLevel.Error, exceptionDetails.text); |
| this._target.consoleModel.addMessage(msg); |
| callback(null, null); |
| return; |
| } |
| var result = []; |
| for (var i = 0; properties && i < properties.length; ++i) { |
| var property = properties[i]; |
| var propertyValue = property.value ? this._target.runtimeModel.createRemoteObject(property.value) : null; |
| var propertySymbol = property.symbol ? this._target.runtimeModel.createRemoteObject(property.symbol) : null; |
| var remoteProperty = new WebInspector.RemoteObjectProperty(property.name, propertyValue, |
| !!property.enumerable, !!property.writable, !!property.isOwn, !!property.wasThrown, propertySymbol); |
| |
| if (typeof property.value === "undefined") { |
| if (property.get && property.get.type !== "undefined") |
| remoteProperty.getter = this._target.runtimeModel.createRemoteObject(property.get); |
| if (property.set && property.set.type !== "undefined") |
| remoteProperty.setter = this._target.runtimeModel.createRemoteObject(property.set); |
| } |
| |
| result.push(remoteProperty); |
| } |
| var internalPropertiesResult = null; |
| if (internalProperties) { |
| internalPropertiesResult = []; |
| for (var i = 0; i < internalProperties.length; i++) { |
| var property = internalProperties[i]; |
| if (!property.value) |
| continue; |
| var propertyValue = this._target.runtimeModel.createRemoteObject(property.value); |
| internalPropertiesResult.push(new WebInspector.RemoteObjectProperty(property.name, propertyValue, true, false)); |
| } |
| } |
| callback(result, internalPropertiesResult); |
| } |
| this._runtimeAgent.getProperties(this._objectId, ownProperties, accessorPropertiesOnly, generatePreview, remoteObjectBinder.bind(this)); |
| }, |
| |
| /** |
| * @override |
| * @param {string|!RuntimeAgent.CallArgument} 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; |
| } |
| |
| this._runtimeAgent.invoke_evaluate({expression:value, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this)); |
| |
| /** |
| * @param {?Protocol.Error} error |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {boolean=} wasThrown |
| * @this {WebInspector.RemoteObject} |
| */ |
| function evaluatedCallback(error, result, wasThrown) |
| { |
| if (error || wasThrown) { |
| callback(error || (result.type !== "string" ? result.description : /** @type {string} */(result.value))); |
| return; |
| } |
| |
| if (typeof name === "string") |
| name = WebInspector.RemoteObject.toCallArgument(name); |
| |
| this.doSetObjectPropertyValue(result, name, callback); |
| |
| if (result.objectId) |
| this._runtimeAgent.releaseObject(result.objectId); |
| } |
| }, |
| |
| /** |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {!RuntimeAgent.CallArgument} name |
| * @param {function(string=)} callback |
| */ |
| doSetObjectPropertyValue: function(result, name, callback) |
| { |
| // This assignment may be for a regular (data) property, and for an accessor property (with getter/setter). |
| // Note the sensitive matter about accessor property: the property may be physically defined in some proto object, |
| // but logically it is bound to the object in question. JavaScript passes this object to getters/setters, not the object |
| // where property was defined; so do we. |
| var setPropertyValueFunction = "function(a, b) { this[a] = b; }"; |
| |
| var argv = [name, WebInspector.RemoteObject.toCallArgument(result)]; |
| this._runtimeAgent.callFunctionOn(this._objectId, setPropertyValueFunction, argv, true, undefined, undefined, undefined, propertySetCallback); |
| |
| /** |
| * @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(); |
| } |
| }, |
| |
| /** |
| * @override |
| * @param {!RuntimeAgent.CallArgument} name |
| * @param {function(string=)} callback |
| */ |
| deleteProperty: function(name, callback) |
| { |
| if (!this._objectId) { |
| callback("Can't delete a property of non-object."); |
| return; |
| } |
| |
| var deletePropertyFunction = "function(a) { delete this[a]; return !(a in this); }"; |
| this._runtimeAgent.callFunctionOn(this._objectId, deletePropertyFunction, [name], true, undefined, undefined, undefined, deletePropertyCallback); |
| |
| /** |
| * @param {?Protocol.Error} error |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {boolean=} wasThrown |
| */ |
| function deletePropertyCallback(error, result, wasThrown) |
| { |
| if (error || wasThrown) { |
| callback(error || result.description); |
| return; |
| } |
| if (!result.value) |
| callback("Failed to delete property."); |
| else |
| callback(); |
| } |
| }, |
| |
| /** |
| * @override |
| * @param {function(this:Object, ...)} functionDeclaration |
| * @param {!Array.<!RuntimeAgent.CallArgument>=} args |
| * @param {function(?WebInspector.RemoteObject, boolean=)=} callback |
| */ |
| callFunction: function(functionDeclaration, args, callback) |
| { |
| /** |
| * @param {?Protocol.Error} error |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {boolean=} wasThrown |
| * @this {WebInspector.RemoteObjectImpl} |
| */ |
| function mycallback(error, result, wasThrown) |
| { |
| if (!callback) |
| return; |
| if (error) |
| callback(null, false); |
| else |
| callback(this.target().runtimeModel.createRemoteObject(result), wasThrown); |
| } |
| |
| this._runtimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, undefined, undefined, mycallback.bind(this)); |
| }, |
| |
| /** |
| * @override |
| * @param {function(this:Object)} functionDeclaration |
| * @param {!Array.<!RuntimeAgent.CallArgument>|undefined} args |
| * @param {function(*)} callback |
| */ |
| callFunctionJSON: function(functionDeclaration, args, callback) |
| { |
| /** |
| * @param {?Protocol.Error} error |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {boolean=} wasThrown |
| */ |
| function mycallback(error, result, wasThrown) |
| { |
| callback((error || wasThrown) ? null : result.value); |
| } |
| |
| this._runtimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, false, undefined, mycallback); |
| }, |
| |
| release: function() |
| { |
| if (!this._objectId) |
| return; |
| this._runtimeAgent.releaseObject(this._objectId); |
| }, |
| |
| /** |
| * @override |
| * @return {number} |
| */ |
| arrayLength: function() |
| { |
| return WebInspector.RemoteObject.arrayLength(this); |
| }, |
| |
| /** |
| * @override |
| * @return {!WebInspector.Target} |
| */ |
| target: function() |
| { |
| return this._target; |
| }, |
| |
| /** |
| * @override |
| * @return {?WebInspector.DebuggerModel} |
| */ |
| debuggerModel: function() |
| { |
| return this._debuggerModel; |
| }, |
| |
| /** |
| * @override |
| * @return {boolean} |
| */ |
| isNode: function() |
| { |
| return !!this._objectId && this.type === "object" && this.subtype === "node"; |
| }, |
| |
| /** |
| * @override |
| * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback |
| */ |
| functionDetails: function(callback) |
| { |
| this._debuggerModel.functionDetails(this, callback); |
| }, |
| |
| /** |
| * @override |
| * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback |
| */ |
| generatorObjectDetails: function(callback) |
| { |
| this._debuggerModel.generatorObjectDetails(this, callback); |
| }, |
| |
| /** |
| * @override |
| * @param {function(?Array.<!DebuggerAgent.CollectionEntry>)} callback |
| */ |
| collectionEntries: function(callback) |
| { |
| if (!this._objectId) { |
| callback(null); |
| return; |
| } |
| this._debuggerModel.getCollectionEntries(this._objectId, callback); |
| }, |
| |
| __proto__: WebInspector.RemoteObject.prototype |
| }; |
| |
| |
| /** |
| * @param {!WebInspector.RemoteObject} object |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| WebInspector.RemoteObject.loadFromObjectPerProto = function(object, callback) |
| { |
| // Combines 2 asynch calls. Doesn't rely on call-back orders (some calls may be loop-back). |
| var savedOwnProperties; |
| var savedAccessorProperties; |
| var savedInternalProperties; |
| var resultCounter = 2; |
| |
| function processCallback() |
| { |
| if (--resultCounter) |
| return; |
| if (savedOwnProperties && savedAccessorProperties) { |
| var combinedList = savedAccessorProperties.slice(0); |
| for (var i = 0; i < savedOwnProperties.length; i++) { |
| var property = savedOwnProperties[i]; |
| if (!property.isAccessorProperty()) |
| combinedList.push(property); |
| } |
| return callback(combinedList, savedInternalProperties ? savedInternalProperties : null); |
| } else { |
| callback(null, null); |
| } |
| } |
| |
| /** |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| */ |
| function allAccessorPropertiesCallback(properties, internalProperties) |
| { |
| savedAccessorProperties = properties; |
| processCallback(); |
| } |
| |
| /** |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| */ |
| function ownPropertiesCallback(properties, internalProperties) |
| { |
| savedOwnProperties = properties; |
| savedInternalProperties = internalProperties; |
| processCallback(); |
| } |
| |
| object.getAllProperties(true, allAccessorPropertiesCallback); |
| object.getOwnProperties(ownPropertiesCallback); |
| }; |
| |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.RemoteObjectImpl} |
| * @param {!WebInspector.Target} target |
| * @param {string|undefined} objectId |
| * @param {!WebInspector.ScopeRef} scopeRef |
| * @param {string} type |
| * @param {string|undefined} subtype |
| * @param {*} value |
| * @param {string=} description |
| * @param {!RuntimeAgent.ObjectPreview=} preview |
| */ |
| WebInspector.ScopeRemoteObject = function(target, objectId, scopeRef, type, subtype, value, description, preview) |
| { |
| WebInspector.RemoteObjectImpl.call(this, target, objectId, type, subtype, value, description, preview); |
| this._scopeRef = scopeRef; |
| this._savedScopeProperties = undefined; |
| }; |
| |
| WebInspector.ScopeRemoteObject.prototype = { |
| /** |
| * @override |
| * @param {boolean} ownProperties |
| * @param {boolean} accessorPropertiesOnly |
| * @param {boolean} generatePreview |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| doGetProperties: function(ownProperties, accessorPropertiesOnly, generatePreview, callback) |
| { |
| if (accessorPropertiesOnly) { |
| callback([], []); |
| return; |
| } |
| |
| if (this._savedScopeProperties) { |
| // No need to reload scope variables, as the remote object never |
| // changes its properties. If variable is updated, the properties |
| // array is patched locally. |
| callback(this._savedScopeProperties.slice(), []); |
| return; |
| } |
| |
| /** |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| * @this {WebInspector.ScopeRemoteObject} |
| */ |
| function wrappedCallback(properties, internalProperties) |
| { |
| if (this._scopeRef && Array.isArray(properties)) { |
| this._savedScopeProperties = properties.slice(); |
| if (!this._scopeRef.callFrameId) { |
| for (var property of this._savedScopeProperties) |
| property.writable = false; |
| } |
| } |
| callback(properties, internalProperties); |
| } |
| |
| // Scope objects always fetch preview. |
| generatePreview = true; |
| |
| WebInspector.RemoteObjectImpl.prototype.doGetProperties.call(this, ownProperties, accessorPropertiesOnly, generatePreview, wrappedCallback.bind(this)); |
| }, |
| |
| /** |
| * @override |
| * @param {!RuntimeAgent.RemoteObject} result |
| * @param {!RuntimeAgent.CallArgument} argumentName |
| * @param {function(string=)} callback |
| */ |
| doSetObjectPropertyValue: function(result, argumentName, callback) |
| { |
| var name = /** @type {string} */ (argumentName.value); |
| this._debuggerModel.setVariableValue(this._scopeRef.number, name, WebInspector.RemoteObject.toCallArgument(result), this._scopeRef.callFrameId, setVariableValueCallback.bind(this)); |
| |
| /** |
| * @param {string=} error |
| * @this {WebInspector.ScopeRemoteObject} |
| */ |
| function setVariableValueCallback(error) |
| { |
| if (error) { |
| callback(error); |
| return; |
| } |
| if (this._savedScopeProperties) { |
| for (var i = 0; i < this._savedScopeProperties.length; i++) { |
| if (this._savedScopeProperties[i].name === name) |
| this._savedScopeProperties[i].value = this._target.runtimeModel.createRemoteObject(result); |
| } |
| } |
| callback(); |
| } |
| }, |
| |
| __proto__: WebInspector.RemoteObjectImpl.prototype |
| }; |
| |
| /** |
| * @constructor |
| * @param {number} number |
| * @param {string=} callFrameId |
| */ |
| WebInspector.ScopeRef = function(number, callFrameId) |
| { |
| this.number = number; |
| this.callFrameId = callFrameId; |
| } |
| |
| /** |
| * @constructor |
| * @param {string} name |
| * @param {?WebInspector.RemoteObject} value |
| * @param {boolean=} enumerable |
| * @param {boolean=} writable |
| * @param {boolean=} isOwn |
| * @param {boolean=} wasThrown |
| * @param {boolean=} synthetic |
| * @param {?WebInspector.RemoteObject=} symbol |
| */ |
| WebInspector.RemoteObjectProperty = function(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic) |
| { |
| this.name = name; |
| if (value !== null) |
| this.value = value; |
| this.enumerable = typeof enumerable !== "undefined" ? enumerable : true; |
| this.writable = typeof writable !== "undefined" ? writable : true; |
| this.isOwn = !!isOwn; |
| this.wasThrown = !!wasThrown; |
| if (symbol) |
| this.symbol = symbol; |
| this.synthetic = !!synthetic; |
| } |
| |
| WebInspector.RemoteObjectProperty.prototype = { |
| /** |
| * @return {boolean} |
| */ |
| isAccessorProperty: function() |
| { |
| return !!(this.getter || this.setter); |
| } |
| }; |
| |
| // Below is a wrapper around a local object that implements the RemoteObject interface, |
| // which can 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 constructor, handling properties |
| // or functions. |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.RemoteObject} |
| * @param {*} value |
| */ |
| WebInspector.LocalJSONObject = function(value) |
| { |
| WebInspector.RemoteObject.call(this); |
| this._value = value; |
| } |
| |
| WebInspector.LocalJSONObject.prototype = { |
| /** |
| * @override |
| * @return {string} |
| */ |
| get description() |
| { |
| if (this._cachedDescription) |
| return this._cachedDescription; |
| |
| /** |
| * @param {!WebInspector.RemoteObjectProperty} property |
| * @return {string} |
| * @this {WebInspector.LocalJSONObject} |
| */ |
| function formatArrayItem(property) |
| { |
| return this._formatValue(property.value); |
| } |
| |
| /** |
| * @param {!WebInspector.RemoteObjectProperty} property |
| * @return {string} |
| * @this {WebInspector.LocalJSONObject} |
| */ |
| function formatObjectItem(property) |
| { |
| var name = property.name; |
| if (/^\s|\s$|^$|\n/.test(name)) |
| name = "\"" + name.replace(/\n/g, "\u21B5") + "\""; |
| return name + ": " + this._formatValue(property.value); |
| } |
| |
| if (this.type === "object") { |
| switch (this.subtype) { |
| case "array": |
| this._cachedDescription = this._concatenate("[", "]", formatArrayItem.bind(this)); |
| break; |
| case "date": |
| this._cachedDescription = "" + this._value; |
| break; |
| case "null": |
| this._cachedDescription = "null"; |
| break; |
| default: |
| this._cachedDescription = this._concatenate("{", "}", formatObjectItem.bind(this)); |
| } |
| } else { |
| this._cachedDescription = String(this._value); |
| } |
| |
| return this._cachedDescription; |
| }, |
| |
| /** |
| * @param {?WebInspector.RemoteObject} value |
| * @return {string} |
| */ |
| _formatValue: function(value) |
| { |
| if (!value) |
| return "undefined"; |
| var description = value.description || ""; |
| if (value.type === "string") |
| return "\"" + description.replace(/\n/g, "\u21B5") + "\""; |
| return description; |
| }, |
| |
| /** |
| * @param {string} prefix |
| * @param {string} suffix |
| * @param {function(!WebInspector.RemoteObjectProperty)} formatProperty |
| * @return {string} |
| */ |
| _concatenate: function(prefix, suffix, formatProperty) |
| { |
| var 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; |
| }, |
| |
| /** |
| * @override |
| * @return {string} |
| */ |
| get type() |
| { |
| return typeof this._value; |
| }, |
| |
| /** |
| * @override |
| * @return {string|undefined} |
| */ |
| get subtype() |
| { |
| if (this._value === null) |
| return "null"; |
| |
| if (Array.isArray(this._value)) |
| return "array"; |
| |
| if (this._value instanceof Date) |
| return "date"; |
| |
| return undefined; |
| }, |
| |
| /** |
| * @override |
| * @return {boolean} |
| */ |
| get hasChildren() |
| { |
| if ((typeof this._value !== "object") || (this._value === null)) |
| return false; |
| return !!Object.keys(/** @type {!Object} */ (this._value)).length; |
| }, |
| |
| /** |
| * @override |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getOwnProperties: function(callback) |
| { |
| callback(this._children(), null); |
| }, |
| |
| /** |
| * @override |
| * @param {boolean} accessorPropertiesOnly |
| * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback |
| */ |
| getAllProperties: function(accessorPropertiesOnly, callback) |
| { |
| if (accessorPropertiesOnly) |
| callback([], null); |
| else |
| callback(this._children(), null); |
| }, |
| |
| /** |
| * @return {!Array.<!WebInspector.RemoteObjectProperty>} |
| */ |
| _children: function() |
| { |
| if (!this.hasChildren) |
| return []; |
| var value = /** @type {!Object} */ (this._value); |
| |
| /** |
| * @param {string} propName |
| * @return {!WebInspector.RemoteObjectProperty} |
| */ |
| function buildProperty(propName) |
| { |
| var propValue = value[propName]; |
| if (!(propValue instanceof WebInspector.RemoteObject)) |
| propValue = WebInspector.RemoteObject.fromLocalObject(propValue); |
| return new WebInspector.RemoteObjectProperty(propName, propValue); |
| } |
| if (!this._cachedChildren) |
| this._cachedChildren = Object.keys(value).map(buildProperty); |
| return this._cachedChildren; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| isError: function() |
| { |
| return false; |
| }, |
| |
| /** |
| * @override |
| * @return {number} |
| */ |
| arrayLength: function() |
| { |
| return Array.isArray(this._value) ? this._value.length : 0; |
| }, |
| |
| /** |
| * @override |
| * @param {function(this:Object, ...)} functionDeclaration |
| * @param {!Array.<!RuntimeAgent.CallArgument>=} args |
| * @param {function(?WebInspector.RemoteObject, boolean=)=} callback |
| */ |
| callFunction: function(functionDeclaration, args, callback) |
| { |
| var target = /** @type {?Object} */ (this._value); |
| var rawArgs = args ? args.map(function(arg) { return arg.value; }) : []; |
| |
| var result; |
| var wasThrown = false; |
| try { |
| result = functionDeclaration.apply(target, rawArgs); |
| } catch (e) { |
| wasThrown = true; |
| } |
| |
| if (!callback) |
| return; |
| callback(WebInspector.RemoteObject.fromLocalObject(result), wasThrown); |
| }, |
| |
| /** |
| * @override |
| * @param {function(this:Object)} functionDeclaration |
| * @param {!Array.<!RuntimeAgent.CallArgument>|undefined} args |
| * @param {function(*)} callback |
| */ |
| callFunctionJSON: function(functionDeclaration, args, callback) |
| { |
| var target = /** @type {?Object} */ (this._value); |
| var rawArgs = args ? args.map(function(arg) { return arg.value; }) : []; |
| |
| var result; |
| try { |
| result = functionDeclaration.apply(target, rawArgs); |
| } catch (e) { |
| result = null; |
| } |
| |
| callback(result); |
| }, |
| |
| __proto__: WebInspector.RemoteObject.prototype |
| } |
| |
| /** |
| * @constructor |
| * @param {!WebInspector.RemoteObject} object |
| */ |
| WebInspector.RemoteArray = function(object) |
| { |
| this._object = object; |
| }; |
| |
| /** |
| * @param {?WebInspector.RemoteObject} object |
| * @return {!WebInspector.RemoteArray} |
| */ |
| WebInspector.RemoteArray.objectAsArray = function(object) |
| { |
| if (!object || object.type !== "object" || object.subtype !== "array") |
| throw new Error("Object is empty or not an array"); |
| return new WebInspector.RemoteArray(object); |
| } |
| |
| /** |
| * @param {!Array<!WebInspector.RemoteObject>} objects |
| * @return {!Promise<!WebInspector.RemoteArray>} |
| */ |
| WebInspector.RemoteArray.createFromRemoteObjects = function(objects) |
| { |
| if (!objects.length) |
| throw new Error("Input array is empty"); |
| var objectArguments = []; |
| for (var i = 0; i < objects.length; ++i) |
| objectArguments.push(WebInspector.RemoteObject.toCallArgument(objects[i])) |
| return objects[0].callFunctionPromise(createArray, objectArguments).then(returnRemoteArray); |
| |
| /** |
| * @return {!Array<*>} |
| */ |
| function createArray() |
| { |
| if (arguments.length > 1) |
| return new Array(arguments); |
| return [arguments[0]]; |
| } |
| |
| /** |
| * @param {!WebInspector.CallFunctionResult} result |
| * @return {!WebInspector.RemoteArray} |
| */ |
| function returnRemoteArray(result) |
| { |
| if (result.wasThrown || !result.object) |
| throw new Error("Call function throws exceptions or returns empty value"); |
| return WebInspector.RemoteArray.objectAsArray(result.object); |
| } |
| } |
| |
| WebInspector.RemoteArray.prototype = { |
| /** |
| * @param {number} index |
| * @return {!Promise<!WebInspector.RemoteObject>} |
| */ |
| at: function(index) |
| { |
| if (index < 0 || index > this._object.arrayLength()) |
| throw new Error("Out of range"); |
| return this._object.callFunctionPromise(at, [WebInspector.RemoteObject.toCallArgument(index)]).then(assertCallFunctionResult); |
| |
| /** |
| * @suppressReceiverCheck |
| * @param {number} index |
| * @return {*} |
| * @this {!Object} |
| */ |
| function at(index) |
| { |
| return this[index]; |
| } |
| |
| /** |
| * @param {!WebInspector.CallFunctionResult} result |
| * @return {!WebInspector.RemoteObject} |
| */ |
| function assertCallFunctionResult(result) |
| { |
| if (result.wasThrown || !result.object) |
| throw new Error("Exception in callFunction or result value is empty"); |
| return result.object; |
| } |
| }, |
| |
| /** |
| * @return {number} |
| */ |
| length: function() |
| { |
| return this._object.arrayLength(); |
| }, |
| |
| /** |
| * @param {function(!WebInspector.RemoteObject):!Promise<T>} func |
| * @return {!Promise<!Array<T>>} |
| * @template T |
| */ |
| map: function(func) |
| { |
| var promises = []; |
| for (var i = 0; i < this.length(); ++i) |
| promises.push(this.at(i).then(func)); |
| return Promise.all(promises); |
| }, |
| |
| /** |
| * @return {!WebInspector.RemoteObject} |
| */ |
| object: function() |
| { |
| return this._object; |
| } |
| } |
| |
| /** |
| * @constructor |
| * @param {!WebInspector.RemoteObject} object |
| */ |
| WebInspector.RemoteFunction = function(object) |
| { |
| this._object = object; |
| } |
| |
| /** |
| * @param {?WebInspector.RemoteObject} object |
| * @return {!WebInspector.RemoteFunction} |
| */ |
| WebInspector.RemoteFunction.objectAsFunction = function(object) |
| { |
| if (!object || object.type !== "function") |
| throw new Error("Object is empty or not a function"); |
| return new WebInspector.RemoteFunction(object); |
| } |
| |
| WebInspector.RemoteFunction.prototype = { |
| /** |
| * @return {!Promise<!WebInspector.RemoteObject>} |
| */ |
| targetFunction: function() |
| { |
| return this._object.getOwnPropertiesPromise().then(targetFunction.bind(this)); |
| |
| /** |
| * @param {!{properties: ?Array<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array<!WebInspector.RemoteObjectProperty>}} ownProperties |
| * @return {!WebInspector.RemoteObject} |
| * @this {WebInspector.RemoteFunction} |
| */ |
| function targetFunction(ownProperties) |
| { |
| if (!ownProperties.internalProperties) |
| return this._object; |
| var internalProperties = ownProperties.internalProperties; |
| for (var property of internalProperties) { |
| if (property.name === "[[TargetFunction]]") |
| return property.value; |
| } |
| return this._object; |
| } |
| }, |
| |
| /** |
| * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} |
| */ |
| targetFunctionDetails: function() |
| { |
| return this.targetFunction().then(functionDetails.bind(this)); |
| |
| /** |
| * @param {!WebInspector.RemoteObject} targetFunction |
| * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} |
| * @this {WebInspector.RemoteFunction} |
| */ |
| function functionDetails(targetFunction) |
| { |
| var boundReleaseFunctionDetails = releaseTargetFunction.bind(null, this._object !== targetFunction ? targetFunction : null); |
| return targetFunction.functionDetailsPromise().then(boundReleaseFunctionDetails); |
| } |
| |
| /** |
| * @param {?WebInspector.RemoteObject} targetFunction |
| * @param {?WebInspector.DebuggerModel.FunctionDetails} functionDetails |
| * @return {?WebInspector.DebuggerModel.FunctionDetails} |
| */ |
| function releaseTargetFunction(targetFunction, functionDetails) |
| { |
| if (targetFunction) |
| targetFunction.release(); |
| return functionDetails; |
| } |
| }, |
| |
| /** |
| * @return {!WebInspector.RemoteObject} |
| */ |
| object: function() |
| { |
| return this._object; |
| } |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.LocalJSONObject} |
| * @param {*} value |
| */ |
| WebInspector.MapEntryLocalJSONObject = function(value) |
| { |
| WebInspector.LocalJSONObject.call(this, value); |
| } |
| |
| WebInspector.MapEntryLocalJSONObject.prototype = { |
| /** |
| * @override |
| * @return {string} |
| */ |
| get description() |
| { |
| if (!this._cachedDescription) { |
| var children = this._children(); |
| this._cachedDescription = "{" + this._formatValue(children[0].value) + " => " + this._formatValue(children[1].value) + "}"; |
| } |
| return this._cachedDescription; |
| }, |
| |
| __proto__: WebInspector.LocalJSONObject.prototype |
| } |