Web Inspector: prefer non-blackboxed scripts when showing a source code location link
https://bugs.webkit.org/show_bug.cgi?id=204811

Reviewed by Timothy Hatcher.

* UserInterface/Models/StackTrace.js:
(WI.StackTrace.prototype.get firstNonNativeNonAnonymousNotBlackboxedCallFrame): Added.
(WI.StackTrace.prototype.get firstNonNativeCallFrame): Deleted.
(WI.StackTrace.prototype.get firstNonNativeNonAnonymousCallFrame): Deleted.
Include logic to skip call frames that are blackboxed, unless there are no non-blackboxed
call frames, in which case fall back to the first non-native non-anonymous call frame.
Drive-by: remove unused function.

* UserInterface/Views/ConsoleMessageView.js:
(WI.ConsoleMessageView.prototype.render):
(WI.ConsoleMessageView.prototype.clearSessionState): Added.
(WI.ConsoleMessageView.prototype._appendLocationLink):
(WI.ConsoleMessageView.prototype._handleDebuggerBlackboxChanged): Added.
(WI.ConsoleMessageView.prototype.clearSavedVariableState): Deleted.
* UserInterface/Views/LogContentView.js:
(WI.LogContentView.prototype._sessionStarted):
(WI.LogContentView.prototype._logCleared):
Listen for changes to the debugger blackbox to re-render the location link.

* UserInterface/Views/StackTraceView.js:
(WI.StackTraceView):
* UserInterface/Views/CallFrameView.js:
(WI.CallFrameView):
* UserInterface/Views/CallFrameView.css:
(.call-frame.blackboxed > .title, .call-frame.blackboxed:not(:hover, :focus) > .subtitle): Added.
Add a constructor option to control whether blackboxed frames are indicated visually.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@253087 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog
index 65a6a97..688d25f 100644
--- a/Source/WebInspectorUI/ChangeLog
+++ b/Source/WebInspectorUI/ChangeLog
@@ -1,5 +1,39 @@
 2019-12-03  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: prefer non-blackboxed scripts when showing a source code location link
+        https://bugs.webkit.org/show_bug.cgi?id=204811
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Models/StackTrace.js:
+        (WI.StackTrace.prototype.get firstNonNativeNonAnonymousNotBlackboxedCallFrame): Added.
+        (WI.StackTrace.prototype.get firstNonNativeCallFrame): Deleted.
+        (WI.StackTrace.prototype.get firstNonNativeNonAnonymousCallFrame): Deleted.
+        Include logic to skip call frames that are blackboxed, unless there are no non-blackboxed
+        call frames, in which case fall back to the first non-native non-anonymous call frame.
+        Drive-by: remove unused function.
+
+        * UserInterface/Views/ConsoleMessageView.js:
+        (WI.ConsoleMessageView.prototype.render):
+        (WI.ConsoleMessageView.prototype.clearSessionState): Added.
+        (WI.ConsoleMessageView.prototype._appendLocationLink):
+        (WI.ConsoleMessageView.prototype._handleDebuggerBlackboxChanged): Added.
+        (WI.ConsoleMessageView.prototype.clearSavedVariableState): Deleted.
+        * UserInterface/Views/LogContentView.js:
+        (WI.LogContentView.prototype._sessionStarted):
+        (WI.LogContentView.prototype._logCleared):
+        Listen for changes to the debugger blackbox to re-render the location link.
+
+        * UserInterface/Views/StackTraceView.js:
+        (WI.StackTraceView):
+        * UserInterface/Views/CallFrameView.js:
+        (WI.CallFrameView):
+        * UserInterface/Views/CallFrameView.css:
+        (.call-frame.blackboxed > .title, .call-frame.blackboxed:not(:hover, :focus) > .subtitle): Added.
+        Add a constructor option to control whether blackboxed frames are indicated visually.
+
+2019-12-03  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: Uncaught Exception: undefined is not an object (evaluating 'navigationItem.parentNavigationBar')
         https://bugs.webkit.org/show_bug.cgi?id=204830
 
diff --git a/Source/WebInspectorUI/UserInterface/Models/StackTrace.js b/Source/WebInspectorUI/UserInterface/Models/StackTrace.js
index 5b0f4fe..bb61f31 100644
--- a/Source/WebInspectorUI/UserInterface/Models/StackTrace.js
+++ b/Source/WebInspectorUI/UserInterface/Models/StackTrace.js
@@ -140,38 +140,35 @@
 
     // Public
 
-    get callFrames()
-    {
-        return this._callFrames;
-    }
+    get callFrames() { return this._callFrames; }
+    get topCallFrameIsBoundary() { return this._topCallFrameIsBoundary; }
+    get truncated() { return this._truncated; }
+    get parentStackTrace() { return this._parentStackTrace; }
 
-    get firstNonNativeCallFrame()
+    get firstNonNativeNonAnonymousNotBlackboxedCallFrame()
     {
-        for (let frame of this._callFrames) {
-            if (!frame.nativeCode)
-                return frame;
-        }
+        let firstNonNativeNonAnonymousCallFrame = null;
 
-        return null;
-    }
-
-    get firstNonNativeNonAnonymousCallFrame()
-    {
         for (let frame of this._callFrames) {
             if (frame.nativeCode)
                 continue;
+
             if (frame.sourceCodeLocation) {
                 let sourceCode = frame.sourceCodeLocation.sourceCode;
                 if (sourceCode instanceof WI.Script && sourceCode.anonymous)
                     continue;
+
+                // Save the first non-native non-anonymous call frame so it can be used as a
+                // fallback if all remaining call frames are blackboxed.
+                firstNonNativeNonAnonymousCallFrame = frame;
+
+                if (WI.debuggerManager.blackboxDataForSourceCode(sourceCode))
+                    continue;
             }
+
             return frame;
         }
 
-        return null;
+        return firstNonNativeNonAnonymousCallFrame;
     }
-
-    get topCallFrameIsBoundary() { return this._topCallFrameIsBoundary; }
-    get truncated() { return this._truncated; }
-    get parentStackTrace() { return this._parentStackTrace; }
 };
diff --git a/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css b/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css
index 35426ff..feb78ee 100644
--- a/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css
+++ b/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css
@@ -30,6 +30,11 @@
     cursor: pointer;
 }
 
+.call-frame.blackboxed > .title,
+.call-frame.blackboxed:not(:hover, :focus) > .subtitle {
+    opacity: 0.5;
+}
+
 .call-frame .icon {
     display: inline-block;
     vertical-align: top;
diff --git a/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js b/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js
index eda5cfc..dc9b90c 100644
--- a/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js
@@ -25,7 +25,7 @@
 
 WI.CallFrameView = class CallFrameView extends WI.Object
 {
-    constructor(callFrame, showFunctionName)
+    constructor(callFrame, {showFunctionName, indicateIfBlackboxed} = {})
     {
         console.assert(callFrame instanceof WI.CallFrame);
 
@@ -37,6 +37,9 @@
 
         var sourceCodeLocation = callFrame.sourceCodeLocation;
         if (sourceCodeLocation) {
+            if (indicateIfBlackboxed)
+                callFrameElement.classList.toggle("blackboxed", WI.debuggerManager.blackboxDataForSourceCode(callFrame.sourceCodeLocation.sourceCode));
+
             WI.linkifyElement(callFrameElement, sourceCodeLocation, {
                 ignoreNetworkTab: true,
                 ignoreSearchTab: true,
diff --git a/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js b/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js
index 9f71433..a338d3d 100644
--- a/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js
@@ -49,6 +49,7 @@
 
     render()
     {
+        console.assert(!this._element);
         this._element = document.createElement("div");
         this._element.classList.add("console-message");
         this._element.dir = "ltr";
@@ -105,6 +106,8 @@
             this._element.classList.add("console-image");
             this._element.addEventListener("contextmenu", this._handleContextMenu.bind(this));
         }
+
+        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BlackboxChanged, this._handleDebuggerBlackboxChanged, this);
     }
 
     get element()
@@ -243,7 +246,7 @@
         return clipboardString;
     }
 
-    clearSavedVariableState()
+    clearSessionState()
     {
         for (let node of this._messageBodyElement.querySelectorAll(".console-saved-variable"))
             node.remove();
@@ -253,6 +256,8 @@
 
         // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
         WI.settings.consoleSavedResultAlias.removeEventListener(null, null, this);
+
+        WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BlackboxChanged, this._handleDebuggerBlackboxChanged, this);
     }
 
     // Private
@@ -418,12 +423,11 @@
             return;
         }
 
-        var firstNonNativeNonAnonymousCallFrame = this._message.stackTrace.firstNonNativeNonAnonymousCallFrame;
-
         var callFrame;
-        if (firstNonNativeNonAnonymousCallFrame) {
+        let firstNonNativeNonAnonymousNotBlackboxedCallFrame = this._message.stackTrace.firstNonNativeNonAnonymousNotBlackboxedCallFrame;
+        if (firstNonNativeNonAnonymousNotBlackboxedCallFrame) {
             // JavaScript errors and console.* methods.
-            callFrame = firstNonNativeNonAnonymousCallFrame;
+            callFrame = firstNonNativeNonAnonymousNotBlackboxedCallFrame;
         } else if (this._message.url && !this._shouldHideURL(this._message.url)) {
             // CSS warnings have no stack traces.
             callFrame = WI.CallFrame.fromPayload(this._message.target, {
@@ -435,10 +439,15 @@
         }
 
         if (callFrame && (!callFrame.isConsoleEvaluation || (WI.isDebugUIEnabled() && WI.settings.debugShowConsoleEvaluations.value))) {
-            const showFunctionName = !!callFrame.functionName;
-            var locationElement = new WI.CallFrameView(callFrame, showFunctionName);
-            locationElement.classList.add("console-message-location");
-            this._element.appendChild(locationElement);
+            let existingCallFrameView = this._callFrameView;
+
+            this._callFrameView = new WI.CallFrameView(callFrame, {showFunctionName: !!callFrame.functionName});
+            this._callFrameView.classList.add("console-message-location");
+
+            if (existingCallFrameView)
+                this._element.replaceChild(this._callFrameView, existingCallFrameView);
+            else
+                this._element.appendChild(this._callFrameView);
             return;
         }
 
@@ -1038,4 +1047,10 @@
 
         contextMenu.appendSeparator();
     }
+
+    _handleDebuggerBlackboxChanged(event)
+    {
+        if (this._callFrameView)
+            this._appendLocationLink();
+    }
 };
diff --git a/Source/WebInspectorUI/UserInterface/Views/LogContentView.js b/Source/WebInspectorUI/UserInterface/Views/LogContentView.js
index 62858a4..aa99f8e 100644
--- a/Source/WebInspectorUI/UserInterface/Views/LogContentView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/LogContentView.js
@@ -398,7 +398,7 @@
 
         for (let messageElement of this._allMessageElements()) {
             if (messageElement.__messageView)
-                messageElement.__messageView.clearSavedVariableState();
+                messageElement.__messageView.clearSessionState();
         }
 
         const isFirstSession = false;
@@ -836,7 +836,7 @@
 
         for (let messageElement of this._allMessageElements()) {
             if (messageElement.__messageView)
-                messageElement.__messageView.clearSavedVariableState();
+                messageElement.__messageView.clearSessionState();
         }
 
         this._logViewController.clear();
diff --git a/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js b/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js
index b53f663..2e436de 100644
--- a/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js
+++ b/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js
@@ -38,7 +38,7 @@
             if (callFrame.isConsoleEvaluation && (!WI.isDebugUIEnabled() || !WI.settings.debugShowConsoleEvaluations.value))
                 continue;
 
-            var callFrameElement = new WI.CallFrameView(callFrame, true);
+            let callFrameElement = new WI.CallFrameView(callFrame, {showFunctionName: true, indicateIfBlackboxed: true});
             element.appendChild(callFrameElement);
         }
     }