Changeset 248485 in webkit


Ignore:
Timestamp:
Aug 9, 2019 3:12:12 PM (5 years ago)
Author:
Devin Rousso
Message:

REGRESSION (Safari 6): Web Inspector: JSON may not be pretty printed if served as text/html
https://bugs.webkit.org/show_bug.cgi?id=122898
<rdar://problem/15241419>

Reviewed by Joseph Pecoraro.

Check the request/response data to see if it's JSON parsable. If so, allow the user to elect
to view the request/response as a JSON preview instead of raw (or pretty printed) text.

Prefer the JSON view wherever possible.

  • UserInterface/Views/ResourceClusterContentView.js:

(WI.ResourceClusterContentView):
(WI.ResourceClusterContentView.prototype.get requestContentView):
(WI.ResourceClusterContentView.prototype.get customRequestContentView): Added.
(WI.ResourceClusterContentView.prototype.get customResponseContentView):
(WI.ResourceClusterContentView.prototype.get selectionPathComponents):
(WI.ResourceClusterContentView.prototype.showRequest):
(WI.ResourceClusterContentView.prototype._canShowCustomRequestContentView): Added.
(WI.ResourceClusterContentView.prototype._canShowCustomResponseContentView):
(WI.ResourceClusterContentView.prototype._contentViewForResourceType):
(WI.ResourceClusterContentView.prototype._pathComponentForContentView):
(WI.ResourceClusterContentView.prototype._identifierForContentView):
(WI.ResourceClusterContentView.prototype._showContentViewForIdentifier):
(WI.ResourceClusterContentView.prototype._canUseJSONContentViewForContent): Added.
(WI.ResourceClusterContentView.prototype._tryEnableCustomRequestContentView): Added.
(WI.ResourceClusterContentView.prototype._tryEnableCustomResponseContentView):
(WI.ResourceClusterContentView.prototype.saveToCookie): Deleted.
(WI.ResourceClusterContentView.prototype._customContentViewConstructorForResource): Deleted.
Since the current view is already saved in a WI.Setting, there's no need to save that
state to a cookie, as it'll be restored elsewhere.

  • UserInterface/Base/Main.js:

(WI.showResourceRequest):

  • UserInterface/Main.html:
  • UserInterface/Views/JSONContentView.js: Added.

(WI.JSONContentView):
(WI.JSONContentView.prototype.initialLayout):
(WI.JSONContentView.prototype.attached):
(WI.JSONContentView.prototype.closed):

  • UserInterface/Views/JSONContentView.css: Added.

(.content-view.json):

  • Source/WebInspectorUI/UserInterface/Views/JSONResourceContentView.js: Deleted.
  • Source/WebInspectorUI/UserInterface/Views/JSONResourceContentView.css: Deleted.

Create a more generic content view that shows a preview for the given JSON parsable string.

  • UserInterface/Base/Utilities.js:

(String.prototype.isJSON): Added.

  • UserInterface/Views/WebSocketDataGridNode.js:

(WI.WebSocketDataGridNode.prototype.appendContextMenuItems):
Utility function for checking if a string is JSON parsable.

  • Localizations/en.lproj/localizedStrings.js:
Location:
trunk/Source/WebInspectorUI
Files:
7 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r248480 r248485  
     12019-08-09  Devin Rousso  <drousso@apple.com>
     2
     3        REGRESSION (Safari 6): Web Inspector: JSON may not be pretty printed if served as text/html
     4        https://bugs.webkit.org/show_bug.cgi?id=122898
     5        <rdar://problem/15241419>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        Check the request/response data to see if it's JSON parsable. If so, allow the user to elect
     10        to view the request/response as a JSON preview instead of raw (or pretty printed) text.
     11
     12        Prefer the JSON view wherever possible.
     13
     14        * UserInterface/Views/ResourceClusterContentView.js:
     15        (WI.ResourceClusterContentView):
     16        (WI.ResourceClusterContentView.prototype.get requestContentView):
     17        (WI.ResourceClusterContentView.prototype.get customRequestContentView): Added.
     18        (WI.ResourceClusterContentView.prototype.get customResponseContentView):
     19        (WI.ResourceClusterContentView.prototype.get selectionPathComponents):
     20        (WI.ResourceClusterContentView.prototype.showRequest):
     21        (WI.ResourceClusterContentView.prototype._canShowCustomRequestContentView): Added.
     22        (WI.ResourceClusterContentView.prototype._canShowCustomResponseContentView):
     23        (WI.ResourceClusterContentView.prototype._contentViewForResourceType):
     24        (WI.ResourceClusterContentView.prototype._pathComponentForContentView):
     25        (WI.ResourceClusterContentView.prototype._identifierForContentView):
     26        (WI.ResourceClusterContentView.prototype._showContentViewForIdentifier):
     27        (WI.ResourceClusterContentView.prototype._canUseJSONContentViewForContent): Added.
     28        (WI.ResourceClusterContentView.prototype._tryEnableCustomRequestContentView): Added.
     29        (WI.ResourceClusterContentView.prototype._tryEnableCustomResponseContentView):
     30        (WI.ResourceClusterContentView.prototype.saveToCookie): Deleted.
     31        (WI.ResourceClusterContentView.prototype._customContentViewConstructorForResource): Deleted.
     32        Since the current view is already saved in a `WI.Setting`, there's no need to save that
     33        state to a cookie, as it'll be restored elsewhere.
     34
     35        * UserInterface/Base/Main.js:
     36        (WI.showResourceRequest):
     37
     38        * UserInterface/Main.html:
     39        * UserInterface/Views/JSONContentView.js: Added.
     40        (WI.JSONContentView):
     41        (WI.JSONContentView.prototype.initialLayout):
     42        (WI.JSONContentView.prototype.attached):
     43        (WI.JSONContentView.prototype.closed):
     44        * UserInterface/Views/JSONContentView.css: Added.
     45        (.content-view.json):
     46        * Source/WebInspectorUI/UserInterface/Views/JSONResourceContentView.js: Deleted.
     47        * Source/WebInspectorUI/UserInterface/Views/JSONResourceContentView.css: Deleted.
     48        Create a more generic content view that shows a preview for the given JSON parsable string.
     49
     50        * UserInterface/Base/Utilities.js:
     51        (String.prototype.isJSON): Added.
     52        * UserInterface/Views/WebSocketDataGridNode.js:
     53        (WI.WebSocketDataGridNode.prototype.appendContextMenuItems):
     54        Utility function for checking if a string is JSON parsable.
     55
     56        * Localizations/en.lproj/localizedStrings.js:
     57
    1582019-08-09  Devin Rousso  <drousso@apple.com>
    259
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r248287 r248485  
    306306localizedStrings["Current State"] = "Current State";
    307307localizedStrings["Custom"] = "Custom";
     308localizedStrings["Custom Request"] = "Custom Request";
     309localizedStrings["Custom Response"] = "Custom Response";
    308310localizedStrings["DNS"] = "DNS";
    309311localizedStrings["DOM"] = "DOM";
     
    616618localizedStrings["JP2"] = "JP2";
    617619localizedStrings["JPEG"] = "JPEG";
    618 localizedStrings["JSON"] = "JSON";
    619620localizedStrings["JavaScript"] = "JavaScript";
    620621localizedStrings["JavaScript & Events"] = "JavaScript & Events";
     
    870871localizedStrings["Request"] = "Request";
    871872localizedStrings["Request & Response"] = "Request & Response";
     873localizedStrings["Request (JSON)"] = "Request (JSON)";
    872874localizedStrings["Request Cookies"] = "Request Cookies";
    873875localizedStrings["Request Data"] = "Request Data";
     
    886888localizedStrings["Resources"] = "Resources";
    887889localizedStrings["Response"] = "Response";
     890localizedStrings["Response (JSON)"] = "Response (JSON)";
    888891localizedStrings["Response Cookies"] = "Response Cookies";
    889892localizedStrings["Response Headers"] = "Response Headers";
     
    11761179localizedStrings["URL Breakpoint\u2026"] = "URL Breakpoint\u2026";
    11771180localizedStrings["Unable to determine path to property from root"] = "Unable to determine path to property from root";
    1178 localizedStrings["Unable to parse as JSON: %s"] = "Unable to parse as JSON: %s";
    11791181localizedStrings["Unable to show certificate for \u201C%s\u201D"] = "Unable to show certificate for \u201C%s\u201D";
    11801182/* Break (pause) on uncaught (unhandled) exceptions */
  • trunk/Source/WebInspectorUI/UserInterface/Base/Main.js

    r248391 r248485  
    14061406WI.showResourceRequest = function(resource, options = {})
    14071407{
    1408     WI.showRepresentedObject(resource, {[WI.ResourceClusterContentView.ContentViewIdentifierCookieKey]: WI.ResourceClusterContentView.RequestIdentifier}, options);
     1408    WI.showRepresentedObject(resource, {[WI.ResourceClusterContentView.ContentViewIdentifierCookieKey]: WI.ResourceClusterContentView.CustomRequestIdentifier}, options);
    14091409};
    14101410
  • trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js

    r247033 r248485  
    735735});
    736736
     737Object.defineProperty(String.prototype, "isJSON",
     738{
     739    value(predicate)
     740    {
     741        try {
     742            let json = JSON.parse(this);
     743            return !predicate || predicate(json);
     744        } catch { }
     745        return false;
     746    }
     747});
     748
    737749Object.defineProperty(String.prototype, "truncateStart",
    738750{
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r248327 r248485  
    124124    <link rel="stylesheet" href="Views/InputPopover.css">
    125125    <link rel="stylesheet" href="Views/IssueTreeElement.css">
    126     <link rel="stylesheet" href="Views/JSONResourceContentView.css">
     126    <link rel="stylesheet" href="Views/JSONContentView.css">
    127127    <link rel="stylesheet" href="Views/LayerDetailsSidebarPanel.css">
    128128    <link rel="stylesheet" href="Views/LayerTreeDetailsSidebarPanel.css">
     
    707707    <script src="Views/InputPopover.js"></script>
    708708    <script src="Views/IssueTreeElement.js"></script>
    709     <script src="Views/JSONResourceContentView.js"></script>
     709    <script src="Views/JSONContentView.js"></script>
    710710    <script src="Views/LayerDetailsSidebarPanel.js"></script>
    711711    <script src="Views/LayerTreeDataGridNode.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Views/JSONContentView.css

    r248481 r248485  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 .content-view.resource.json {
     26.content-view.json {
    2727    padding: 10px;
    2828    overflow: scroll;
  • trunk/Source/WebInspectorUI/UserInterface/Views/JSONContentView.js

    r248481 r248485  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 WI.JSONResourceContentView = class JSONResourceContentView extends WI.ResourceContentView
     26WI.JSONContentView = class JSONContentView extends WI.ContentView
    2727{
    28     constructor(resource)
     28    constructor(json, representedObject)
    2929    {
    30         super(resource, "json");
     30        console.assert(typeof json === "string" && json.isJSON());
    3131
     32        super(representedObject);
     33
     34        this._json = json;
    3235        this._remoteObject = null;
    33     }
     36        this._spinnerTimeout = undefined;
    3437
    35     // Static
    36 
    37     static customContentViewDisplayName()
    38     {
    39         return WI.UIString("JSON");
     38        this.element.classList.add("json");
    4039    }
    4140
    4241    // Protected
    4342
    44     contentAvailable(content, base64Encoded)
     43    initialLayout()
    4544    {
    46         try {
    47             JSON.parse(content);
    48         } catch (e) {
    49             this.showMessage(WI.UIString("Unable to parse as JSON: %s").format(e.message));
    50             return;
    51         }
     45        super.initialLayout();
    5246
    5347        const options = {
    54             expression: "(" + content + ")",
    55             includeCommandLineAPI: false,
     48            expression: "(" + this._json + ")",
    5649            doNotPauseOnExceptionsAndMuteConsole: true,
    57             contextId: undefined,
    58             returnByValue: false,
    5950            generatePreview: true,
    6051        };
    61         this.resource.target.RuntimeAgent.evaluate.invoke(options, (error, result, wasThrown) => {
    62             if (error || wasThrown) {
    63                 this.showMessage(WI.UIString("Unable to parse as JSON: %s").format(result.description));
    64                 return;
    65             }
     52        RuntimeAgent.evaluate.invoke(options, (error, result, wasThrown) => {
     53            console.assert(!error);
     54            console.assert(!wasThrown);
    6655
    67             this.removeLoadingIndicator();
    68 
    69             this._remoteObject = WI.RemoteObject.fromPayload(result, this.resource.target);
     56            this._remoteObject = WI.RemoteObject.fromPayload(result);
    7057
    7158            let objectTree = new WI.ObjectTreeView(this._remoteObject);
     
    7360            objectTree.expand();
    7461
     62            if (this._spinnerTimeout) {
     63                clearTimeout(this._spinnerTimeout);
     64                this._spinnerTimeout = undefined;
     65            }
     66
     67            this.element.removeChildren();
    7568            this.element.appendChild(objectTree.element);
    76         }, this.resource.target);
     69        });
     70    }
     71
     72    attached()
     73    {
     74        super.attached();
     75
     76        if (this._spinnerTimeout || this._remoteObject)
     77            return;
     78
     79        this._spinnerTimeout = setTimeout(() => {
     80            console.assert(this._spinnerTimeout);
     81
     82            let spinner = new WI.IndeterminateProgressSpinner;
     83            this.element.appendChild(spinner.element);
     84
     85            this._spinnerTimeout = undefined;
     86        }, 100);
    7787    }
    7888
    7989    closed()
    8090    {
     91        super.closed();
     92
    8193        if (this._remoteObject) {
    8294            this._remoteObject.release();
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js

    r248274 r248485  
    3636        function createPathComponent(displayName, className, identifier)
    3737        {
    38             let pathComponent = new WI.HierarchicalPathComponent(displayName, className, identifier, false, true);
     38            const textOnly = false;
     39            const showSelectorArrows = true;
     40            let pathComponent = new WI.HierarchicalPathComponent(displayName, className, identifier, textOnly, showSelectorArrows);
    3941            pathComponent.addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._pathComponentSelected, this);
    4042            pathComponent.comparisonData = resource;
     
    4446        this._requestContentView = null;
    4547        this._responseContentView = null;
     48        this._customRequestContentView = null;
     49        this._customRequestContentViewInitializer = null;
    4650        this._customResponseContentView = null;
    47         this._customResponseContentViewConstructor = null;
     51        this._customResponseContentViewInitializer = null;
    4852
    4953        this._requestPathComponent = createPathComponent.call(this, WI.UIString("Request"), WI.ResourceClusterContentView.RequestIconStyleClassName, WI.ResourceClusterContentView.RequestIdentifier);
     54        this._customRequestPathComponent = createPathComponent.call(this, WI.UIString("Custom Request"), WI.ResourceClusterContentView.RequestIconStyleClassName, WI.ResourceClusterContentView.CustomRequestIdentifier);
    5055        this._responsePathComponent = createPathComponent.call(this, WI.UIString("Response"), WI.ResourceClusterContentView.ResponseIconStyleClassName, WI.ResourceClusterContentView.ResponseIdentifier);
    51         this._customResponsePathComponent = createPathComponent.call(this, WI.UIString("Custom"), WI.ResourceClusterContentView.ResponseIconStyleClassName, WI.ResourceClusterContentView.CustomResponseIdentifier);
     56        this._customResponsePathComponent = createPathComponent.call(this, WI.UIString("Custom Response"), WI.ResourceClusterContentView.ResponseIconStyleClassName, WI.ResourceClusterContentView.CustomResponseIdentifier);
    5257
    5358        if (this._canShowRequestContentView()) {
    5459            this._requestPathComponent.nextSibling = this._responsePathComponent;
    5560            this._responsePathComponent.previousSibling = this._requestPathComponent;
     61
     62            this._tryEnableCustomRequestContentView();
    5663        }
    5764
     
    6067        // always want to prefer the JSON view to the normal Response text view.
    6168
    62         this._currentContentViewSetting = new WI.Setting("resource-current-view-" + this._resource.url.hash, WI.ResourceClusterContentView.ResponseIdentifier);
     69        this._currentContentViewSetting = new WI.Setting("resource-current-view-" + this._resource.url.hash, WI.ResourceClusterContentView.CustomResponseIdentifier);
    6370
    6471        this._tryEnableCustomResponseContentView();
     
    6774    // Public
    6875
    69     get resource()
    70     {
    71         return this._resource;
     76    get resource() { return this._resource; }
     77
     78    get requestContentView()
     79    {
     80        if (!this._canShowRequestContentView())
     81            return null;
     82
     83        if (this._requestContentView)
     84            return this._requestContentView;
     85
     86        this._requestContentView = new WI.TextContentView(this._resource.requestData || "", this._resource.requestDataContentType);
     87
     88        return this._requestContentView;
    7289    }
    7390
     
    95112    }
    96113
    97     get requestContentView()
    98     {
    99         if (!this._canShowRequestContentView())
    100             return null;
    101 
    102         if (this._requestContentView)
    103             return this._requestContentView;
    104 
    105         this._requestContentView = new WI.TextContentView(this._resource.requestData || "", this._resource.requestDataContentType);
    106 
    107         return this._requestContentView;
     114    get customRequestContentView()
     115    {
     116        if (!this._customRequestContentView && this._customRequestContentViewInitializer) {
     117            this._customRequestContentView = this._customRequestContentViewInitializer();
     118            this._customRequestContentViewInitializer = null;
     119        }
     120        return this._customRequestContentView;
    108121    }
    109122
    110123    get customResponseContentView()
    111124    {
    112         if (!this._canShowCustomResponseContentView())
    113             return null;
    114 
    115         if (!this._customResponseContentView)
    116             this._customResponseContentView = new this._customResponseContentViewConstructor(this._resource);
    117 
     125        if (!this._customResponseContentView && this._customResponseContentViewInitializer) {
     126            this._customResponseContentView = this._customResponseContentViewInitializer();
     127            this._customResponseContentViewInitializer = null;
     128        }
    118129        return this._customResponseContentView;
    119130    }
     
    125136            return [];
    126137
    127         if (!this._canShowRequestContentView() && !this._canShowCustomResponseContentView())
     138        if (!this._canShowRequestContentView() && !this._canShowCustomRequestContentView() && !this._canShowCustomResponseContentView())
    128139            return currentContentView.selectionPathComponents;
    129140
     
    150161    }
    151162
    152     saveToCookie(cookie)
    153     {
    154         cookie[WI.ResourceClusterContentView.ContentViewIdentifierCookieKey] = this._currentContentViewSetting.value;
    155     }
    156 
    157163    restoreFromCookie(cookie)
    158164    {
     
    166172        this._shownInitialContent = true;
    167173
    168         return this._showContentViewForIdentifier(WI.ResourceClusterContentView.RequestIdentifier);
     174        return this._showContentViewForIdentifier(WI.ResourceClusterContentView.CustomRequestIdentifier);
    169175    }
    170176
     
    199205    }
    200206
     207    _canShowCustomRequestContentView()
     208    {
     209        return !!(this._customRequestContentView || this._customRequestContentViewInitializer);
     210    }
     211
    201212    _canShowCustomResponseContentView()
    202213    {
    203         return !!this._customResponseContentViewConstructor;
     214        return !!(this._customResponseContentView || this._customResponseContentViewInitializer);
    204215    }
    205216
     
    213224
    214225        case WI.Resource.Type.Image:
    215             if (this._resource.mimeTypeComponents.type === "image/svg+xml")
     226            if (WI.fileExtensionForMIMEType(this._resource.mimeType) === "svg")
    216227                return new WI.SVGImageResourceClusterContentView(this._resource);
    217228            return new WI.ImageResourceContentView(this._resource);
     
    237248        if (contentView === this._responseContentView)
    238249            return this._responsePathComponent;
     250        if (contentView === this._customRequestContentView)
     251            return this._customRequestPathComponent;
    239252        if (contentView === this._customResponseContentView)
    240253            return this._customResponsePathComponent;
     
    252265        if (contentView === this._responseContentView)
    253266            return WI.ResourceClusterContentView.ResponseIdentifier;
     267        if (contentView === this._customRequestContentView)
     268            return WI.ResourceClusterContentView.CustomRequestIdentifier;
    254269        if (contentView === this._customResponseContentView)
    255270            return WI.ResourceClusterContentView.CustomResponseIdentifier;
     
    262277        let contentViewToShow = null;
    263278
     279        // This is expected to fall through all the way to the `default`.
    264280        switch (identifier) {
     281        case WI.ResourceClusterContentView.CustomRequestIdentifier:
     282            contentViewToShow = this.customRequestContentView;
     283            if (contentViewToShow)
     284                break;
     285            // fallthrough
    265286        case WI.ResourceClusterContentView.RequestIdentifier:
    266287            contentViewToShow = this.requestContentView;
    267             break;
     288            if (contentViewToShow)
     289                break;
     290            // fallthrough
     291        case WI.ResourceClusterContentView.CustomResponseIdentifier:
     292            contentViewToShow = this.customResponseContentView;
     293            if (contentViewToShow)
     294                break;
     295            // fallthrough
    268296        case WI.ResourceClusterContentView.ResponseIdentifier:
     297        default:
    269298            contentViewToShow = this.responseContentView;
    270299            break;
    271         case WI.ResourceClusterContentView.CustomResponseIdentifier:
    272             contentViewToShow = this.customResponseContentView;
    273             break;
    274         }
    275 
    276         if (!contentViewToShow)
    277             contentViewToShow = this.responseContentView;
     300        }
    278301
    279302        console.assert(contentViewToShow);
     
    318341    }
    319342
     343    _canUseJSONContentViewForContent(content)
     344    {
     345        return content.isJSON((json) => json && (typeof json === "object" || Array.isArray(json)));
     346    }
     347
     348    _tryEnableCustomRequestContentView()
     349    {
     350        if (!this._canUseJSONContentViewForContent(this._resource.requestData))
     351            return;
     352
     353        this._customRequestContentViewInitializer = () => new WI.JSONContentView(this._resource.requestData, this._resource);
     354
     355        this._customRequestPathComponent.displayName = WI.UIString("Request (JSON)");
     356        this._customRequestPathComponent.previousSibling = this._requestPathComponent;
     357        this._customRequestPathComponent.nextSibling = this._responsePathComponent;
     358        this._requestPathComponent.nextSibling = this._customRequestPathComponent;
     359        this._responsePathComponent.previousSibling = this._customRequestPathComponent;
     360    }
     361
    320362    _tryEnableCustomResponseContentView()
    321363    {
     
    323365            return;
    324366
    325         this._customResponseContentViewConstructor = this._customContentViewConstructorForResource(this._resource);
    326         if (!this._customResponseContentViewConstructor)
    327             return;
    328 
    329         console.assert(this._customResponseContentViewConstructor.customContentViewDisplayName, "Custom Response ContentViews should have a static customContentViewDisplayName method.", this._customResponseContentViewConstructor);
    330 
    331         this._responsePathComponent.nextSibling = this._customResponsePathComponent;
    332         this._customResponsePathComponent.previousSibling = this._responsePathComponent;
    333         this._customResponsePathComponent.displayName = this._customResponseContentViewConstructor.customContentViewDisplayName();
    334 
    335         this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
    336     }
    337 
    338     _customContentViewConstructorForResource(resource)
    339     {
    340         let mimeType = this._resource.mimeType;
    341         let fileExtension = WI.fileExtensionForMIMEType(mimeType);
    342         if (fileExtension === "json")
    343             return WI.JSONResourceContentView;
    344 
    345         return null;
     367        this._resource.requestContent()
     368        .then(({error, content}) => {
     369            if (error || !content || !this._canUseJSONContentViewForContent(content))
     370                return;
     371
     372            this._customResponseContentViewInitializer = () => new WI.JSONContentView(content, this._resource);
     373
     374            this._customResponsePathComponent.displayName = WI.UIString("Response (JSON)");
     375            this._customResponsePathComponent.previousSibling = this._responsePathComponent;
     376            this._responsePathComponent.nextSibling = this._customResponsePathComponent;
     377
     378            this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
     379        });
    346380    }
    347381};
     
    353387WI.ResourceClusterContentView.RequestIdentifier = "request";
    354388WI.ResourceClusterContentView.ResponseIdentifier = "response";
     389WI.ResourceClusterContentView.CustomRequestIdentifier = "custom-request";
    355390WI.ResourceClusterContentView.CustomResponseIdentifier = "custom-response";
  • trunk/Source/WebInspectorUI/UserInterface/Views/WebSocketDataGridNode.js

    r224433 r248485  
    6767            });
    6868
    69             try {
    70                 // The result of this is unnecessary, as we just need the string to evaluate.
    71                 // We still need to execute this, however, in order to try-catch if it fails.
    72                 JSON.parse(this._data.data);
    73 
     69            if (this._data.data.isJSON()) {
    7470                contextMenu.appendItem(WI.UIString("Log Frame Value"), () => {
    7571                    const options = {
     
    8379                    WI.runtimeManager.evaluateInInspectedWindow(expression, options, logResult);
    8480                });
    85             } catch { }
     81            }
    8682
    8783            contextMenu.appendSeparator();
Note: See TracChangeset for help on using the changeset viewer.