| /* |
| * Copyright (C) 2007 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| //# sourceURL=__InjectedScript_CommandLineAPIModuleSource.js |
| |
| (function (InjectedScriptHost, inspectedWindow, injectedScriptId, injectedScript, RemoteObject, CommandLineAPIHost) { |
| |
| // FIXME: <https://webkit.org/b/152294> Web Inspector: Parse InjectedScriptSource as a built-in to get guaranteed non-user-overridden built-ins |
| |
| function bind(func, thisObject, ...outerArgs) |
| { |
| return function(...innerArgs) { |
| return func.apply(thisObject, outerArgs.concat(innerArgs)); |
| }; |
| } |
| |
| /** |
| * @constructor |
| * @param {CommandLineAPIImpl} commandLineAPIImpl |
| * @param {Object} callFrame |
| */ |
| function CommandLineAPI(commandLineAPIImpl, callFrame) |
| { |
| this.$_ = injectedScript._lastResult; |
| this.$event = injectedScript._eventValue; |
| this.$exception = injectedScript._exceptionValue; |
| |
| // $0 |
| this.__defineGetter__("$0", bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl)); |
| |
| // $1-$99 |
| for (let i = 1; i <= injectedScript._savedResults.length; ++i) |
| this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i)); |
| |
| // Command Line API methods. |
| for (let i = 0; i < CommandLineAPI.methods.length; ++i) { |
| let method = CommandLineAPI.methods[i]; |
| this[method] = bind(commandLineAPIImpl[method], commandLineAPIImpl); |
| this[method].toString = function() { return "function " + method + "() { [Command Line API] }" }; |
| } |
| } |
| |
| /** |
| * @type {Array.<string>} |
| * @const |
| */ |
| CommandLineAPI.methods = [ |
| "$", |
| "$$", |
| "$x", |
| "clear", |
| "copy", |
| "dir", |
| "dirxml", |
| "getEventListeners", |
| "inspect", |
| "keys", |
| "monitorEvents", |
| "profile", |
| "profileEnd", |
| "queryObjects", |
| "screenshot", |
| "table", |
| "unmonitorEvents", |
| "values", |
| ]; |
| |
| /** |
| * @constructor |
| */ |
| function CommandLineAPIImpl() |
| { |
| } |
| |
| CommandLineAPIImpl.prototype = { |
| /** |
| * @param {string} selector |
| * @param {Node=} start |
| */ |
| $: function (selector, start) |
| { |
| if (this._canQuerySelectorOnNode(start)) |
| return start.querySelector(selector); |
| |
| var result = inspectedWindow.document.querySelector(selector); |
| if (result) |
| return result; |
| if (selector && selector[0] !== "#") { |
| result = inspectedWindow.document.getElementById(selector); |
| if (result) { |
| inspectedWindow.console.warn("The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $(\"#%s\")", selector); |
| return null; |
| } |
| } |
| return result; |
| }, |
| |
| /** |
| * @param {string} selector |
| * @param {Node=} start |
| */ |
| $$: function (selector, start) |
| { |
| if (this._canQuerySelectorOnNode(start)) |
| return Array.from(start.querySelectorAll(selector)); |
| return Array.from(inspectedWindow.document.querySelectorAll(selector)); |
| }, |
| |
| /** |
| * @param {Node=} node |
| * @return {boolean} |
| */ |
| _canQuerySelectorOnNode: function(node) |
| { |
| return !!node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE); |
| }, |
| |
| /** |
| * @param {string} xpath |
| * @param {Node=} context |
| */ |
| $x: function(xpath, context) |
| { |
| var doc = (context && context.ownerDocument) || inspectedWindow.document; |
| var result = doc.evaluate(xpath, context || doc, null, XPathResult.ANY_TYPE, null); |
| switch (result.resultType) { |
| case XPathResult.NUMBER_TYPE: |
| return result.numberValue; |
| case XPathResult.STRING_TYPE: |
| return result.stringValue; |
| case XPathResult.BOOLEAN_TYPE: |
| return result.booleanValue; |
| default: |
| var nodes = []; |
| var node; |
| while (node = result.iterateNext()) |
| nodes.push(node); |
| return nodes; |
| } |
| }, |
| |
| dir: function() |
| { |
| return inspectedWindow.console.dir.apply(inspectedWindow.console, arguments) |
| }, |
| |
| dirxml: function() |
| { |
| return inspectedWindow.console.dirxml.apply(inspectedWindow.console, arguments) |
| }, |
| |
| keys: function(object) |
| { |
| return Object.keys(object); |
| }, |
| |
| values: function(object) |
| { |
| var result = []; |
| for (var key in object) |
| result.push(object[key]); |
| return result; |
| }, |
| |
| profile: function() |
| { |
| return inspectedWindow.console.profile.apply(inspectedWindow.console, arguments) |
| }, |
| |
| profileEnd: function() |
| { |
| return inspectedWindow.console.profileEnd.apply(inspectedWindow.console, arguments) |
| }, |
| |
| table: function() |
| { |
| return inspectedWindow.console.table.apply(inspectedWindow.console, arguments) |
| }, |
| |
| screenshot: function() |
| { |
| return inspectedWindow.console.screenshot.apply(inspectedWindow.console, arguments) |
| }, |
| |
| /** |
| * @param {Object} object |
| * @param {Array.<string>|string=} types |
| */ |
| monitorEvents: function(object, types) |
| { |
| if (!object || !object.addEventListener || !object.removeEventListener) |
| return; |
| types = this._normalizeEventTypes(types); |
| for (var i = 0; i < types.length; ++i) { |
| object.removeEventListener(types[i], this._logEvent, false); |
| object.addEventListener(types[i], this._logEvent, false); |
| } |
| }, |
| |
| /** |
| * @param {Object} object |
| * @param {Array.<string>|string=} types |
| */ |
| unmonitorEvents: function(object, types) |
| { |
| if (!object || !object.addEventListener || !object.removeEventListener) |
| return; |
| types = this._normalizeEventTypes(types); |
| for (var i = 0; i < types.length; ++i) |
| object.removeEventListener(types[i], this._logEvent, false); |
| }, |
| |
| /** |
| * @param {*} object |
| * @return {*} |
| */ |
| inspect: function(object) |
| { |
| return this._inspect(object); |
| }, |
| |
| queryObjects() |
| { |
| return InjectedScriptHost.queryObjects(...arguments); |
| }, |
| |
| copy: function(object) |
| { |
| var string; |
| var subtype = RemoteObject.subtype(object); |
| if (subtype === "node") |
| string = object.outerHTML; |
| else if (subtype === "regexp") |
| string = "" + object; |
| else if (injectedScript.isPrimitiveValue(object)) |
| string = "" + object; |
| else if (typeof object === "symbol") |
| string = String(object); |
| else if (typeof object === "function") |
| string = "" + object; |
| else { |
| try { |
| string = JSON.stringify(object, null, " "); |
| } catch (e) { |
| string = "" + object; |
| } |
| } |
| |
| CommandLineAPIHost.copyText(string); |
| }, |
| |
| clear: function() |
| { |
| CommandLineAPIHost.clearConsoleMessages(); |
| }, |
| |
| getEventListeners: function(target) |
| { |
| return CommandLineAPIHost.getEventListeners(target); |
| }, |
| |
| _inspectedObject: function() |
| { |
| return CommandLineAPIHost.inspectedObject(); |
| }, |
| |
| /** |
| * @param {Array.<string>|string=} types |
| * @return {Array.<string>} |
| */ |
| _normalizeEventTypes: function(types) |
| { |
| if (typeof types === "undefined") |
| types = [ "mouse", "key", "touch", "control", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation" ]; |
| 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", "mousewheel"); |
| else if (types[i] === "key") |
| result.splice(0, 0, "keydown", "keyup", "keypress", "textInput"); |
| else if (types[i] === "touch") |
| result.splice(0, 0, "touchstart", "touchmove", "touchend", "touchcancel"); |
| else if (types[i] === "control") |
| result.splice(0, 0, "resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"); |
| else |
| result.push(types[i]); |
| } |
| return result; |
| }, |
| |
| /** |
| * @param {Event} event |
| */ |
| _logEvent: function(event) |
| { |
| inspectedWindow.console.log(event.type, event); |
| }, |
| |
| /** |
| * @param {*} object |
| * @return {*} |
| */ |
| _inspect: function(object) |
| { |
| if (arguments.length === 0) |
| return; |
| |
| var objectId = RemoteObject.create(object, ""); |
| var hints = {}; |
| |
| switch (RemoteObject.describe(object)) { |
| case "Database": |
| var databaseId = CommandLineAPIHost.databaseId(object) |
| if (databaseId) |
| hints.databaseId = databaseId; |
| break; |
| case "Storage": |
| var storageId = CommandLineAPIHost.storageId(object) |
| if (storageId) |
| hints.domStorageId = InjectedScriptHost.evaluate("(" + storageId + ")"); |
| break; |
| } |
| |
| CommandLineAPIHost.inspect(objectId, hints); |
| return object; |
| } |
| } |
| |
| injectedScript.CommandLineAPI = CommandLineAPI; |
| injectedScript._commandLineAPIImpl = new CommandLineAPIImpl(); |
| |
| // This Module doesn't expose an object, it just adds an extension that InjectedScript uses. |
| // However, we return an empty object, so that InjectedScript knows this module has been loaded. |
| return {}; |
| |
| }) |