Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(869)

Unified Diff: inspector/front-end/InjectedScript.js

Issue 542055: DevTools: injected script per context(WebCore part) (Closed) Base URL: http://svn.webkit.org/repository/webkit/trunk/WebCore/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « inspector/front-end/EventListenersSidebarPane.js ('k') | inspector/front-end/InjectedScriptAccess.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: inspector/front-end/InjectedScript.js
===================================================================
--- inspector/front-end/InjectedScript.js (revision 53180)
+++ inspector/front-end/InjectedScript.js (working copy)
@@ -26,8 +26,45 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+var injectedScriptConstructor = (function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
+
var InjectedScript = {};
+InjectedScript.lastBoundObjectId = 1;
+InjectedScript.idToWrappedObject = {};
+InjectedScript.objectGroups = {};
+InjectedScript.wrapObject = function(object, objectGroupName)
+{
+ var objectId;
+ if (typeof object === "object" || typeof object === "function" ||
+ (typeof object === "undefined" && object instanceof inspectedWindow.HTMLAllCollection)) { // FIXME(33716)
+ var id = InjectedScript.lastBoundObjectId++;
+ objectId = "object#" + id;
+ InjectedScript.idToWrappedObject[objectId] = object;
+
+ var group = InjectedScript.objectGroups[objectGroupName];
+ if (!group) {
+ group = [];
+ InjectedScript.objectGroups[objectGroupName] = group;
+ }
+ group.push(objectId);
+ }
+ return InjectedScript.createProxyObject(object, objectId);
+};
+
+InjectedScript.wrapAndStringifyObject = function(object, objectGroupName) {
+ var r = InjectedScript.wrapObject(object, objectGroupName);
+ return InjectedScript.JSON.stringify(r);
+};
+
+InjectedScript.unwrapObject = function(objectId) {
+ return InjectedScript.idToWrappedObject[objectId];
+};
+
+InjectedScript.releaseWrapperObjectGroup = function(objectGroupName) {
+ delete InjectedScript.objectGroups[objectGroupName];
+};
+
// Called from within InspectorController on the 'inspected page' side.
InjectedScript.reset = function()
{
@@ -51,7 +88,7 @@
InjectedScript._window().console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
result = null;
}
- return JSON.stringify(result);
+ return InjectedScript.JSON.stringify(result);
}
InjectedScript.getStyles = function(nodeId, authorOnly)
@@ -169,10 +206,9 @@
if (disabled) {
if (!style.__disabledPropertyValues || !style.__disabledPropertyPriorities) {
- var inspectedWindow = InjectedScript._window();
- style.__disabledProperties = new inspectedWindow.Object;
- style.__disabledPropertyValues = new inspectedWindow.Object;
- style.__disabledPropertyPriorities = new inspectedWindow.Object;
+ style.__disabledProperties = {};
+ style.__disabledPropertyValues = {};
+ style.__disabledPropertyPriorities = {};
}
style.__disabledPropertyValues[propertyName] = style.getPropertyValue(propertyName);
@@ -306,6 +342,7 @@
InjectedScript._styleRules[rule.id] = rule;
}
ruleValue.id = rule.id;
+ ruleValue.injectedScriptId = injectedScriptId;
}
return ruleValue;
}
@@ -344,6 +381,7 @@
InjectedScript._styles[style.id] = style;
}
result.id = style.id;
+ result.injectedScriptId = injectedScriptId;
}
return result;
}
@@ -445,7 +483,7 @@
InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate)
{
var object = InjectedScript._resolveObject(objectProxy);
- if (!object)
+ if (!InjectedScript._isDefined(object))
return false;
var properties = [];
@@ -479,7 +517,7 @@
InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression)
{
var object = InjectedScript._resolveObject(objectProxy);
- if (!object)
+ if (!InjectedScript._isDefined(object))
return false;
var expressionLength = expression.length;
@@ -583,7 +621,8 @@
{
var result = {};
try {
- result.value = InjectedScriptHost.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression), objectGroup);
+ result.value = InjectedScript.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression), objectGroup);
+
// Handle error that might have happened while describing result.
if (result.value.errorText) {
result.value = result.value.errorText;
@@ -880,7 +919,7 @@
result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
callFrame = callFrame.caller;
} while (callFrame);
- return result;
+ return InjectedScript.JSON.stringify(result);
}
InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup)
@@ -910,7 +949,6 @@
if (arguments.length === 0)
return;
- var inspectedWindow = InjectedScript._window();
inspectedWindow.console.log(o);
if (Object.type(o) === "node") {
InjectedScriptHost.pushNodePathToFrontend(o, false, true);
@@ -1009,9 +1047,9 @@
get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] }, \n\
};");
- inspectorCommandLineAPI.clear = InjectedScriptHost.wrapCallback(InjectedScript.clearConsoleMessages);
- inspectorCommandLineAPI.inspect = InjectedScriptHost.wrapCallback(InjectedScript._inspectObject);
- inspectorCommandLineAPI.copy = InjectedScriptHost.wrapCallback(InjectedScript._copy);
+ inspectorCommandLineAPI.clear = InjectedScript.clearConsoleMessages;
+ inspectorCommandLineAPI.inspect = InjectedScript._inspectObject;
+ inspectorCommandLineAPI.copy = InjectedScript._copy;
}
InjectedScript._resolveObject = function(objectProxy)
@@ -1021,11 +1059,11 @@
var protoDepth = objectProxy.protoDepth;
// Follow the property path.
- for (var i = 0; object && path && i < path.length; ++i)
+ for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length; ++i)
object = object[path[i]];
// Get to the necessary proto layer.
- for (var i = 0; object && protoDepth && i < protoDepth; ++i)
+ for (var i = 0; InjectedScript._isDefined(object) && protoDepth && i < protoDepth; ++i)
object = object.__proto__;
return object;
@@ -1035,7 +1073,7 @@
{
// TODO: replace with 'return window;' once this script is injected into
// the page's context.
- return InjectedScriptHost.inspectedWindow();
+ return inspectedWindow;
}
InjectedScript._nodeForId = function(nodeId)
@@ -1054,7 +1092,7 @@
if (typeof objectId === "number") {
return InjectedScript._nodeForId(objectId);
} else if (typeof objectId === "string") {
- return InjectedScriptHost.unwrapObject(objectId);
+ return InjectedScript.unwrapObject(objectId);
} else if (typeof objectId === "object") {
var callFrame = InjectedScript._callFrameForId(objectId.callFrame);
if (objectId.thisObject)
@@ -1084,6 +1122,7 @@
InjectedScript.createProxyObject = function(object, objectId, abbreviate)
{
var result = {};
+ result.injectedScriptId = injectedScriptId;
result.objectId = objectId;
result.type = Object.type(object);
@@ -1165,31 +1204,40 @@
data[columnIdentifier] = String(text);
}
}
- InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.stringify(result), false);
+ InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, InjectedScript.JSON.stringify(result), false);
}
function errorCallback(tx, error)
{
- InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.stringify(error), false);
+ InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, InjectedScript.JSON.stringify(error), false);
}
function queryTransaction(tx)
{
- tx.executeSql(query, null, InjectedScriptHost.wrapCallback(successCallback), InjectedScriptHost.wrapCallback(errorCallback));
+ tx.executeSql(query, null, successCallback, errorCallback);
}
var database = InjectedScriptHost.databaseForId(databaseId);
if (!database)
errorCallback(null, { code : 2 }); // Return as unexpected version.
- database.transaction(InjectedScriptHost.wrapCallback(queryTransaction), InjectedScriptHost.wrapCallback(errorCallback));
+ database.transaction(queryTransaction, errorCallback);
return true;
}
+InjectedScript._isDefined = function(object)
+{
+ return object || object instanceof inspectedWindow.HTMLAllCollection;
+}
+
Object.type = function(obj)
{
if (obj === null)
return "null";
+ // FIXME(33716): typeof document.all is always 'undefined'.
+ if (obj instanceof inspectedWindow.HTMLAllCollection)
+ return "array";
+
var type = typeof obj;
if (type !== "object" && type !== "function")
return type;
@@ -1293,3 +1341,297 @@
return result;
}
+
+InjectedScript.JSON = {};
+
+// The following code is a slightly modified version of http://www.json.org/json2.js last modified on 2009-09-29.
+// Compared to the original version it ignores toJSON method on objects it serializes.
+// It's done to avoid weird behaviour when inspected application provides it's own implementation
+// of toJSON methods to the Object and other intrinsic types. We use InjectedScript.JSON implementation
+// instead of global JSON object since it can have been modified by the inspected code.
+(function() {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+ InjectedScript.JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ InjectedScript.JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+}());
+
+return InjectedScript;
+});
« no previous file with comments | « inspector/front-end/EventListenersSidebarPane.js ('k') | inspector/front-end/InjectedScriptAccess.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698