diff options
Diffstat (limited to 'WebCore/inspector/front-end/InjectedScript.js')
-rw-r--r-- | WebCore/inspector/front-end/InjectedScript.js | 967 |
1 files changed, 469 insertions, 498 deletions
diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index b8bf9f2..d4e3d80 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -28,392 +28,517 @@ var injectedScriptConstructor = (function (InjectedScriptHost, inspectedWindow, injectedScriptId, jsEngine) { -var InjectedScript = {}; - -InjectedScript.lastBoundObjectId = 1; -InjectedScript.idToWrappedObject = {}; -InjectedScript.objectGroups = {}; - -InjectedScript.wrapObjectForConsole = function(object, canAccessInspectedWindow) +var InjectedScript = function() { - if (canAccessInspectedWindow) - return InjectedScript.wrapObject(object, "console"); - var result = {}; - result.type = typeof object; - result.description = InjectedScript._toString(object); - return result; + this._lastBoundObjectId = 1; + this._idToWrappedObject = {}; + this._objectGroups = {}; } -InjectedScript.wrapObject = function(object, objectGroupName) -{ - try { - var objectId; - if (typeof object === "object" || typeof object === "function" || InjectedScript._isHTMLAllCollection(object)) { - var id = InjectedScript.lastBoundObjectId++; - objectId = "object#" + id; - InjectedScript.idToWrappedObject[objectId] = object; - - var group = InjectedScript.objectGroups[objectGroupName]; - if (!group) { - group = []; - InjectedScript.objectGroups[objectGroupName] = group; +InjectedScript.prototype = { + wrapObjectForConsole: function(object, canAccessInspectedWindow) + { + if (canAccessInspectedWindow) + return this._wrapObject(object, "console"); + var result = {}; + result.type = typeof object; + result.description = this._toString(object); + return result; + }, + + _wrapObject: function(object, objectGroupName, abbreviate) + { + try { + var objectId; + if (typeof object === "object" || typeof object === "function" || this._isHTMLAllCollection(object)) { + var id = this._lastBoundObjectId++; + objectId = id; + this._idToWrappedObject[id] = object; + + var group = this._objectGroups[objectGroupName]; + if (!group) { + group = []; + this._objectGroups[objectGroupName] = group; + } + group.push(id); + objectId = this._serializeObjectId(id, objectGroupName); } - group.push(objectId); + return InjectedScript.RemoteObject.fromObject(object, objectId, abbreviate); + } catch (e) { + return InjectedScript.RemoteObject.fromObject("[ Exception: " + e.toString() + " ]"); } - return InjectedScript.createProxyObject(object, objectId); - } catch (e) { - return InjectedScript.createProxyObject("[ Exception: " + e.toString() + " ]"); - } - return InjectedScript.createProxyObject(object, objectId); -}; - -InjectedScript.unwrapObject = function(objectId) { - return InjectedScript.idToWrappedObject[objectId]; -}; - -InjectedScript.releaseWrapperObjectGroup = function(objectGroupName) { - var group = InjectedScript.objectGroups[objectGroupName]; - if (!group) - return; - for (var i = 0; i < group.length; i++) - delete InjectedScript.idToWrappedObject[group[i]]; - delete InjectedScript.objectGroups[objectGroupName]; -}; - -InjectedScript.dispatch = function(methodName, args, callId) -{ - var argsArray = eval("(" + args + ")"); - if (callId) - argsArray.splice(0, 0, callId); // Methods that run asynchronously have a call back id parameter. - var result = InjectedScript[methodName].apply(InjectedScript, argsArray); - if (typeof result === "undefined") { - inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName); - result = null; - } - return result; -} + }, -InjectedScript.getPrototypes = function(nodeId) -{ - var node = InjectedScript._nodeForId(nodeId); - if (!node) - return false; - - var result = []; - for (var prototype = node; prototype; prototype = prototype.__proto__) { - var title = InjectedScript._describe(prototype, true); - if (title.match(/Prototype$/)) { - title = title.replace(/Prototype$/, ""); + _serializeObjectId: function(id, groupName) + { + return injectedScriptId + ":" + id + ":" + groupName; + }, + + _parseObjectId: function(objectId) + { + var tokens = objectId.split(":"); + var parsedObjectId = {}; + parsedObjectId.id = parseInt(tokens[1]); + parsedObjectId.groupName = tokens[2]; + return parsedObjectId; + }, + + releaseWrapperObjectGroup: function(objectGroupName) + { + var group = this._objectGroups[objectGroupName]; + if (!group) + return; + for (var i = 0; i < group.length; i++) + delete this._idToWrappedObject[group[i]]; + delete this._objectGroups[objectGroupName]; + }, + + dispatch: function(methodName, args) + { + var argsArray = eval("(" + args + ")"); + var result = this[methodName].apply(this, argsArray); + if (typeof result === "undefined") { + inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName); + result = null; } - result.push(title); - } - return result; -} + return result; + }, -InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate) -{ - var object = InjectedScript._resolveObject(objectProxy); - if (!InjectedScript._isDefined(object)) - return false; - var properties = []; + getPrototypes: function(nodeId) + { + this.releaseWrapperObjectGroup("prototypes"); + var node = this._nodeForId(nodeId); + if (!node) + return false; + + var result = []; + var prototype = node; + do { + result.push(this._wrapObject(prototype, "prototypes")); + prototype = prototype.__proto__; + } while (prototype) + return result; + }, + + getProperties: function(objectId, ignoreHasOwnProperty, abbreviate) + { + var parsedObjectId = this._parseObjectId(objectId); + var object = this._objectForId(parsedObjectId); + if (!this._isDefined(object)) + return false; + var properties = []; + + var propertyNames = ignoreHasOwnProperty ? this._getPropertyNames(object) : Object.getOwnPropertyNames(object); + if (!ignoreHasOwnProperty && object.__proto__) + propertyNames.push("__proto__"); - var propertyNames = ignoreHasOwnProperty ? InjectedScript._getPropertyNames(object) : Object.getOwnPropertyNames(object); - if (!ignoreHasOwnProperty && object.__proto__) - propertyNames.push("__proto__"); - - // Go over properties, prepare results. - for (var i = 0; i < propertyNames.length; ++i) { - var propertyName = propertyNames[i]; - - var property = {}; - property.name = propertyName + ""; - property.parentObjectProxy = objectProxy; - var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); - if (!isGetter) { - try { - var childObject = object[propertyName]; - var childObjectProxy = new InjectedScript.createProxyObject(childObject, objectProxy.objectId, abbreviate); - childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; - childObjectProxy.path.push(propertyName); - property.value = childObjectProxy; - } catch(e) { - property.value = { description: e.toString() }; - property.isError = true; + // Go over properties, prepare results. + for (var i = 0; i < propertyNames.length; ++i) { + var propertyName = propertyNames[i]; + + var property = {}; + property.name = propertyName + ""; + var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); + if (!isGetter) { + try { + property.value = this._wrapObject(object[propertyName], parsedObjectId.groupName, abbreviate); + } catch(e) { + property.value = new InjectedScript.RemoteObject.fromException(e); + } + } else { + // FIXME: this should show something like "getter" (bug 16734). + property.value = new InjectedScript.RemoteObject.fromObject("\u2014"); // em dash + property.isGetter = true; } - } else { - // FIXME: this should show something like "getter" (bug 16734). - property.value = { description: "\u2014" }; // em dash - property.isGetter = true; + properties.push(property); } - properties.push(property); - } - return properties; -} - -InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression) -{ - var object = InjectedScript._resolveObject(objectProxy); - if (!InjectedScript._isDefined(object)) - return false; - - var expressionLength = expression.length; - if (!expressionLength) { - delete object[propertyName]; - return !(propertyName in object); - } + return properties; + }, - try { - // Surround the expression in parenthesis so the result of the eval is the result - // of the whole expression not the last potential sub-expression. - - // There is a regression introduced here: eval is now happening against global object, - // not call frame while on a breakpoint. - // TODO: bring evaluation against call frame back. - var result = inspectedWindow.eval("(" + expression + ")"); - // Store the result in the property. - object[propertyName] = result; - return true; - } catch(e) { + setPropertyValue: function(objectId, propertyName, expression) + { + var parsedObjectId = this._parseObjectId(objectId); + var object = this._objectForId(parsedObjectId); + if (!this._isDefined(object)) + return false; + + var expressionLength = expression.length; + if (!expressionLength) { + delete object[propertyName]; + return !(propertyName in object); + } + try { - var result = inspectedWindow.eval("\"" + expression.replace(/"/g, "\\\"") + "\""); + // Surround the expression in parenthesis so the result of the eval is the result + // of the whole expression not the last potential sub-expression. + + // There is a regression introduced here: eval is now happening against global object, + // not call frame while on a breakpoint. + // TODO: bring evaluation against call frame back. + var result = inspectedWindow.eval("(" + expression + ")"); + // Store the result in the property. object[propertyName] = result; return true; } catch(e) { - return false; + try { + var result = inspectedWindow.eval("\"" + expression.replace(/"/g, "\\\"") + "\""); + object[propertyName] = result; + return true; + } catch(e) { + return false; + } } - } -} + }, -InjectedScript._populatePropertyNames = function(object, resultSet) -{ - for (var o = object; o; o = o.__proto__) { - try { - var names = Object.getOwnPropertyNames(o); - for (var i = 0; i < names.length; ++i) - resultSet[names[i]] = true; - } catch (e) { + _populatePropertyNames: function(object, resultSet) + { + for (var o = object; o; o = o.__proto__) { + try { + var names = Object.getOwnPropertyNames(o); + for (var i = 0; i < names.length; ++i) + resultSet[names[i]] = true; + } catch (e) { + } } - } -} + }, -InjectedScript._getPropertyNames = function(object, resultSet) -{ - var propertyNameSet = {}; - InjectedScript._populatePropertyNames(object, propertyNameSet); - return Object.keys(propertyNameSet); -} + _getPropertyNames: function(object, resultSet) + { + var propertyNameSet = {}; + this._populatePropertyNames(object, propertyNameSet); + return Object.keys(propertyNameSet); + }, -InjectedScript.getCompletions = function(expression, includeInspectorCommandLineAPI, callFrameId) -{ - var props = {}; - try { - var expressionResult; - // Evaluate on call frame if call frame id is available. - if (typeof callFrameId === "number") { - var callFrame = InjectedScript._callFrameForId(callFrameId); - if (!callFrame) - return props; - if (expression) - expressionResult = InjectedScript._evaluateOn(callFrame.evaluate, callFrame, expression, true); - else { - // Evaluate into properties in scope of the selected call frame. - var scopeChain = callFrame.scopeChain; - for (var i = 0; i < scopeChain.length; ++i) - InjectedScript._populatePropertyNames(scopeChain[i], props); + getCompletions: function(expression, includeInspectorCommandLineAPI, callFrameId) + { + var props = {}; + try { + var expressionResult; + // Evaluate on call frame if call frame id is available. + if (typeof callFrameId === "number") { + var callFrame = this._callFrameForId(callFrameId); + if (!callFrame) + return props; + if (expression) + expressionResult = this._evaluateOn(callFrame.evaluate, callFrame, expression); + else { + // Evaluate into properties in scope of the selected call frame. + var scopeChain = callFrame.scopeChain; + for (var i = 0; i < scopeChain.length; ++i) + this._populatePropertyNames(scopeChain[i], props); + } + } else { + if (!expression) + expression = "this"; + expressionResult = this._evaluateOn(inspectedWindow.eval, inspectedWindow, expression); } - } else { - if (!expression) - expression = "this"; - expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false); + if (typeof expressionResult === "object") + this._populatePropertyNames(expressionResult, props); + + if (includeInspectorCommandLineAPI) { + for (var prop in this._commandLineAPI) + props[prop] = true; + } + } catch(e) { } - if (typeof expressionResult === "object") - InjectedScript._populatePropertyNames(expressionResult, props); + return props; + }, - if (includeInspectorCommandLineAPI) { - for (var prop in InjectedScript._commandLineAPI) - props[prop] = true; + evaluate: function(expression, objectGroup) + { + return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup); + }, + + _evaluateAndWrap: function(evalFunction, object, expression, objectGroup) + { + try { + return this._wrapObject(this._evaluateOn(evalFunction, object, expression), objectGroup); + } catch (e) { + return InjectedScript.RemoteObject.fromException(e); } - } catch(e) { - } - return props; -} + }, -InjectedScript.evaluateAndStringify = function(expression) -{ - var result = {}; - try { - var value = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false); - result.value = JSON.stringify(value); - } catch (e) { - result.value = e.toString(); - result.isException = true; - } - return result; -} + _evaluateOn: function(evalFunction, object, expression) + { + // Only install command line api object for the time of evaluation. + // Surround the expression in with statements to inject our command line API so that + // the window object properties still take more precedent than our API functions. + inspectedWindow.console._commandLineAPI = this._commandLineAPI; + + expression = "with (window.console._commandLineAPI) { with (window) {\n" + expression + "\n} }"; + var value = evalFunction.call(object, expression); + + delete inspectedWindow.console._commandLineAPI; + + // When evaluating on call frame error is not thrown, but returned as a value. + if (this._type(value) === "error") + throw value.toString(); + + return value; + }, -InjectedScript.evaluate = function(expression, objectGroup) -{ - return InjectedScript._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup); -} + getNodeId: function(node) + { + return InjectedScriptHost.pushNodePathToFrontend(node, false, false); + }, -InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, objectGroup, dontUseCommandLineAPI) -{ - var result = {}; - try { - result.value = InjectedScript.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression, dontUseCommandLineAPI), objectGroup); + callFrames: function() + { + var callFrame = InjectedScriptHost.currentCallFrame(); + if (!callFrame) + return false; + + injectedScript.releaseWrapperObjectGroup("backtrace"); + var result = []; + var depth = 0; + do { + result.push(new InjectedScript.CallFrameProxy(depth++, callFrame)); + callFrame = callFrame.caller; + } while (callFrame); + return result; + }, - // Handle error that might have happened while describing result. - if (result.value.errorText) { - result.value = result.value.errorText; - result.isException = true; - } - } catch (e) { - result.value = e.toString(); - result.isException = true; - } - return result; -} + evaluateInCallFrame: function(callFrameId, code, objectGroup) + { + var callFrame = this._callFrameForId(callFrameId); + if (!callFrame) + return false; + return this._evaluateAndWrap(callFrame.evaluate, callFrame, code, objectGroup); + }, -InjectedScript._evaluateOn = function(evalFunction, object, expression, dontUseCommandLineAPI) -{ - if (!dontUseCommandLineAPI) { - // Only install command line api object for the time of evaluation. + _callFrameForId: function(id) + { + var callFrame = InjectedScriptHost.currentCallFrame(); + while (--id >= 0 && callFrame) + callFrame = callFrame.caller; + return callFrame; + }, - // Surround the expression in with statements to inject our command line API so that - // the window object properties still take more precedent than our API functions. - inspectedWindow.console._commandLineAPI = InjectedScript._commandLineAPI; + _nodeForId: function(nodeId) + { + if (!nodeId) + return null; + return InjectedScriptHost.nodeForId(nodeId); + }, - expression = "with (window.console._commandLineAPI) { with (window) {\n" + expression + "\n} }"; - } + _objectForId: function(parsedObjectId) + { + return this._idToWrappedObject[parsedObjectId.id]; + }, - var value = evalFunction.call(object, expression); + resolveNode: function(nodeId) + { + var node = this._nodeForId(nodeId); + if (!node) + return false; + // FIXME: receive the object group from client. + return this._wrapObject(node, "prototype"); + }, - if (!dontUseCommandLineAPI) - delete inspectedWindow.console._commandLineAPI; + getNodeProperties: function(nodeId, properties) + { + var node = this._nodeForId(nodeId); + if (!node) + return false; + var result = {}; + for (var i = 0; i < properties.length; ++i) + result[properties[i]] = node[properties[i]]; + return result; + }, - // When evaluating on call frame error is not thrown, but returned as a value. - if (InjectedScript._type(value) === "error") - throw value.toString(); + pushNodeToFrontend: function(objectId) + { + var parsedObjectId = this._parseObjectId(objectId); + var object = this._objectForId(parsedObjectId); + if (!object || this._type(object) !== "node") + return false; + return InjectedScriptHost.pushNodePathToFrontend(object, false, false); + }, - return value; -} + evaluateOnSelf: function(funcBody, args) + { + var func = window.eval("(" + funcBody + ")"); + return func.apply(this, args || []); + }, -InjectedScript.getNodeId = function(node) -{ - return InjectedScriptHost.pushNodePathToFrontend(node, false, false); -} + _isDefined: function(object) + { + return object || this._isHTMLAllCollection(object); + }, -InjectedScript.openInInspectedWindow = function(url) -{ - // Don't call window.open on wrapper - popup blocker mutes it. - // URIs should have no double quotes. - inspectedWindow.eval("window.open(\"" + url + "\")"); - return true; -} + _isHTMLAllCollection: function(object) + { + // document.all is reported as undefined, but we still want to process it. + return (typeof object === "undefined") && inspectedWindow.HTMLAllCollection && object instanceof inspectedWindow.HTMLAllCollection; + }, -InjectedScript.callFrames = function() -{ - var callFrame = InjectedScriptHost.currentCallFrame(); - if (!callFrame) - return false; - - var result = []; - var depth = 0; - do { - result.push(new InjectedScript.CallFrameProxy(depth++, callFrame)); - callFrame = callFrame.caller; - } while (callFrame); - return result; -} + _type: function(obj) + { + if (obj === null) + return "null"; + + var type = typeof obj; + if (type !== "object" && type !== "function") { + // FIXME(33716): typeof document.all is always 'undefined'. + if (this._isHTMLAllCollection(obj)) + return "array"; + return type; + } -InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup) -{ - var callFrame = InjectedScript._callFrameForId(callFrameId); - if (!callFrame) - return false; - return InjectedScript._evaluateAndWrap(callFrame.evaluate, callFrame, code, objectGroup, true); -} + // If owning frame has navigated to somewhere else window properties will be undefined. + // In this case just return result of the typeof. + if (!inspectedWindow.document) + return type; -InjectedScript._callFrameForId = function(id) -{ - var callFrame = InjectedScriptHost.currentCallFrame(); - while (--id >= 0 && callFrame) - callFrame = callFrame.caller; - return callFrame; -} + if (obj instanceof inspectedWindow.Node) + return (obj.nodeType === undefined ? type : "node"); + if (obj instanceof inspectedWindow.String) + return "string"; + if (obj instanceof inspectedWindow.Array) + return "array"; + if (obj instanceof inspectedWindow.Boolean) + return "boolean"; + if (obj instanceof inspectedWindow.Number) + return "number"; + if (obj instanceof inspectedWindow.Date) + return "date"; + if (obj instanceof inspectedWindow.RegExp) + return "regexp"; + // FireBug's array detection. + if (isFinite(obj.length) && typeof obj.splice === "function") + return "array"; + if (isFinite(obj.length) && typeof obj.callee === "function") // arguments. + return "array"; + if (obj instanceof inspectedWindow.NodeList) + return "array"; + if (obj instanceof inspectedWindow.HTMLCollection) + return "array"; + if (obj instanceof inspectedWindow.Error) + return "error"; + return type; + }, -InjectedScript._resolveObject = function(objectProxy) -{ - var object = InjectedScript._objectForId(objectProxy.objectId); - var path = objectProxy.path; + _describe: function(obj, abbreviated) + { + var type = this._type(obj); + + switch (type) { + case "object": + case "node": + return this._className(obj); + case "array": + var className = this._className(obj); + if (typeof obj.length === "number") + className += "[" + obj.length + "]"; + return className; + case "string": + if (!abbreviated) + return obj; + if (obj.length > 100) + return "\"" + obj.substring(0, 100) + "\u2026\""; + return "\"" + obj + "\""; + case "function": + var objectText = this._toString(obj); + if (abbreviated) + objectText = /.*/.exec(objectText)[0].replace(/ +$/g, ""); + return objectText; + default: + return this._toString(obj); + } + }, - // Follow the property path. - for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length; ++i) - object = object[path[i]]; + _toString: function(obj) + { + // We don't use String(obj) because inspectedWindow.String is undefined if owning frame navigated to another page. + return "" + obj; + }, - return object; -} + _className: function(obj) + { + // We can't use the same code for fetching class names of the dom bindings prototype chain. + // Both of the methods below result in "Object" names on the foreign engine bindings. + // I gave up and am using a check below to distinguish between the egine bingings. -InjectedScript._nodeForId = function(nodeId) -{ - if (!nodeId) - return null; - return InjectedScriptHost.nodeForId(nodeId); + if (jsEngine == "JSC") { + var str = inspectedWindow.Object ? inspectedWindow.Object.prototype.toString.call(obj) : this._toString(obj); + return str.replace(/^\[object (.*)\]$/i, "$1"); + } else { + // V8 + return obj.constructor && obj.constructor.name || "Object"; + } + }, + + _logEvent: function(event) + { + console.log(event.type, event); + }, + + _normalizeEventTypes: function(types) + { + if (typeof types === "undefined") + types = [ "mouse", "key", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll" ]; + else if (typeof types === "string") + types = [ types ]; + + var result = []; + for (var i = 0; i < types.length; i++) { + if (types[i] === "mouse") + result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout"); + else if (types[i] === "key") + result.splice(0, 0, "keydown", "keyup", "keypress"); + else + result.push(types[i]); + } + return result; + }, + + _inspectedNode: function(num) + { + var nodeId = InjectedScriptHost.inspectedNode(num); + return this._nodeForId(nodeId); + }, + + _bindToScript: function(func) + { + var args = Array.prototype.slice.call(arguments, 1); + function bound() + { + return func.apply(injectedScript, args.concat(Array.prototype.slice.call(arguments))); + } + bound.toString = function() { + return "bound: " + func; + }; + return bound; + } } -InjectedScript._objectForId = function(objectId) +var injectedScript = new InjectedScript(); + +InjectedScript.RemoteObject = function(objectId, type, description, hasChildren) { - // There are three types of object ids used: - // - numbers point to DOM Node via the InspectorDOMAgent mapping - // - strings point to console objects cached in InspectorController for lazy evaluation upon them - // - objects contain complex ids and are currently used for scoped objects - if (typeof objectId === "number") - return InjectedScript._nodeForId(objectId); - else if (typeof objectId === "string") - return InjectedScript.unwrapObject(objectId); - else if (typeof objectId === "object") { - var callFrame = InjectedScript._callFrameForId(objectId.callFrame); - if (objectId.thisObject) - return callFrame.thisObject; - else - return callFrame.scopeChain[objectId.chainIndex]; - } - return objectId; + this.objectId = objectId; + this.type = type; + this.description = description; + this.hasChildren = hasChildren; } -InjectedScript.pushNodeToFrontend = function(objectProxy) +InjectedScript.RemoteObject.fromException = function(e) { - var object = InjectedScript._resolveObject(objectProxy); - if (!object || InjectedScript._type(object) !== "node") - return false; - return InjectedScriptHost.pushNodePathToFrontend(object, false, false); + return new InjectedScript.RemoteObject(null, "error", e.toString()); } -// Called from within InspectorController on the 'inspected page' side. -InjectedScript.createProxyObject = function(object, objectId, abbreviate) +InjectedScript.RemoteObject.fromObject = function(object, objectId, abbreviate) { - var result = {}; - result.injectedScriptId = injectedScriptId; - result.objectId = objectId; - result.type = InjectedScript._type(object); - if (result.type === "array") - result.propertyLength = object.length; - - var type = typeof object; - - result.hasChildren = (type === "object" && object !== null && (Object.getOwnPropertyNames(object).length || !!object.__proto__)) || type === "function"; + var type = injectedScript._type(object); + var rawType = typeof object; + var hasChildren = (rawType === "object" && object !== null && (Object.getOwnPropertyNames(object).length || !!object.__proto__)) || rawType === "function"; + var description = ""; try { - result.description = InjectedScript._describe(object, abbreviate); + var description = injectedScript._describe(object, abbreviate); + return new InjectedScript.RemoteObject(objectId, type, description, hasChildren); } catch (e) { - result.errorText = e.toString(); + return InjectedScript.RemoteObject.fromException(e); } - return result; -} - -InjectedScript.evaluateOnSelf = function(funcBody, args) -{ - var func = window.eval("(" + funcBody + ")"); - return func.apply(this, args || []); } InjectedScript.CallFrameProxy = function(id, callFrame) @@ -424,7 +549,7 @@ InjectedScript.CallFrameProxy = function(id, callFrame) this.sourceID = callFrame.sourceID; this.line = callFrame.line; this.scopeChain = this._wrapScopeChain(callFrame); - this.injectedScriptId = injectedScriptId; + this.worldId = injectedScriptId; } InjectedScript.CallFrameProxy.prototype = { @@ -442,13 +567,13 @@ InjectedScript.CallFrameProxy.prototype = { for (var i = 0; i < scopeChain.length; i++) { var scopeType = callFrame.scopeType(i); var scopeObject = scopeChain[i]; - var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i }, true); + var scopeObjectProxy = injectedScript._wrapObject(scopeObject, "backtrace", true); switch(scopeType) { case LOCAL_SCOPE: { foundLocalScope = true; scopeObjectProxy.isLocal = true; - scopeObjectProxy.thisObject = InjectedScript.createProxyObject(callFrame.thisObject, { callFrame: this.id, thisObject: true }, true); + scopeObjectProxy.thisObject = injectedScript._wrapObject(callFrame.thisObject, "backtrace", true); break; } case CLOSURE_SCOPE: { @@ -472,138 +597,10 @@ InjectedScript.CallFrameProxy.prototype = { } } -InjectedScript._isDefined = function(object) -{ - return object || InjectedScript._isHTMLAllCollection(object); -} - -InjectedScript._isHTMLAllCollection = function(object) -{ - // document.all is reported as undefined, but we still want to process it. - return (typeof object === "undefined") && inspectedWindow.HTMLAllCollection && object instanceof inspectedWindow.HTMLAllCollection; -} - -InjectedScript._type = function(obj) -{ - if (obj === null) - return "null"; - - var type = typeof obj; - if (type !== "object" && type !== "function") { - // FIXME(33716): typeof document.all is always 'undefined'. - if (InjectedScript._isHTMLAllCollection(obj)) - return "array"; - return type; - } - - // If owning frame has navigated to somewhere else window properties will be undefined. - // In this case just return result of the typeof. - if (!inspectedWindow.document) - return type; - - if (obj instanceof inspectedWindow.Node) - return (obj.nodeType === undefined ? type : "node"); - if (obj instanceof inspectedWindow.String) - return "string"; - if (obj instanceof inspectedWindow.Array) - return "array"; - if (obj instanceof inspectedWindow.Boolean) - return "boolean"; - if (obj instanceof inspectedWindow.Number) - return "number"; - if (obj instanceof inspectedWindow.Date) - return "date"; - if (obj instanceof inspectedWindow.RegExp) - return "regexp"; - if (obj instanceof inspectedWindow.NodeList) - return "array"; - if (obj instanceof inspectedWindow.HTMLCollection) - return "array"; - if (typeof inspectedWindow.jQuery === "function" && obj instanceof inspectedWindow.jQuery) - return "array"; - if (obj instanceof inspectedWindow.Error) - return "error"; - return type; -} - -InjectedScript._describe = function(obj, abbreviated) -{ - var type = InjectedScript._type(obj); - - switch (type) { - case "object": - case "node": - case "array": - return InjectedScript._className(obj); - case "string": - if (!abbreviated) - return obj; - if (obj.length > 100) - return "\"" + obj.substring(0, 100) + "\u2026\""; - return "\"" + obj + "\""; - case "function": - var objectText = InjectedScript._toString(obj); - if (abbreviated) - objectText = /.*/.exec(objectText)[0].replace(/ +$/g, ""); - return objectText; - default: - return InjectedScript._toString(obj); - } -} - -InjectedScript._toString = function(obj) -{ - // We don't use String(obj) because inspectedWindow.String is undefined if owning frame navigated to another page. - return "" + obj; -} - -InjectedScript._className = function(obj) -{ - // We can't use the same code for fetching class names of the dom bindings prototype chain. - // Both of the methods below result in "Object" names on the foreign engine bindings. - // I gave up and am using a check below to distinguish between the egine bingings. - - if (jsEngine == "JSC") { - var str = inspectedWindow.Object ? inspectedWindow.Object.prototype.toString.call(obj) : InjectedScript._toString(obj); - return str.replace(/^\[object (.*)\]$/i, "$1"); - } else { - // V8 - return obj.constructor && obj.constructor.name || "Object"; - } -} - -InjectedScript._logEvent = function(event) -{ - console.log(event.type, event); -} - -InjectedScript._normalizeEventTypes = function(types) -{ - if (typeof types === "undefined") - types = [ "mouse", "key", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll" ]; - else if (typeof types === "string") - types = [ types ]; - - var result = []; - for (var i = 0; i < types.length; i++) { - if (types[i] === "mouse") - result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout"); - else if (types[i] === "key") - result.splice(0, 0, "keydown", "keyup", "keypress"); - else - result.push(types[i]); - } - return result; -} - -InjectedScript._inspectedNode = function(num) -{ - var nodeId = InjectedScriptHost.inspectedNode(num); - return InjectedScript._nodeForId(nodeId); -} - function CommandLineAPI() { + for (var i = 0; i < 5; ++i) + this.__defineGetter__("$" + i, injectedScript._bindToScript(injectedScript._inspectedNode, i)); } CommandLineAPI.prototype = { @@ -670,10 +667,10 @@ CommandLineAPI.prototype = { { if (!object || !object.addEventListener || !object.removeEventListener) return; - types = InjectedScript._normalizeEventTypes(types); + types = injectedScript._normalizeEventTypes(types); for (var i = 0; i < types.length; ++i) { - object.removeEventListener(types[i], InjectedScript._logEvent, false); - object.addEventListener(types[i], InjectedScript._logEvent, false); + object.removeEventListener(types[i], injectedScript._logEvent, false); + object.addEventListener(types[i], injectedScript._logEvent, false); } }, @@ -681,9 +678,9 @@ CommandLineAPI.prototype = { { if (!object || !object.addEventListener || !object.removeEventListener) return; - types = InjectedScript._normalizeEventTypes(types); + types = injectedScript._normalizeEventTypes(types); for (var i = 0; i < types.length; ++i) - object.removeEventListener(types[i], InjectedScript._logEvent, false); + object.removeEventListener(types[i], injectedScript._logEvent, false); }, inspect: function(object) @@ -692,10 +689,10 @@ CommandLineAPI.prototype = { return; inspectedWindow.console.log(object); - if (InjectedScript._type(object) === "node") + if (injectedScript._type(object) === "node") InjectedScriptHost.pushNodePathToFrontend(object, false, true); else { - switch (InjectedScript._describe(object)) { + switch (injectedScript._describe(object)) { case "Database": InjectedScriptHost.selectDatabase(object); break; @@ -708,7 +705,7 @@ CommandLineAPI.prototype = { copy: function(object) { - if (InjectedScript._type(object) === "node") { + if (injectedScript._type(object) === "node") { var nodeId = InjectedScriptHost.pushNodePathToFrontend(object, false, false); InjectedScriptHost.copyNode(nodeId); } else @@ -718,35 +715,9 @@ CommandLineAPI.prototype = { clear: function() { InjectedScriptHost.clearConsoleMessages(); - }, - - get $0() - { - return InjectedScript._inspectedNode(0); - }, - - get $1() - { - return InjectedScript._inspectedNode(1); - }, - - get $2() - { - return InjectedScript._inspectedNode(2); - }, - - get $3() - { - return InjectedScript._inspectedNode(3); - }, - - get $4() - { - return InjectedScript._inspectedNode(4); } } -InjectedScript._commandLineAPI = new CommandLineAPI(); - -return InjectedScript; +injectedScript._commandLineAPI = new CommandLineAPI(); +return injectedScript; }); |