2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * @param {!InjectedScriptHostClass} InjectedScriptHost
32 * @param {!Window} inspectedWindow
33 * @param {number} injectedScriptId
35 (function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
38 * Protect against Object overwritten by the user code.
39 * @suppress {duplicate}
41 var Object = /** @type {function(new:Object, *=)} */ ({}.constructor);
44 * @param {!Array.<T>} array
45 * @param {...} var_args
48 function push(array, var_args)
50 for (var i = 1; i < arguments.length; ++i)
51 array[array.length] = arguments[i];
55 * @param {!Arguments.<T>} array
56 * @param {number=} index
57 * @return {!Array.<T>}
60 function slice(array, index)
63 for (var i = index || 0, j = 0; i < array.length; ++i, ++j)
69 * @param {!Array.<T>} array1
70 * @param {!Array.<T>} array2
71 * @return {!Array.<T>}
74 function concat(array1, array2)
77 for (var i = 0; i < array1.length; ++i)
78 push(result, array1[i]);
79 for (var i = 0; i < array2.length; ++i)
80 push(result, array2[i]);
87 * @suppress {uselessCode}
89 function toString(obj)
91 // We don't use String(obj) because String could be overridden.
92 // Also the ("" + obj) expression may throw.
96 var name = InjectedScriptHost.internalConstructorName(obj) || InjectedScriptHost.subtype(obj) || (typeof obj);
97 return "#<" + name + ">";
105 function toStringDescription(obj)
107 if (typeof obj === "number" && obj === 0 && 1 / obj < 0)
108 return "-0"; // Negative zero.
109 return toString(obj);
113 * Please use this bind, not the one from Function.prototype
114 * @param {function(...)} func
115 * @param {?Object} thisObject
116 * @param {...} var_args
117 * @return {function(...)}
119 function bind(func, thisObject, var_args)
121 var args = slice(arguments, 2);
124 * @param {...} var_args
126 function bound(var_args)
128 return InjectedScriptHost.callFunction(func, thisObject, concat(args, slice(arguments)));
130 bound.toString = function()
132 return "bound: " + toString(func);
142 function nullifyObjectProto(obj)
144 if (obj && typeof obj === "object")
145 obj.__proto__ = null;
153 function isUInt32(obj)
155 return typeof obj === "number" && obj >>> 0 === obj && (obj > 0 || 1 / obj > 0);
159 * FireBug's array detection.
163 function isArrayLike(obj)
165 if (typeof obj !== "object")
168 if (typeof obj.splice === "function")
169 return isUInt32(obj.length);
182 return a > b ? a : b;
186 * FIXME: Remove once ES6 is supported natively by JS compiler.
190 function isSymbol(obj)
192 var type = typeof obj;
193 return (type === "symbol");
199 var InjectedScript = function()
201 /** @type {number} */
202 this._lastBoundObjectId = 1;
203 /** @type {!Object.<number, (!Object|symbol)>} */
204 this._idToWrappedObject = { __proto__: null };
205 /** @type {!Object.<number, string>} */
206 this._idToObjectGroupName = { __proto__: null };
207 /** @type {!Object.<string, !Array.<number>>} */
208 this._objectGroups = { __proto__: null };
209 /** @type {!Object.<string, !Object>} */
210 this._modules = { __proto__: null };
214 * @type {!Object.<string, boolean>}
217 InjectedScript.primitiveTypes = {
225 InjectedScript.prototype = {
230 isPrimitiveValue: function(object)
232 // FIXME(33716): typeof document.all is always 'undefined'.
233 return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllCollection(object);
238 * @param {string} groupName
239 * @param {boolean} canAccessInspectedWindow
240 * @param {boolean} generatePreview
241 * @return {!RuntimeAgent.RemoteObject}
243 wrapObject: function(object, groupName, canAccessInspectedWindow, generatePreview)
245 if (canAccessInspectedWindow)
246 return this._wrapObject(object, groupName, false, generatePreview);
247 return this._fallbackWrapper(object);
252 * @return {!RuntimeAgent.RemoteObject}
254 _fallbackWrapper: function(object)
256 var result = { __proto__: null };
257 result.type = typeof object;
258 if (this.isPrimitiveValue(object))
259 result.value = object;
261 result.description = toString(object);
262 return /** @type {!RuntimeAgent.RemoteObject} */ (result);
266 * @param {boolean} canAccessInspectedWindow
267 * @param {!Object} table
268 * @param {!Array.<string>|string|boolean} columns
269 * @return {!RuntimeAgent.RemoteObject}
271 wrapTable: function(canAccessInspectedWindow, table, columns)
273 if (!canAccessInspectedWindow)
274 return this._fallbackWrapper(table);
275 var columnNames = null;
276 if (typeof columns === "string")
278 if (InjectedScriptHost.subtype(columns) === "array") {
280 for (var i = 0; i < columns.length; ++i)
281 columnNames[i] = toString(columns[i]);
283 return this._wrapObject(table, "console", false, true, columnNames, true);
289 inspectNode: function(object)
291 this._inspect(object);
298 _inspect: function(object)
300 if (arguments.length === 0)
303 var objectId = this._wrapObject(object, "");
304 var hints = { __proto__: null };
306 InjectedScriptHost.inspect(objectId, hints);
311 * This method cannot throw.
313 * @param {string=} objectGroupName
314 * @param {boolean=} forceValueType
315 * @param {boolean=} generatePreview
316 * @param {?Array.<string>=} columnNames
317 * @param {boolean=} isTable
318 * @return {!RuntimeAgent.RemoteObject}
319 * @suppress {checkTypes}
321 _wrapObject: function(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable)
324 return new InjectedScript.RemoteObject(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable);
327 var description = injectedScript._describe(e);
329 var description = "<failed to convert exception to string>";
331 return new InjectedScript.RemoteObject(description);
336 * @param {!Object|symbol} object
337 * @param {string=} objectGroupName
340 _bind: function(object, objectGroupName)
342 var id = this._lastBoundObjectId++;
343 this._idToWrappedObject[id] = object;
344 var objectId = "{\"injectedScriptId\":" + injectedScriptId + ",\"id\":" + id + "}";
345 if (objectGroupName) {
346 var group = this._objectGroups[objectGroupName];
349 this._objectGroups[objectGroupName] = group;
352 this._idToObjectGroupName[id] = objectGroupName;
358 * @param {string} objectId
361 _parseObjectId: function(objectId)
363 return nullifyObjectProto(/** @type {!Object} */ (InjectedScriptHost.eval("(" + objectId + ")")));
367 * @param {string} objectGroupName
369 releaseObjectGroup: function(objectGroupName)
371 if (objectGroupName === "console")
372 delete this._lastResult;
373 var group = this._objectGroups[objectGroupName];
376 for (var i = 0; i < group.length; i++)
377 this._releaseObject(group[i]);
378 delete this._objectGroups[objectGroupName];
382 * @param {string} objectId
384 setLastEvaluationResult: function(objectId)
386 var parsedObjectId = this._parseObjectId(objectId);
387 var object = this._objectForId(parsedObjectId);
388 this._lastResult = object;
392 * @param {string} methodName
393 * @param {string} args
396 dispatch: function(methodName, args)
398 var argsArray = /** @type {!Array.<*>} */ (InjectedScriptHost.eval("(" + args + ")"));
399 var result = InjectedScriptHost.callFunction(this[methodName], this, argsArray);
400 if (typeof result === "undefined") {
401 inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
408 * @param {string} objectId
409 * @param {boolean} ownProperties
410 * @param {boolean} accessorPropertiesOnly
411 * @return {!Array.<!RuntimeAgent.PropertyDescriptor>|boolean}
413 getProperties: function(objectId, ownProperties, accessorPropertiesOnly)
415 var parsedObjectId = this._parseObjectId(objectId);
416 var object = this._objectForId(parsedObjectId);
417 var objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
419 if (!this._isDefined(object) || isSymbol(object))
421 object = /** @type {!Object} */ (object);
422 var descriptors = this._propertyDescriptors(object, ownProperties, accessorPropertiesOnly);
424 // Go over properties, wrap object values.
425 for (var i = 0; i < descriptors.length; ++i) {
426 var descriptor = descriptors[i];
427 if ("get" in descriptor)
428 descriptor.get = this._wrapObject(descriptor.get, objectGroupName);
429 if ("set" in descriptor)
430 descriptor.set = this._wrapObject(descriptor.set, objectGroupName);
431 if ("value" in descriptor)
432 descriptor.value = this._wrapObject(descriptor.value, objectGroupName);
433 if (!("configurable" in descriptor))
434 descriptor.configurable = false;
435 if (!("enumerable" in descriptor))
436 descriptor.enumerable = false;
437 if ("symbol" in descriptor)
438 descriptor.symbol = this._wrapObject(descriptor.symbol, objectGroupName);
444 * @param {string} objectId
445 * @return {!Array.<!Object>|boolean}
447 getInternalProperties: function(objectId)
449 var parsedObjectId = this._parseObjectId(objectId);
450 var object = this._objectForId(parsedObjectId);
451 var objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
452 if (!this._isDefined(object) || isSymbol(object))
454 object = /** @type {!Object} */ (object);
455 var descriptors = [];
456 var internalProperties = InjectedScriptHost.getInternalProperties(object);
457 if (internalProperties) {
458 for (var i = 0; i < internalProperties.length; i++) {
459 var property = internalProperties[i];
462 value: this._wrapObject(property.value, objectGroupName),
465 push(descriptors, descriptor);
472 * @param {string} functionId
473 * @return {!DebuggerAgent.FunctionDetails|string}
475 getFunctionDetails: function(functionId)
477 var parsedFunctionId = this._parseObjectId(functionId);
478 var func = this._objectForId(parsedFunctionId);
479 if (typeof func !== "function")
480 return "Cannot resolve function by id.";
481 var details = nullifyObjectProto(/** @type {!DebuggerAgent.FunctionDetails} */ (InjectedScriptHost.functionDetails(func)));
482 if ("rawScopes" in details) {
483 var objectGroupName = this._idToObjectGroupName[parsedFunctionId.id];
484 var rawScopes = details["rawScopes"];
485 delete details["rawScopes"];
487 for (var i = 0; i < rawScopes.length; ++i)
488 scopes[i] = InjectedScript.CallFrameProxy._createScopeJson(rawScopes[i].type, rawScopes[i].object, objectGroupName);
489 details.scopeChain = scopes;
495 * @param {string} objectId
496 * @return {!Array.<!Object>|string}
498 getCollectionEntries: function(objectId)
500 var parsedObjectId = this._parseObjectId(objectId);
501 var object = this._objectForId(parsedObjectId);
502 if (!object || typeof object !== "object")
503 return "Could not find object with given id";
504 var entries = InjectedScriptHost.collectionEntries(object);
506 return "Object with given id is not a collection";
507 var objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
508 for (var i = 0; i < entries.length; ++i) {
509 var entry = nullifyObjectProto(entries[i]);
511 entry.key = this._wrapObject(entry.key, objectGroupName);
512 entry.value = this._wrapObject(entry.value, objectGroupName);
519 * @param {string} objectId
521 releaseObject: function(objectId)
523 var parsedObjectId = this._parseObjectId(objectId);
524 this._releaseObject(parsedObjectId.id);
530 _releaseObject: function(id)
532 delete this._idToWrappedObject[id];
533 delete this._idToObjectGroupName[id];
537 * @param {!Object} object
538 * @param {boolean=} ownProperties
539 * @param {boolean=} accessorPropertiesOnly
540 * @return {!Array.<!Object>}
542 _propertyDescriptors: function(object, ownProperties, accessorPropertiesOnly)
544 var descriptors = [];
545 var propertyProcessed = { __proto__: null };
549 * @param {!Array.<string|symbol>} properties
551 function process(o, properties)
553 for (var i = 0; i < properties.length; ++i) {
554 var property = properties[i];
555 if (propertyProcessed[property])
559 if (isSymbol(property))
560 name = injectedScript._describe(property);
563 propertyProcessed[property] = true;
564 var descriptor = nullifyObjectProto(InjectedScriptHost.suppressWarningsAndCallFunction(Object.getOwnPropertyDescriptor, Object, [o, property]));
566 if (accessorPropertiesOnly && !("get" in descriptor || "set" in descriptor))
569 // Not all bindings provide proper descriptors. Fall back to the writable, configurable property.
570 if (accessorPropertiesOnly)
573 descriptor = { name: name, value: o[property], writable: false, configurable: false, enumerable: false, __proto__: null };
575 descriptor.isOwn = true;
576 push(descriptors, descriptor);
583 if (accessorPropertiesOnly)
585 var descriptor = { __proto__: null };
586 descriptor.value = e;
587 descriptor.wasThrown = true;
590 descriptor.name = name;
592 descriptor.isOwn = true;
593 if (isSymbol(property))
594 descriptor.symbol = property;
595 push(descriptors, descriptor);
599 for (var o = object; this._isDefined(o); o = o.__proto__) {
600 // First call Object.keys() to enforce ordering of the property descriptors.
601 process(o, Object.keys(/** @type {!Object} */ (o)));
602 process(o, Object.getOwnPropertyNames(/** @type {!Object} */ (o)));
603 if (Object.getOwnPropertySymbols)
604 process(o, Object.getOwnPropertySymbols(/** @type {!Object} */ (o)));
607 if (object.__proto__ && !accessorPropertiesOnly)
608 push(descriptors, { name: "__proto__", value: object.__proto__, writable: true, configurable: true, enumerable: false, isOwn: true, __proto__: null });
617 * @param {string} expression
618 * @param {string} objectGroup
619 * @param {boolean} injectCommandLineAPI
620 * @param {boolean} returnByValue
621 * @param {boolean} generatePreview
624 evaluate: function(expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
626 return this._evaluateAndWrap(null, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview);
630 * @param {string} objectId
631 * @param {string} expression
632 * @param {string} args
633 * @param {boolean} returnByValue
634 * @return {!Object|string}
636 callFunctionOn: function(objectId, expression, args, returnByValue)
638 var parsedObjectId = this._parseObjectId(objectId);
639 var object = this._objectForId(parsedObjectId);
640 if (!this._isDefined(object))
641 return "Could not find object with given id";
644 var resolvedArgs = [];
645 var callArgs = /** @type {!Array.<!RuntimeAgent.CallArgument>} */ (InjectedScriptHost.eval(args));
646 for (var i = 0; i < callArgs.length; ++i) {
648 resolvedArgs[i] = this._resolveCallArgument(callArgs[i]);
656 var objectGroup = this._idToObjectGroupName[parsedObjectId.id];
657 var func = InjectedScriptHost.eval("(" + expression + ")");
658 if (typeof func !== "function")
659 return "Given expression does not evaluate to a function";
661 return { wasThrown: false,
662 result: this._wrapObject(InjectedScriptHost.callFunction(func, object, resolvedArgs), objectGroup, returnByValue),
665 return this._createThrownValue(e, objectGroup, false);
670 * Resolves a value from CallArgument description.
671 * @param {!RuntimeAgent.CallArgument} callArgumentJson
672 * @return {*} resolved value
673 * @throws {string} error message
675 _resolveCallArgument: function(callArgumentJson)
677 callArgumentJson = nullifyObjectProto(callArgumentJson);
678 var objectId = callArgumentJson.objectId;
680 var parsedArgId = this._parseObjectId(objectId);
681 if (!parsedArgId || parsedArgId["injectedScriptId"] !== injectedScriptId)
682 throw "Arguments should belong to the same JavaScript world as the target object.";
684 var resolvedArg = this._objectForId(parsedArgId);
685 if (!this._isDefined(resolvedArg))
686 throw "Could not find object with given id";
689 } else if ("value" in callArgumentJson) {
690 var value = callArgumentJson.value;
691 if (callArgumentJson.type === "number" && typeof value !== "number")
692 value = Number(value);
699 * @param {?JavaScriptCallFrame} callFrame
700 * @param {string} expression
701 * @param {string} objectGroup
702 * @param {boolean} injectCommandLineAPI
703 * @param {boolean} returnByValue
704 * @param {boolean} generatePreview
705 * @param {!Array.<!Object>=} scopeChain
708 _evaluateAndWrap: function(callFrame, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview, scopeChain)
710 var wrappedResult = this._evaluateOn(callFrame, objectGroup, expression, injectCommandLineAPI, scopeChain);
711 if (!wrappedResult.exceptionDetails) {
712 return { wasThrown: false,
713 result: this._wrapObject(wrappedResult.result, objectGroup, returnByValue, generatePreview),
716 return this._createThrownValue(wrappedResult.result, objectGroup, generatePreview, wrappedResult.exceptionDetails);
721 * @param {string} objectGroup
722 * @param {boolean} generatePreview
723 * @param {!DebuggerAgent.ExceptionDetails=} exceptionDetails
726 _createThrownValue: function(value, objectGroup, generatePreview, exceptionDetails)
728 var remoteObject = this._wrapObject(value, objectGroup, false, generatePreview && InjectedScriptHost.subtype(value) !== "error");
729 if (!remoteObject.description){
731 remoteObject.description = toStringDescription(value);
734 return { wasThrown: true, result: remoteObject, exceptionDetails: exceptionDetails, __proto__: null };
738 * @param {?JavaScriptCallFrame} callFrame
739 * @param {string} objectGroup
740 * @param {string} expression
741 * @param {boolean} injectCommandLineAPI
742 * @param {!Array.<!Object>=} scopeChain
745 _evaluateOn: function(callFrame, objectGroup, expression, injectCommandLineAPI, scopeChain)
747 // Only install command line api object for the time of evaluation.
748 // Surround the expression in with statements to inject our command line API so that
749 // the window object properties still take more precedent than our API functions.
751 var scopeExtensionForEval = (callFrame && injectCommandLineAPI) ? new CommandLineAPI(this._commandLineAPIImpl, callFrame) : undefined;
753 injectCommandLineAPI = !scopeExtensionForEval && !callFrame && injectCommandLineAPI && !("__commandLineAPI" in inspectedWindow);
754 var injectScopeChain = scopeChain && scopeChain.length && !("__scopeChainForEval" in inspectedWindow);
759 if (injectCommandLineAPI) {
760 InjectedScriptHost.setNonEnumProperty(inspectedWindow, "__commandLineAPI", new CommandLineAPI(this._commandLineAPIImpl, callFrame));
761 prefix = "with (typeof __commandLineAPI !== 'undefined' ? __commandLineAPI : { __proto__: null }) {";
764 if (injectScopeChain) {
765 InjectedScriptHost.setNonEnumProperty(inspectedWindow, "__scopeChainForEval", scopeChain);
766 for (var i = 0; i < scopeChain.length; ++i) {
767 prefix = "with (typeof __scopeChainForEval !== 'undefined' ? __scopeChainForEval[" + i + "] : { __proto__: null }) {" + (suffix ? " " : "") + prefix;
776 expression = prefix + "\n" + expression + "\n" + suffix;
777 var wrappedResult = callFrame ? callFrame.evaluateWithExceptionDetails(expression, scopeExtensionForEval) : InjectedScriptHost.evaluateWithExceptionDetails(expression);
778 if (objectGroup === "console" && !wrappedResult.exceptionDetails)
779 this._lastResult = wrappedResult.result;
780 return wrappedResult;
782 if (injectCommandLineAPI)
783 delete inspectedWindow["__commandLineAPI"];
784 if (injectScopeChain)
785 delete inspectedWindow["__scopeChainForEval"];
790 * @param {?Object} callFrame
791 * @param {number} asyncOrdinal
792 * @return {!Array.<!InjectedScript.CallFrameProxy>|boolean}
794 wrapCallFrames: function(callFrame, asyncOrdinal)
802 result[depth] = new InjectedScript.CallFrameProxy(depth, callFrame, asyncOrdinal);
803 callFrame = callFrame.caller;
810 * @param {!JavaScriptCallFrame} topCallFrame
811 * @param {!Array.<!JavaScriptCallFrame>} asyncCallStacks
812 * @param {string} callFrameId
813 * @param {string} expression
814 * @param {string} objectGroup
815 * @param {boolean} injectCommandLineAPI
816 * @param {boolean} returnByValue
817 * @param {boolean} generatePreview
820 evaluateOnCallFrame: function(topCallFrame, asyncCallStacks, callFrameId, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
822 var parsedCallFrameId = nullifyObjectProto(/** @type {!Object} */ (InjectedScriptHost.eval("(" + callFrameId + ")")));
823 var callFrame = this._callFrameForParsedId(topCallFrame, parsedCallFrameId, asyncCallStacks);
825 return "Could not find call frame with given id";
826 if (parsedCallFrameId["asyncOrdinal"])
827 return this._evaluateAndWrap(null, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview, callFrame.scopeChain);
828 return this._evaluateAndWrap(callFrame, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview);
832 * @param {!JavaScriptCallFrame} topCallFrame
833 * @param {string} callFrameId
836 restartFrame: function(topCallFrame, callFrameId)
838 var callFrame = this._callFrameForId(topCallFrame, callFrameId);
840 return "Could not find call frame with given id";
841 var result = callFrame.restart();
842 if (result === false)
843 result = "Restart frame is not supported";
848 * @param {!JavaScriptCallFrame} topCallFrame
849 * @param {string} callFrameId
850 * @return {*} a stepIn position array ready for protocol JSON or a string error
852 getStepInPositions: function(topCallFrame, callFrameId)
854 var callFrame = this._callFrameForId(topCallFrame, callFrameId);
856 return "Could not find call frame with given id";
857 var stepInPositionsUnpacked = JSON.parse(callFrame.stepInPositions);
858 if (typeof stepInPositionsUnpacked !== "object")
859 return "Step in positions not available";
860 return stepInPositionsUnpacked;
864 * Either callFrameId or functionObjectId must be specified.
865 * @param {!JavaScriptCallFrame} topCallFrame
866 * @param {string|boolean} callFrameId or false
867 * @param {string|boolean} functionObjectId or false
868 * @param {number} scopeNumber
869 * @param {string} variableName
870 * @param {string} newValueJsonString RuntimeAgent.CallArgument structure serialized as string
871 * @return {string|undefined} undefined if success or an error message
873 setVariableValue: function(topCallFrame, callFrameId, functionObjectId, scopeNumber, variableName, newValueJsonString)
876 var newValueJson = /** @type {!RuntimeAgent.CallArgument} */ (InjectedScriptHost.eval("(" + newValueJsonString + ")"));
877 var resolvedValue = this._resolveCallArgument(newValueJson);
878 if (typeof callFrameId === "string") {
879 var callFrame = this._callFrameForId(topCallFrame, callFrameId);
881 return "Could not find call frame with given id";
882 callFrame.setVariableValue(scopeNumber, variableName, resolvedValue)
884 var parsedFunctionId = this._parseObjectId(/** @type {string} */ (functionObjectId));
885 var func = this._objectForId(parsedFunctionId);
886 if (typeof func !== "function")
887 return "Could not resolve function by id";
888 InjectedScriptHost.setFunctionVariableValue(func, scopeNumber, variableName, resolvedValue);
897 * @param {!JavaScriptCallFrame} topCallFrame
898 * @param {string} callFrameId
899 * @return {?JavaScriptCallFrame}
901 _callFrameForId: function(topCallFrame, callFrameId)
903 var parsedCallFrameId = nullifyObjectProto(/** @type {!Object} */ (InjectedScriptHost.eval("(" + callFrameId + ")")));
904 return this._callFrameForParsedId(topCallFrame, parsedCallFrameId, []);
908 * @param {!JavaScriptCallFrame} topCallFrame
909 * @param {!Object} parsedCallFrameId
910 * @param {!Array.<!JavaScriptCallFrame>} asyncCallStacks
911 * @return {?JavaScriptCallFrame}
913 _callFrameForParsedId: function(topCallFrame, parsedCallFrameId, asyncCallStacks)
915 var asyncOrdinal = parsedCallFrameId["asyncOrdinal"]; // 1-based index
917 topCallFrame = asyncCallStacks[asyncOrdinal - 1];
918 var ordinal = parsedCallFrameId["ordinal"];
919 var callFrame = topCallFrame;
920 while (--ordinal >= 0 && callFrame)
921 callFrame = callFrame.caller;
926 * @param {!Object} objectId
927 * @return {!Object|symbol}
929 _objectForId: function(objectId)
931 return this._idToWrappedObject[objectId.id];
935 * @param {string} objectId
936 * @return {!Object|symbol}
938 findObjectById: function(objectId)
940 var parsedObjectId = this._parseObjectId(objectId);
941 return this._objectForId(parsedObjectId);
945 * @param {string} objectId
948 nodeForObjectId: function(objectId)
950 var object = this.findObjectById(objectId);
951 if (!object || this._subtype(object) !== "node")
953 return /** @type {!Node} */ (object);
957 * @param {string} name
960 module: function(name)
962 return this._modules[name];
966 * @param {string} name
967 * @param {string} source
970 injectModule: function(name, source)
972 delete this._modules[name];
973 var moduleFunction = InjectedScriptHost.eval("(" + source + ")");
974 if (typeof moduleFunction !== "function") {
975 inspectedWindow.console.error("Web Inspector error: A function was expected for module %s evaluation", name);
978 var module = /** @type {!Object} */ (InjectedScriptHost.callFunction(moduleFunction, inspectedWindow, [InjectedScriptHost, inspectedWindow, injectedScriptId, this]));
979 this._modules[name] = module;
987 _isDefined: function(object)
989 return !!object || this._isHTMLAllCollection(object);
996 _isHTMLAllCollection: function(object)
998 // document.all is reported as undefined, but we still want to process it.
999 return (typeof object === "undefined") && InjectedScriptHost.isHTMLAllCollection(object);
1006 _subtype: function(obj)
1011 if (this.isPrimitiveValue(obj))
1014 var subtype = InjectedScriptHost.subtype(obj);
1015 // FIXME: Consider exposing "error" subtype via protocol.
1016 if (subtype && subtype !== "error")
1019 if (isArrayLike(obj))
1022 // If owning frame has navigated to somewhere else window properties will be undefined.
1030 _describe: function(obj)
1032 if (this.isPrimitiveValue(obj))
1035 var subtype = this._subtype(obj);
1037 if (subtype === "regexp")
1038 return toString(obj);
1040 if (subtype === "date")
1041 return toString(obj);
1043 if (subtype === "node") {
1044 var description = obj.nodeName.toLowerCase();
1045 switch (obj.nodeType) {
1046 case 1 /* Node.ELEMENT_NODE */:
1047 description += obj.id ? "#" + obj.id : "";
1048 var className = obj.className;
1049 description += (className && typeof className === "string") ? "." + className.trim().replace(/\s+/g, ".") : "";
1051 case 10 /*Node.DOCUMENT_TYPE_NODE */:
1052 description = "<!DOCTYPE " + description + ">";
1058 var className = InjectedScriptHost.internalConstructorName(obj);
1059 if (subtype === "array") {
1060 if (typeof obj.length === "number")
1061 className += "[" + obj.length + "]";
1065 // NodeList in JSC is a function, check for array prior to this.
1066 if (typeof obj === "function")
1067 return toString(obj);
1069 if (isSymbol(obj)) {
1071 return /** @type {string} */ (InjectedScriptHost.callFunction(Symbol.prototype.toString, obj)) || "Symbol";
1077 if (InjectedScriptHost.subtype(obj) === "error") {
1079 var message = obj.message;
1081 return className + ": " + message;
1091 * @type {!InjectedScript}
1094 var injectedScript = new InjectedScript();
1099 * @param {string=} objectGroupName
1100 * @param {boolean=} forceValueType
1101 * @param {boolean=} generatePreview
1102 * @param {?Array.<string>=} columnNames
1103 * @param {boolean=} isTable
1104 * @param {boolean=} skipEntriesPreview
1106 InjectedScript.RemoteObject = function(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable, skipEntriesPreview)
1108 this.type = typeof object;
1109 if (this.type === "undefined" && injectedScript._isHTMLAllCollection(object))
1110 this.type = "object";
1112 if (injectedScript.isPrimitiveValue(object) || object === null || forceValueType) {
1113 // We don't send undefined values over JSON.
1114 if (this.type !== "undefined")
1115 this.value = object;
1117 // Null object is object with 'null' subtype.
1118 if (object === null)
1119 this.subtype = "null";
1121 // Provide user-friendly number values.
1122 if (this.type === "number") {
1123 this.description = toStringDescription(object);
1124 // Override "value" property for values that can not be JSON-stringified.
1125 switch (this.description) {
1130 this.value = this.description;
1138 object = /** @type {!Object} */ (object);
1140 this.objectId = injectedScript._bind(object, objectGroupName);
1141 var subtype = injectedScript._subtype(object);
1143 this.subtype = subtype;
1144 var className = InjectedScriptHost.internalConstructorName(object);
1146 this.className = className;
1147 this.description = injectedScript._describe(object);
1149 if (generatePreview && this.type === "object")
1150 this.preview = this._generatePreview(object, undefined, columnNames, isTable, skipEntriesPreview);
1153 InjectedScript.RemoteObject.prototype = {
1155 * @return {!RuntimeAgent.ObjectPreview} preview
1157 _createEmptyPreview: function()
1160 type: /** @type {!RuntimeAgent.ObjectPreviewType.<string>} */ (this.type),
1161 description: this.description || toStringDescription(this.value),
1168 preview.subtype = /** @type {!RuntimeAgent.ObjectPreviewSubtype.<string>} */ (this.subtype);
1173 * @param {!Object} object
1174 * @param {?Array.<string>=} firstLevelKeys
1175 * @param {?Array.<string>=} secondLevelKeys
1176 * @param {boolean=} isTable
1177 * @param {boolean=} skipEntriesPreview
1178 * @return {!RuntimeAgent.ObjectPreview} preview
1180 _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable, skipEntriesPreview)
1182 var preview = this._createEmptyPreview();
1183 var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0;
1185 var propertiesThreshold = {
1186 properties: isTable ? 1000 : max(5, firstLevelKeysCount),
1187 indexes: isTable ? 1000 : max(100, firstLevelKeysCount),
1192 var descriptors = injectedScript._propertyDescriptors(object);
1194 if (firstLevelKeys) {
1195 var nameToDescriptors = { __proto__: null };
1196 for (var i = 0; i < descriptors.length; ++i) {
1197 var descriptor = descriptors[i];
1198 nameToDescriptors["#" + descriptor.name] = descriptor;
1201 for (var i = 0; i < firstLevelKeys.length; ++i)
1202 descriptors[i] = nameToDescriptors["#" + firstLevelKeys[i]];
1205 this._appendPropertyDescriptors(preview, descriptors, propertiesThreshold, secondLevelKeys, isTable);
1206 if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
1209 // Add internal properties to preview.
1210 var internalProperties = InjectedScriptHost.getInternalProperties(object) || [];
1211 for (var i = 0; i < internalProperties.length; ++i) {
1212 internalProperties[i] = nullifyObjectProto(internalProperties[i]);
1213 internalProperties[i].enumerable = true;
1215 this._appendPropertyDescriptors(preview, internalProperties, propertiesThreshold, secondLevelKeys, isTable);
1217 if (this.subtype === "map" || this.subtype === "set")
1218 this._appendEntriesPreview(object, preview, skipEntriesPreview);
1221 preview.lossless = false;
1228 * @param {!RuntimeAgent.ObjectPreview} preview
1229 * @param {!Array.<!Object>} descriptors
1230 * @param {!Object} propertiesThreshold
1231 * @param {?Array.<string>=} secondLevelKeys
1232 * @param {boolean=} isTable
1234 _appendPropertyDescriptors: function(preview, descriptors, propertiesThreshold, secondLevelKeys, isTable)
1236 for (var i = 0; i < descriptors.length; ++i) {
1237 if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
1240 var descriptor = descriptors[i];
1243 if (descriptor.wasThrown) {
1244 preview.lossless = false;
1247 if (!descriptor.enumerable && !descriptor.isOwn)
1250 var name = descriptor.name;
1251 if (name === "__proto__")
1253 if (this.subtype === "array" && name === "length")
1256 if (!("value" in descriptor)) {
1257 preview.lossless = false;
1258 this._appendPropertyPreview(preview, { name: name, type: "accessor", __proto__: null }, propertiesThreshold);
1262 var value = descriptor.value;
1263 if (value === null) {
1264 this._appendPropertyPreview(preview, { name: name, type: "object", subtype: "null", value: "null", __proto__: null }, propertiesThreshold);
1268 var type = typeof value;
1269 if (!descriptor.enumerable && type === "function")
1271 if (type === "undefined" && injectedScript._isHTMLAllCollection(value))
1274 var maxLength = 100;
1275 if (InjectedScript.primitiveTypes[type]) {
1276 if (type === "string" && value.length > maxLength) {
1277 value = this._abbreviateString(value, maxLength, true);
1278 preview.lossless = false;
1280 this._appendPropertyPreview(preview, { name: name, type: type, value: toStringDescription(value), __proto__: null }, propertiesThreshold);
1284 var property = { name: name, type: type, __proto__: null };
1285 var subtype = injectedScript._subtype(value);
1287 property.subtype = subtype;
1289 if (secondLevelKeys === null || secondLevelKeys) {
1290 var subPreview = this._generatePreview(value, secondLevelKeys || undefined, undefined, isTable);
1291 property.valuePreview = subPreview;
1292 if (!subPreview.lossless)
1293 preview.lossless = false;
1294 if (subPreview.overflow)
1295 preview.overflow = true;
1297 var description = "";
1298 if (type !== "function")
1299 description = this._abbreviateString(/** @type {string} */ (injectedScript._describe(value)), maxLength, subtype === "regexp");
1300 property.value = description;
1301 preview.lossless = false;
1303 this._appendPropertyPreview(preview, property, propertiesThreshold);
1308 * @param {!RuntimeAgent.ObjectPreview} preview
1309 * @param {!Object} property
1310 * @param {!Object} propertiesThreshold
1312 _appendPropertyPreview: function(preview, property, propertiesThreshold)
1314 if (toString(property.name >>> 0) === property.name)
1315 propertiesThreshold.indexes--;
1317 propertiesThreshold.properties--;
1318 if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0) {
1319 preview.overflow = true;
1320 preview.lossless = false;
1322 push(preview.properties, property);
1327 * @param {!Object} object
1328 * @param {!RuntimeAgent.ObjectPreview} preview
1329 * @param {boolean=} skipEntriesPreview
1331 _appendEntriesPreview: function(object, preview, skipEntriesPreview)
1333 var entries = InjectedScriptHost.collectionEntries(object);
1336 if (skipEntriesPreview) {
1337 if (entries.length) {
1338 preview.overflow = true;
1339 preview.lossless = false;
1343 preview.entries = [];
1344 var entriesThreshold = 5;
1345 for (var i = 0; i < entries.length; ++i) {
1346 if (preview.entries.length >= entriesThreshold) {
1347 preview.overflow = true;
1348 preview.lossless = false;
1351 var entry = nullifyObjectProto(entries[i]);
1352 var previewEntry = {
1353 value: generateValuePreview(entry.value),
1357 previewEntry.key = generateValuePreview(entry.key);
1358 push(preview.entries, previewEntry);
1363 * @return {!RuntimeAgent.ObjectPreview}
1365 function generateValuePreview(value)
1367 var remoteObject = new InjectedScript.RemoteObject(value, undefined, undefined, true, undefined, undefined, true);
1368 var valuePreview = remoteObject.preview || remoteObject._createEmptyPreview();
1369 if (remoteObject.objectId)
1370 injectedScript.releaseObject(remoteObject.objectId);
1371 if (!valuePreview.lossless)
1372 preview.lossless = false;
1373 return valuePreview;
1378 * @param {string} string
1379 * @param {number} maxLength
1380 * @param {boolean=} middle
1383 _abbreviateString: function(string, maxLength, middle)
1385 if (string.length <= maxLength)
1388 var leftHalf = maxLength >> 1;
1389 var rightHalf = maxLength - leftHalf - 1;
1390 return string.substr(0, leftHalf) + "\u2026" + string.substr(string.length - rightHalf, rightHalf);
1392 return string.substr(0, maxLength) + "\u2026";
1399 * @param {number} ordinal
1400 * @param {!JavaScriptCallFrame} callFrame
1401 * @param {number} asyncOrdinal
1403 InjectedScript.CallFrameProxy = function(ordinal, callFrame, asyncOrdinal)
1405 this.callFrameId = "{\"ordinal\":" + ordinal + ",\"injectedScriptId\":" + injectedScriptId + (asyncOrdinal ? ",\"asyncOrdinal\":" + asyncOrdinal : "") + "}";
1406 this.functionName = (callFrame.type === "function" ? callFrame.functionName : "");
1407 this.location = { scriptId: toString(callFrame.sourceID), lineNumber: callFrame.line, columnNumber: callFrame.column, __proto__: null };
1408 this.scopeChain = this._wrapScopeChain(callFrame);
1409 this.this = injectedScript._wrapObject(callFrame.thisObject, "backtrace");
1410 if (callFrame.isAtReturn)
1411 this.returnValue = injectedScript._wrapObject(callFrame.returnValue, "backtrace");
1414 InjectedScript.CallFrameProxy.prototype = {
1416 * @param {!JavaScriptCallFrame} callFrame
1417 * @return {!Array.<!DebuggerAgent.Scope>}
1419 _wrapScopeChain: function(callFrame)
1421 var scopeChain = callFrame.scopeChain;
1422 var scopeChainProxy = [];
1423 for (var i = 0; i < scopeChain.length; ++i)
1424 scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(callFrame.scopeType(i), scopeChain[i], "backtrace");
1425 return scopeChainProxy;
1432 * @param {number} scopeTypeCode
1433 * @param {*} scopeObject
1434 * @param {string} groupId
1435 * @return {!DebuggerAgent.Scope}
1437 InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)
1439 const GLOBAL_SCOPE = 0;
1440 const LOCAL_SCOPE = 1;
1441 const WITH_SCOPE = 2;
1442 const CLOSURE_SCOPE = 3;
1443 const CATCH_SCOPE = 4;
1445 /** @type {!Object.<number, string>} */
1446 var scopeTypeNames = { __proto__: null };
1447 scopeTypeNames[GLOBAL_SCOPE] = "global";
1448 scopeTypeNames[LOCAL_SCOPE] = "local";
1449 scopeTypeNames[WITH_SCOPE] = "with";
1450 scopeTypeNames[CLOSURE_SCOPE] = "closure";
1451 scopeTypeNames[CATCH_SCOPE] = "catch";
1454 object: injectedScript._wrapObject(scopeObject, groupId),
1455 type: /** @type {!DebuggerAgent.ScopeType} */ (scopeTypeNames[scopeTypeCode]),
1462 * @param {!CommandLineAPIImpl} commandLineAPIImpl
1463 * @param {?JavaScriptCallFrame} callFrame
1465 function CommandLineAPI(commandLineAPIImpl, callFrame)
1468 * @param {string} member
1471 function inScopeVariables(member)
1474 return (member in inspectedWindow);
1476 var scopeChain = callFrame.scopeChain;
1477 for (var i = 0; i < scopeChain.length; ++i) {
1478 if (member in scopeChain[i])
1485 * @param {string} name The name of the method for which a toString method should be generated.
1486 * @return {function():string}
1488 function customToStringMethod(name)
1492 var funcArgsSyntax = "";
1494 var funcSyntax = "" + commandLineAPIImpl[name];
1495 funcSyntax = funcSyntax.replace(/\n/g, " ");
1496 funcSyntax = funcSyntax.replace(/^function[^\(]*\(([^\)]*)\).*$/, "$1");
1497 funcSyntax = funcSyntax.replace(/\s*,\s*/g, ", ");
1498 funcSyntax = funcSyntax.replace(/\bopt_(\w+)\b/g, "[$1]");
1499 funcArgsSyntax = funcSyntax.trim();
1502 return "function " + name + "(" + funcArgsSyntax + ") { [Command Line API] }";
1506 for (var i = 0; i < CommandLineAPI.members_.length; ++i) {
1507 var member = CommandLineAPI.members_[i];
1508 if (inScopeVariables(member))
1511 this[member] = bind(commandLineAPIImpl[member], commandLineAPIImpl);
1512 this[member].toString = customToStringMethod(member);
1515 for (var i = 0; i < 5; ++i) {
1516 var member = "$" + i;
1517 if (inScopeVariables(member))
1520 this.__defineGetter__("$" + i, bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl, i));
1523 this.$_ = injectedScript._lastResult;
1525 this.__proto__ = null;
1528 // NOTE: Please keep the list of API methods below snchronized to that in WebInspector.RuntimeModel!
1529 // NOTE: Argument names of these methods will be printed in the console, so use pretty names!
1531 * @type {!Array.<string>}
1534 CommandLineAPI.members_ = [
1535 "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd",
1536 "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners",
1537 "debug", "undebug", "monitor", "unmonitor", "table"
1543 function CommandLineAPIImpl()
1547 CommandLineAPIImpl.prototype = {
1549 * @param {string} selector
1550 * @param {!Node=} opt_startNode
1553 $: function (selector, opt_startNode)
1555 if (this._canQuerySelectorOnNode(opt_startNode))
1556 return opt_startNode.querySelector(selector);
1558 return inspectedWindow.document.querySelector(selector);
1562 * @param {string} selector
1563 * @param {!Node=} opt_startNode
1566 $$: function (selector, opt_startNode)
1568 if (this._canQuerySelectorOnNode(opt_startNode))
1569 return opt_startNode.querySelectorAll(selector);
1570 return inspectedWindow.document.querySelectorAll(selector);
1574 * @param {!Node=} node
1577 _canQuerySelectorOnNode: function(node)
1579 return !!node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
1583 * @param {string} xpath
1584 * @param {!Node=} opt_startNode
1587 $x: function(xpath, opt_startNode)
1589 var doc = (opt_startNode && opt_startNode.ownerDocument) || inspectedWindow.document;
1590 var result = doc.evaluate(xpath, opt_startNode || doc, null, XPathResult.ANY_TYPE, null);
1591 switch (result.resultType) {
1592 case XPathResult.NUMBER_TYPE:
1593 return result.numberValue;
1594 case XPathResult.STRING_TYPE:
1595 return result.stringValue;
1596 case XPathResult.BOOLEAN_TYPE:
1597 return result.booleanValue;
1601 while (node = result.iterateNext())
1610 dir: function(var_args)
1612 return InjectedScriptHost.callFunction(inspectedWindow.console.dir, inspectedWindow.console, slice(arguments));
1618 dirxml: function(var_args)
1620 return InjectedScriptHost.callFunction(inspectedWindow.console.dirxml, inspectedWindow.console, slice(arguments));
1624 * @return {!Array.<string>}
1626 keys: function(object)
1628 return Object.keys(object);
1632 * @return {!Array.<*>}
1634 values: function(object)
1637 for (var key in object)
1638 push(result, object[key]);
1645 profile: function(opt_title)
1647 return InjectedScriptHost.callFunction(inspectedWindow.console.profile, inspectedWindow.console, slice(arguments));
1653 profileEnd: function(opt_title)
1655 return InjectedScriptHost.callFunction(inspectedWindow.console.profileEnd, inspectedWindow.console, slice(arguments));
1659 * @param {!Object} object
1660 * @param {!Array.<string>|string=} opt_types
1662 monitorEvents: function(object, opt_types)
1664 if (!object || !object.addEventListener || !object.removeEventListener)
1666 var types = this._normalizeEventTypes(opt_types);
1667 for (var i = 0; i < types.length; ++i) {
1668 object.removeEventListener(types[i], this._logEvent, false);
1669 object.addEventListener(types[i], this._logEvent, false);
1674 * @param {!Object} object
1675 * @param {!Array.<string>|string=} opt_types
1677 unmonitorEvents: function(object, opt_types)
1679 if (!object || !object.addEventListener || !object.removeEventListener)
1681 var types = this._normalizeEventTypes(opt_types);
1682 for (var i = 0; i < types.length; ++i)
1683 object.removeEventListener(types[i], this._logEvent, false);
1690 inspect: function(object)
1692 return injectedScript._inspect(object);
1695 copy: function(object)
1698 if (injectedScript._subtype(object) === "node") {
1699 string = object.outerHTML;
1700 } else if (injectedScript.isPrimitiveValue(object)) {
1701 string = toString(object);
1704 string = JSON.stringify(object, null, " ");
1706 string = toString(object);
1710 var hints = { copyToClipboard: true, __proto__: null };
1711 var remoteObject = injectedScript._wrapObject(string, "")
1712 InjectedScriptHost.inspect(remoteObject, hints);
1717 InjectedScriptHost.clearConsoleMessages();
1721 * @param {!Node} node
1722 * @return {!Array.<!{type: string, listener: function(), useCapture: boolean, remove: function()}>|undefined}
1724 getEventListeners: function(node)
1726 var result = nullifyObjectProto(InjectedScriptHost.getEventListeners(node));
1729 /** @this {{type: string, listener: function(), useCapture: boolean}} */
1730 var removeFunc = function()
1732 node.removeEventListener(this.type, this.listener, this.useCapture);
1734 for (var type in result) {
1735 var listeners = result[type];
1736 for (var i = 0, listener; listener = listeners[i]; ++i) {
1737 listener["type"] = type;
1738 listener["remove"] = removeFunc;
1746 InjectedScriptHost.debugFunction(fn);
1749 undebug: function(fn)
1751 InjectedScriptHost.undebugFunction(fn);
1754 monitor: function(fn)
1756 InjectedScriptHost.monitorFunction(fn);
1759 unmonitor: function(fn)
1761 InjectedScriptHost.unmonitorFunction(fn);
1764 table: function(data, opt_columns)
1766 InjectedScriptHost.callFunction(inspectedWindow.console.table, inspectedWindow.console, slice(arguments));
1770 * @param {number} num
1772 _inspectedObject: function(num)
1774 return InjectedScriptHost.inspectedObject(num);
1778 * @param {!Array.<string>|string=} types
1779 * @return {!Array.<string>}
1781 _normalizeEventTypes: function(types)
1783 if (typeof types === "undefined")
1784 types = ["mouse", "key", "touch", "control", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation"];
1785 else if (typeof types === "string")
1789 for (var i = 0; i < types.length; ++i) {
1790 if (types[i] === "mouse")
1791 push(result, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout", "mousewheel");
1792 else if (types[i] === "key")
1793 push(result, "keydown", "keyup", "keypress", "textInput");
1794 else if (types[i] === "touch")
1795 push(result, "touchstart", "touchmove", "touchend", "touchcancel");
1796 else if (types[i] === "control")
1797 push(result, "resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset");
1799 push(result, types[i]);
1805 * @param {!Event} event
1807 _logEvent: function(event)
1809 inspectedWindow.console.log(event.type, event);
1813 injectedScript._commandLineAPIImpl = new CommandLineAPIImpl();
1814 return injectedScript;