WebKit Bugzilla
Attachment 372117 Details for
Bug 17240
: Web Inspector: implement blackboxing of script resources
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-17240-20190614012800.patch (text/plain), 36.58 KB, created by
Devin Rousso
on 2019-06-14 01:28:01 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2019-06-14 01:28:01 PDT
Size:
36.58 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 65ee267357143c50676cb7e14a2d9ac568a2d18b..f00347749e4b3452d1e9d029aa36a29b19d0e1bc 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,31 @@ >+2019-06-14 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: implement blackboxing of script resources >+ https://bugs.webkit.org/show_bug.cgi?id=17240 >+ <rdar://problem/5732847> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/protocol/Debugger.json: >+ * inspector/agents/InspectorDebuggerAgent.h: >+ * inspector/agents/InspectorDebuggerAgent.cpp: >+ (Inspector::isWebKitInjectedScript): >+ (Inspector::InspectorDebuggerAgent::enable): >+ (Inspector::InspectorDebuggerAgent::setShouldBlackboxURL): Added. >+ (Inspector::InspectorDebuggerAgent::setPauseForInternalScripts): >+ (Inspector::InspectorDebuggerAgent::didParseSource): >+ (Inspector::InspectorDebuggerAgent::toggleBlackboxForScriptsMatchingPredicate): Added. >+ (Inspector::InspectorDebuggerAgent::clearDebuggerBreakpointState): >+ >+ * debugger/Debugger.h: >+ * debugger/Debugger.cpp: >+ (JSC::Debugger::pauseIfNeeded): >+ (JSC::Debugger::isBlackboxed const): Added. >+ (JSC::Debugger::setShouldBlackbox): Added. >+ (JSC::Debugger::isBlacklisted const): Deleted. >+ (JSC::Debugger::addToBlacklist): Deleted. >+ (JSC::Debugger::clearBlacklist): Deleted. >+ > 2019-06-13 Yusuke Suzuki <ysuzuki@apple.com> > > Yarr bytecode compilation failure should be gracefully handled >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index 615d5c677c289050929f15585f4fcbf838de0d33..97ea5d86a2b0495cc77237a3c515bdf1402c5907 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,54 @@ >+2019-06-14 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: implement blackboxing of script resources >+ https://bugs.webkit.org/show_bug.cgi?id=17240 >+ <rdar://problem/5732847> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UserInterface/Controllers/DebuggerManager.js: >+ (WI.DebuggerManager): >+ (WI.DebuggerManager.prototype.initializeTarget): >+ (WI.DebuggerManager.supportsBlackboxingScripts): Added. >+ (WI.DebuggerManager.prototype.isScriptBlackboxed): Added. >+ (WI.DebuggerManager.prototype.setShouldBlackboxScript): Added. >+ >+ * UserInterface/Models/SourceCode.js: >+ (WI.SourceCode.prototype.get isScript): Added. >+ * UserInterface/Models/Script.js: >+ (WI.Script.prototype.get isScript): Added. >+ * UserInterface/Models/Resource.js: >+ (WI.Resource.prototype.get isScript): Added. >+ Provide a more straightforward way of determining if a `WI.SourceCode` is a script. >+ >+ * UserInterface/Views/SourceCodeTreeElement.js: >+ (WI.SourceCodeTreeElement.prototype.canSelectOnMouseDown): >+ (WI.SourceCodeTreeElement.prototype.updateStatus): >+ (WI.SourceCodeTreeElement.prototype._updateSourceCode): >+ (WI.SourceCodeTreeElement.prototype._updateToggleBlackboxImageElementState): >+ (WI.SourceCodeTreeElement.prototype._handleToggleBlackboxedImageElementClicked): >+ * UserInterface/Views/SourceCodeTreeElement.css: Added. >+ (.tree-outline .item .status > .toggle-script-blackboxed): >+ (.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackboxed,): >+ (.tree-outline:focus .item.selected .status > .toggle-script-blackboxed): >+ (.tree-outline .item .status > .toggle-script-blackboxed.blackboxed): >+ (@media (prefers-color-scheme: dark) .tree-outline .item .status > .toggle-script-blackboxed): >+ >+ * UserInterface/Views/ResourceTreeElement.js: >+ (WI.ResourceTreeElement.prototype._updateResource): >+ (WI.ResourceTreeElement.prototype.updateStatus): Added. >+ (WI.ResourceTreeElement.prototype._updateStatus): Deleted. >+ Make sure that the loading indicator doesn't override the blackbox toggle. >+ >+ * UserInterface/Base/Setting.js: >+ (WI.Setting.prototype.set value): >+ (WI.Setting.prototype.save): Added. >+ When modifying an array value, that doesn't go through `WI.Setting.prototype.set value`, so >+ we need a more "manual" way of saving the new value. >+ >+ * UserInterface/Main.html: >+ * Localizations/en.lproj/localizedStrings.js: >+ > 2019-06-13 Devin Rousso <drousso@apple.com> > > Web Inspector: Settings: indent type and size settings aren't respected everywhere >diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp >index 09a6ded96e077e34c44d07ad93efa16a70c8609e..b3ca98645ab3f93a531b6c9611c7b35cc930b880 100644 >--- a/Source/JavaScriptCore/debugger/Debugger.cpp >+++ b/Source/JavaScriptCore/debugger/Debugger.cpp >@@ -695,7 +695,7 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame) > return; > > intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame); >- if (isBlacklisted(sourceID)) >+ if (isBlackboxed(sourceID)) > return; > > DebuggerPausedScope debuggerPausedScope(*this); >@@ -928,19 +928,17 @@ DebuggerCallFrame& Debugger::currentDebuggerCallFrame() > return *m_currentDebuggerCallFrame; > } > >-bool Debugger::isBlacklisted(SourceID sourceID) const >+bool Debugger::isBlackboxed(SourceID sourceID) const > { >- return m_blacklistedScripts.contains(sourceID); >+ return m_blackboxedScripts.contains(sourceID); > } > >-void Debugger::addToBlacklist(SourceID sourceID) >+void Debugger::setShouldBlackbox(SourceID sourceID, bool shouldBlackbox) > { >- m_blacklistedScripts.add(sourceID); >-} >- >-void Debugger::clearBlacklist() >-{ >- m_blacklistedScripts.clear(); >+ if (shouldBlackbox) >+ m_blackboxedScripts.add(sourceID); >+ else >+ m_blackboxedScripts.remove(sourceID); > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/debugger/Debugger.h b/Source/JavaScriptCore/debugger/Debugger.h >index bcd72ea09f5f717a65f65d7d2efc175e023e6990..1e32160bdad07850aa5af9e03780915585b4ca25 100644 >--- a/Source/JavaScriptCore/debugger/Debugger.h >+++ b/Source/JavaScriptCore/debugger/Debugger.h >@@ -110,9 +110,8 @@ public: > void stepOverStatement(); > void stepOutOfFunction(); > >- bool isBlacklisted(SourceID) const; >- void addToBlacklist(SourceID); >- void clearBlacklist(); >+ bool isBlackboxed(SourceID) const; >+ void setShouldBlackbox(SourceID, bool shouldBlackbox); > > bool isPaused() const { return m_isPaused; } > bool isStepping() const { return m_steppingMode == SteppingModeEnabled; } >@@ -221,7 +220,7 @@ private: > VM& m_vm; > HashSet<JSGlobalObject*> m_globalObjects; > HashMap<SourceID, DebuggerParseData, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> m_parseDataMap; >- HashSet<SourceID, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> m_blacklistedScripts; >+ HashSet<SourceID, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> m_blackboxedScripts; > > PauseOnExceptionsState m_pauseOnExceptionsState; > bool m_pauseAtNextOpportunity : 1; >diff --git a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >index 7e3dc65e645cd8f1e898c46af55518c9c34ff40d..20c751b84dd0f8f98cf7909f02c407d4d640039a 100644 >--- a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >+++ b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >@@ -41,6 +41,7 @@ > #include "ScriptCallStackFactory.h" > #include "ScriptDebugServer.h" > #include "ScriptObject.h" >+#include <wtf/Function.h> > #include <wtf/JSONValues.h> > #include <wtf/NeverDestroyed.h> > #include <wtf/Stopwatch.h> >@@ -60,6 +61,11 @@ static String objectGroupForBreakpointAction(const ScriptBreakpointAction& actio > return makeString("breakpoint-action-", action.identifier); > } > >+static bool isWebKitInjectedScript(const String& sourceURL) >+{ >+ return sourceURL.startsWith("__InjectedScript_") && sourceURL.endsWith(".js"); >+} >+ > InspectorDebuggerAgent::InspectorDebuggerAgent(AgentContext& context) > : InspectorAgentBase("Debugger"_s) > , m_frontendDispatcher(std::make_unique<DebuggerFrontendDispatcher>(context.frontendRouter)) >@@ -96,6 +102,20 @@ void InspectorDebuggerAgent::enable() > > for (auto* listener : copyToVector(m_listeners)) > listener->debuggerWasEnabled(); >+ >+ toggleBlackboxForScriptsMatchingPredicate(true, [&] (const Script& script) { >+ if (!script.sourceURL.isEmpty()) { >+ if (m_pauseForInternalScripts && isWebKitInjectedScript(script.sourceURL)) >+ return true; >+ if (m_blackboxedURLs.contains(script.sourceURL)) >+ return true; >+ } >+ if (!script.url.isEmpty()) { >+ if (m_blackboxedURLs.contains(script.url)) >+ return true; >+ } >+ return false; >+ }); > } > > void InspectorDebuggerAgent::disable(bool isBeingDestroyed) >@@ -857,6 +877,28 @@ void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const > } > } > >+void InspectorDebuggerAgent::setShouldBlackboxURL(ErrorString& errorString, const String& url, bool shouldBlackbox) >+{ >+ if (url.isEmpty()) { >+ errorString = "URL must not be empty"_s; >+ return; >+ } >+ >+ if (isWebKitInjectedScript(url)) { >+ errorString = "Blackboxing of internal scripts is controlled by 'setPauseForInternalScripts'"; >+ return; >+ } >+ >+ if (shouldBlackbox) >+ m_blackboxedURLs.add(url); >+ else >+ m_blackboxedURLs.remove(url); >+ >+ toggleBlackboxForScriptsMatchingPredicate(shouldBlackbox, [&] (const Script& script) { >+ return script.sourceURL == url || script.url == url; >+ }); >+} >+ > void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText) > { > if (m_scriptDebugServer.pauseOnExceptionsState() != JSC::Debugger::DontPauseOnExceptions) >@@ -884,13 +926,9 @@ void InspectorDebuggerAgent::setPauseForInternalScripts(ErrorString&, bool shoul > > m_pauseForInternalScripts = shouldPause; > >- if (m_pauseForInternalScripts) >- m_scriptDebugServer.clearBlacklist(); >-} >- >-static bool isWebKitInjectedScript(const String& sourceURL) >-{ >- return sourceURL.startsWith("__InjectedScript_") && sourceURL.endsWith(".js"); >+ toggleBlackboxForScriptsMatchingPredicate(m_pauseForInternalScripts, [&] (const Script& script) { >+ return isWebKitInjectedScript(script.sourceURL); >+ }); > } > > void InspectorDebuggerAgent::didParseSource(JSC::SourceID sourceID, const Script& script) >@@ -910,7 +948,10 @@ void InspectorDebuggerAgent::didParseSource(JSC::SourceID sourceID, const Script > m_scripts.set(sourceID, script); > > if (hasSourceURL && isWebKitInjectedScript(sourceURL) && !m_pauseForInternalScripts) >- m_scriptDebugServer.addToBlacklist(sourceID); >+ m_scriptDebugServer.setShouldBlackbox(sourceID, true); >+ >+ if ((hasSourceURL && m_blackboxedURLs.contains(sourceURL)) || (!script.url.isEmpty() && m_blackboxedURLs.contains(script.url))) >+ m_scriptDebugServer.setShouldBlackbox(sourceID, true); > > String scriptURLForBreakpoints = hasSourceURL ? script.sourceURL : script.url; > if (scriptURLForBreakpoints.isEmpty()) >@@ -962,6 +1003,14 @@ void InspectorDebuggerAgent::failedToParseSource(const String& url, const String > m_frontendDispatcher->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage); > } > >+void InspectorDebuggerAgent::toggleBlackboxForScriptsMatchingPredicate(bool shouldBlackbox, WTF::Function<bool(const Script&)> predicate) >+{ >+ for (auto& entry : m_scripts) { >+ if (predicate(entry.value)) >+ m_scriptDebugServer.setShouldBlackbox(entry.key, shouldBlackbox); >+ } >+} >+ > void InspectorDebuggerAgent::didPause(JSC::ExecState& scriptState, JSC::JSValue callFrames, JSC::JSValue exceptionOrCaughtValue) > { > ASSERT(!m_pausedScriptState); >@@ -1093,7 +1142,7 @@ void InspectorDebuggerAgent::clearDebuggerBreakpointState() > JSC::JSLockHolder holder(m_scriptDebugServer.vm()); > m_scriptDebugServer.clearBreakpointActions(); > m_scriptDebugServer.clearBreakpoints(); >- m_scriptDebugServer.clearBlacklist(); >+ toggleBlackboxForScriptsMatchingPredicate(false, [] (const Script&) { return true; }); > } > > m_pausedScriptState = nullptr; >diff --git a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h >index 1311c4f162c6f00e1c577bb2ea1a79eafb8efc5c..493b51562d683b04cd466bcb9681fbd535ba1f08 100644 >--- a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h >+++ b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h >@@ -81,6 +81,7 @@ public: > void setPauseOnExceptions(ErrorString&, const String& pauseState) final; > void setPauseOnAssertions(ErrorString&, bool enabled) 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, RefPtr<Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex) final; >+ void setShouldBlackboxURL(ErrorString&, const String& url, bool shouldBlackbox) final; > > bool isPaused() const; > bool breakpointsActive() const; >@@ -144,6 +145,8 @@ private: > void didParseSource(JSC::SourceID, const Script&) final; > void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) final; > >+ void toggleBlackboxForScriptsMatchingPredicate(bool shouldBlackbox, WTF::Function<bool(const Script&)>); >+ > void breakpointActionSound(int breakpointActionIdentifier) final; > void breakpointActionProbe(JSC::ExecState&, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, JSC::JSValue sample) final; > >@@ -177,6 +180,7 @@ private: > ScriptDebugServer& m_scriptDebugServer; > InjectedScriptManager& m_injectedScriptManager; > HashMap<JSC::SourceID, Script> m_scripts; >+ HashSet<String> m_blackboxedURLs; > > HashSet<Listener*> m_listeners; > >diff --git a/Source/JavaScriptCore/inspector/protocol/Debugger.json b/Source/JavaScriptCore/inspector/protocol/Debugger.json >index a5495ca1103a870728013cfdf4063bff98341189..9768bda24e5e3f4799b35ac84be9e2da864d08e8 100644 >--- a/Source/JavaScriptCore/inspector/protocol/Debugger.json >+++ b/Source/JavaScriptCore/inspector/protocol/Debugger.json >@@ -286,6 +286,14 @@ > { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }, > { "name": "savedResultIndex", "type": "integer", "optional": true, "description": "If the result was saved, this is the $n index that can be used to access the value." } > ] >+ }, >+ { >+ "name": "setShouldBlackboxURL", >+ "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" } >+ ] > } > ], > "events": [ >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index 9a3c9ea4c4a35e98c0aa6440aee3fc91aae16296..f2908177c5933c86a2e76aa947c51cfdad0cc3a4 100644 >--- a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >+++ b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >@@ -565,6 +565,7 @@ localizedStrings["IP Address"] = "IP Address"; > localizedStrings["Identity"] = "Identity"; > localizedStrings["Idle"] = "Idle"; > 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"; > localizedStrings["Ignored"] = "Ignored"; > localizedStrings["Image"] = "Image"; >@@ -575,6 +576,7 @@ localizedStrings["Import"] = "Import"; > localizedStrings["Imported"] = "Imported"; > localizedStrings["Imported - %s"] = "Imported - %s"; > localizedStrings["Imported \u2014 %s"] = "Imported \u2014 %s"; >+localizedStrings["Include script when debugging"] = "Include script when debugging"; > localizedStrings["Incomplete"] = "Incomplete"; > localizedStrings["Indent width:"] = "Indent width:"; > localizedStrings["Index"] = "Index"; >diff --git a/Source/WebInspectorUI/UserInterface/Base/Setting.js b/Source/WebInspectorUI/UserInterface/Base/Setting.js >index bfa983806359e22083863b7fe6dc0e6fde2a50d3..c8eb793d657bf805168b9e464dbcfa60086e636a 100644 >--- a/Source/WebInspectorUI/UserInterface/Base/Setting.js >+++ b/Source/WebInspectorUI/UserInterface/Base/Setting.js >@@ -113,9 +113,13 @@ WI.Setting = class Setting extends WI.Object > > this._value = value; > >+ this.save(); >+ } >+ >+ save() >+ { > if (!window.InspectorTest && window.localStorage) { > try { >- // Use Object.shallowEqual to properly compare objects. > if (Object.shallowEqual(this._value, this._defaultValue)) > delete window.localStorage[this._localStorageKey]; > else >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >index 7aaeeb86849c9a3642363d9b208db9414b618567..89583f2623f616fda7dff7651cc36fac90eb5d42 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >@@ -72,6 +72,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > }); > this._assertionFailuresBreakpoint.resolved = true; > >+ this._blackboxURLsSetting = new WI.Setting("debugger-blackbox-urls", []); >+ > this._breakpoints = []; > this._breakpointContentIdentifierMap = new Multimap; > this._breakpointScriptIdentifierMap = new Multimap; >@@ -150,6 +152,11 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > if (target.DebuggerAgent.setPauseForInternalScripts) > target.DebuggerAgent.setPauseForInternalScripts(WI.settings.pauseForInternalScripts.value); > >+ if (target.DebuggerAgent.setShouldBlackboxURL) { >+ for (let url of this._blackboxURLsSetting.value) >+ target.DebuggerAgent.setShouldBlackboxURL(url, true); >+ } >+ > if (this.paused) > targetData.pauseIfNeeded(); > >@@ -165,6 +172,13 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > this._restoringBreakpoints = false; > } > >+ // Static >+ >+ static supportsBlackboxingScripts() >+ { >+ return InspectorBackend.domains.Debugger.setShouldBlackboxURL; >+ } >+ > // Public > > get paused() >@@ -334,6 +348,23 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > return knownScripts; > } > >+ isScriptBlackboxed(sourceCode) >+ { >+ return this._blackboxURLsSetting.value.includes(sourceCode.contentIdentifier); >+ } >+ >+ setShouldBlackboxScript(sourceCode, shouldBlackbox) >+ { >+ console.assert(DebuggerManager.supportsBlackboxingScripts()); >+ console.assert(!isWebKitInjectedScript(sourceCode.contentIdentifier)); >+ >+ this._blackboxURLsSetting.value.toggleIncludes(sourceCode.contentIdentifier, shouldBlackbox); >+ this._blackboxURLsSetting.save(); >+ >+ for (let target of WI.targets) >+ target.DebuggerAgent.setShouldBlackboxURL(sourceCode.contentIdentifier, shouldBlackbox); >+ } >+ > get asyncStackTraceDepth() > { > return this._asyncStackTraceDepthSetting.value; >diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html >index 6b4d613704ff5ba6123df03cac09cf917ac413ee..53be532b4189196ef2df230f4bedcf3c167d3d72 100644 >--- a/Source/WebInspectorUI/UserInterface/Main.html >+++ b/Source/WebInspectorUI/UserInterface/Main.html >@@ -197,6 +197,7 @@ > <link rel="stylesheet" href="Views/Slider.css"> > <link rel="stylesheet" href="Views/SoftContextMenu.css"> > <link rel="stylesheet" href="Views/SourceCodeTextEditor.css"> >+ <link rel="stylesheet" href="Views/SourceCodeTreeElement.css"> > <link rel="stylesheet" href="Views/SourcesNavigationSidebarPanel.css"> > <link rel="stylesheet" href="Views/SpreadsheetCSSStyleDeclarationEditor.css"> > <link rel="stylesheet" href="Views/SpreadsheetCSSStyleDeclarationSection.css"> >diff --git a/Source/WebInspectorUI/UserInterface/Models/Resource.js b/Source/WebInspectorUI/UserInterface/Models/Resource.js >index e931c127481310c21fc941e945c8dd3cb55f3d3f..304019a0cc27610bc71dfca722b9d7a2aa865321 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/Resource.js >+++ b/Source/WebInspectorUI/UserInterface/Models/Resource.js >@@ -352,6 +352,11 @@ WI.Resource = class Resource extends WI.SourceCode > return true; > } > >+ get isScript() >+ { >+ return this._type === Resource.Type.Script; >+ } >+ > get displayName() > { > return WI.displayNameForURL(this._url, this.urlComponents); >diff --git a/Source/WebInspectorUI/UserInterface/Models/Script.js b/Source/WebInspectorUI/UserInterface/Models/Script.js >index 82a2151e284d9474f1c2ec0c2a94e686b6bcf5f4..309ae138b05ceebeb203dbb7cc83d2e967b99b9e 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/Script.js >+++ b/Source/WebInspectorUI/UserInterface/Models/Script.js >@@ -120,6 +120,11 @@ WI.Script = class Script extends WI.SourceCode > return this._resource.mimeType; > } > >+ get isScript() >+ { >+ return true; >+ } >+ > get displayName() > { > if (this._url && !this._dynamicallyAddedScriptElement) >diff --git a/Source/WebInspectorUI/UserInterface/Models/SourceCode.js b/Source/WebInspectorUI/UserInterface/Models/SourceCode.js >index 834333641ac814936f8aedbbc4d9223fa9fafb87..0c339e86d6f173a346dc76e4807f8701ea9d2640 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/SourceCode.js >+++ b/Source/WebInspectorUI/UserInterface/Models/SourceCode.js >@@ -46,6 +46,12 @@ WI.SourceCode = class SourceCode extends WI.Object > return ""; > } > >+ get isScript() >+ { >+ // Implemented by subclasses if needed. >+ return false; >+ } >+ > get originalRevision() > { > return this._originalRevision; >diff --git a/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js b/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js >index 278c005ebf98fd05c78c6ed3e8c4dcdba0b37b85..85a90de30075a4ea6a3761212d2390f8e9c9239f 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js >@@ -118,8 +118,8 @@ WI.ResourceTreeElement = class ResourceTreeElement extends WI.SourceCodeTreeElem > if (this._resource) { > this._resource.removeEventListener(WI.Resource.Event.URLDidChange, this._urlDidChange, this); > this._resource.removeEventListener(WI.Resource.Event.TypeDidChange, this._typeDidChange, this); >- this._resource.removeEventListener(WI.Resource.Event.LoadingDidFinish, this._updateStatus, this); >- this._resource.removeEventListener(WI.Resource.Event.LoadingDidFail, this._updateStatus, this); >+ this._resource.removeEventListener(WI.Resource.Event.LoadingDidFinish, this.updateStatus, this); >+ this._resource.removeEventListener(WI.Resource.Event.LoadingDidFail, this.updateStatus, this); > } > > this._updateSourceCode(resource); >@@ -128,11 +128,11 @@ WI.ResourceTreeElement = class ResourceTreeElement extends WI.SourceCodeTreeElem > > resource.addEventListener(WI.Resource.Event.URLDidChange, this._urlDidChange, this); > resource.addEventListener(WI.Resource.Event.TypeDidChange, this._typeDidChange, this); >- resource.addEventListener(WI.Resource.Event.LoadingDidFinish, this._updateStatus, this); >- resource.addEventListener(WI.Resource.Event.LoadingDidFail, this._updateStatus, this); >+ resource.addEventListener(WI.Resource.Event.LoadingDidFinish, this.updateStatus, this); >+ resource.addEventListener(WI.Resource.Event.LoadingDidFail, this.updateStatus, this); > > this._updateTitles(); >- this._updateStatus(); >+ this.updateStatus(); > this._updateToolTip(); > } > >@@ -175,17 +175,13 @@ WI.ResourceTreeElement = class ResourceTreeElement extends WI.SourceCodeTreeElem > this.callFirstAncestorFunction("descendantResourceTreeElementMainTitleDidChange", [this, oldMainTitle]); > } > >- populateContextMenu(contextMenu, event) >+ updateStatus() > { >- WI.appendContextMenuItemsForSourceCode(contextMenu, this._resource); >+ super.updateStatus(); > >- super.populateContextMenu(contextMenu, event); >- } >+ if (!this._resource) >+ return; > >- // Private >- >- _updateStatus() >- { > if (this._resource.hadLoadingError()) > this.addClassName(WI.ResourceTreeElement.FailedStyleClassName); > else >@@ -194,15 +190,33 @@ WI.ResourceTreeElement = class ResourceTreeElement extends WI.SourceCodeTreeElem > if (this._resource.isLoading()) { > if (!this.status || !this.status[WI.ResourceTreeElement.SpinnerSymbol]) { > let spinner = new WI.IndeterminateProgressSpinner; >- this.status = spinner.element; >- this.status[WI.ResourceTreeElement.SpinnerSymbol] = true; >+ if (this.status) >+ this.statusElement.insertAdjacentElement("afterbegin", spinner.element); >+ else >+ this.status = spinner.element; >+ this.status[WI.ResourceTreeElement.SpinnerSymbol] = spinner.element; > } > } else { >- if (this.status && this.status[WI.ResourceTreeElement.SpinnerSymbol]) >- this.status = ""; >+ if (this.status && this.status[WI.ResourceTreeElement.SpinnerSymbol]) { >+ if (this.status === this.status[WI.ResourceTreeElement.SpinnerSymbol]) >+ this.status = null; >+ else { >+ this.status[WI.ResourceTreeElement.SpinnerSymbol].remove(); >+ this.status[WI.ResourceTreeElement.SpinnerSymbol] = null; >+ } >+ } > } > } > >+ populateContextMenu(contextMenu, event) >+ { >+ WI.appendContextMenuItemsForSourceCode(contextMenu, this._resource); >+ >+ super.populateContextMenu(contextMenu, event); >+ } >+ >+ // Private >+ > _updateToolTip() > { > this.tooltip = this._resource.displayURL; >diff --git a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css >new file mode 100644 >index 0000000000000000000000000000000000000000..dc35f412406ba1498797319e7d120a26e6ae8b06 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.css >@@ -0,0 +1,49 @@ >+/* >+ * 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. >+ */ >+ >+.tree-outline .item .status > .toggle-script-blackboxed { >+ width: 18px; >+ margin-top: 2px; >+ content: url(../Images/Eye.svg); >+} >+ >+.tree-outline:not(.navigation-sidebar-panel-content-tree-outline) .item .status > .toggle-script-blackboxed, >+.tree-outline .item:not(:hover, .selected) .status > .toggle-script-blackboxed:not(.blackboxed) { >+ display: none; >+} >+ >+.tree-outline:focus .item.selected .status > .toggle-script-blackboxed { >+ filter: invert(); >+} >+ >+.tree-outline .item .status > .toggle-script-blackboxed.blackboxed { >+ opacity: 0.5; >+} >+ >+@media (prefers-color-scheme: dark) { >+ .tree-outline .item .status > .toggle-script-blackboxed { >+ filter: invert(); >+ } >+} >diff --git a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js >index 87de40d599981984b2de9be9e1e66e9fe6bedb68..a24e125c40206c4a6422c09fb318073719dba7cb 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js >+++ b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js >@@ -128,6 +128,13 @@ WI.SourceCodeTreeElement = class SourceCodeTreeElement extends WI.FolderizedTree > findAndCombineFolderChains(this.children[i], null); > } > >+ canSelectOnMouseDown(event) >+ { >+ if (this._toggleBlackboxedImageElement && this._toggleBlackboxedImageElement.contains(event.target)) >+ return false; >+ return super.canSelectOnMouseDown(event); >+ } >+ > // Protected > > descendantResourceTreeElementTypeDidChange(childTreeElement, oldType) >@@ -150,6 +157,18 @@ WI.SourceCodeTreeElement = class SourceCodeTreeElement extends WI.FolderizedTree > childTreeElement.revealAndSelect(true, false, true); > } > >+ updateStatus() >+ { >+ if (WI.DebuggerManager.supportsBlackboxingScripts() && this._sourceCode.isScript && this._sourceCode.contentIdentifier && !isWebKitInjectedScript(this._sourceCode.contentIdentifier)) { >+ this._toggleBlackboxedImageElement = document.createElement("img"); >+ this._toggleBlackboxedImageElement.classList.add("toggle-script-blackboxed"); >+ this._toggleBlackboxedImageElement.addEventListener("click", this._handleToggleBlackboxedImageElementClicked.bind(this)); >+ this.status = this._toggleBlackboxedImageElement; >+ >+ this._updateToggleBlackboxImageElementState(); >+ } >+ } >+ > // Protected (ResourceTreeElement calls this when its Resource changes dynamically for Frames) > > _updateSourceCode(sourceCode) >@@ -166,5 +185,24 @@ WI.SourceCodeTreeElement = class SourceCodeTreeElement extends WI.FolderizedTree > this._sourceCode.addEventListener(WI.SourceCode.Event.SourceMapAdded, this.updateSourceMapResources, this); > > this.updateSourceMapResources(); >+ >+ this.updateStatus(); >+ } >+ >+ // Private >+ >+ _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"); >+ } >+ >+ _handleToggleBlackboxedImageElementClicked(event) >+ { >+ let isBlackboxed = WI.debuggerManager.isScriptBlackboxed(this._sourceCode); >+ WI.debuggerManager.setShouldBlackboxScript(this._sourceCode, !isBlackboxed); >+ >+ this._updateToggleBlackboxImageElementState(); > } > }; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index f8d2e0a4baf08b6f7a22f36df0aab129bf1155c2..b4160dbad1fe728a6b9cc07466529aa07a644387 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,14 @@ >+2019-06-14 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: implement blackboxing of script resources >+ https://bugs.webkit.org/show_bug.cgi?id=17240 >+ <rdar://problem/5732847> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/debugger/setShouldBlackboxURL.html: Added. >+ * inspector/debugger/setShouldBlackboxURL-expected.txt: Added. >+ > 2019-06-13 Daniel Bates <dabates@apple.com> > > [iOS] Normalize test result of fast/events/ios/keyboard-event-key-attribute.html to handle possible modifier dispatch >diff --git a/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt b/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..c5e97217d5a6f4d43709e7ad1228ad05bd3e925b >--- /dev/null >+++ b/LayoutTests/inspector/debugger/setShouldBlackboxURL-expected.txt >@@ -0,0 +1,13 @@ >+Tests Debugger.setShouldBlackboxURL >+ >+Blackboxing 'bar.js'... >+Setting breakpoint in 'foo.js'... >+Running 'baz(10)'... >+PASS: Paused in 'foo'. >+Stepping over... >+PASS: Paused in 'baz'. >+Stepping over... >+PASS: Paused in 'global code'. >+Stepping over... >+PASS: Should not pause in 'bar'. >+ >diff --git a/LayoutTests/inspector/debugger/setShouldBlackboxURL.html b/LayoutTests/inspector/debugger/setShouldBlackboxURL.html >new file mode 100644 >index 0000000000000000000000000000000000000000..5349aa1a13eee261277d57cb61ddc2cec1ed4d70 >--- /dev/null >+++ b/LayoutTests/inspector/debugger/setShouldBlackboxURL.html >@@ -0,0 +1,83 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/protocol-test.js"></script> >+<script> >+eval("function foo(x) {\n return x + 42;\n}\n//# sourceURL=foo.js"); >+eval("function bar(x) {\n return foo(x);\n}\n//# sourceURL=bar.js"); >+eval("function baz(x) {\n return bar(x);\n}\n//# sourceURL=baz.js"); >+ >+function test() >+{ >+ ProtocolTest.debug(); >+ >+ InspectorProtocol.sendCommand("Debugger.enable", {}); >+ InspectorProtocol.sendCommand("Debugger.setBreakpointsActive", {active: true}); >+ >+ let fooSourceURL = null; >+ let barSourceURL = null; >+ let bazSourceURL = null; >+ let pausedFunctionNames = []; >+ >+ function setBlackbox() { >+ if (!fooSourceURL || !barSourceURL || !bazSourceURL) >+ return; >+ >+ ProtocolTest.log("Blackboxing 'bar.js'..."); >+ InspectorProtocol.sendCommand("Debugger.setShouldBlackboxURL", {url: barSourceURL, shouldBlackbox: true}, function(response) { >+ InspectorProtocol.checkForError(response); >+ >+ ProtocolTest.log("Setting breakpoint in 'foo.js'..."); >+ InspectorProtocol.sendCommand("Debugger.setBreakpointByUrl", {url: fooSourceURL, lineNumber: 2, columnNumber: 0}, function(response) { >+ InspectorProtocol.checkForError(response); >+ >+ ProtocolTest.log("Running 'baz(10)'..."); >+ InspectorProtocol.sendCommand("Runtime.evaluate", {expression: "baz(10)"}, function(response) { >+ InspectorProtocol.checkForError(response); >+ >+ ProtocolTest.expectThat(!pausedFunctionNames.includes("bar"), "Should not pause in 'bar'."); >+ ProtocolTest.completeTest(); >+ }); >+ }); >+ }); >+ } >+ >+ InspectorProtocol.eventHandler["Debugger.scriptParsed"] = function(message) { >+ let sourceURL = message.params.sourceURL; >+ >+ if (/foo\.js$/.test(sourceURL)) { >+ fooSourceURL = sourceURL; >+ setBlackbox(); >+ return; >+ } >+ >+ if (/bar\.js$/.test(sourceURL)) { >+ barSourceURL = sourceURL; >+ setBlackbox(); >+ return; >+ } >+ >+ if (/baz\.js$/.test(sourceURL)) { >+ bazSourceURL = sourceURL; >+ setBlackbox(); >+ return; >+ } >+ }; >+ >+ InspectorProtocol.eventHandler["Debugger.paused"] = function(message) { >+ let functionName = message.params.callFrames[0].functionName; >+ ProtocolTest.expectNotEqual(functionName, "bar", `Paused in '${functionName}'.`); >+ pausedFunctionNames.push(functionName); >+ >+ ProtocolTest.log("Stepping over..."); >+ InspectorProtocol.sendCommand("Debugger.stepOver", {}, function(response) { >+ InspectorProtocol.checkForError(response); >+ }); >+ }; >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests Debugger.setShouldBlackboxURL</p> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 17240
:
372117
|
372119
|
372120
|
372123
|
372154
|
372162
|
372163
|
372166
|
372168
|
372172
|
372176
|
372189
|
375517
|
375853
|
375869
|
375870
|
377655
|
377656
|
377935