Index: Source/core/inspector/InjectedScriptSource.js |
diff --git a/Source/core/inspector/InjectedScriptSource.js b/Source/core/inspector/InjectedScriptSource.js |
index bd29c2eea54dace8b183befd52118f76b7281e46..55aba7b57e4d2e098b7909a5527f62cad00a569f 100644 |
--- a/Source/core/inspector/InjectedScriptSource.js |
+++ b/Source/core/inspector/InjectedScriptSource.js |
@@ -371,13 +371,14 @@ InjectedScript.prototype = { |
* @param {?Array.<string>=} columnNames |
* @param {boolean=} isTable |
* @param {boolean=} doNotBind |
+ * @param {*=} customObjectConfig |
* @return {!RuntimeAgent.RemoteObject} |
* @suppress {checkTypes} |
*/ |
- _wrapObject: function(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable, doNotBind) |
+ _wrapObject: function(object, objectGroupName, forceValueType, generatePreview, columnNames, isTable, doNotBind, customObjectConfig) |
{ |
try { |
- return new InjectedScript.RemoteObject(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, undefined); |
+ return new InjectedScript.RemoteObject(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, undefined, customObjectConfig); |
} catch (e) { |
try { |
var description = injectedScript._describe(e); |
@@ -729,12 +730,13 @@ InjectedScript.prototype = { |
* @param {boolean=} generatePreview |
* @param {?Array.<string>=} columnNames |
* @param {boolean=} isTable |
+ * @param {*=} customObjectConfig |
* @return {!RuntimeAgent.RemoteObject} |
* @this {InjectedScript} |
*/ |
- function wrap(object, forceValueType, generatePreview, columnNames, isTable) |
+ function wrap(object, forceValueType, generatePreview, columnNames, isTable, customObjectConfig) |
{ |
- return this._wrapObject(object, objectGroup, forceValueType, generatePreview, columnNames, isTable); |
+ return this._wrapObject(object, objectGroup, forceValueType, generatePreview, columnNames, isTable, false, customObjectConfig); |
} |
try { |
@@ -764,16 +766,33 @@ InjectedScript.prototype = { |
* @param {*} jsonMLObject |
* @throws {string} error message |
*/ |
- _checkObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject) |
+ _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject) |
{ |
- if (!isArrayLike(jsonMLObject)) |
- return; |
+ var maxCustomPreviewRecursionDepth = 20; |
+ this._customPreviewRecursionDepth = (this._customPreviewRecursionDepth || 0) + 1 |
+ try { |
+ if (this._customPreviewRecursionDepth >= maxCustomPreviewRecursionDepth) |
+ throw new Error("Too deep hierarchy of inlined custom previews"); |
+ |
+ if (!isArrayLike(jsonMLObject)) |
+ return; |
- if (jsonMLObject[0] === "object") |
- throw "Illegal format: object tag is forbidden in header"; |
+ if (jsonMLObject[0] === "object") { |
+ var attributes = jsonMLObject[1]; |
+ var originObject = attributes["object"]; |
+ var config = attributes["config"]; |
+ if (typeof originObject === "undefined") |
+ throw new Error("Illegal format: obligatory attribute \"object\" isn't specified"); |
- for (var i = 0; i < jsonMLObject.length; ++i) |
- this._checkObjectTagsInCustomPreview(objectGroupName, jsonMLObject[i]); |
+ jsonMLObject[1] = this._wrapObject(originObject, objectGroupName, false, false, null, false, false, config); |
+ return; |
+ } |
+ |
+ for (var i = 0; i < jsonMLObject.length; ++i) |
+ this._substituteObjectTagsInCustomPreview(objectGroupName, jsonMLObject[i]); |
+ } finally { |
+ this._customPreviewRecursionDepth--; |
+ } |
}, |
/** |
@@ -1233,8 +1252,9 @@ var injectedScript = new InjectedScript(); |
* @param {?Array.<string>=} columnNames |
* @param {boolean=} isTable |
* @param {boolean=} skipEntriesPreview |
+ * @param {*=} customObjectConfig |
*/ |
-InjectedScript.RemoteObject = function(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, skipEntriesPreview) |
+InjectedScript.RemoteObject = function(object, objectGroupName, doNotBind, forceValueType, generatePreview, columnNames, isTable, skipEntriesPreview, customObjectConfig) |
{ |
this.type = typeof object; |
if (this.type === "undefined" && injectedScript._isHTMLAllCollection(object)) |
@@ -1282,7 +1302,7 @@ InjectedScript.RemoteObject = function(object, objectGroupName, doNotBind, force |
this.preview = this._generatePreview(object, undefined, columnNames, isTable, skipEntriesPreview); |
if (injectedScript._customObjectFormatterEnabled) { |
- var customPreview = this._customPreview(object, objectGroupName); |
+ var customPreview = this._customPreview(object, objectGroupName, customObjectConfig); |
if (customPreview) |
this.customPreview = customPreview; |
} |
@@ -1293,10 +1313,19 @@ InjectedScript.RemoteObject.prototype = { |
/** |
* @param {*} object |
* @param {string=} objectGroupName |
+ * @param {*=} customObjectConfig |
* @return {?RuntimeAgent.CustomPreview} |
*/ |
- _customPreview: function(object, objectGroupName) |
+ _customPreview: function(object, objectGroupName, customObjectConfig) |
{ |
+ /** |
+ * @param {!Error} error |
+ */ |
+ function logError(error) |
+ { |
+ Promise.resolve().then(inspectedWindow.console.error.bind(inspectedWindow.console, "Custom Formatter Failed: " + error.message)); |
+ } |
+ |
try { |
var formatters = inspectedWindow["devtoolsFormatters"]; |
if (!formatters || !isArrayLike(formatters)) |
@@ -1304,20 +1333,21 @@ InjectedScript.RemoteObject.prototype = { |
for (var i = 0; i < formatters.length; ++i) { |
try { |
- var formatted = formatters[i].header(object); |
+ var formatted = formatters[i].header(object, customObjectConfig); |
if (!formatted) |
continue; |
- var hasBody = formatters[i].hasBody(object); |
- injectedScript._checkObjectTagsInCustomPreview(objectGroupName, formatted); |
+ var hasBody = formatters[i].hasBody(object, customObjectConfig); |
+ injectedScript._substituteObjectTagsInCustomPreview(objectGroupName, formatted); |
+ var customObjectId = customObjectConfig ? injectedScript._bind(customObjectConfig, objectGroupName) : undefined; |
var formatterObjectId = injectedScript._bind(formatters[i], objectGroupName); |
- return {header: JSON.stringify(formatted), hasBody: !!hasBody, formatterObjectId: formatterObjectId}; |
+ return {header: JSON.stringify(formatted), hasBody: !!hasBody, formatterObjectId: formatterObjectId, configObjectId: customObjectId}; |
} catch (e) { |
- inspectedWindow.console.error("Custom Formatter Failed: " + e); |
+ logError(e); |
} |
} |
} catch (e) { |
- inspectedWindow.console.error("Custom Formatter Failed: " + e); |
+ logError(e); |
} |
return null; |
}, |