Title: [251039] trunk
Revision
251039
Author
[email protected]
Date
2019-10-11 20:57:43 -0700 (Fri, 11 Oct 2019)

Log Message

Web Inspector: Debugger: support pattern blackboxing
https://bugs.webkit.org/show_bug.cgi?id=198855

Reviewed by Timothy Hatcher.

Source/_javascript_Core:

Allow scripts to be blackboxed based on URL patterns (in addition to individual URLs) which
can be extremely useful when trying to step through unminified library/framework code.

* inspector/agents/InspectorDebuggerAgent.h:
* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::enable):
(Inspector::InspectorDebuggerAgent::setShouldBlackboxURL):
(Inspector::InspectorDebuggerAgent::shouldBlackboxURL const): Added.
(Inspector::InspectorDebuggerAgent::didParseSource):

* inspector/protocol/Debugger.json:
Add `caseSensitive` and `isRegex` optional boolean parameters to `setShouldBlackboxURL`.

Source/WebInspectorUI:

Allow scripts to be blackboxed based on URL patterns (in addition to individual URLs) which
can be extremely useful when trying to step through unminified library/framework code.

* UserInterface/Controllers/DebuggerManager.js:
(WI.DebuggerManager):
(WI.DebuggerManager.prototype.initializeTarget):
(WI.DebuggerManager.prototype.blackboxTypeForSourceCode): Added.
(WI.DebuggerManager.prototype.get blackboxPatterns): Added.
(WI.DebuggerManager.prototype.setShouldBlackboxScript):
(WI.DebuggerManager.prototype.setShouldBlackboxPattern): Added.
(WI.DebuggerManager.prototype.isScriptBlackboxed): Deleted.
Provide a separate path for setting URL pattern blackboxes, rather than an exact/given URL.

* UserInterface/Views/SettingsTabContentView.js:
(WI.SettingsTabContentView):
(WI.SettingsTabContentView.prototype.selectBlackboxPattern): Added.
(WI.SettingsTabContentView.prototype.initialLayout):
(WI.SettingsTabContentView.prototype._createSourcesSettingsView):
* UserInterface/Views/BlackboxSettingsView.js: Added.
(WI.BlackboxSettingsView):
(WI.BlackboxSettingsView.prototype.selectBlackboxPattern):
(WI.BlackboxSettingsView.prototype.initialLayout):
(WI.BlackboxSettingsView.prototype._addRow):
* UserInterface/Views/BlackboxSettingsView.css: Added.
(.settings-view.blackbox > :matches(p, table)):
(.settings-view.blackbox > p):
(.settings-view.blackbox > * + p):
(.settings-view.blackbox > p:last-child):
(.settings-view.blackbox > p > .toggle-script-blackbox):
(.settings-view.blackbox > table):
(.settings-view.blackbox > table > thead th):
(.settings-view.blackbox > table > tbody td):
(.settings-view.blackbox > table > tbody td:not(.remove-blackbox)):
(.settings-view.blackbox > table :matches(th, td).url):
(.settings-view.blackbox > table > tbody td.url > .CodeMirror):
(.settings-view.blackbox > table :matches(th, td):matches(.case-sensitive, .remove-blackbox)):
(.settings-view.blackbox > table > tbody > tr:not(:hover) > td.remove-blackbox):
(.settings-view.blackbox > table > tbody td.remove-blackbox > .remove-blackbox-button):
Add a "Blackbox" pane that contains an editable table of pattern blackboxes, each having its
own row (code mirror for the URL regular _expression_ and a checkbox for case sensitivity).

* UserInterface/Views/SourceCodeTreeElement.js:
(WI.SourceCodeTreeElement.prototype.updateStatus):
(WI.SourceCodeTreeElement.prototype._updateSourceCode):
(WI.SourceCodeTreeElement.prototype._updateToggleBlackboxImageElementState):
(WI.SourceCodeTreeElement.prototype._handleToggleBlackboxedImageElementClicked):
* UserInterface/Views/SourceCodeTreeElement.css:
(.tree-outline .item .status > .toggle-script-blackbox, .tree-outline:focus .item.selected .status > .toggle-script-blackbox.pattern-blackboxed): Added.
(.tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed): Added.
(.tree-outline .item .status > .toggle-script-blackbox): Added.
(.tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed)): Added.
(.tree-outline .item .status > .toggle-script-blackbox:not(.url-blackboxed, .pattern-blackboxed)): Added.
(.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackbox, .tree-outline .item:not(:hover) .status > .toggle-script-blackbox:not(.pattern-blackboxed, .url-blackboxed)): Added.
(@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox): Added.
(@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed): Added.
(@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed)): Added.
(.tree-outline .item .status > .toggle-script-blackboxed): Deleted.
(.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackboxed, .tree-outline .item:not(:hover) .status > .toggle-script-blackboxed:not(.blackboxed)): Deleted.
(.tree-outline:focus .item.selected .status > .toggle-script-blackboxed): Deleted.
(.tree-outline .item .status > .toggle-script-blackboxed.blackboxed): Deleted.
(@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackboxed): Deleted.
* UserInterface/Views/ShaderProgramTreeElement.css:
(.tree-outline .item.shader-program .status > img):
(.tree-outline .item.shader-program:not(:hover, .disabled) .status > img): Added.
(.tree-outline .item.shader-program:not(.disabled) .status > img): Added.
(@media (prefers-color-scheme: dark) .tree-outline .item.shader-program .status > img):
(.tree-outline .item.shader-program:not(:hover, .selected, .disabled) .status > img): Deleted.
(.tree-outline:focus .item.shader-program.selected .status > img): Deleted.
(.tree-outline .item.shader-program.disabled .status > img): Deleted.
* UserInterface/Views/ContextMenuUtilities.js:
(WI.appendContextMenuItemsForSourceCode):
* UserInterface/Images/Hide.svg:
Use a slightly different style for the blackbox icon if the source code's URL matches a
blackbox pattern. Clicking on the blackbox icon in this state will show the Settings Tab.

* UserInterface/Base/Main.js:
(WI.contentLoaded):
(WI._handleSettingsKeyboardShortcut): Added.
(WI.showSettingsTab): Added.
(WI._showSettingsTab): Deleted.

* Localizations/en.lproj/localizedStrings.js:

LayoutTests:

* inspector/debugger/setShouldBlackboxURL.html:
* inspector/debugger/setShouldBlackboxURL-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (251038 => 251039)


--- trunk/LayoutTests/ChangeLog	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/LayoutTests/ChangeLog	2019-10-12 03:57:43 UTC (rev 251039)
@@ -1,5 +1,15 @@
 2019-10-11  Devin Rousso  <[email protected]>
 
+        Web Inspector: Debugger: support pattern blackboxing
+        https://bugs.webkit.org/show_bug.cgi?id=198855
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/debugger/setShouldBlackboxURL.html:
+        * inspector/debugger/setShouldBlackboxURL-expected.txt:
+
+2019-10-11  Devin Rousso  <[email protected]>
+
         Web Inspector: Elements: Computed: show shorthand properties in addition to longhand ones
         https://bugs.webkit.org/show_bug.cgi?id=200554
 

Modified: trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt (251038 => 251039)


--- trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt	2019-10-12 03:57:43 UTC (rev 251039)
@@ -2,25 +2,23 @@
 
 
 == Running test suite: Debugger.setShouldBlackboxURL
--- Running test case: Debugger.setShouldBlackboxURL.stepOver
-Evaluating 'createScripts("stepOver")'...
-Blackboxing 'stepOverMiddle.js'...
-Setting breakpoint in 'stepOverInner.js'...
-Evaluating 'stepOverOuter(10)'...
+-- Running test case: Debugger.setShouldBlackboxURL.String.stepOver
+Evaluating 'createScripts("String_StepOver")'...
+Blackboxing 'string_stepover_middle.js'...
+Setting breakpoint in 'String_StepOver_Inner.js'...
+Evaluating 'String_StepOver_Outer(10)'...
 
-Paused in 'stepOverInner:3:1'.
-Reason: 'Breakpoint'
+PAUSED: 'Breakpoint' at 'String_StepOver_Inner:3:1'.
 {
-  "breakpointId": "stepOverInner.js:3:0"
+  "breakpointId": "String_StepOver_Inner.js:3:0"
 }
 Stepping over...
 
-Paused in 'stepOverOuter:3:1'.
-Reason: 'BlackboxedScript'
+PAUSED: 'BlackboxedScript' at 'String_StepOver_Outer:3:1'.
 {
   "originalReason": "other",
   "originalData": {
-    "breakpointId": "stepOverInner.js:3:0"
+    "breakpointId": "String_StepOver_Inner.js:3:0"
   }
 }
 Stepping over...
@@ -27,56 +25,283 @@
 
 Resuming...
 PASS: Resumed.
-PASS: Should not pause in 'stepOverMiddle'.
+PASS: Should not pause in 'String_StepOver_Middle'.
 
--- Running test case: Debugger.setShouldBlackboxURL.PauseInCaller
-Evaluating 'createScripts("pauseInCaller")'...
-Blackboxing 'pauseInCallerInner.js'...
-Setting breakpoint in 'pauseInCallerInner.js'...
-Evaluating 'pauseInCallerOuter(10)'...
 
-Paused in 'pauseInCallerMiddle:3:1'.
-Reason: 'BlackboxedScript'
+-- Running test case: Debugger.setShouldBlackboxURL.String.PauseInCaller
+Evaluating 'createScripts("String_PauseInCaller")'...
+Blackboxing 'string_pauseincaller_inner.js'...
+Setting breakpoint in 'String_PauseInCaller_Inner.js'...
+Evaluating 'String_PauseInCaller_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'String_PauseInCaller_Middle:3:1'.
 {
   "originalReason": "Breakpoint",
   "originalData": {
-    "breakpointId": "pauseInCallerInner.js:2:0"
+    "breakpointId": "String_PauseInCaller_Inner.js:2:0"
   }
 }
 Stepping over...
 
-Paused in 'pauseInCallerOuter:3:1'.
-Reason: 'other'
+PAUSED: 'other' at 'String_PauseInCaller_Outer:3:1'.
 Stepping over...
 
 Resuming...
 PASS: Resumed.
-PASS: Should not pause in 'pauseInCallerInner'.
+PASS: Should not pause in 'String_PauseInCaller_Inner'.
 
--- Running test case: Debugger.setShouldBlackboxURL.PauseInCallee
-Evaluating 'createScripts("pauseInCallee")'...
-Blackboxing 'pauseInCalleeOuter.js'...
-Setting breakpoint in 'pauseInCalleeOuter.js'...
-Evaluating 'pauseInCalleeOuter(10)'...
 
-Paused in 'pauseInCalleeMiddle:2:4'.
-Reason: 'BlackboxedScript'
+-- Running test case: Debugger.setShouldBlackboxURL.String.PauseInCallee
+Evaluating 'createScripts("String_PauseInCallee")'...
+Blackboxing 'string_pauseincallee_outer.js'...
+Setting breakpoint in 'String_PauseInCallee_Outer.js'...
+Evaluating 'String_PauseInCallee_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'String_PauseInCallee_Middle:2:4'.
 {
   "originalReason": "Breakpoint",
   "originalData": {
-    "breakpointId": "pauseInCalleeOuter.js:2:0"
+    "breakpointId": "String_PauseInCallee_Outer.js:2:0"
   }
 }
 Stepping over...
 
-Paused in 'pauseInCalleeMiddle:3:1'.
-Reason: 'other'
+PAUSED: 'other' at 'String_PauseInCallee_Middle:3:1'.
 Stepping over...
 
 Resuming...
 PASS: Resumed.
-PASS: Should not pause in 'pauseInCalleeOuter'.
+PASS: Should not pause in 'String_PauseInCallee_Outer'.
 
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveString.stepOver
+Evaluating 'createScripts("CaseSensitiveString_StepOver")'...
+Blackboxing (case sensitive) 'casesensitivestring_stepover_inner.js'...
+Blackboxing (case sensitive) 'CaseSensitiveString_StepOver_Middle.js'...
+Setting breakpoint in 'CaseSensitiveString_StepOver_Inner.js'...
+Evaluating 'CaseSensitiveString_StepOver_Outer(10)'...
+
+PAUSED: 'Breakpoint' at 'CaseSensitiveString_StepOver_Inner:3:1'.
+{
+  "breakpointId": "CaseSensitiveString_StepOver_Inner.js:3:0"
+}
+Stepping over...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveString_StepOver_Outer:3:1'.
+{
+  "originalReason": "other",
+  "originalData": {
+    "breakpointId": "CaseSensitiveString_StepOver_Inner.js:3:0"
+  }
+}
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should pause in 'CaseSensitiveString_StepOver_Inner'.
+PASS: Should not pause in 'CaseSensitiveString_StepOver_Middle'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveString.PauseInCaller
+Evaluating 'createScripts("CaseSensitiveString_PauseInCaller")'...
+Blackboxing (case sensitive) 'CaseSensitiveString_PauseInCaller_Inner.js'...
+Blackboxing (case sensitive) 'casesensitivestring_pauseincaller_middle.js'...
+Setting breakpoint in 'CaseSensitiveString_PauseInCaller_Inner.js'...
+Evaluating 'CaseSensitiveString_PauseInCaller_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveString_PauseInCaller_Middle:3:1'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "CaseSensitiveString_PauseInCaller_Inner.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'CaseSensitiveString_PauseInCaller_Outer:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should not pause in 'CaseSensitiveString_PauseInCaller_Inner'.
+PASS: Should pause in 'CaseSensitiveString_PauseInCaller_Middle'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveString.PauseInCallee
+Evaluating 'createScripts("CaseSensitiveString_PauseInCallee")'...
+Blackboxing (case sensitive) 'casesensitivestring_pauseincallee_middle.js'...
+Blackboxing (case sensitive) 'CaseSensitiveString_PauseInCallee_Outer.js'...
+Setting breakpoint in 'CaseSensitiveString_PauseInCallee_Outer.js'...
+Evaluating 'CaseSensitiveString_PauseInCallee_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveString_PauseInCallee_Middle:2:4'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "CaseSensitiveString_PauseInCallee_Outer.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'CaseSensitiveString_PauseInCallee_Middle:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should pause in 'CaseSensitiveString_PauseInCallee_Middle'.
+PASS: Should not pause in 'CaseSensitiveString_PauseInCallee_Outer'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.Regex.stepOver
+Evaluating 'createScripts("Regex_StepOver")'...
+Blackboxing (regex) 'regex[ -_]stepover[ -_]middle\.js$'...
+Setting breakpoint in 'Regex_StepOver_Inner.js'...
+Evaluating 'Regex_StepOver_Outer(10)'...
+
+PAUSED: 'Breakpoint' at 'Regex_StepOver_Inner:3:1'.
+{
+  "breakpointId": "Regex_StepOver_Inner.js:3:0"
+}
+Stepping over...
+
+PAUSED: 'BlackboxedScript' at 'Regex_StepOver_Outer:3:1'.
+{
+  "originalReason": "other",
+  "originalData": {
+    "breakpointId": "Regex_StepOver_Inner.js:3:0"
+  }
+}
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should not pause in 'Regex_StepOver_Middle'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.Regex.PauseInCaller
+Evaluating 'createScripts("Regex_PauseInCaller")'...
+Blackboxing (regex) 'regex[ -_]pauseincaller[ -_]inner\.js$'...
+Setting breakpoint in 'Regex_PauseInCaller_Inner.js'...
+Evaluating 'Regex_PauseInCaller_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'Regex_PauseInCaller_Middle:3:1'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "Regex_PauseInCaller_Inner.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'Regex_PauseInCaller_Outer:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should not pause in 'Regex_PauseInCaller_Inner'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.Regex.PauseInCallee
+Evaluating 'createScripts("Regex_PauseInCallee")'...
+Blackboxing (regex) 'regex[ -_]pauseincallee[ -_]outer\.js$'...
+Setting breakpoint in 'Regex_PauseInCallee_Outer.js'...
+Evaluating 'Regex_PauseInCallee_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'Regex_PauseInCallee_Middle:2:4'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "Regex_PauseInCallee_Outer.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'Regex_PauseInCallee_Middle:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should not pause in 'Regex_PauseInCallee_Outer'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveRegex.stepOver
+Evaluating 'createScripts("CaseSensitiveRegex_StepOver")'...
+Blackboxing (case sensitive) (regex) 'casesensitiveregex_stepover_inner\.js$'...
+Blackboxing (case sensitive) (regex) 'CaseSensitiveRegex_StepOver_Middle\.js$'...
+Setting breakpoint in 'CaseSensitiveRegex_StepOver_Inner.js'...
+Evaluating 'CaseSensitiveRegex_StepOver_Outer(10)'...
+
+PAUSED: 'Breakpoint' at 'CaseSensitiveRegex_StepOver_Inner:3:1'.
+{
+  "breakpointId": "CaseSensitiveRegex_StepOver_Inner.js:3:0"
+}
+Stepping over...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveRegex_StepOver_Outer:3:1'.
+{
+  "originalReason": "other",
+  "originalData": {
+    "breakpointId": "CaseSensitiveRegex_StepOver_Inner.js:3:0"
+  }
+}
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should pause in 'CaseSensitiveRegex_StepOver_Inner'.
+PASS: Should not pause in 'CaseSensitiveRegex_StepOver_Middle'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveRegex.PauseInCaller
+Evaluating 'createScripts("CaseSensitiveRegex_PauseInCaller")'...
+Blackboxing (case sensitive) (regex) 'casesensitiveregex_pauseincaller_inner\.js$'...
+Blackboxing (case sensitive) (regex) 'CaseSensitiveRegex_PauseInCaller_middle\.js$'...
+Setting breakpoint in 'CaseSensitiveRegex_PauseInCaller_Inner.js'...
+Evaluating 'CaseSensitiveRegex_PauseInCaller_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveRegex_PauseInCaller_Middle:3:1'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "CaseSensitiveRegex_PauseInCaller_Inner.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'CaseSensitiveRegex_PauseInCaller_Outer:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should not pause in 'CaseSensitiveRegex_PauseInCaller_Inner'.
+PASS: Should pause in 'CaseSensitiveRegex_PauseInCaller_Middle'.
+
+
+-- Running test case: Debugger.setShouldBlackboxURL.CaseSensitiveRegex.PauseInCallee
+Evaluating 'createScripts("CaseSensitiveRegex_PauseInCallee")'...
+Blackboxing (case sensitive) (regex) 'casesensitiveregex_pauseincallee_middle\.js$'...
+Blackboxing (case sensitive) (regex) 'CaseSensitiveRegex_PauseInCallee_Outer\.js$'...
+Setting breakpoint in 'CaseSensitiveRegex_PauseInCallee_Outer.js'...
+Evaluating 'CaseSensitiveRegex_PauseInCallee_Outer(10)'...
+
+PAUSED: 'BlackboxedScript' at 'CaseSensitiveRegex_PauseInCallee_Middle:2:4'.
+{
+  "originalReason": "Breakpoint",
+  "originalData": {
+    "breakpointId": "CaseSensitiveRegex_PauseInCallee_Outer.js:2:0"
+  }
+}
+Stepping over...
+
+PAUSED: 'other' at 'CaseSensitiveRegex_PauseInCallee_Middle:3:1'.
+Stepping over...
+
+Resuming...
+PASS: Resumed.
+PASS: Should pause in 'CaseSensitiveRegex_PauseInCallee_Middle'.
+PASS: Should not pause in 'CaseSensitiveRegex_PauseInCallee_Outer'.
+
+
 -- Running test case: Debugger.setShouldBlackboxURL.Invalid.emptyURL
 PASS: Should produce an exception.
 {

Modified: trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL.html (251038 => 251039)


--- trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL.html	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/LayoutTests/inspector/debugger/setShouldBlackboxURL.html	2019-10-12 03:57:43 UTC (rev 251039)
@@ -6,28 +6,28 @@
 function createScripts(id) {
     eval(
 `
-window.${id}Inner = function ${id}Inner(x) {
+window.${id}_Inner = function ${id}_Inner(x) {
     return x + 42;
 };
-//# sourceURL=${id}Inner.js
+//# sourceURL=${id}_Inner.js
 `
     );
 
     eval(
 `
-window.${id}Middle = function ${id}Middle(x) {
-    return ${id}Inner(x);
+window.${id}_Middle = function ${id}_Middle(x) {
+    return ${id}_Inner(x);
 };
-//# sourceURL=${id}Middle.js
+//# sourceURL=${id}_Middle.js
 `
     );
 
     eval(
 `
-window.${id}Outer = function ${id}Outer(x) {
-    return ${id}Middle(x);
+window.${id}_Outer = function ${id}_Outer(x) {
+    return ${id}_Middle(x);
 };
-//# sourceURL=${id}Outer.js
+//# sourceURL=${id}_Outer.js
 `
     );
 }
@@ -54,6 +54,8 @@
     };
 
     InspectorProtocol.eventHandler["Debugger.paused"] = function(message) {
+        ProtocolTest.newline();
+
         let topCallFrame = message.params.callFrames[0];
         let functionName = topCallFrame.functionName;
         if (functionName === "global code") {
@@ -62,14 +64,12 @@
             return;
         }
 
-        ProtocolTest.log(`Paused in '${functionName}:${topCallFrame.location.lineNumber}:${topCallFrame.location.columnNumber}'.`);
-        ProtocolTest.log(`Reason: '${message.params.reason}'`);
+        ProtocolTest.log(`PAUSED: '${message.params.reason}' at '${functionName}:${topCallFrame.location.lineNumber}:${topCallFrame.location.columnNumber}'.`);
         if (message.params.data)
             ProtocolTest.json(message.params.data);
         pausedFunctionNames.push(functionName);
 
         ProtocolTest.log("Stepping over...");
-        ProtocolTest.newline();
         InspectorProtocol.sendCommand(`Debugger.stepOver`, {}, InspectorProtocol.checkForError);
     };
 
@@ -78,11 +78,14 @@
         resumeCallback();
     };
 
-    async function setBlackbox(url) {
-        ProtocolTest.log(`Blackboxing '${url}'...`);
+    async function setBlackbox(url, options = {}) {
+        if (!options.caseSensitive)
+            url = ""
+
+        ProtocolTest.log(`Blackboxing ${options.caseSensitive ? "(case sensitive) " : ""}${options.isRegex ? "(regex) " : ""}'${url}'...`);
         await InspectorProtocol.awaitCommand({
             method: "Debugger.setShouldBlackboxURL",
-            params: {url, shouldBlackbox: true},
+            params: {url, shouldBlackbox: true, ...options},
         });
     }
 
@@ -109,26 +112,26 @@
     }
 
     suite.addTestCase({
-        name: "Debugger.setShouldBlackboxURL.stepOver",
+        name: "Debugger.setShouldBlackboxURL.String.stepOver",
         description: "Check that stepping through a blackboxed script doesn't pause.",
         async test() {
             let resumePromise = new Promise((resolve, reject) => {
                 resumeCallback = function() {
-                    ProtocolTest.expectThat(!pausedFunctionNames.includes("stepOverMiddle"), "Should not pause in 'stepOverMiddle'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("String_StepOver_Middle"), "Should not pause in 'String_StepOver_Middle'.");
                     resolve();
                 };
             });
 
-            let [stepOverInnerSourceURL, stepOverMiddleSourceURL] = await Promise.all([
-                listenForSourceParsed(/stepOverInner\.js$/),
-                listenForSourceParsed(/stepOverMiddle\.js$/),
-                listenForSourceParsed(/stepOverOuter\.js$/),
-                evaluate(`createScripts("stepOver")`),
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/String_StepOver_Inner\.js$/),
+                listenForSourceParsed(/String_StepOver_Middle\.js$/),
+                listenForSourceParsed(/String_StepOver_Outer\.js$/),
+                evaluate(`createScripts("String_StepOver")`),
             ]);
 
-            await setBlackbox(stepOverMiddleSourceURL);
-            await setBreakpoint(stepOverInnerSourceURL, 3); // last line of function, so it only pauses once
-            evaluate(`stepOverOuter(10)`);
+            await setBlackbox(middleSourceURL);
+            await setBreakpoint(innerSourceURL, 3); // last line of function, so it only pauses once
+            await evaluate(`String_StepOver_Outer(10)`);
 
             ProtocolTest.newline();
 
@@ -137,26 +140,26 @@
     });
 
     suite.addTestCase({
-        name: "Debugger.setShouldBlackboxURL.PauseInCaller",
+        name: "Debugger.setShouldBlackboxURL.String.PauseInCaller",
         description: "Check that the debugger will pause in the caller if a breakpoint is set in a blackboxed script.",
         async test() {
             let resumePromise = new Promise((resolve, reject) => {
                 resumeCallback = function() {
-                    ProtocolTest.expectThat(!pausedFunctionNames.includes("pauseInCallerInner"), "Should not pause in 'pauseInCallerInner'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("String_PauseInCaller_Inner"), "Should not pause in 'String_PauseInCaller_Inner'.");
                     resolve();
                 };
             });
 
-            let [pauseInCallerInnerSourceURL] = await Promise.all([
-                listenForSourceParsed(/pauseInCallerInner\.js$/),
-                listenForSourceParsed(/pauseInCallerMiddle\.js$/),
-                listenForSourceParsed(/pauseInCallerOuter\.js$/),
-                evaluate(`createScripts("pauseInCaller")`),
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/String_PauseInCaller_Inner\.js$/),
+                listenForSourceParsed(/String_PauseInCaller_Middle\.js$/),
+                listenForSourceParsed(/String_PauseInCaller_Outer\.js$/),
+                evaluate(`createScripts("String_PauseInCaller")`),
             ]);
 
-            await setBlackbox(pauseInCallerInnerSourceURL);
-            await setBreakpoint(pauseInCallerInnerSourceURL, 2);
-            evaluate(`pauseInCallerOuter(10)`);
+            await setBlackbox(innerSourceURL);
+            await setBreakpoint(innerSourceURL, 2);
+            await evaluate(`String_PauseInCaller_Outer(10)`);
 
             ProtocolTest.newline();
 
@@ -165,26 +168,26 @@
     });
 
     suite.addTestCase({
-        name: "Debugger.setShouldBlackboxURL.PauseInCallee",
+        name: "Debugger.setShouldBlackboxURL.String.PauseInCallee",
         description: "Check that the debugger will pause in the callee if a breakpoint is set in a blackboxed script.",
         async test() {
             let resumePromise = new Promise((resolve, reject) => {
                 resumeCallback = function() {
-                    ProtocolTest.expectThat(!pausedFunctionNames.includes("pauseInCalleeOuter"), "Should not pause in 'pauseInCalleeOuter'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("String_PauseInCallee_Outer"), "Should not pause in 'String_PauseInCallee_Outer'.");
                     resolve();
                 };
             });
 
-            let [pauseInCalleeInnerSourceURL, pauseInCalleeMiddleSourceURL, pauseInCalleeOuterSourceURL] = await Promise.all([
-                listenForSourceParsed(/pauseInCalleeInner\.js$/),
-                listenForSourceParsed(/pauseInCalleeMiddle\.js$/),
-                listenForSourceParsed(/pauseInCalleeOuter\.js$/),
-                evaluate(`createScripts("pauseInCallee")`),
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/String_PauseInCallee_Inner\.js$/),
+                listenForSourceParsed(/String_PauseInCallee_Middle\.js$/),
+                listenForSourceParsed(/String_PauseInCallee_Outer\.js$/),
+                evaluate(`createScripts("String_PauseInCallee")`),
             ]);
 
-            await setBlackbox(pauseInCalleeOuterSourceURL);
-            await setBreakpoint(pauseInCalleeOuterSourceURL, 2);
-            evaluate(`pauseInCalleeOuter(10)`);
+            await setBlackbox(outerSourceURL);
+            await setBreakpoint(outerSourceURL, 2);
+            await evaluate(`String_PauseInCallee_Outer(10)`);
 
             ProtocolTest.newline();
 
@@ -193,6 +196,270 @@
     });
 
     suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveString.stepOver",
+        description: "Check that stepping through a blackboxed script doesn't pause.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveString_StepOver_Inner"), "Should pause in 'CaseSensitiveString_StepOver_Inner'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveString_StepOver_Middle"), "Should not pause in 'CaseSensitiveString_StepOver_Middle'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveString_StepOver_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_StepOver_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_StepOver_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveString_StepOver")`),
+            ]);
+
+            await setBlackbox(innerSourceURL.toLowerCase(), {caseSensitive: true});
+            await setBlackbox(middleSourceURL, {caseSensitive: true});
+            await setBreakpoint(innerSourceURL, 3); // last line of function, so it only pauses once
+            await evaluate(`CaseSensitiveString_StepOver_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveString.PauseInCaller",
+        description: "Check that the debugger will pause in the caller if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveString_PauseInCaller_Inner"), "Should not pause in 'CaseSensitiveString_PauseInCaller_Inner'.");
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveString_PauseInCaller_Middle"), "Should pause in 'CaseSensitiveString_PauseInCaller_Middle'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveString_PauseInCaller_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_PauseInCaller_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_PauseInCaller_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveString_PauseInCaller")`),
+            ]);
+
+            await setBlackbox(innerSourceURL, {caseSensitive: true});
+            await setBlackbox(middleSourceURL.toLowerCase(), {caseSensitive: true});
+            await setBreakpoint(innerSourceURL, 2);
+            await evaluate(`CaseSensitiveString_PauseInCaller_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveString.PauseInCallee",
+        description: "Check that the debugger will pause in the callee if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveString_PauseInCallee_Middle"), "Should pause in 'CaseSensitiveString_PauseInCallee_Middle'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveString_PauseInCallee_Outer"), "Should not pause in 'CaseSensitiveString_PauseInCallee_Outer'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveString_PauseInCallee_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_PauseInCallee_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveString_PauseInCallee_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveString_PauseInCallee")`),
+            ]);
+
+            await setBlackbox(middleSourceURL.toLowerCase(), {caseSensitive: true});
+            await setBlackbox(outerSourceURL, {caseSensitive: true});
+            await setBreakpoint(outerSourceURL, 2);
+            await evaluate(`CaseSensitiveString_PauseInCallee_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.Regex.stepOver",
+        description: "Check that stepping through a blackboxed script doesn't pause.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("Regex_StepOver_Middle"), "Should not pause in 'Regex_StepOver_Middle'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/Regex_StepOver_Inner\.js$/),
+                listenForSourceParsed(/Regex_StepOver_Middle\.js$/),
+                listenForSourceParsed(/Regex_StepOver_Outer\.js$/),
+                evaluate(`createScripts("Regex_StepOver")`),
+            ]);
+
+            await setBlackbox("Regex[ -_]StepOver[ -_]Middle\\.js$", {isRegex: true});
+            await setBreakpoint(innerSourceURL, 3); // last line of function, so it only pauses once
+            await evaluate(`Regex_StepOver_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.Regex.PauseInCaller",
+        description: "Check that the debugger will pause in the caller if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("Regex_PauseInCaller_Inner"), "Should not pause in 'Regex_PauseInCaller_Inner'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/Regex_PauseInCaller_Inner\.js$/),
+                listenForSourceParsed(/Regex_PauseInCaller_Middle\.js$/),
+                listenForSourceParsed(/Regex_PauseInCaller_Outer\.js$/),
+                evaluate(`createScripts("Regex_PauseInCaller")`),
+            ]);
+
+            await setBlackbox("Regex[ -_]PauseInCaller[ -_]Inner\\.js$", {isRegex: true});
+            await setBreakpoint(innerSourceURL, 2);
+            await evaluate(`Regex_PauseInCaller_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.Regex.PauseInCallee",
+        description: "Check that the debugger will pause in the callee if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("Regex_PauseInCallee_Outer"), "Should not pause in 'Regex_PauseInCallee_Outer'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/Regex_PauseInCallee_Inner\.js$/),
+                listenForSourceParsed(/Regex_PauseInCallee_Middle\.js$/),
+                listenForSourceParsed(/Regex_PauseInCallee_Outer\.js$/),
+                evaluate(`createScripts("Regex_PauseInCallee")`),
+            ]);
+
+            await setBlackbox("Regex[ -_]PauseInCallee[ -_]Outer\\.js$", {isRegex: true});
+            await setBreakpoint(outerSourceURL, 2);
+            await evaluate(`Regex_PauseInCallee_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveRegex.stepOver",
+        description: "Check that stepping through a blackboxed script doesn't pause.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveRegex_StepOver_Inner"), "Should pause in 'CaseSensitiveRegex_StepOver_Inner'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveRegex_StepOver_Middle"), "Should not pause in 'CaseSensitiveRegex_StepOver_Middle'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveRegex_StepOver_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_StepOver_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_StepOver_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveRegex_StepOver")`),
+            ]);
+
+            await setBlackbox("casesensitiveregex_stepover_inner\\.js$", {caseSensitive: true, isRegex: true});
+            await setBlackbox("CaseSensitiveRegex_StepOver_Middle\\.js$", {caseSensitive: true, isRegex: true});
+            await setBreakpoint(innerSourceURL, 3); // last line of function, so it only pauses once
+            await evaluate(`CaseSensitiveRegex_StepOver_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveRegex.PauseInCaller",
+        description: "Check that the debugger will pause in the caller if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveRegex_PauseInCaller_Inner"), "Should not pause in 'CaseSensitiveRegex_PauseInCaller_Inner'.");
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveRegex_PauseInCaller_Middle"), "Should pause in 'CaseSensitiveRegex_PauseInCaller_Middle'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCaller_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCaller_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCaller_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveRegex_PauseInCaller")`),
+            ]);
+
+            await setBlackbox("casesensitiveregex_pauseincaller_inner\\.js$", {caseSensitive: true, isRegex: true});
+            await setBlackbox("CaseSensitiveRegex_PauseInCaller_middle\\.js$", {caseSensitive: true, isRegex: true});
+            await setBreakpoint(innerSourceURL, 2);
+            await evaluate(`CaseSensitiveRegex_PauseInCaller_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
+        name: "Debugger.setShouldBlackboxURL.CaseSensitiveRegex.PauseInCallee",
+        description: "Check that the debugger will pause in the callee if a breakpoint is set in a blackboxed script.",
+        async test() {
+            let resumePromise = new Promise((resolve, reject) => {
+                resumeCallback = function() {
+                    ProtocolTest.expectThat(pausedFunctionNames.includes("CaseSensitiveRegex_PauseInCallee_Middle"), "Should pause in 'CaseSensitiveRegex_PauseInCallee_Middle'.");
+                    ProtocolTest.expectThat(!pausedFunctionNames.includes("CaseSensitiveRegex_PauseInCallee_Outer"), "Should not pause in 'CaseSensitiveRegex_PauseInCallee_Outer'.");
+                    resolve();
+                };
+            });
+
+            let [innerSourceURL, middleSourceURL, outerSourceURL] = await Promise.all([
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCallee_Inner\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCallee_Middle\.js$/),
+                listenForSourceParsed(/CaseSensitiveRegex_PauseInCallee_Outer\.js$/),
+                evaluate(`createScripts("CaseSensitiveRegex_PauseInCallee")`),
+            ]);
+
+            await setBlackbox("casesensitiveregex_pauseincallee_middle\\.js$", {caseSensitive: true, isRegex: true});
+            await setBlackbox("CaseSensitiveRegex_PauseInCallee_Outer\\.js$", {caseSensitive: true, isRegex: true});
+            await setBreakpoint(outerSourceURL, 2);
+            await evaluate(`CaseSensitiveRegex_PauseInCallee_Outer(10)`);
+
+            ProtocolTest.newline();
+
+            await resumePromise;
+        },
+    });
+
+    suite.addTestCase({
         name: "Debugger.setShouldBlackboxURL.Invalid.emptyURL",
         description: "Check that an error is thrown if the given url is empty.",
         async test() {

Modified: trunk/Source/_javascript_Core/ChangeLog (251038 => 251039)


--- trunk/Source/_javascript_Core/ChangeLog	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-10-12 03:57:43 UTC (rev 251039)
@@ -1,3 +1,23 @@
+2019-10-11  Devin Rousso  <[email protected]>
+
+        Web Inspector: Debugger: support pattern blackboxing
+        https://bugs.webkit.org/show_bug.cgi?id=198855
+
+        Reviewed by Timothy Hatcher.
+
+        Allow scripts to be blackboxed based on URL patterns (in addition to individual URLs) which
+        can be extremely useful when trying to step through unminified library/framework code.
+
+        * inspector/agents/InspectorDebuggerAgent.h:
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::enable):
+        (Inspector::InspectorDebuggerAgent::setShouldBlackboxURL):
+        (Inspector::InspectorDebuggerAgent::shouldBlackboxURL const): Added.
+        (Inspector::InspectorDebuggerAgent::didParseSource):
+
+        * inspector/protocol/Debugger.json:
+        Add `caseSensitive` and `isRegex` optional boolean parameters to `setShouldBlackboxURL`.
+
 2019-10-08  Ryosuke Niwa  <[email protected]>
 
         Make WebInspector's remote debug EventLoop code into RunLoop

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp (251038 => 251039)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2019-10-12 03:57:43 UTC (rev 251039)
@@ -103,7 +103,7 @@
         if (isWebKitInjectedScript(script.sourceURL)) {
             if (!m_pauseForInternalScripts)
                 blackboxType = JSC::Debugger::BlackboxType::Ignored;
-        } else if ((!script.sourceURL.isEmpty() && m_blackboxedURLs.contains(script.sourceURL)) || (!script.url.isEmpty() && m_blackboxedURLs.contains(script.url)))
+        } else if (shouldBlackboxURL(script.sourceURL) || shouldBlackboxURL(script.url))
             blackboxType = JSC::Debugger::BlackboxType::Deferred;
         m_scriptDebugServer.setBlackboxType(sourceID, blackboxType);
     }
@@ -890,7 +890,7 @@
     }
 }
 
-void InspectorDebuggerAgent::setShouldBlackboxURL(ErrorString& errorString, const String& url, bool shouldBlackbox)
+void InspectorDebuggerAgent::setShouldBlackboxURL(ErrorString& errorString, const String& url, bool shouldBlackbox, const bool* optionalCaseSensitive, const bool* optionalIsRegex)
 {
     if (url.isEmpty()) {
         errorString = "URL must not be empty"_s;
@@ -897,26 +897,47 @@
         return;
     }
 
-    if (isWebKitInjectedScript(url)) {
+    bool caseSensitive = optionalCaseSensitive && *optionalCaseSensitive;
+    bool isRegex = optionalIsRegex && *optionalIsRegex;
+
+    if (!caseSensitive && !isRegex && isWebKitInjectedScript(url)) {
         errorString = "Blackboxing of internal scripts is controlled by 'Debugger.setPauseForInternalScripts'"_s;
         return;
     }
 
     if (shouldBlackbox)
-        m_blackboxedURLs.add(url);
-    else
-        m_blackboxedURLs.remove(url);
+        m_blackboxedURLs.append({ url, caseSensitive, isRegex });
 
     auto blackboxType = shouldBlackbox ? Optional<JSC::Debugger::BlackboxType>(JSC::Debugger::BlackboxType::Deferred) : WTF::nullopt;
     for (auto& [sourceID, script] : m_scripts) {
         if (isWebKitInjectedScript(script.sourceURL))
             continue;
-        if (script.sourceURL != url && script.url != url)
+        if (!shouldBlackboxURL(script.sourceURL) && !shouldBlackboxURL(script.url))
             continue;
         m_scriptDebugServer.setBlackboxType(sourceID, blackboxType);
     }
+
+    if (!shouldBlackbox) {
+        m_blackboxedURLs.removeAllMatching([&] (const auto& blackboxConfig) {
+            return blackboxConfig.url == url
+                && blackboxConfig.caseSensitive == caseSensitive
+                && blackboxConfig.isRegex == isRegex;
+        });
+    }
 }
 
+bool InspectorDebuggerAgent::shouldBlackboxURL(const String& url) const
+{
+    if (!url.isEmpty()) {
+        for (const auto& blackboxConfig : m_blackboxedURLs) {
+            auto regex = ContentSearchUtilities::createSearchRegex(blackboxConfig.url, blackboxConfig.caseSensitive, blackboxConfig.isRegex);
+            if (regex.match(url) != -1)
+                return true;
+        }
+    }
+    return false;
+}
+
 void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText)
 {
     if (m_scriptDebugServer.pauseOnExceptionsState() != JSC::Debugger::DontPauseOnExceptions)
@@ -971,7 +992,7 @@
     if (isWebKitInjectedScript(sourceURL)) {
         if (!m_pauseForInternalScripts)
             m_scriptDebugServer.setBlackboxType(sourceID, JSC::Debugger::BlackboxType::Ignored);
-    } else if ((hasSourceURL && m_blackboxedURLs.contains(sourceURL)) || (!script.url.isEmpty() && m_blackboxedURLs.contains(script.url)))
+    } else if (shouldBlackboxURL(sourceURL) || shouldBlackboxURL(script.url))
         m_scriptDebugServer.setBlackboxType(sourceID, JSC::Debugger::BlackboxType::Deferred);
 
     String scriptURLForBreakpoints = hasSourceURL ? script.sourceURL : script.url;

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h (251038 => 251039)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h	2019-10-12 03:57:43 UTC (rev 251039)
@@ -85,7 +85,7 @@
     void setPauseOnMicrotasks(ErrorString&, bool enabled) final;
     void setPauseForInternalScripts(ErrorString&, bool shouldPause) final;
     void evaluateOnCallFrame(ErrorString&, const String& callFrameId, const String& _expression_, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex) override;
-    void setShouldBlackboxURL(ErrorString&, const String& url, bool shouldBlackbox) final;
+    void setShouldBlackboxURL(ErrorString&, const String& url, bool shouldBlackbox, const bool* caseSensitive, const bool* isRegex) final;
 
     // ScriptDebugListener
     void didParseSource(JSC::SourceID, const Script&) final;
@@ -151,10 +151,12 @@
     virtual void didClearAsyncStackTraceData() { }
 
 private:
+    bool shouldBlackboxURL(const String&) const;
+
     Ref<JSON::ArrayOf<Protocol::Debugger::CallFrame>> currentCallFrames(const InjectedScript&);
 
     void resolveBreakpoint(const Script&, JSC::Breakpoint&);
-    void setBreakpoint(JSC::Breakpoint&, bool& existing);    
+    void setBreakpoint(JSC::Breakpoint&, bool& existing);
     void didSetBreakpoint(const JSC::Breakpoint&, const String&, const ScriptBreakpoint&);
 
     bool assertPaused(ErrorString&);
@@ -185,8 +187,14 @@
     ScriptDebugServer& m_scriptDebugServer;
     InjectedScriptManager& m_injectedScriptManager;
     HashMap<JSC::SourceID, Script> m_scripts;
-    HashSet<String> m_blackboxedURLs;
 
+    struct BlackboxConfig {
+        String url;
+        bool caseSensitive { false };
+        bool isRegex { false };
+    };
+    Vector<BlackboxConfig> m_blackboxedURLs;
+
     HashSet<Listener*> m_listeners;
 
     JSC::ExecState* m_pausedScriptState { nullptr };

Modified: trunk/Source/_javascript_Core/inspector/protocol/Debugger.json (251038 => 251039)


--- trunk/Source/_javascript_Core/inspector/protocol/Debugger.json	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/_javascript_Core/inspector/protocol/Debugger.json	2019-10-12 03:57:43 UTC (rev 251039)
@@ -300,7 +300,9 @@
             "description": "Sets whether the given URL should be in the list of blackboxed scripts, which are ignored when pausing/stepping/debugging.",
             "parameters": [
                 { "name": "url", "type": "string" },
-                { "name": "shouldBlackbox", "type": "boolean" }
+                { "name": "shouldBlackbox", "type": "boolean" },
+                { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, <code>url</code> is case sensitive." },
+                { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treat <code>url</code> as regular _expression_." }
             ]
         }
     ],

Modified: trunk/Source/WebInspectorUI/ChangeLog (251038 => 251039)


--- trunk/Source/WebInspectorUI/ChangeLog	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/ChangeLog	2019-10-12 03:57:43 UTC (rev 251039)
@@ -1,5 +1,95 @@
 2019-10-11  Devin Rousso  <[email protected]>
 
+        Web Inspector: Debugger: support pattern blackboxing
+        https://bugs.webkit.org/show_bug.cgi?id=198855
+
+        Reviewed by Timothy Hatcher.
+
+        Allow scripts to be blackboxed based on URL patterns (in addition to individual URLs) which
+        can be extremely useful when trying to step through unminified library/framework code.
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WI.DebuggerManager):
+        (WI.DebuggerManager.prototype.initializeTarget):
+        (WI.DebuggerManager.prototype.blackboxTypeForSourceCode): Added.
+        (WI.DebuggerManager.prototype.get blackboxPatterns): Added.
+        (WI.DebuggerManager.prototype.setShouldBlackboxScript):
+        (WI.DebuggerManager.prototype.setShouldBlackboxPattern): Added.
+        (WI.DebuggerManager.prototype.isScriptBlackboxed): Deleted.
+        Provide a separate path for setting URL pattern blackboxes, rather than an exact/given URL.
+
+        * UserInterface/Views/SettingsTabContentView.js:
+        (WI.SettingsTabContentView):
+        (WI.SettingsTabContentView.prototype.selectBlackboxPattern): Added.
+        (WI.SettingsTabContentView.prototype.initialLayout):
+        (WI.SettingsTabContentView.prototype._createSourcesSettingsView):
+        * UserInterface/Views/BlackboxSettingsView.js: Added.
+        (WI.BlackboxSettingsView):
+        (WI.BlackboxSettingsView.prototype.selectBlackboxPattern):
+        (WI.BlackboxSettingsView.prototype.initialLayout):
+        (WI.BlackboxSettingsView.prototype._addRow):
+        * UserInterface/Views/BlackboxSettingsView.css: Added.
+        (.settings-view.blackbox > :matches(p, table)):
+        (.settings-view.blackbox > p):
+        (.settings-view.blackbox > * + p):
+        (.settings-view.blackbox > p:last-child):
+        (.settings-view.blackbox > p > .toggle-script-blackbox):
+        (.settings-view.blackbox > table):
+        (.settings-view.blackbox > table > thead th):
+        (.settings-view.blackbox > table > tbody td):
+        (.settings-view.blackbox > table > tbody td:not(.remove-blackbox)):
+        (.settings-view.blackbox > table :matches(th, td).url):
+        (.settings-view.blackbox > table > tbody td.url > .CodeMirror):
+        (.settings-view.blackbox > table :matches(th, td):matches(.case-sensitive, .remove-blackbox)):
+        (.settings-view.blackbox > table > tbody > tr:not(:hover) > td.remove-blackbox):
+        (.settings-view.blackbox > table > tbody td.remove-blackbox > .remove-blackbox-button):
+        Add a "Blackbox" pane that contains an editable table of pattern blackboxes, each having its
+        own row (code mirror for the URL regular _expression_ and a checkbox for case sensitivity).
+
+        * UserInterface/Views/SourceCodeTreeElement.js:
+        (WI.SourceCodeTreeElement.prototype.updateStatus):
+        (WI.SourceCodeTreeElement.prototype._updateSourceCode):
+        (WI.SourceCodeTreeElement.prototype._updateToggleBlackboxImageElementState):
+        (WI.SourceCodeTreeElement.prototype._handleToggleBlackboxedImageElementClicked):
+        * UserInterface/Views/SourceCodeTreeElement.css:
+        (.tree-outline .item .status > .toggle-script-blackbox, .tree-outline:focus .item.selected .status > .toggle-script-blackbox.pattern-blackboxed): Added.
+        (.tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed): Added.
+        (.tree-outline .item .status > .toggle-script-blackbox): Added.
+        (.tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed)): Added.
+        (.tree-outline .item .status > .toggle-script-blackbox:not(.url-blackboxed, .pattern-blackboxed)): Added.
+        (.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackbox, .tree-outline .item:not(:hover) .status > .toggle-script-blackbox:not(.pattern-blackboxed, .url-blackboxed)): Added.
+        (@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox): Added.
+        (@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed): Added.
+        (@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed)): Added.
+        (.tree-outline .item .status > .toggle-script-blackboxed): Deleted.
+        (.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackboxed, .tree-outline .item:not(:hover) .status > .toggle-script-blackboxed:not(.blackboxed)): Deleted.
+        (.tree-outline:focus .item.selected .status > .toggle-script-blackboxed): Deleted.
+        (.tree-outline .item .status > .toggle-script-blackboxed.blackboxed): Deleted.
+        (@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackboxed): Deleted.
+        * UserInterface/Views/ShaderProgramTreeElement.css:
+        (.tree-outline .item.shader-program .status > img):
+        (.tree-outline .item.shader-program:not(:hover, .disabled) .status > img): Added.
+        (.tree-outline .item.shader-program:not(.disabled) .status > img): Added.
+        (@media (prefers-color-scheme: dark) .tree-outline .item.shader-program .status > img):
+        (.tree-outline .item.shader-program:not(:hover, .selected, .disabled) .status > img): Deleted.
+        (.tree-outline:focus .item.shader-program.selected .status > img): Deleted.
+        (.tree-outline .item.shader-program.disabled .status > img): Deleted.
+        * UserInterface/Views/ContextMenuUtilities.js:
+        (WI.appendContextMenuItemsForSourceCode):
+        * UserInterface/Images/Hide.svg:
+        Use a slightly different style for the blackbox icon if the source code's URL matches a
+        blackbox pattern. Clicking on the blackbox icon in this state will show the Settings Tab.
+
+        * UserInterface/Base/Main.js:
+        (WI.contentLoaded):
+        (WI._handleSettingsKeyboardShortcut): Added.
+        (WI.showSettingsTab): Added.
+        (WI._showSettingsTab): Deleted.
+
+        * Localizations/en.lproj/localizedStrings.js:
+
+2019-10-11  Devin Rousso  <[email protected]>
+
         Web Inspector: Elements: Computed: show shorthand properties in addition to longhand ones
         https://bugs.webkit.org/show_bug.cgi?id=200554
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -92,6 +92,7 @@
 localizedStrings["Add New Class"] = "Add New Class";
 localizedStrings["Add New Probe _expression_"] = "Add New Probe _expression_";
 localizedStrings["Add New Watch _expression_"] = "Add New Watch _expression_";
+localizedStrings["Add Pattern"] = "Add Pattern";
 localizedStrings["Add a Class"] = "Add a Class";
 localizedStrings["Add new breakpoint action after this action"] = "Add new breakpoint action after this action";
 localizedStrings["Add new rule"] = "Add new rule";
@@ -170,6 +171,7 @@
 localizedStrings["Beacons"] = "Beacons";
 localizedStrings["Binary Frame"] = "Binary Frame";
 localizedStrings["Binding"] = "Binding";
+localizedStrings["Blackbox"] = "Blackbox";
 localizedStrings["Block Variables"] = "Block Variables";
 localizedStrings["Body:"] = "Body:";
 localizedStrings["Boundary"] = "Boundary";
@@ -212,6 +214,7 @@
 /* Capture screenshot of the selected DOM node */
 localizedStrings["Capture Screenshot"] = "Capture Screenshot";
 localizedStrings["Capturing"] = "Capturing";
+localizedStrings["Case Sensitive"] = "Case Sensitive";
 /* Context menu label for whether searches should be case sensitive. */
 localizedStrings["Case Sensitive @ Context Menu"] = "Case Sensitive";
 /* Settings tab checkbox label for whether searches should be case sensitive. */
@@ -333,7 +336,7 @@
 localizedStrings["Debugger Statement"] = "Debugger Statement";
 localizedStrings["Debugger disabled during Audit"] = "Debugger disabled during Audit";
 localizedStrings["Debugger disabled during Timeline recording"] = "Debugger disabled during Timeline recording";
-localizedStrings["Debugger:"] = "Debugger:";
+localizedStrings["Debugging:"] = "Debugging:";
 localizedStrings["Debugs"] = "Debugs";
 localizedStrings["Decoded"] = "Decoded";
 localizedStrings["Default"] = "Default";
@@ -593,6 +596,7 @@
 localizedStrings["IP Address"] = "IP Address";
 localizedStrings["Identity"] = "Identity";
 localizedStrings["Idle"] = "Idle";
+localizedStrings["If the URL of any script matches one of the regular _expression_ patterns below, any pauses that would have happened in that script will be deferred until execution has continued to outside of that script."] = "If the URL of any script matches one of the regular _expression_ patterns below, any pauses that would have happened in that script will be deferred until execution has continued to outside of that script.";
 localizedStrings["Ignore"] = "Ignore";
 localizedStrings["Ignore script when debugging"] = "Ignore script when debugging";
 localizedStrings["Ignore the resource cache when loading resources"] = "Ignore the resource cache when loading resources";
@@ -879,6 +883,7 @@
 localizedStrings["Reload Web Inspector"] = "Reload Web Inspector";
 localizedStrings["Reload page (%s)\nReload page ignoring cache (%s)"] = "Reload page (%s)\nReload page ignoring cache (%s)";
 localizedStrings["Removals"] = "Removals";
+localizedStrings["Remove Blackbox"] = "Remove Blackbox";
 localizedStrings["Remove Local Override"] = "Remove Local Override";
 localizedStrings["Remove Watch _expression_"] = "Remove Watch _expression_";
 localizedStrings["Remove probe"] = "Remove probe";
@@ -928,6 +933,7 @@
 localizedStrings["Return value is not an object, string, or boolean"] = "Return value is not an object, string, or boolean";
 localizedStrings["Reveal"] = "Reveal";
 localizedStrings["Reveal Descendant Breakpoints"] = "Reveal Descendant Breakpoints";
+localizedStrings["Reveal blackbox pattern"] = "Reveal blackbox pattern";
 /* Open Elements tab and select this node in DOM tree */
 localizedStrings["Reveal in DOM Tree"] = "Reveal in DOM Tree";
 localizedStrings["Reveal in Elements Tab"] = "Reveal in Elements Tab";
@@ -960,7 +966,9 @@
 localizedStrings["Script Element %d"] = "Script Element %d";
 localizedStrings["Script Entries:"] = "Script Entries:";
 localizedStrings["Script Evaluated"] = "Script Evaluated";
+localizedStrings["Script ignored when debugging due to previously set blackbox URL pattern"] = "Script ignored when debugging due to previously set blackbox URL pattern";
 localizedStrings["Scripts"] = "Scripts";
+localizedStrings["Scripts can also be individually blackboxed by clicking on the %s icon that is shown on hover."] = "Scripts can also be individually blackboxed by clicking on the %s icon that is shown on hover.";
 /* Scroll selected DOM node into view on the inspected web page */
 localizedStrings["Scroll into View"] = "Scroll into View";
 localizedStrings["Search"] = "Search";
@@ -1196,6 +1204,7 @@
 localizedStrings["Type information for variable: %s"] = "Type information for variable: %s";
 localizedStrings["URL"] = "URL";
 localizedStrings["URL Breakpoint\u2026"] = "URL Breakpoint\u2026";
+localizedStrings["URL Pattern"] = "URL Pattern";
 localizedStrings["Unable to determine path to property from root"] = "Unable to determine path to property from root";
 localizedStrings["Unable to show certificate for \u201C%s\u201D"] = "Unable to show certificate for \u201C%s\u201D";
 /* Break (pause) on uncaught (unhandled) exceptions */

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -322,7 +322,7 @@
 
     WI.settingsTabContentView = new WI.SettingsTabContentView;
 
-    WI._settingsKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Comma, WI._showSettingsTab);
+    WI._settingsKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Comma, WI._handleSettingsKeyboardShortcut);
 
     // Create the user interface elements.
     WI.toolbar = new WI.Toolbar(document.getElementById("toolbar"));
@@ -714,7 +714,7 @@
     WI.showNewTabTab({suppressAnimations: true});
 };
 
-WI._showSettingsTab = function(event)
+WI._handleSettingsKeyboardShortcut = function(event)
 {
     if (event.keyIdentifier === "U+002C") // ","
         WI.tabBrowser.showTabForContentView(WI.settingsTabContentView);
@@ -1145,6 +1145,14 @@
     return WI.tabBrowser.selectedTabContentView instanceof WI.LayersTabContentView;
 };
 
+WI.showSettingsTab = function(options = {})
+{
+    WI.tabBrowser.showTabForContentView(WI.settingsTabContentView);
+
+    if (options.blackboxPatternToSelect)
+        WI.settingsTabContentView.selectBlackboxPattern(options.blackboxPatternToSelect);
+};
+
 WI.indentString = function()
 {
     if (WI.settings.indentWithTabs.value)

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -89,7 +89,9 @@
 
         this._nextBreakpointActionIdentifier = 1;
 
-        this._blackboxURLsSetting = new WI.Setting("debugger-blackbox-urls", []);
+        this._blackboxedURLsSetting = new WI.Setting("debugger-blackboxed-urls", []);
+        this._blackboxedPatternsSetting = new WI.Setting("debugger-blackboxed-patterns", []);
+        this._blackboxedPatternDataMap = new Map;
 
         this._activeCallFrame = null;
 
@@ -161,8 +163,21 @@
 
         // COMPATIBILITY (iOS 13): Debugger.setShouldBlackboxURL did not exist yet.
         if (target.DebuggerAgent.setShouldBlackboxURL) {
-            for (let url of this._blackboxURLsSetting.value)
-                target.DebuggerAgent.setShouldBlackboxURL(url, true);
+            const shouldBlackbox = true;
+
+            {
+                const caseSensitive = true;
+                for (let url of this._blackboxedURLsSetting.value)
+                    target.DebuggerAgent.setShouldBlackboxURL(url, shouldBlackbox, caseSensitive);
+            }
+
+            {
+                const isRegex = true;
+                for (let data of this._blackboxedPatternsSetting.value) {
+                    this._blackboxedPatternDataMap.set(new RegExp(data.url, !data.caseSensitive ? "i" : ""), data);
+                    target.DebuggerAgent.setShouldBlackboxURL(data.url, shouldBlackbox, data.caseSensitive, isRegex);
+                }
+            }
         }
 
         if (WI.isEngineeringBuild) {
@@ -406,11 +421,24 @@
         return knownScripts;
     }
 
-    isScriptBlackboxed(sourceCode)
+    blackboxDataForSourceCode(sourceCode)
     {
-        return this._blackboxURLsSetting.value.includes(sourceCode.contentIdentifier);
+        for (let regex of this._blackboxedPatternDataMap.keys()) {
+            if (regex.test(sourceCode.contentIdentifier))
+                return {type: DebuggerManager.BlackboxType.Pattern, regex};
+        }
+
+        if (this._blackboxedURLsSetting.value.includes(sourceCode.contentIdentifier))
+            return {type: DebuggerManager.BlackboxType.URL};
+
+        return null;
     }
 
+    get blackboxPatterns()
+    {
+        return Array.from(this._blackboxedPatternDataMap.keys());
+    }
+
     setShouldBlackboxScript(sourceCode, shouldBlackbox)
     {
         console.assert(DebuggerManager.supportsBlackboxingScripts());
@@ -417,19 +445,52 @@
         console.assert(sourceCode instanceof WI.SourceCode);
         console.assert(sourceCode.contentIdentifier);
         console.assert(!isWebKitInjectedScript(sourceCode.contentIdentifier));
+        console.assert(shouldBlackbox !== ((this.blackboxDataForSourceCode(sourceCode) || {}).type === DebuggerManager.BlackboxType.URL));
 
-        this._blackboxURLsSetting.value.toggleIncludes(sourceCode.contentIdentifier, shouldBlackbox);
-        this._blackboxURLsSetting.save();
+        this._blackboxedURLsSetting.value.toggleIncludes(sourceCode.contentIdentifier, shouldBlackbox);
+        this._blackboxedURLsSetting.save();
 
+        const caseSensitive = true;
         for (let target of WI.targets) {
             // COMPATIBILITY (iOS 13): Debugger.setShouldBlackboxURL did not exist yet.
             if (target.DebuggerAgent.setShouldBlackboxURL)
-                target.DebuggerAgent.setShouldBlackboxURL(sourceCode.contentIdentifier, !!shouldBlackbox);
+                target.DebuggerAgent.setShouldBlackboxURL(sourceCode.contentIdentifier, !!shouldBlackbox, caseSensitive);
         }
 
-        this.dispatchEventToListeners(DebuggerManager.Event.BlackboxedURLsChanged);
+        this.dispatchEventToListeners(DebuggerManager.Event.BlackboxChanged);
     }
 
+    setShouldBlackboxPattern(regex, shouldBlackbox)
+    {
+        console.assert(DebuggerManager.supportsBlackboxingScripts());
+        console.assert(regex instanceof RegExp);
+
+        if (shouldBlackbox) {
+            console.assert(!this._blackboxedPatternDataMap.has(regex));
+
+            let data = {
+                url: regex.source,
+                caseSensitive: !regex.ignoreCase,
+            };
+            this._blackboxedPatternDataMap.set(regex, data);
+            this._blackboxedPatternsSetting.value.push(data);
+        } else {
+            console.assert(this._blackboxedPatternDataMap.has(regex));
+            this._blackboxedPatternsSetting.value.remove(this._blackboxedPatternDataMap.take(regex));
+        }
+
+        this._blackboxedPatternsSetting.save();
+
+        const isRegex = true;
+        for (let target of WI.targets) {
+            // COMPATIBILITY (iOS 13): Debugger.setShouldBlackboxURL did not exist yet.
+            if (target.DebuggerAgent.setShouldBlackboxURL)
+                target.DebuggerAgent.setShouldBlackboxURL(regex.source, !!shouldBlackbox, !regex.ignoreCase, isRegex);
+        }
+
+        this.dispatchEventToListeners(DebuggerManager.Event.BlackboxChanged);
+    }
+
     get asyncStackTraceDepth()
     {
         return this._asyncStackTraceDepthSetting.value;
@@ -1430,7 +1491,7 @@
     BreakpointsEnabledDidChange: "debugger-manager-breakpoints-enabled-did-change",
     ProbeSetAdded: "debugger-manager-probe-set-added",
     ProbeSetRemoved: "debugger-manager-probe-set-removed",
-    BlackboxedURLsChanged: "blackboxed-urls-changed",
+    BlackboxChanged: "blackboxed-urls-changed",
 };
 
 WI.DebuggerManager.PauseReason = {
@@ -1457,3 +1518,8 @@
     // COMPATIBILITY (iOS 13): DOMDebugger.EventBreakpointType.EventListener was replaced by DOMDebugger.EventBreakpointType.Listener.
     EventListener: "event-listener",
 };
+
+WI.DebuggerManager.BlackboxType = {
+    Pattern: "pattern",
+    URL: "url",
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Images/Hide.svg (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Images/Hide.svg	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/Hide.svg	2019-10-12 03:57:43 UTC (rev 251039)
@@ -1,7 +1,37 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Copyright © 2019 Apple Inc. All rights reserved. -->
-<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 11">
-    <path fill="none" stroke="currentColor" d="M 7.942 8.124 C 6.53 8.124 5.385 6.95 5.385 5.499 C 5.385 4.05 6.53 2.875 7.942 2.875 C 9.355 2.875 10.5 4.05 10.5 5.499 C 10.5 6.95 9.355 8.124 7.942 8.124 M 7.942 1.0 C 3.923 1.0 1.001 5.499 1.001 5.499 C 1.001 5.499 3.923 9.999 7.942 9.999 C 11.962 9.999 14.884 5.499 14.884 5.499 C 14.884 5.499 11.962 1.0 7.942 1.0"/>
-    <path fill="currentColor" d="M 7.942 4.375 C 7.337 4.375 6.846 4.878 6.846 5.5 C 6.846 6.121 7.337 6.625 7.942 6.625 C 8.548 6.625 9.038 6.121 9.038 5.5 C 9.038 4.878 8.548 4.375 7.942 4.375"/>
-    <path stroke="currentColor" d="M 15.5 2 L 0.5 9"></path>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 16 11">
+    <style>
+        svg {
+            display: none;
+        }
+
+        svg:target {
+            display: initial;
+        }
+
+        #currentColor {
+            --color: currentColor;
+        }
+
+        #white {
+            --color: white;
+        }
+
+        #black {
+            --color: black;
+        }
+    </style>
+
+    <svg>
+        <symbol id="content">
+            <path fill="none" stroke="var(--color)" d="M 7.942 8.124 C 6.53 8.124 5.385 6.95 5.385 5.499 C 5.385 4.05 6.53 2.875 7.942 2.875 C 9.355 2.875 10.5 4.05 10.5 5.499 C 10.5 6.95 9.355 8.124 7.942 8.124 M 7.942 1.0 C 3.923 1.0 1.001 5.499 1.001 5.499 C 1.001 5.499 3.923 9.999 7.942 9.999 C 11.962 9.999 14.884 5.499 14.884 5.499 C 14.884 5.499 11.962 1.0 7.942 1.0"/>
+            <path fill="var(--color)" d="M 7.942 4.375 C 7.337 4.375 6.846 4.878 6.846 5.5 C 6.846 6.121 7.337 6.625 7.942 6.625 C 8.548 6.625 9.038 6.121 9.038 5.5 C 9.038 4.878 8.548 4.375 7.942 4.375"/>
+            <path stroke="var(--color)" d="M 15.5 2 L 0.5 9"></path>
+        </symbol>
+    </svg>
+
+    <svg id="currentColor"><use xlink:href=""
+    <svg id="white"><use xlink:href=""
+    <svg id="black"><use xlink:href=""
 </svg>

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2019-10-12 03:57:43 UTC (rev 251039)
@@ -37,6 +37,7 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
+    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -599,6 +600,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""

Added: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.css (0 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.css	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.css	2019-10-12 03:57:43 UTC (rev 251039)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.settings-view.blackbox > :matches(p, table) {
+    width: 100%;
+    max-width: calc(min(50em, 100% - 40px));
+    margin: 1em auto 2em;
+}
+
+.settings-view.blackbox > p {
+    font-size: 12px;
+}
+
+.settings-view.blackbox > * + p {
+    margin-top: 2em;
+}
+
+.settings-view.blackbox > p:last-child {
+    margin-bottom: 0;
+}
+
+.settings-view.blackbox > p > .toggle-script-blackbox {
+    display: inline-block;
+    width: 15px;
+    height: 15px;
+    vertical-align: bottom;
+}
+
+.settings-view.blackbox > table {
+    border-collapse: collapse;
+}
+
+.settings-view.blackbox > table > thead th {
+    padding: 0 4px 4px;
+}
+
+.settings-view.blackbox > table > tbody td {
+    padding: 2px 0;
+}
+
+.settings-view.blackbox > table > tbody td:not(.remove-blackbox) {
+    border: 1px solid var(--border-color);
+}
+
+.settings-view.blackbox > table :matches(th, td).url {
+    text-align: start;
+}
+
+.settings-view.blackbox > table > tbody td.url > .CodeMirror {
+    min-width: 110px;
+    height: auto;
+}
+
+.settings-view.blackbox > table :matches(th, td):matches(.case-sensitive, .remove-blackbox) {
+    width: 1px;
+    white-space: nowrap;
+    text-align: center;
+}
+
+.settings-view.blackbox > table > tbody > tr:not(:hover) > td.remove-blackbox {
+    opacity: 0;
+}
+
+.settings-view.blackbox > table > tbody td.remove-blackbox > .remove-blackbox-button {
+    width: 15px;
+    height: 15px;
+    -webkit-margin-start: 4px;
+}

Added: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.js (0 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxSettingsView.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.BlackboxSettingsView = class BlackboxSettingsView extends WI.SettingsView
+{
+    constructor()
+    {
+        super("blackbox", WI.UIString("Blackbox"));
+
+        this._blackboxPatternCodeMirrorMap = new Map;
+    }
+
+    // Public
+
+    selectBlackboxPattern(regex)
+    {
+        console.assert(regex instanceof RegExp);
+        console.assert(this.didInitialLayout);
+
+        let codeMirror = this._blackboxPatternCodeMirrorMap.get(regex);
+        console.assert(codeMirror);
+        if (!codeMirror)
+            return;
+
+        codeMirror.focus();
+    }
+
+    // Protected
+
+    initialLayout()
+    {
+        super.initialLayout();
+
+        let patternBlackboxExplanationElement = this.element.appendChild(document.createElement("p"));
+        patternBlackboxExplanationElement.textContent = WI.UIString("If the URL of any script matches one of the regular _expression_ patterns below, any pauses that would have happened in that script will be deferred until execution has continued to outside of that script.");
+
+        let table = this.element.appendChild(document.createElement("table"));
+
+        let tableHead = table.appendChild(document.createElement("thead"));
+
+        let tableHeadRow = tableHead.appendChild(document.createElement("tr"));
+
+        let urlHeaderCell = tableHeadRow.appendChild(document.createElement("th"));
+        urlHeaderCell.classList.add("url");
+        urlHeaderCell.textContent = WI.UIString("URL Pattern");
+
+        let caseSensitiveHeaderCell = tableHeadRow.appendChild(document.createElement("th"));
+        caseSensitiveHeaderCell.classList.add("case-sensitive");
+        caseSensitiveHeaderCell.textContent = WI.UIString("Case Sensitive");
+
+        let removeBlackboxHeaderCell = tableHeadRow.appendChild(document.createElement("th"));
+        removeBlackboxHeaderCell.classList.add("remove-blackbox");
+
+        this._tableBody = table.appendChild(document.createElement("tbody"));
+
+        for (let regex of WI.debuggerManager.blackboxPatterns)
+            this._addRow(regex);
+
+        if (!this._tableBody.children.length)
+            this._addRow(null);
+
+        let tableFoot = table.appendChild(document.createElement("tfoot"));
+
+        let tableFooterRow = tableFoot.appendChild(document.createElement("tr"));
+
+        let addBlackboxCell = tableFooterRow.appendChild(document.createElement("td"));
+
+        let addBlackboxButton = addBlackboxCell.appendChild(document.createElement("button"));
+        addBlackboxButton.textContent = WI.UIString("Add Pattern");
+        addBlackboxButton.addEventListener("click", (event) => {
+            for (let [regex, codeMirror] of this._blackboxPatternCodeMirrorMap) {
+                if (!regex) {
+                    codeMirror.focus();
+                    return;
+                }
+            }
+
+            this._addRow(null);
+        });
+
+        let individualBlackboxExplanationElement = this.element.appendChild(document.createElement("p"));
+        let blackboxIconElement = WI.ImageUtilities.useSVGSymbol("Images/Hide.svg#currentColor", "toggle-script-blackbox", WI.UIString("Ignore script when debugging"));
+        String.format(WI.UIString("Scripts can also be individually blackboxed by clicking on the %s icon that is shown on hover."), [blackboxIconElement], String.standardFormatters, individualBlackboxExplanationElement, (a, b) => {
+            a.append(b);
+            return a;
+        });
+    }
+
+    // Private
+
+    _addRow(regex)
+    {
+        let tableBodyRow = this._tableBody.appendChild(document.createElement("tr"));
+
+        let urlBodyCell = tableBodyRow.appendChild(document.createElement("td"));
+        urlBodyCell.classList.add("url");
+
+        let urlCodeMirror = WI.CodeMirrorEditor.create(urlBodyCell, {
+            extraKeys: {"Tab": false, "Shift-Tab": false},
+            lineWrapping: false,
+            matchBrackets: false,
+            mode: "text/x-regex",
+            placeholder: WI.UIString("Regular _expression_"),
+            scrollbarStyle: null,
+            value: regex ? regex.source : "",
+        });
+        this._blackboxPatternCodeMirrorMap.set(regex, urlCodeMirror);
+
+        this.needsLayout();
+
+        let caseSensitiveBodyCell = tableBodyRow.appendChild(document.createElement("td"));
+        caseSensitiveBodyCell.classList.add("case-sensitive");
+
+        let caseSensitiveCheckbox = caseSensitiveBodyCell.appendChild(document.createElement("input"));
+        caseSensitiveCheckbox.type = "checkbox";
+        caseSensitiveCheckbox.checked = regex ? !regex.ignoreCase : true;
+
+        let removeBlackboxBodyCell = tableBodyRow.appendChild(document.createElement("td"));
+        removeBlackboxBodyCell.classList.add("remove-blackbox");
+
+        let removeBlackboxButton = removeBlackboxBodyCell.appendChild(WI.ImageUtilities.useSVGSymbol("Images/NavigationItemTrash.svg", "remove-blackbox-button", WI.UIString("Remove Blackbox")));
+        removeBlackboxButton.addEventListener("click", (event) => {
+            if (regex)
+                WI.debuggerManager.setShouldBlackboxPattern(regex, false);
+            regex = null;
+
+            this._blackboxPatternCodeMirrorMap.delete(regex);
+
+            tableBodyRow.remove();
+
+            if (!this._tableBody.children.length)
+                this._addRow(null);
+        });
+
+        let update = () => {
+            let url = ""
+
+            if (regex) {
+                if (regex.source === url && regex.ignoreCase !== caseSensitiveCheckbox.checked)
+                    return;
+
+                WI.debuggerManager.setShouldBlackboxPattern(regex, false);
+            }
+
+            this._blackboxPatternCodeMirrorMap.delete(regex);
+
+            regex = url ? new RegExp(url, !caseSensitiveCheckbox.checked ? "i" : "") : null;
+            if (regex)
+                WI.debuggerManager.setShouldBlackboxPattern(regex, true);
+
+            console.assert(regex || !this._blackboxPatternCodeMirrorMap.has(regex));
+            this._blackboxPatternCodeMirrorMap.set(regex, urlCodeMirror);
+        };
+        urlCodeMirror.addKeyMap({
+            "Enter": update,
+            "Esc": update,
+        });
+        urlCodeMirror.on("blur", update);
+        caseSensitiveCheckbox.addEventListener("change", update);
+
+        if (!regex)
+            urlCodeMirror.focus();
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContextMenuUtilities.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContextMenuUtilities.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContextMenuUtilities.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -85,10 +85,18 @@
     contextMenu.appendSeparator();
 
     if (sourceCode.supportsScriptBlackboxing) {
-        let isBlackboxed = WI.debuggerManager.isScriptBlackboxed(sourceCode);
-        contextMenu.appendItem(isBlackboxed ? WI.UIString("Include script when debugging") : WI.UIString("Ignore script when debugging"), () => {
-            WI.debuggerManager.setShouldBlackboxScript(sourceCode, !isBlackboxed);
-        });
+        let blackboxData = WI.debuggerManager.blackboxDataForSourceCode(sourceCode);
+        if (blackboxData && blackboxData.type === WI.DebuggerManager.BlackboxType.Pattern) {
+            contextMenu.appendItem(WI.UIString("Reveal blackbox pattern"), () => {
+                WI.showSettingsTab({
+                    blackboxPatternToSelect: blackboxData.regex,
+                });
+            });
+        } else {
+            contextMenu.appendItem(blackboxData ? WI.UIString("Include script when debugging") : WI.UIString("Ignore script when debugging"), () => {
+                WI.debuggerManager.setShouldBlackboxScript(sourceCode, !blackboxData);
+            });
+        }
     }
 
     contextMenu.appendSeparator();

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -153,10 +153,22 @@
         }
     }
 
+    selectBlackboxPattern(regex)
+    {
+        console.assert(regex instanceof RegExp);
+
+        console.assert(this._blackboxSettingsView);
+        this.selectedSettingsView = this._blackboxSettingsView;
+
+        this._blackboxSettingsView.selectBlackboxPattern(regex);
+    }
+
     // Protected
 
     initialLayout()
     {
+        super.initialLayout();
+
         this._navigationBar = new WI.NavigationBar;
         this._navigationBar.addEventListener(WI.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);
         this.addSubview(this._navigationBar);
@@ -165,6 +177,12 @@
         this._createElementsSettingsView();
         this._createSourcesSettingsView();
         this._createConsoleSettingsView();
+
+        if (WI.DebuggerManager.supportsBlackboxingScripts()) {
+            this._blackboxSettingsView = new WI.BlackboxSettingsView;
+            this.addSettingsView(this._blackboxSettingsView);
+        }
+
         this._createExperimentalSettingsView();
 
         if (WI.isEngineeringBuild) {
@@ -251,7 +269,7 @@
     {
         let sourcesSettingsView = new WI.SettingsView("sources", WI.UIString("Sources"));
 
-        sourcesSettingsView.addSetting(WI.UIString("Debugger:"), WI.settings.showScopeChainOnPause, WI.UIString("Show Scope Chain on pause"));
+        sourcesSettingsView.addSetting(WI.UIString("Debugging:"), WI.settings.showScopeChainOnPause, WI.UIString("Show Scope Chain on pause"));
 
         sourcesSettingsView.addSeparator();
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.css	2019-10-12 03:57:43 UTC (rev 251039)
@@ -25,24 +25,25 @@
 
  .tree-outline .item.shader-program .status > img {
     width: 18px;
-    margin-top: 2px;
-    content: url(../Images/Hide.svg);
+    height: 16px;
+    padding: 0 2px;
+    content: url(../Images/Hide.svg#white);
+    background-color: grey;
+    border-radius: 3px;
 }
 
-.tree-outline .item.shader-program:not(:hover, .selected, .disabled) .status > img {
+.tree-outline .item.shader-program:not(:hover, .disabled) .status > img {
     display: none;
 }
 
-.tree-outline:focus .item.shader-program.selected .status > img {
-    filter: invert();
+.tree-outline .item.shader-program:not(.disabled) .status > img {
+    opacity: 0.7;
 }
 
-.tree-outline .item.shader-program.disabled .status > img {
-    opacity: 0.5;
-}
-
 @media (prefers-color-scheme: dark) {
     .tree-outline .item.shader-program .status > img {
-        filter: invert();
+        content: url(../Images/Hide.svg#black);
+        background-color: hsl(0, 0%, 70%);
     }
 }
+

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css	2019-10-12 03:57:43 UTC (rev 251039)
@@ -23,27 +23,47 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-.tree-outline .item .status > .toggle-script-blackboxed {
+.tree-outline .item .status > .toggle-script-blackbox,
+.tree-outline:focus .item.selected .status > .toggle-script-blackbox.pattern-blackboxed {
+    content: url(../Images/Hide.svg#white);
+}
+
+.tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed {
+    content: url(../Images/Hide.svg#black);
+}
+
+.tree-outline .item .status > .toggle-script-blackbox {
     width: 18px;
     margin-top: 2px;
-    content: url(../Images/Hide.svg);
 }
 
-.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackboxed,
-.tree-outline .item:not(:hover) .status > .toggle-script-blackboxed:not(.blackboxed) {
-    display: none;
+.tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed) {
+    height: 16px;
+    margin-top: 0;
+    padding: 0 2px;
+    background-color: grey;
+    border-radius: 3px;
 }
 
-.tree-outline:focus .item.selected .status > .toggle-script-blackboxed {
-    filter: invert();
+.tree-outline .item .status > .toggle-script-blackbox:not(.url-blackboxed, .pattern-blackboxed) {
+    opacity: 0.7;
 }
 
-.tree-outline .item .status > .toggle-script-blackboxed.blackboxed {
-    opacity: 0.5;
+.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackbox,
+.tree-outline .item:not(:hover) .status > .toggle-script-blackbox:not(.pattern-blackboxed, .url-blackboxed) {
+    display: none;
 }
 
 @media (prefers-color-scheme: dark) {
-    .tree-outline .item .status > .toggle-script-blackboxed {
-        filter: invert();
+    .tree-outline .item .status > .toggle-script-blackbox {
+        content: url(../Images/Hide.svg#black);
     }
+
+    .tree-outline .item .status > .toggle-script-blackbox.pattern-blackboxed {
+        content: url(../Images/Hide.svg#white);
+    }
+
+    .tree-outline .item .status > .toggle-script-blackbox:not(.pattern-blackboxed) {
+        background-color: hsl(0, 0%, 70%);
+    }
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js (251038 => 251039)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js	2019-10-12 03:40:42 UTC (rev 251038)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js	2019-10-12 03:57:43 UTC (rev 251039)
@@ -162,7 +162,7 @@
         if (this._sourceCode.supportsScriptBlackboxing) {
             if (!this._toggleBlackboxedImageElement) {
                 this._toggleBlackboxedImageElement = document.createElement("img");
-                this._toggleBlackboxedImageElement.classList.add("toggle-script-blackboxed");
+                this._toggleBlackboxedImageElement.classList.add("toggle-script-blackbox");
                 this._toggleBlackboxedImageElement.addEventListener("click", this._handleToggleBlackboxedImageElementClicked.bind(this));
             }
 
@@ -195,9 +195,9 @@
         let newSupportsScriptBlackboxing = this._sourceCode.supportsScriptBlackboxing;
         if (oldSupportsScriptBlackboxing !== newSupportsScriptBlackboxing) {
             if (newSupportsScriptBlackboxing)
-                WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BlackboxedURLsChanged, this._updateToggleBlackboxImageElementState, this);
+                WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BlackboxChanged, this._updateToggleBlackboxImageElementState, this);
             else
-                WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BlackboxedURLsChanged, this._updateToggleBlackboxImageElementState, this);
+                WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.BlackboxChanged, this._updateToggleBlackboxImageElementState, this);
         }
 
         this.updateSourceMapResources();
@@ -209,16 +209,39 @@
 
     _updateToggleBlackboxImageElementState()
     {
-        let isBlackboxed = WI.debuggerManager.isScriptBlackboxed(this._sourceCode);
-        this._toggleBlackboxedImageElement.classList.toggle("blackboxed", isBlackboxed);
-        this._toggleBlackboxedImageElement.title = isBlackboxed ? WI.UIString("Include script when debugging") : WI.UIString("Ignore script when debugging");
+        let blackboxData = WI.debuggerManager.blackboxDataForSourceCode(this._sourceCode);
+
+        this._toggleBlackboxedImageElement.classList.toggle("pattern-blackboxed", blackboxData && blackboxData.type === WI.DebuggerManager.BlackboxType.Pattern);
+        this._toggleBlackboxedImageElement.classList.toggle("url-blackboxed", blackboxData && blackboxData.type === WI.DebuggerManager.BlackboxType.URL);
+
+        if (blackboxData) {
+            switch (blackboxData.type) {
+            case WI.DebuggerManager.BlackboxType.Pattern:
+                this._toggleBlackboxedImageElement.title = WI.UIString("Script ignored when debugging due to previously set blackbox URL pattern");
+                break;
+
+            case WI.DebuggerManager.BlackboxType.URL:
+                this._toggleBlackboxedImageElement.title = WI.UIString("Include script when debugging");
+                break;
+            }
+
+            console.assert(this._toggleBlackboxedImageElement.title);
+        } else
+            this._toggleBlackboxedImageElement.title = WI.UIString("Ignore script when debugging");
     }
 
     _handleToggleBlackboxedImageElementClicked(event)
     {
-        let isBlackboxed = WI.debuggerManager.isScriptBlackboxed(this._sourceCode);
-        WI.debuggerManager.setShouldBlackboxScript(this._sourceCode, !isBlackboxed);
+        let blackboxData = WI.debuggerManager.blackboxDataForSourceCode(this._sourceCode);
+        if (blackboxData && blackboxData.type === WI.DebuggerManager.BlackboxType.Pattern) {
+            WI.showSettingsTab({
+                blackboxPatternToSelect: blackboxData.regex,
+            });
+            return;
+        }
 
+        WI.debuggerManager.setShouldBlackboxScript(this._sourceCode, !blackboxData);
+
         this._updateToggleBlackboxImageElementState();
     }
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to