OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
14 * its contributors may be used to endorse or promote products derived | 14 * its contributors may be used to endorse or promote products derived |
15 * from this software without specific prior written permission. | 15 * from this software without specific prior written permission. |
16 * | 16 * |
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | 28 |
| 29 var injectedScriptConstructor = (function (InjectedScriptHost, inspectedWindow,
injectedScriptId) { |
| 30 |
29 var InjectedScript = {}; | 31 var InjectedScript = {}; |
30 | 32 |
| 33 InjectedScript.lastBoundObjectId = 1; |
| 34 InjectedScript.idToWrappedObject = {}; |
| 35 InjectedScript.objectGroups = {}; |
| 36 InjectedScript.wrapObject = function(object, objectGroupName) |
| 37 { |
| 38 var objectId; |
| 39 if (typeof object === "object" || typeof object === "function" || |
| 40 (typeof object === "undefined" && object instanceof inspectedWindow.HTML
AllCollection)) { // FIXME(33716) |
| 41 var id = InjectedScript.lastBoundObjectId++; |
| 42 objectId = "object#" + id; |
| 43 InjectedScript.idToWrappedObject[objectId] = object; |
| 44 |
| 45 var group = InjectedScript.objectGroups[objectGroupName]; |
| 46 if (!group) { |
| 47 group = []; |
| 48 InjectedScript.objectGroups[objectGroupName] = group; |
| 49 } |
| 50 group.push(objectId); |
| 51 } |
| 52 return InjectedScript.createProxyObject(object, objectId); |
| 53 }; |
| 54 |
| 55 InjectedScript.wrapAndStringifyObject = function(object, objectGroupName) { |
| 56 var r = InjectedScript.wrapObject(object, objectGroupName); |
| 57 return InjectedScript.JSON.stringify(r); |
| 58 }; |
| 59 |
| 60 InjectedScript.unwrapObject = function(objectId) { |
| 61 return InjectedScript.idToWrappedObject[objectId]; |
| 62 }; |
| 63 |
| 64 InjectedScript.releaseWrapperObjectGroup = function(objectGroupName) { |
| 65 delete InjectedScript.objectGroups[objectGroupName]; |
| 66 }; |
| 67 |
31 // Called from within InspectorController on the 'inspected page' side. | 68 // Called from within InspectorController on the 'inspected page' side. |
32 InjectedScript.reset = function() | 69 InjectedScript.reset = function() |
33 { | 70 { |
34 InjectedScript._styles = {}; | 71 InjectedScript._styles = {}; |
35 InjectedScript._styleRules = {}; | 72 InjectedScript._styleRules = {}; |
36 InjectedScript._lastStyleId = 0; | 73 InjectedScript._lastStyleId = 0; |
37 InjectedScript._lastStyleRuleId = 0; | 74 InjectedScript._lastStyleRuleId = 0; |
38 InjectedScript._searchResults = []; | 75 InjectedScript._searchResults = []; |
39 InjectedScript._includedInSearchResultsPropertyName = "__includedInInspector
SearchResults"; | 76 InjectedScript._includedInSearchResultsPropertyName = "__includedInInspector
SearchResults"; |
40 } | 77 } |
41 | 78 |
42 InjectedScript.reset(); | 79 InjectedScript.reset(); |
43 | 80 |
44 InjectedScript.dispatch = function(methodName, args, callId) | 81 InjectedScript.dispatch = function(methodName, args, callId) |
45 { | 82 { |
46 var argsArray = JSON.parse(args); | 83 var argsArray = JSON.parse(args); |
47 if (callId) | 84 if (callId) |
48 argsArray.splice(0, 0, callId); // Methods that run asynchronously have
a call back id parameter. | 85 argsArray.splice(0, 0, callId); // Methods that run asynchronously have
a call back id parameter. |
49 var result = InjectedScript[methodName].apply(InjectedScript, argsArray); | 86 var result = InjectedScript[methodName].apply(InjectedScript, argsArray); |
50 if (typeof result === "undefined") { | 87 if (typeof result === "undefined") { |
51 InjectedScript._window().console.error("Web Inspector error: InjectedScr
ipt.%s returns undefined", methodName); | 88 InjectedScript._window().console.error("Web Inspector error: InjectedScr
ipt.%s returns undefined", methodName); |
52 result = null; | 89 result = null; |
53 } | 90 } |
54 return JSON.stringify(result); | 91 return InjectedScript.JSON.stringify(result); |
55 } | 92 } |
56 | 93 |
57 InjectedScript.getStyles = function(nodeId, authorOnly) | 94 InjectedScript.getStyles = function(nodeId, authorOnly) |
58 { | 95 { |
59 var node = InjectedScript._nodeForId(nodeId); | 96 var node = InjectedScript._nodeForId(nodeId); |
60 if (!node) | 97 if (!node) |
61 return false; | 98 return false; |
62 var defaultView = node.ownerDocument.defaultView; | 99 var defaultView = node.ownerDocument.defaultView; |
63 var matchedRules = defaultView.getMatchedCSSRules(node, "", authorOnly); | 100 var matchedRules = defaultView.getMatchedCSSRules(node, "", authorOnly); |
64 var matchedCSSRules = []; | 101 var matchedCSSRules = []; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 } | 199 } |
163 | 200 |
164 InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled) | 201 InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled) |
165 { | 202 { |
166 var style = InjectedScript._styles[styleId]; | 203 var style = InjectedScript._styles[styleId]; |
167 if (!style) | 204 if (!style) |
168 return false; | 205 return false; |
169 | 206 |
170 if (disabled) { | 207 if (disabled) { |
171 if (!style.__disabledPropertyValues || !style.__disabledPropertyPrioriti
es) { | 208 if (!style.__disabledPropertyValues || !style.__disabledPropertyPrioriti
es) { |
172 var inspectedWindow = InjectedScript._window(); | 209 style.__disabledProperties = {}; |
173 style.__disabledProperties = new inspectedWindow.Object; | 210 style.__disabledPropertyValues = {}; |
174 style.__disabledPropertyValues = new inspectedWindow.Object; | 211 style.__disabledPropertyPriorities = {}; |
175 style.__disabledPropertyPriorities = new inspectedWindow.Object; | |
176 } | 212 } |
177 | 213 |
178 style.__disabledPropertyValues[propertyName] = style.getPropertyValue(pr
opertyName); | 214 style.__disabledPropertyValues[propertyName] = style.getPropertyValue(pr
opertyName); |
179 style.__disabledPropertyPriorities[propertyName] = style.getPropertyPrio
rity(propertyName); | 215 style.__disabledPropertyPriorities[propertyName] = style.getPropertyPrio
rity(propertyName); |
180 | 216 |
181 if (style.getPropertyShorthand(propertyName)) { | 217 if (style.getPropertyShorthand(propertyName)) { |
182 var longhandProperties = InjectedScript._getLonghandProperties(style
, propertyName); | 218 var longhandProperties = InjectedScript._getLonghandProperties(style
, propertyName); |
183 for (var i = 0; i < longhandProperties.length; ++i) { | 219 for (var i = 0; i < longhandProperties.length; ++i) { |
184 style.__disabledProperties[longhandProperties[i]] = true; | 220 style.__disabledProperties[longhandProperties[i]] = true; |
185 style.removeProperty(longhandProperties[i]); | 221 style.removeProperty(longhandProperties[i]); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 // Bind editable scripts only. | 335 // Bind editable scripts only. |
300 var doBind = !ruleValue.isUserAgent && !ruleValue.isUser; | 336 var doBind = !ruleValue.isUserAgent && !ruleValue.isUser; |
301 ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind); | 337 ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind); |
302 | 338 |
303 if (doBind) { | 339 if (doBind) { |
304 if (!rule.id) { | 340 if (!rule.id) { |
305 rule.id = InjectedScript._lastStyleRuleId++; | 341 rule.id = InjectedScript._lastStyleRuleId++; |
306 InjectedScript._styleRules[rule.id] = rule; | 342 InjectedScript._styleRules[rule.id] = rule; |
307 } | 343 } |
308 ruleValue.id = rule.id; | 344 ruleValue.id = rule.id; |
| 345 ruleValue.injectedScriptId = injectedScriptId; |
309 } | 346 } |
310 return ruleValue; | 347 return ruleValue; |
311 } | 348 } |
312 | 349 |
313 InjectedScript._serializeStyle = function(style, doBind) | 350 InjectedScript._serializeStyle = function(style, doBind) |
314 { | 351 { |
315 var result = {}; | 352 var result = {}; |
316 result.width = style.width; | 353 result.width = style.width; |
317 result.height = style.height; | 354 result.height = style.height; |
318 result.__disabledProperties = style.__disabledProperties; | 355 result.__disabledProperties = style.__disabledProperties; |
(...skipping 18 matching lines...) Expand all Loading... |
337 result.properties.push(property); | 374 result.properties.push(property); |
338 } | 375 } |
339 result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(styl
e); | 376 result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(styl
e); |
340 | 377 |
341 if (doBind) { | 378 if (doBind) { |
342 if (!style.id) { | 379 if (!style.id) { |
343 style.id = InjectedScript._lastStyleId++; | 380 style.id = InjectedScript._lastStyleId++; |
344 InjectedScript._styles[style.id] = style; | 381 InjectedScript._styles[style.id] = style; |
345 } | 382 } |
346 result.id = style.id; | 383 result.id = style.id; |
| 384 result.injectedScriptId = injectedScriptId; |
347 } | 385 } |
348 return result; | 386 return result; |
349 } | 387 } |
350 | 388 |
351 InjectedScript._getUniqueStyleProperties = function(style) | 389 InjectedScript._getUniqueStyleProperties = function(style) |
352 { | 390 { |
353 var properties = []; | 391 var properties = []; |
354 var foundProperties = {}; | 392 var foundProperties = {}; |
355 | 393 |
356 for (var i = 0; i < style.length; ++i) { | 394 for (var i = 0; i < style.length; ++i) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 title = title.replace(/Prototype$/, ""); | 476 title = title.replace(/Prototype$/, ""); |
439 } | 477 } |
440 result.push(title); | 478 result.push(title); |
441 } | 479 } |
442 return result; | 480 return result; |
443 } | 481 } |
444 | 482 |
445 InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty, abbre
viate) | 483 InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty, abbre
viate) |
446 { | 484 { |
447 var object = InjectedScript._resolveObject(objectProxy); | 485 var object = InjectedScript._resolveObject(objectProxy); |
448 if (!object) | 486 if (!InjectedScript._isDefined(object)) |
449 return false; | 487 return false; |
450 | 488 |
451 var properties = []; | 489 var properties = []; |
452 | 490 |
453 // Go over properties, prepare results. | 491 // Go over properties, prepare results. |
454 for (var propertyName in object) { | 492 for (var propertyName in object) { |
455 if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOw
nProperty(propertyName)) | 493 if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOw
nProperty(propertyName)) |
456 continue; | 494 continue; |
457 | 495 |
458 var property = {}; | 496 var property = {}; |
(...skipping 13 matching lines...) Expand all Loading... |
472 property.isGetter = true; | 510 property.isGetter = true; |
473 } | 511 } |
474 properties.push(property); | 512 properties.push(property); |
475 } | 513 } |
476 return properties; | 514 return properties; |
477 } | 515 } |
478 | 516 |
479 InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression
) | 517 InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression
) |
480 { | 518 { |
481 var object = InjectedScript._resolveObject(objectProxy); | 519 var object = InjectedScript._resolveObject(objectProxy); |
482 if (!object) | 520 if (!InjectedScript._isDefined(object)) |
483 return false; | 521 return false; |
484 | 522 |
485 var expressionLength = expression.length; | 523 var expressionLength = expression.length; |
486 if (!expressionLength) { | 524 if (!expressionLength) { |
487 delete object[propertyName]; | 525 delete object[propertyName]; |
488 return !(propertyName in object); | 526 return !(propertyName in object); |
489 } | 527 } |
490 | 528 |
491 try { | 529 try { |
492 // Surround the expression in parenthesis so the result of the eval is t
he result | 530 // Surround the expression in parenthesis so the result of the eval is t
he result |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 | 614 |
577 InjectedScript.evaluate = function(expression, objectGroup) | 615 InjectedScript.evaluate = function(expression, objectGroup) |
578 { | 616 { |
579 return InjectedScript._evaluateAndWrap(InjectedScript._window().eval, Inject
edScript._window(), expression, objectGroup); | 617 return InjectedScript._evaluateAndWrap(InjectedScript._window().eval, Inject
edScript._window(), expression, objectGroup); |
580 } | 618 } |
581 | 619 |
582 InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, obj
ectGroup) | 620 InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, obj
ectGroup) |
583 { | 621 { |
584 var result = {}; | 622 var result = {}; |
585 try { | 623 try { |
586 result.value = InjectedScriptHost.wrapObject(InjectedScript._evaluateOn(
evalFunction, object, expression), objectGroup); | 624 result.value = InjectedScript.wrapObject(InjectedScript._evaluateOn(eval
Function, object, expression), objectGroup); |
| 625 |
587 // Handle error that might have happened while describing result. | 626 // Handle error that might have happened while describing result. |
588 if (result.value.errorText) { | 627 if (result.value.errorText) { |
589 result.value = result.value.errorText; | 628 result.value = result.value.errorText; |
590 result.isException = true; | 629 result.isException = true; |
591 } | 630 } |
592 } catch (e) { | 631 } catch (e) { |
593 result.value = e.toString(); | 632 result.value = e.toString(); |
594 result.isException = true; | 633 result.isException = true; |
595 } | 634 } |
596 return result; | 635 return result; |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 var callFrame = InjectedScriptHost.currentCallFrame(); | 912 var callFrame = InjectedScriptHost.currentCallFrame(); |
874 if (!callFrame) | 913 if (!callFrame) |
875 return false; | 914 return false; |
876 | 915 |
877 var result = []; | 916 var result = []; |
878 var depth = 0; | 917 var depth = 0; |
879 do { | 918 do { |
880 result.push(new InjectedScript.CallFrameProxy(depth++, callFrame)); | 919 result.push(new InjectedScript.CallFrameProxy(depth++, callFrame)); |
881 callFrame = callFrame.caller; | 920 callFrame = callFrame.caller; |
882 } while (callFrame); | 921 } while (callFrame); |
883 return result; | 922 return InjectedScript.JSON.stringify(result); |
884 } | 923 } |
885 | 924 |
886 InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup) | 925 InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup) |
887 { | 926 { |
888 var callFrame = InjectedScript._callFrameForId(callFrameId); | 927 var callFrame = InjectedScript._callFrameForId(callFrameId); |
889 if (!callFrame) | 928 if (!callFrame) |
890 return false; | 929 return false; |
891 return InjectedScript._evaluateAndWrap(callFrame.evaluate, callFrame, code,
objectGroup); | 930 return InjectedScript._evaluateAndWrap(callFrame.evaluate, callFrame, code,
objectGroup); |
892 } | 931 } |
893 | 932 |
894 InjectedScript._callFrameForId = function(id) | 933 InjectedScript._callFrameForId = function(id) |
895 { | 934 { |
896 var callFrame = InjectedScriptHost.currentCallFrame(); | 935 var callFrame = InjectedScriptHost.currentCallFrame(); |
897 while (--id >= 0 && callFrame) | 936 while (--id >= 0 && callFrame) |
898 callFrame = callFrame.caller; | 937 callFrame = callFrame.caller; |
899 return callFrame; | 938 return callFrame; |
900 } | 939 } |
901 | 940 |
902 InjectedScript.clearConsoleMessages = function() | 941 InjectedScript.clearConsoleMessages = function() |
903 { | 942 { |
904 InjectedScriptHost.clearConsoleMessages(); | 943 InjectedScriptHost.clearConsoleMessages(); |
905 return true; | 944 return true; |
906 } | 945 } |
907 | 946 |
908 InjectedScript._inspectObject = function(o) | 947 InjectedScript._inspectObject = function(o) |
909 { | 948 { |
910 if (arguments.length === 0) | 949 if (arguments.length === 0) |
911 return; | 950 return; |
912 | 951 |
913 var inspectedWindow = InjectedScript._window(); | |
914 inspectedWindow.console.log(o); | 952 inspectedWindow.console.log(o); |
915 if (Object.type(o) === "node") { | 953 if (Object.type(o) === "node") { |
916 InjectedScriptHost.pushNodePathToFrontend(o, false, true); | 954 InjectedScriptHost.pushNodePathToFrontend(o, false, true); |
917 } else { | 955 } else { |
918 switch (Object.describe(o)) { | 956 switch (Object.describe(o)) { |
919 case "Database": | 957 case "Database": |
920 InjectedScriptHost.selectDatabase(o); | 958 InjectedScriptHost.selectDatabase(o); |
921 break; | 959 break; |
922 case "Storage": | 960 case "Storage": |
923 InjectedScriptHost.selectDOMStorage(o); | 961 InjectedScriptHost.selectDOMStorage(o); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 } \n\ | 1040 } \n\ |
1003 }, \n\ | 1041 }, \n\ |
1004 _inspectedNodes: [], \n\ | 1042 _inspectedNodes: [], \n\ |
1005 get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] },
\n\ | 1043 get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] },
\n\ |
1006 get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] },
\n\ | 1044 get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] },
\n\ |
1007 get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] },
\n\ | 1045 get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] },
\n\ |
1008 get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] },
\n\ | 1046 get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] },
\n\ |
1009 get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] },
\n\ | 1047 get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] },
\n\ |
1010 };"); | 1048 };"); |
1011 | 1049 |
1012 inspectorCommandLineAPI.clear = InjectedScriptHost.wrapCallback(InjectedScri
pt.clearConsoleMessages); | 1050 inspectorCommandLineAPI.clear = InjectedScript.clearConsoleMessages; |
1013 inspectorCommandLineAPI.inspect = InjectedScriptHost.wrapCallback(InjectedSc
ript._inspectObject); | 1051 inspectorCommandLineAPI.inspect = InjectedScript._inspectObject; |
1014 inspectorCommandLineAPI.copy = InjectedScriptHost.wrapCallback(InjectedScrip
t._copy); | 1052 inspectorCommandLineAPI.copy = InjectedScript._copy; |
1015 } | 1053 } |
1016 | 1054 |
1017 InjectedScript._resolveObject = function(objectProxy) | 1055 InjectedScript._resolveObject = function(objectProxy) |
1018 { | 1056 { |
1019 var object = InjectedScript._objectForId(objectProxy.objectId); | 1057 var object = InjectedScript._objectForId(objectProxy.objectId); |
1020 var path = objectProxy.path; | 1058 var path = objectProxy.path; |
1021 var protoDepth = objectProxy.protoDepth; | 1059 var protoDepth = objectProxy.protoDepth; |
1022 | 1060 |
1023 // Follow the property path. | 1061 // Follow the property path. |
1024 for (var i = 0; object && path && i < path.length; ++i) | 1062 for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length
; ++i) |
1025 object = object[path[i]]; | 1063 object = object[path[i]]; |
1026 | 1064 |
1027 // Get to the necessary proto layer. | 1065 // Get to the necessary proto layer. |
1028 for (var i = 0; object && protoDepth && i < protoDepth; ++i) | 1066 for (var i = 0; InjectedScript._isDefined(object) && protoDepth && i < proto
Depth; ++i) |
1029 object = object.__proto__; | 1067 object = object.__proto__; |
1030 | 1068 |
1031 return object; | 1069 return object; |
1032 } | 1070 } |
1033 | 1071 |
1034 InjectedScript._window = function() | 1072 InjectedScript._window = function() |
1035 { | 1073 { |
1036 // TODO: replace with 'return window;' once this script is injected into | 1074 // TODO: replace with 'return window;' once this script is injected into |
1037 // the page's context. | 1075 // the page's context. |
1038 return InjectedScriptHost.inspectedWindow(); | 1076 return inspectedWindow; |
1039 } | 1077 } |
1040 | 1078 |
1041 InjectedScript._nodeForId = function(nodeId) | 1079 InjectedScript._nodeForId = function(nodeId) |
1042 { | 1080 { |
1043 if (!nodeId) | 1081 if (!nodeId) |
1044 return null; | 1082 return null; |
1045 return InjectedScriptHost.nodeForId(nodeId); | 1083 return InjectedScriptHost.nodeForId(nodeId); |
1046 } | 1084 } |
1047 | 1085 |
1048 InjectedScript._objectForId = function(objectId) | 1086 InjectedScript._objectForId = function(objectId) |
1049 { | 1087 { |
1050 // There are three types of object ids used: | 1088 // There are three types of object ids used: |
1051 // - numbers point to DOM Node via the InspectorDOMAgent mapping | 1089 // - numbers point to DOM Node via the InspectorDOMAgent mapping |
1052 // - strings point to console objects cached in InspectorController for lazy
evaluation upon them | 1090 // - strings point to console objects cached in InspectorController for lazy
evaluation upon them |
1053 // - objects contain complex ids and are currently used for scoped objects | 1091 // - objects contain complex ids and are currently used for scoped objects |
1054 if (typeof objectId === "number") { | 1092 if (typeof objectId === "number") { |
1055 return InjectedScript._nodeForId(objectId); | 1093 return InjectedScript._nodeForId(objectId); |
1056 } else if (typeof objectId === "string") { | 1094 } else if (typeof objectId === "string") { |
1057 return InjectedScriptHost.unwrapObject(objectId); | 1095 return InjectedScript.unwrapObject(objectId); |
1058 } else if (typeof objectId === "object") { | 1096 } else if (typeof objectId === "object") { |
1059 var callFrame = InjectedScript._callFrameForId(objectId.callFrame); | 1097 var callFrame = InjectedScript._callFrameForId(objectId.callFrame); |
1060 if (objectId.thisObject) | 1098 if (objectId.thisObject) |
1061 return callFrame.thisObject; | 1099 return callFrame.thisObject; |
1062 else | 1100 else |
1063 return callFrame.scopeChain[objectId.chainIndex]; | 1101 return callFrame.scopeChain[objectId.chainIndex]; |
1064 } | 1102 } |
1065 return objectId; | 1103 return objectId; |
1066 } | 1104 } |
1067 | 1105 |
1068 InjectedScript.pushNodeToFrontend = function(objectProxy) | 1106 InjectedScript.pushNodeToFrontend = function(objectProxy) |
1069 { | 1107 { |
1070 var object = InjectedScript._resolveObject(objectProxy); | 1108 var object = InjectedScript._resolveObject(objectProxy); |
1071 if (!object || Object.type(object) !== "node") | 1109 if (!object || Object.type(object) !== "node") |
1072 return false; | 1110 return false; |
1073 return InjectedScriptHost.pushNodePathToFrontend(object, false, false); | 1111 return InjectedScriptHost.pushNodePathToFrontend(object, false, false); |
1074 } | 1112 } |
1075 | 1113 |
1076 InjectedScript.nodeByPath = function(path) | 1114 InjectedScript.nodeByPath = function(path) |
1077 { | 1115 { |
1078 // We make this call through the injected script only to get a nice | 1116 // We make this call through the injected script only to get a nice |
1079 // callback for it. | 1117 // callback for it. |
1080 return InjectedScriptHost.pushNodeByPathToFrontend(path.join(",")); | 1118 return InjectedScriptHost.pushNodeByPathToFrontend(path.join(",")); |
1081 } | 1119 } |
1082 | 1120 |
1083 // Called from within InspectorController on the 'inspected page' side. | 1121 // Called from within InspectorController on the 'inspected page' side. |
1084 InjectedScript.createProxyObject = function(object, objectId, abbreviate) | 1122 InjectedScript.createProxyObject = function(object, objectId, abbreviate) |
1085 { | 1123 { |
1086 var result = {}; | 1124 var result = {}; |
| 1125 result.injectedScriptId = injectedScriptId; |
1087 result.objectId = objectId; | 1126 result.objectId = objectId; |
1088 result.type = Object.type(object); | 1127 result.type = Object.type(object); |
1089 | 1128 |
1090 var type = typeof object; | 1129 var type = typeof object; |
1091 if ((type === "object" && object !== null) || type === "function") { | 1130 if ((type === "object" && object !== null) || type === "function") { |
1092 for (var subPropertyName in object) { | 1131 for (var subPropertyName in object) { |
1093 result.hasChildren = true; | 1132 result.hasChildren = true; |
1094 break; | 1133 break; |
1095 } | 1134 } |
1096 } | 1135 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 result.push(data); | 1197 result.push(data); |
1159 var row = rows.item(i); | 1198 var row = rows.item(i); |
1160 for (var columnIdentifier in row) { | 1199 for (var columnIdentifier in row) { |
1161 // FIXME: (Bug 19439) We should specially format SQL NULL here | 1200 // FIXME: (Bug 19439) We should specially format SQL NULL here |
1162 // (which is represented by JavaScript null here, and turned | 1201 // (which is represented by JavaScript null here, and turned |
1163 // into the string "null" by the String() function). | 1202 // into the string "null" by the String() function). |
1164 var text = row[columnIdentifier]; | 1203 var text = row[columnIdentifier]; |
1165 data[columnIdentifier] = String(text); | 1204 data[columnIdentifier] = String(text); |
1166 } | 1205 } |
1167 } | 1206 } |
1168 InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.string
ify(result), false); | 1207 InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, InjectedScr
ipt.JSON.stringify(result), false); |
1169 } | 1208 } |
1170 | 1209 |
1171 function errorCallback(tx, error) | 1210 function errorCallback(tx, error) |
1172 { | 1211 { |
1173 InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.string
ify(error), false); | 1212 InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, InjectedScr
ipt.JSON.stringify(error), false); |
1174 } | 1213 } |
1175 | 1214 |
1176 function queryTransaction(tx) | 1215 function queryTransaction(tx) |
1177 { | 1216 { |
1178 tx.executeSql(query, null, InjectedScriptHost.wrapCallback(successCallba
ck), InjectedScriptHost.wrapCallback(errorCallback)); | 1217 tx.executeSql(query, null, successCallback, errorCallback); |
1179 } | 1218 } |
1180 | 1219 |
1181 var database = InjectedScriptHost.databaseForId(databaseId); | 1220 var database = InjectedScriptHost.databaseForId(databaseId); |
1182 if (!database) | 1221 if (!database) |
1183 errorCallback(null, { code : 2 }); // Return as unexpected version. | 1222 errorCallback(null, { code : 2 }); // Return as unexpected version. |
1184 database.transaction(InjectedScriptHost.wrapCallback(queryTransaction), Inje
ctedScriptHost.wrapCallback(errorCallback)); | 1223 database.transaction(queryTransaction, errorCallback); |
1185 return true; | 1224 return true; |
1186 } | 1225 } |
1187 | 1226 |
| 1227 InjectedScript._isDefined = function(object) |
| 1228 { |
| 1229 return object || object instanceof inspectedWindow.HTMLAllCollection; |
| 1230 } |
| 1231 |
1188 Object.type = function(obj) | 1232 Object.type = function(obj) |
1189 { | 1233 { |
1190 if (obj === null) | 1234 if (obj === null) |
1191 return "null"; | 1235 return "null"; |
1192 | 1236 |
| 1237 // FIXME(33716): typeof document.all is always 'undefined'. |
| 1238 if (obj instanceof inspectedWindow.HTMLAllCollection) |
| 1239 return "array"; |
| 1240 |
1193 var type = typeof obj; | 1241 var type = typeof obj; |
1194 if (type !== "object" && type !== "function") | 1242 if (type !== "object" && type !== "function") |
1195 return type; | 1243 return type; |
1196 | 1244 |
1197 var win = InjectedScript._window(); | 1245 var win = InjectedScript._window(); |
1198 | 1246 |
1199 if (obj instanceof win.Node) | 1247 if (obj instanceof win.Node) |
1200 return (obj.nodeType === undefined ? type : "node"); | 1248 return (obj.nodeType === undefined ? type : "node"); |
1201 if (obj instanceof win.String) | 1249 if (obj instanceof win.String) |
1202 return "string"; | 1250 return "string"; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 | 1334 |
1287 var result = ""; | 1335 var result = ""; |
1288 for (var i = 0; i < this.length; ++i) { | 1336 for (var i = 0; i < this.length; ++i) { |
1289 if (chars.indexOf(this.charAt(i)) !== -1) | 1337 if (chars.indexOf(this.charAt(i)) !== -1) |
1290 result += "\\"; | 1338 result += "\\"; |
1291 result += this.charAt(i); | 1339 result += this.charAt(i); |
1292 } | 1340 } |
1293 | 1341 |
1294 return result; | 1342 return result; |
1295 } | 1343 } |
| 1344 |
| 1345 InjectedScript.JSON = {}; |
| 1346 |
| 1347 // The following code is a slightly modified version of http://www.json.org/json
2.js last modified on 2009-09-29. |
| 1348 // Compared to the original version it ignores toJSON method on objects it seria
lizes. |
| 1349 // It's done to avoid weird behaviour when inspected application provides it's o
wn implementation |
| 1350 // of toJSON methods to the Object and other intrinsic types. We use InjectedScr
ipt.JSON implementation |
| 1351 // instead of global JSON object since it can have been modified by the inspecte
d code. |
| 1352 (function() { |
| 1353 |
| 1354 function f(n) { |
| 1355 // Format integers to have at least two digits. |
| 1356 return n < 10 ? '0' + n : n; |
| 1357 } |
| 1358 |
| 1359 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u
202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
| 1360 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b
5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
| 1361 gap, |
| 1362 indent, |
| 1363 meta = { // table of character substitutions |
| 1364 '\b': '\\b', |
| 1365 '\t': '\\t', |
| 1366 '\n': '\\n', |
| 1367 '\f': '\\f', |
| 1368 '\r': '\\r', |
| 1369 '"' : '\\"', |
| 1370 '\\': '\\\\' |
| 1371 }, |
| 1372 rep; |
| 1373 |
| 1374 |
| 1375 function quote(string) { |
| 1376 |
| 1377 // If the string contains no control characters, no quote characters, and no |
| 1378 // backslash characters, then we can safely slap some quotes around it. |
| 1379 // Otherwise we must also replace the offending characters with safe escape |
| 1380 // sequences. |
| 1381 |
| 1382 escapable.lastIndex = 0; |
| 1383 return escapable.test(string) ? |
| 1384 '"' + string.replace(escapable, function (a) { |
| 1385 var c = meta[a]; |
| 1386 return typeof c === 'string' ? c : |
| 1387 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
| 1388 }) + '"' : |
| 1389 '"' + string + '"'; |
| 1390 } |
| 1391 |
| 1392 |
| 1393 function str(key, holder) { |
| 1394 |
| 1395 // Produce a string from holder[key]. |
| 1396 |
| 1397 var i, // The loop counter. |
| 1398 k, // The member key. |
| 1399 v, // The member value. |
| 1400 length, |
| 1401 mind = gap, |
| 1402 partial, |
| 1403 value = holder[key]; |
| 1404 |
| 1405 // If we were called with a replacer function, then call the replacer to |
| 1406 // obtain a replacement value. |
| 1407 |
| 1408 if (typeof rep === 'function') { |
| 1409 value = rep.call(holder, key, value); |
| 1410 } |
| 1411 |
| 1412 // What happens next depends on the value's type. |
| 1413 |
| 1414 switch (typeof value) { |
| 1415 case 'string': |
| 1416 return quote(value); |
| 1417 |
| 1418 case 'number': |
| 1419 |
| 1420 // JSON numbers must be finite. Encode non-finite numbers as null. |
| 1421 |
| 1422 return isFinite(value) ? String(value) : 'null'; |
| 1423 |
| 1424 case 'boolean': |
| 1425 case 'null': |
| 1426 |
| 1427 // If the value is a boolean or null, convert it to a string. Note: |
| 1428 // typeof null does not produce 'null'. The case is included here in |
| 1429 // the remote chance that this gets fixed someday. |
| 1430 |
| 1431 return String(value); |
| 1432 |
| 1433 // If the type is 'object', we might be dealing with an object or an array or |
| 1434 // null. |
| 1435 |
| 1436 case 'object': |
| 1437 |
| 1438 // Due to a specification blunder in ECMAScript, typeof null is 'object', |
| 1439 // so watch out for that case. |
| 1440 |
| 1441 if (!value) { |
| 1442 return 'null'; |
| 1443 } |
| 1444 |
| 1445 // Make an array to hold the partial results of stringifying this object value. |
| 1446 |
| 1447 gap += indent; |
| 1448 partial = []; |
| 1449 |
| 1450 // Is the value an array? |
| 1451 |
| 1452 if (Object.prototype.toString.apply(value) === '[object Array]') { |
| 1453 |
| 1454 // The value is an array. Stringify every element. Use null as a placeholder |
| 1455 // for non-JSON values. |
| 1456 |
| 1457 length = value.length; |
| 1458 for (i = 0; i < length; i += 1) { |
| 1459 partial[i] = str(i, value) || 'null'; |
| 1460 } |
| 1461 |
| 1462 // Join all of the elements together, separated with commas, and wrap them in |
| 1463 // brackets. |
| 1464 |
| 1465 v = partial.length === 0 ? '[]' : |
| 1466 gap ? '[\n' + gap + |
| 1467 partial.join(',\n' + gap) + '\n' + |
| 1468 mind + ']' : |
| 1469 '[' + partial.join(',') + ']'; |
| 1470 gap = mind; |
| 1471 return v; |
| 1472 } |
| 1473 |
| 1474 // If the replacer is an array, use it to select the members to be stringified. |
| 1475 |
| 1476 if (rep && typeof rep === 'object') { |
| 1477 length = rep.length; |
| 1478 for (i = 0; i < length; i += 1) { |
| 1479 k = rep[i]; |
| 1480 if (typeof k === 'string') { |
| 1481 v = str(k, value); |
| 1482 if (v) { |
| 1483 partial.push(quote(k) + (gap ? ': ' : ':') + v); |
| 1484 } |
| 1485 } |
| 1486 } |
| 1487 } else { |
| 1488 |
| 1489 // Otherwise, iterate through all of the keys in the object. |
| 1490 |
| 1491 for (k in value) { |
| 1492 if (Object.hasOwnProperty.call(value, k)) { |
| 1493 v = str(k, value); |
| 1494 if (v) { |
| 1495 partial.push(quote(k) + (gap ? ': ' : ':') + v); |
| 1496 } |
| 1497 } |
| 1498 } |
| 1499 } |
| 1500 |
| 1501 // Join all of the member texts together, separated with commas, |
| 1502 // and wrap them in braces. |
| 1503 |
| 1504 v = partial.length === 0 ? '{}' : |
| 1505 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + |
| 1506 mind + '}' : '{' + partial.join(',') + '}'; |
| 1507 gap = mind; |
| 1508 return v; |
| 1509 } |
| 1510 } |
| 1511 |
| 1512 InjectedScript.JSON.stringify = function (value, replacer, space) { |
| 1513 |
| 1514 // The stringify method takes a value and an optional replacer, and an optional |
| 1515 // space parameter, and returns a JSON text. The replacer can be a function |
| 1516 // that can replace values, or an array of strings that will select the keys. |
| 1517 // A default replacer method can be provided. Use of the space parameter can |
| 1518 // produce text that is more easily readable. |
| 1519 |
| 1520 var i; |
| 1521 gap = ''; |
| 1522 indent = ''; |
| 1523 |
| 1524 // If the space parameter is a number, make an indent string containing that |
| 1525 // many spaces. |
| 1526 |
| 1527 if (typeof space === 'number') { |
| 1528 for (i = 0; i < space; i += 1) { |
| 1529 indent += ' '; |
| 1530 } |
| 1531 |
| 1532 // If the space parameter is a string, it will be used as the indent string. |
| 1533 |
| 1534 } else if (typeof space === 'string') { |
| 1535 indent = space; |
| 1536 } |
| 1537 |
| 1538 // If there is a replacer, it must be a function or an array. |
| 1539 // Otherwise, throw an error. |
| 1540 |
| 1541 rep = replacer; |
| 1542 if (replacer && typeof replacer !== 'function' && |
| 1543 (typeof replacer !== 'object' || |
| 1544 typeof replacer.length !== 'number')) { |
| 1545 throw new Error('JSON.stringify'); |
| 1546 } |
| 1547 |
| 1548 // Make a fake root object containing our value under the key of ''. |
| 1549 // Return the result of stringifying the value. |
| 1550 |
| 1551 return str('', {'': value}); |
| 1552 }; |
| 1553 |
| 1554 |
| 1555 // If the JSON object does not yet have a parse method, give it one. |
| 1556 |
| 1557 InjectedScript.JSON.parse = function (text, reviver) { |
| 1558 |
| 1559 // The parse method takes a text and an optional reviver function, and returns |
| 1560 // a JavaScript value if the text is a valid JSON text. |
| 1561 |
| 1562 var j; |
| 1563 |
| 1564 function walk(holder, key) { |
| 1565 |
| 1566 // The walk method is used to recursively walk the resulting structure so |
| 1567 // that modifications can be made. |
| 1568 |
| 1569 var k, v, value = holder[key]; |
| 1570 if (value && typeof value === 'object') { |
| 1571 for (k in value) { |
| 1572 if (Object.hasOwnProperty.call(value, k)) { |
| 1573 v = walk(value, k); |
| 1574 if (v !== undefined) { |
| 1575 value[k] = v; |
| 1576 } else { |
| 1577 delete value[k]; |
| 1578 } |
| 1579 } |
| 1580 } |
| 1581 } |
| 1582 return reviver.call(holder, key, value); |
| 1583 } |
| 1584 |
| 1585 |
| 1586 // Parsing happens in four stages. In the first stage, we replace certain |
| 1587 // Unicode characters with escape sequences. JavaScript handles many characters |
| 1588 // incorrectly, either silently deleting them, or treating them as line endings. |
| 1589 |
| 1590 cx.lastIndex = 0; |
| 1591 if (cx.test(text)) { |
| 1592 text = text.replace(cx, function (a) { |
| 1593 return '\\u' + |
| 1594 ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
| 1595 }); |
| 1596 } |
| 1597 |
| 1598 // In the second stage, we run the text against regular expressions that look |
| 1599 // for non-JSON patterns. We are especially concerned with '()' and 'new' |
| 1600 // because they can cause invocation, and '=' because it can cause mutation. |
| 1601 // But just to be safe, we want to reject all unexpected forms. |
| 1602 |
| 1603 // We split the second stage into 4 regexp operations in order to work around |
| 1604 // crippling inefficiencies in IE's and Safari's regexp engines. First we |
| 1605 // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we |
| 1606 // replace all simple value tokens with ']' characters. Third, we delete all |
| 1607 // open brackets that follow a colon or comma or that begin the text. Finally, |
| 1608 // we look to see that the remaining characters are only whitespace or ']' or |
| 1609 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. |
| 1610 |
| 1611 if (/^[\],:{}\s]*$/. |
| 1612 test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). |
| 1613 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
. |
| 1614 replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
| 1615 |
| 1616 // In the third stage we use the eval function to compile the text into a |
| 1617 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity |
| 1618 // in JavaScript: it can begin a block or an object literal. We wrap the text |
| 1619 // in parens to eliminate the ambiguity. |
| 1620 |
| 1621 j = eval('(' + text + ')'); |
| 1622 |
| 1623 // In the optional fourth stage, we recursively walk the new structure, passing |
| 1624 // each name/value pair to a reviver function for possible transformation. |
| 1625 |
| 1626 return typeof reviver === 'function' ? |
| 1627 walk({'': j}, '') : j; |
| 1628 } |
| 1629 |
| 1630 // If the text is not JSON parseable, then a SyntaxError is thrown. |
| 1631 |
| 1632 throw new SyntaxError('JSON.parse'); |
| 1633 }; |
| 1634 }()); |
| 1635 |
| 1636 return InjectedScript; |
| 1637 }); |
OLD | NEW |