Diff
Modified: trunk/LayoutTests/ChangeLog (176356 => 176357)
--- trunk/LayoutTests/ChangeLog 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/LayoutTests/ChangeLog 2014-11-19 23:49:36 UTC (rev 176357)
@@ -1,3 +1,31 @@
+2014-11-19 Joseph Pecoraro <[email protected]>
+
+ Web Inspector: Provide $exception in the console for the thrown exception value
+ https://bugs.webkit.org/show_bug.cgi?id=138726
+
+ Reviewed by Timothy Hatcher.
+
+ Provide some tests to ensure $exception is the value we expect at different times,
+ such as on the exception line, when there is no exception, or when stepping through
+ catch blocks (it should always be the most recent caught exception).
+
+ * inspector/debugger/command-line-api-exception-expected.txt: Added.
+ * inspector/debugger/command-line-api-exception-nested-catch-expected.txt: Added.
+ * inspector/debugger/command-line-api-exception-nested-catch.html: Added.
+ * inspector/debugger/command-line-api-exception.html: Added.
+ * inspector/debugger/resources/exceptions.js: Added.
+ (triggerUncaughtTypeException):
+ (triggerUncaughtReferenceException):
+ (triggerUncaughtSyntaxException):
+ (triggerUncaughtDOMException):
+ (throwString):
+ (throwNumber):
+ (throwNull):
+ (throwObject):
+ (throwNode):
+ (catcher):
+ (nestedCatchBlocks):
+
2014-11-19 David Hyatt <[email protected]>
Images/replaced elements that are as tall as a page should be on their own page
Added: trunk/LayoutTests/inspector/debugger/command-line-api-exception-expected.txt (0 => 176357)
--- trunk/LayoutTests/inspector/debugger/command-line-api-exception-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception-expected.txt 2014-11-19 23:49:36 UTC (rev 176357)
@@ -0,0 +1,32 @@
+CONSOLE MESSAGE: line 4: TypeError: undefined is not an object (evaluating '[].x.x')
+CONSOLE MESSAGE: line 10: ReferenceError: Can't find variable: variableThatDoesNotExist
+CONSOLE MESSAGE: line 16: SyntaxError: Unexpected token ')'
+CONSOLE MESSAGE: line 22: IndexSizeError: DOM Exception 1: Index or size was negative, or greater than the allowed value.
+CONSOLE MESSAGE: line 27: thrown string
+CONSOLE MESSAGE: line 32: 123.456
+CONSOLE MESSAGE: line 37: null
+CONSOLE MESSAGE: line 42: [object Object]
+CONSOLE MESSAGE: line 47: [object HTMLBodyElement]
+CONSOLE MESSAGE: line 55: CATCHER: TypeError: undefined is not an object (evaluating '[].x.x')
+CONSOLE MESSAGE: line 55: CATCHER: thrown string
+CONSOLE MESSAGE: line 55: CATCHER: [object Object]
+Checks that $exception is available and accurate in evaluations when paused on an exception.
+
+BEFORE: $exception => undefined
+PAUSE #1: $exception => TypeError: undefined is not an object (evaluating '[].x.x')
+PAUSE #2: $exception => ReferenceError: Can't find variable: variableThatDoesNotExist
+PAUSE #3: $exception => SyntaxError: Unexpected token ')'
+PAUSE #4: $exception => DOMException
+PAUSE #5: $exception => thrown string
+PAUSE #6: $exception => 123.456
+PAUSE #7: $exception => null
+PAUSE #8: $exception => Object
+PAUSE #9: $exception => body
+PAUSE #10: $exception => TypeError: undefined is not an object (evaluating '[].x.x')
+STEPPED OUT TO CATCH BLOCK: $exception === e ? true
+PAUSE #11: $exception => thrown string
+STEPPED OUT TO CATCH BLOCK: $exception === e ? true
+PAUSE #12: $exception => Object
+STEPPED OUT TO CATCH BLOCK: $exception === e ? true
+AFTER: $exception => undefined
+
Added: trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch-expected.txt (0 => 176357)
--- trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch-expected.txt 2014-11-19 23:49:36 UTC (rev 176357)
@@ -0,0 +1,13 @@
+CONSOLE MESSAGE: line 67: inner exception
+CONSOLE MESSAGE: line 69: outer exception
+Checks that $exception is the value of the current exception, even in nested catch blocks.
+
+BEFORE : $exception => undefined
+OUTER 1: $exception => outer exception
+INNER 1: $exception => inner exception
+INNER 2: $exception => inner exception
+ CATCH: $exception === e2 ? true
+OUTER 2: $exception => outer exception
+ CATCH: $exception === e1 ? true
+AFTER : $exception => undefined
+
Added: trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html (0 => 176357)
--- trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html (rev 0)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html 2014-11-19 23:49:36 UTC (rev 176357)
@@ -0,0 +1,84 @@
+<!doctype html>
+<html>
+<head>
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
+<script>
+function triggerException()
+{
+ // We expect uncaught exceptions, so avoid logs for them.
+ window._onerror_ = function(){};
+ setTimeout(nestedCatchBlocks, 0);
+}
+
+function test()
+{
+ WebInspector.debuggerManager.allExceptionsBreakpoint.disabled = false;
+
+ function dumpCommandLineAPIValue(prefix) {
+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, function(result, wasThrown) {
+ InspectorTest.log(prefix + ": $exception => " + result.description);
+ });
+ }
+
+ function checkIfExceptionValueMatchesVariable(varName) {
+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === " + varName, "test", true, true, false, function(result, wasThrown) {
+ InspectorTest.log(" CATCH: $exception === " + varName + " ? " + result.description);
+ });
+ }
+
+ var done = false;
+ var phase = 0;
+
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, function(event) {
+ if (done)
+ return;
+
+ phase++;
+
+ // Skip past the first pause to the second pause.
+ if (phase === 1) {
+ dumpCommandLineAPIValue("OUTER 1");
+ WebInspector.debuggerManager.resume();
+ return;
+ }
+
+ // Paused on the exception in the inner try, step over to get into the inner catch.
+ if (phase === 2) {
+ dumpCommandLineAPIValue("INNER 1");
+ WebInspector.debuggerManager.stepOver();
+ return;
+ }
+
+ // Paused in the inner catch, verify $exception is "inner exception".
+ if (phase === 3) {
+ dumpCommandLineAPIValue("INNER 2");
+ checkIfExceptionValueMatchesVariable("e2");
+ WebInspector.debuggerManager.stepOver();
+ return;
+ }
+
+ // Stepped into the outer catch, verify $exception is "outer exception".
+ if (phase === 4) {
+ dumpCommandLineAPIValue("OUTER 2");
+ checkIfExceptionValueMatchesVariable("e1");
+ WebInspector.debuggerManager.resume();
+ return;
+ }
+ });
+
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, function(event) {
+ done = true;
+ dumpCommandLineAPIValue("AFTER ");
+ InspectorTest.completeTest();
+ });
+
+ dumpCommandLineAPIValue("BEFORE ");
+ InspectorTest.evaluateInPage("triggerException()");
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Checks that <code>$exception</code> is the value of the current exception, even in nested catch blocks.</p>
+</body>
+</html>
Added: trunk/LayoutTests/inspector/debugger/command-line-api-exception.html (0 => 176357)
--- trunk/LayoutTests/inspector/debugger/command-line-api-exception.html (rev 0)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception.html 2014-11-19 23:49:36 UTC (rev 176357)
@@ -0,0 +1,98 @@
+<!doctype html>
+<html>
+<head>
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
+<script>
+var exceptionIndex = 0;
+var exceptionCausers = [
+ triggerUncaughtTypeException,
+ triggerUncaughtReferenceException,
+ triggerUncaughtSyntaxException,
+ triggerUncaughtDOMException,
+ throwString,
+ throwNumber,
+ throwNull,
+ throwObject,
+ throwNode,
+ function() { catcher(triggerUncaughtTypeException); },
+ function() { catcher(throwString); },
+ function() { catcher(throwObject); },
+];
+
+
+function triggerNextException()
+{
+ // We expect uncaught exceptions, so avoid logs for them.
+ window._onerror_ = function(){};
+
+ setTimeout(function() {
+ exceptionCausers[exceptionIndex++]();
+ }, 0);
+}
+
+function test()
+{
+ WebInspector.debuggerManager.allExceptionsBreakpoint.disabled = false;
+
+ function triggerNextException() {
+ InspectorTest.evaluateInPage("triggerNextException()");
+ }
+
+ function dumpCommandLineAPIValue(prefix) {
+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, function(result, wasThrown) {
+ InspectorTest.log(prefix + ": $exception => " + result.description);
+ });
+ }
+
+ function checkIfExceptionValueMatchesCatchVariable() {
+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === e", "test", true, true, false, function(result, wasThrown) {
+ InspectorTest.log("STEPPED OUT TO CATCH BLOCK: $exception === e ? " + result.description);
+ });
+ }
+
+ var pauses = 0;
+ var stepping = false;
+ var done = false;
+ const pointWhereExpectionsAreBeingCaught = 9;
+ const expectedPauses = 12;
+
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, function(event) {
+ if (done)
+ return;
+
+ if (!stepping) {
+ dumpCommandLineAPIValue("PAUSE #" + (++pauses));
+ if (pauses > pointWhereExpectionsAreBeingCaught) {
+ WebInspector.debuggerManager.stepOut();
+ stepping = true;
+ return;
+ }
+ } else {
+ checkIfExceptionValueMatchesCatchVariable();
+ stepping = false;
+ }
+
+ WebInspector.debuggerManager.resume();
+
+ if (pauses !== expectedPauses) {
+ triggerNextException();
+ return;
+ }
+ });
+
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, function(event) {
+ done = true;
+ dumpCommandLineAPIValue("AFTER");
+ InspectorTest.completeTest();
+ });
+
+ dumpCommandLineAPIValue("BEFORE");
+ triggerNextException();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Checks that <code>$exception</code> is available and accurate in evaluations when paused on an exception.</p>
+</body>
+</html>
Added: trunk/LayoutTests/inspector/debugger/resources/exceptions.js (0 => 176357)
--- trunk/LayoutTests/inspector/debugger/resources/exceptions.js (rev 0)
+++ trunk/LayoutTests/inspector/debugger/resources/exceptions.js 2014-11-19 23:49:36 UTC (rev 176357)
@@ -0,0 +1,71 @@
+function triggerUncaughtTypeException()
+{
+ // Exception: TypeError: undefined is not an object (evaluating '[].x.x')
+ [].x.x;
+}
+
+function triggerUncaughtReferenceException()
+{
+ // Exception: ReferenceError: Can't find variable: variableThatDoesNotExist
+ variableThatDoesNotExist += 1;
+}
+
+function triggerUncaughtSyntaxException()
+{
+ // Exception: SyntaxError: Unexpected token ')'
+ eval("if()");
+}
+
+function triggerUncaughtDOMException()
+{
+ // Error: IndexSizeError: DOM Exception 1
+ document.createTextNode("").splitText(100);
+}
+
+function throwString()
+{
+ throw "thrown string";
+}
+
+function throwNumber()
+{
+ throw 123.456;
+}
+
+function throwNull()
+{
+ throw null;
+}
+
+function throwObject()
+{
+ throw {x:1,y:2};
+}
+
+function throwNode()
+{
+ throw document.body;
+}
+
+function catcher(func)
+{
+ try {
+ func();
+ } catch (e) {
+ console.log("CATCHER: " + e);
+ }
+}
+
+function nestedCatchBlocks()
+{
+ try {
+ throw "outer exception";
+ } catch (e1) {
+ try {
+ throw "inner exception";
+ } catch (e2) {
+ console.log(e2);
+ }
+ console.log(e1);
+ }
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (176356 => 176357)
--- trunk/Source/_javascript_Core/ChangeLog 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-11-19 23:49:36 UTC (rev 176357)
@@ -1,5 +1,63 @@
2014-11-19 Joseph Pecoraro <[email protected]>
+ Web Inspector: Provide $exception in the console for the thrown exception value
+ https://bugs.webkit.org/show_bug.cgi?id=138726
+
+ Reviewed by Timothy Hatcher.
+
+ * debugger/DebuggerScope.cpp:
+ (JSC::DebuggerScope::caughtValue):
+ * debugger/DebuggerScope.h:
+ Access the caught value if this scope is a catch scope.
+
+ * runtime/JSNameScope.h:
+ (JSC::JSNameScope::isFunctionNameScope):
+ (JSC::JSNameScope::isCatchScope):
+ (JSC::JSNameScope::value):
+ Provide an accessor for the single value in the JSNameScope (with / catch block).
+
+ * inspector/InjectedScriptSource.js:
+ Save the exception value and expose it via $exception. Since the command line api
+ is recreated on each evaluation, $exception is essentially readonly.
+
+ * inspector/ScriptDebugServer.h:
+ * inspector/ScriptDebugServer.cpp:
+ (Inspector::ScriptDebugServer::dispatchDidPause):
+ (Inspector::ScriptDebugServer::exceptionOrCaughtValue):
+ When pausing, get the exception or caught value. The exception will be provided
+ if we are breaking on an explicit exception. When inside of a catch block, we
+ can get the caught value by walking up the scope chain.
+
+ * inspector/agents/InspectorDebuggerAgent.h:
+ * inspector/agents/InspectorDebuggerAgent.cpp:
+ (Inspector::InspectorDebuggerAgent::InspectorDebuggerAgent):
+ (Inspector::InspectorDebuggerAgent::resume):
+ (Inspector::InspectorDebuggerAgent::stepOver):
+ (Inspector::InspectorDebuggerAgent::stepInto):
+ (Inspector::InspectorDebuggerAgent::stepOut):
+ Clearing state can be done in didContinue.
+
+ (Inspector::InspectorDebuggerAgent::didPause):
+ Set the exception value explicitly in the injected script when we have it.
+
+ (Inspector::InspectorDebuggerAgent::didContinue):
+ Clear state saved when we had paused, including clearly an exception value if needed.
+
+ (Inspector::InspectorDebuggerAgent::clearDebuggerBreakpointState):
+ (Inspector::InspectorDebuggerAgent::clearExceptionValue):
+ Call into the injected script only when needed.
+
+ * inspector/InjectedScript.cpp:
+ (Inspector::InjectedScript::setExceptionValue):
+ (Inspector::InjectedScript::clearExceptionValue):
+ * inspector/InjectedScript.h:
+ * inspector/InjectedScriptManager.cpp:
+ (Inspector::InjectedScriptManager::clearExceptionValue):
+ * inspector/InjectedScriptManager.h:
+ Clear on all injected scripts.
+
+2014-11-19 Joseph Pecoraro <[email protected]>
+
Unreviewed build fixes after r176329.
- export all of the codegen python files as they are included by the main generator
Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp (176356 => 176357)
--- trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp 2014-11-19 23:49:36 UTC (rev 176357)
@@ -183,4 +183,10 @@
return m_scope->isActivationObject();
}
+JSValue DebuggerScope::caughtValue() const
+{
+ ASSERT(isCatchScope());
+ return reinterpret_cast<JSNameScope*>(m_scope.get())->value();
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.h (176356 => 176357)
--- trunk/Source/_javascript_Core/debugger/DebuggerScope.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -90,6 +90,8 @@
bool isGlobalScope() const;
bool isFunctionOrEvalScope() const;
+ JSValue caughtValue() const;
+
private:
JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
JS_EXPORT_PRIVATE void finishCreation(VM&);
Modified: trunk/Source/_javascript_Core/inspector/InjectedScript.cpp (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/InjectedScript.cpp 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/InjectedScript.cpp 2014-11-19 23:49:36 UTC (rev 176357)
@@ -202,6 +202,23 @@
return BindingTraits<Inspector::Protocol::Runtime::RemoteObject>::runtimeCast(resultObject);
}
+void InjectedScript::setExceptionValue(const Deprecated::ScriptValue& value)
+{
+ ASSERT(!hasNoValue());
+ Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("setExceptionValue"), inspectorEnvironment()->functionCallHandler());
+ function.appendArgument(value);
+ RefPtr<InspectorValue> result;
+ makeCall(function, &result);
+}
+
+void InjectedScript::clearExceptionValue()
+{
+ ASSERT(!hasNoValue());
+ Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("clearExceptionValue"), inspectorEnvironment()->functionCallHandler());
+ RefPtr<InspectorValue> result;
+ makeCall(function, &result);
+}
+
Deprecated::ScriptValue InjectedScript::findObjectById(const String& objectId) const
{
ASSERT(!hasNoValue());
Modified: trunk/Source/_javascript_Core/inspector/InjectedScript.h (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/InjectedScript.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/InjectedScript.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -66,6 +66,9 @@
PassRefPtr<Protocol::Runtime::RemoteObject> wrapObject(const Deprecated::ScriptValue&, const String& groupName, bool generatePreview = false) const;
PassRefPtr<Protocol::Runtime::RemoteObject> wrapTable(const Deprecated::ScriptValue& table, const Deprecated::ScriptValue& columns) const;
+ void setExceptionValue(const Deprecated::ScriptValue&);
+ void clearExceptionValue();
+
Deprecated::ScriptValue findObjectById(const String& objectId) const;
void inspectObject(Deprecated::ScriptValue);
void releaseObject(const String& objectId);
Modified: trunk/Source/_javascript_Core/inspector/InjectedScriptManager.cpp (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/InjectedScriptManager.cpp 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/InjectedScriptManager.cpp 2014-11-19 23:49:36 UTC (rev 176357)
@@ -118,10 +118,16 @@
void InjectedScriptManager::releaseObjectGroup(const String& objectGroup)
{
- for (auto it = m_idToInjectedScript.begin(); it != m_idToInjectedScript.end(); ++it)
- it->value.releaseObjectGroup(objectGroup);
+ for (auto& injectedScript : m_idToInjectedScript.values())
+ injectedScript.releaseObjectGroup(objectGroup);
}
+void InjectedScriptManager::clearExceptionValue()
+{
+ for (auto& injectedScript : m_idToInjectedScript.values())
+ injectedScript.clearExceptionValue();
+}
+
String InjectedScriptManager::injectedScriptSource()
{
return StringImpl::createWithoutCopying(InjectedScriptSource_js, sizeof(InjectedScriptSource_js));
Modified: trunk/Source/_javascript_Core/inspector/InjectedScriptManager.h (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/InjectedScriptManager.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/InjectedScriptManager.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -66,6 +66,7 @@
InjectedScript injectedScriptForObjectId(const String& objectId);
void discardInjectedScripts();
void releaseObjectGroup(const String& objectGroup);
+ void clearExceptionValue();
protected:
virtual void didCreateInjectedScript(InjectedScript);
Modified: trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js 2014-11-19 23:49:36 UTC (rev 176357)
@@ -86,6 +86,16 @@
return this._fallbackWrapper(object);
},
+ setExceptionValue: function(value)
+ {
+ this._exceptionValue = value;
+ },
+
+ clearExceptionValue: function()
+ {
+ delete this._exceptionValue;
+ },
+
/**
* @param {*} object
* @return {!RuntimeAgent.RemoteObject}
@@ -1041,6 +1051,7 @@
function BasicCommandLineAPI()
{
this.$_ = injectedScript._lastResult;
+ this.$exception = injectedScript._exceptionValue;
}
return injectedScript;
Modified: trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp 2014-11-19 23:49:36 UTC (rev 176357)
@@ -138,8 +138,8 @@
JSC::ExecState* state = globalObject->globalExec();
RefPtr<_javascript_CallFrame> _javascript_CallFrame = _javascript_CallFrame::create(debuggerCallFrame);
JSValue jsCallFrame = toJS(state, globalObject, _javascript_CallFrame.get());
- Deprecated::ScriptValue exception = reasonForPause() == PausedForException ? Deprecated::ScriptValue(state->vm(), currentException()) : Deprecated::ScriptValue();
- listener->didPause(state, Deprecated::ScriptValue(state->vm(), jsCallFrame), exception);
+
+ listener->didPause(state, Deprecated::ScriptValue(state->vm(), jsCallFrame), exceptionOrCaughtValue(state));
}
void ScriptDebugServer::dispatchBreakpointActionLog(ExecState* exec, const String& message)
@@ -327,6 +327,22 @@
return emptyActionVector;
}
+Deprecated::ScriptValue ScriptDebugServer::exceptionOrCaughtValue(JSC::ExecState* state)
+{
+ if (reasonForPause() == PausedForException)
+ return Deprecated::ScriptValue(state->vm(), currentException());
+
+ RefPtr<DebuggerCallFrame> debuggerCallFrame = currentDebuggerCallFrame();
+ while (debuggerCallFrame) {
+ DebuggerScope* scope = debuggerCallFrame->scope();
+ if (scope->isCatchScope())
+ return Deprecated::ScriptValue(state->vm(), scope->caughtValue());
+ debuggerCallFrame = debuggerCallFrame->callerFrame();
+ }
+
+ return Deprecated::ScriptValue();
+}
+
} // namespace Inspector
#endif // ENABLE(INSPECTOR)
Modified: trunk/Source/_javascript_Core/inspector/ScriptDebugServer.h (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/ScriptDebugServer.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/ScriptDebugServer.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -105,6 +105,8 @@
virtual void handlePause(JSC::Debugger::ReasonForPause, JSC::JSGlobalObject*) override final;
virtual void notifyDoneProcessingDebuggerEvents() override final;
+ Deprecated::ScriptValue exceptionOrCaughtValue(JSC::ExecState*);
+
unsigned m_hitCount;
bool m_callingListeners;
BreakpointIDToActionsMap m_breakpointIDToActions;
Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp 2014-11-19 23:49:36 UTC (rev 176357)
@@ -65,6 +65,7 @@
, m_continueToLocationBreakpointID(JSC::noBreakpointID)
, m_enabled(false)
, m_javaScriptPauseScheduled(false)
+ , m_hasExceptionValue(false)
, m_nextProbeSampleId(1)
{
// FIXME: make breakReason optional so that there was no need to init it with "other".
@@ -468,7 +469,6 @@
if (!assertPaused(errorString))
return;
- m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().continueProgram();
}
@@ -477,7 +477,6 @@
if (!assertPaused(errorString))
return;
- m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepOverStatement();
}
@@ -486,7 +485,6 @@
if (!assertPaused(errorString))
return;
- m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepIntoStatement();
if (m_listener)
@@ -498,7 +496,6 @@
if (!assertPaused(errorString))
return;
- m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepOutOfFunction();
}
@@ -643,6 +640,8 @@
m_breakReason = InspectorDebuggerFrontendDispatcher::Reason::Exception;
m_breakAuxData = injectedScript.wrapObject(exception, InspectorDebuggerAgent::backtraceObjectGroup)->openAccessors();
// m_breakAuxData might be null after this.
+ injectedScript.setExceptionValue(exception);
+ m_hasExceptionValue = true;
}
}
@@ -687,8 +686,10 @@
{
m_pausedScriptState = nullptr;
m_currentCallStack = Deprecated::ScriptValue();
+ m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
m_injectedScriptManager->inspectorEnvironment().executionStopwatch()->start();
clearBreakDetails();
+ clearExceptionValue();
m_frontendDispatcher->resumed();
}
@@ -724,6 +725,7 @@
m_continueToLocationBreakpointID = JSC::noBreakpointID;
clearBreakDetails();
m_javaScriptPauseScheduled = false;
+ m_hasExceptionValue = false;
scriptDebugServer().continueProgram();
}
@@ -754,6 +756,14 @@
m_breakAuxData = nullptr;
}
+void InspectorDebuggerAgent::clearExceptionValue()
+{
+ if (m_hasExceptionValue) {
+ m_injectedScriptManager->clearExceptionValue();
+ m_hasExceptionValue = false;
+ }
+}
+
} // namespace Inspector
#endif // ENABLE(INSPECTOR)
Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h (176356 => 176357)
--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -146,6 +146,7 @@
void clearDebuggerBreakpointState();
void clearInspectorBreakpointState();
void clearBreakDetails();
+ void clearExceptionValue();
bool breakpointActionsFromProtocol(ErrorString&, RefPtr<InspectorArray>& actions, BreakpointActions* result);
@@ -167,6 +168,7 @@
RefPtr<InspectorObject> m_breakAuxData;
bool m_enabled;
bool m_javaScriptPauseScheduled;
+ bool m_hasExceptionValue;
RefPtr<WTF::Stopwatch> m_stopwatch;
int m_nextProbeSampleId;
};
Modified: trunk/Source/_javascript_Core/runtime/JSNameScope.h (176356 => 176357)
--- trunk/Source/_javascript_Core/runtime/JSNameScope.h 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/_javascript_Core/runtime/JSNameScope.h 2014-11-19 23:49:36 UTC (rev 176357)
@@ -65,9 +65,11 @@
DECLARE_INFO;
- bool isFunctionNameScope() { return m_type == FunctionNameScope; }
- bool isCatchScope() { return m_type == CatchScope; }
+ bool isFunctionNameScope() const { return m_type == FunctionNameScope; }
+ bool isCatchScope() const { return m_type == CatchScope; }
+ JSValue value() const { return m_registerStore.get(); }
+
protected:
void finishCreation(VM& vm, const Identifier& identifier, JSValue value, unsigned attributes)
{
Modified: trunk/Source/WebCore/ChangeLog (176356 => 176357)
--- trunk/Source/WebCore/ChangeLog 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/WebCore/ChangeLog 2014-11-19 23:49:36 UTC (rev 176357)
@@ -1,3 +1,16 @@
+2014-11-19 Joseph Pecoraro <[email protected]>
+
+ Web Inspector: Provide $exception in the console for the thrown exception value
+ https://bugs.webkit.org/show_bug.cgi?id=138726
+
+ Reviewed by Timothy Hatcher.
+
+ Tests: inspector/debugger/command-line-api-exception-nested-catch.html
+ inspector/debugger/command-line-api-exception.html
+
+ * inspector/CommandLineAPIModuleSource.js:
+ Expose $exception in the more complete command line API.
+
2014-11-19 David Hyatt <[email protected]>
Images/replaced elements that are as tall as a page should be on their own page
Modified: trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js (176356 => 176357)
--- trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js 2014-11-19 23:49:36 UTC (rev 176357)
@@ -124,6 +124,7 @@
}
this.$_ = injectedScript._lastResult;
+ this.$exception = injectedScript._exceptionValue;
}
/**
Modified: trunk/Source/WebInspectorUI/ChangeLog (176356 => 176357)
--- trunk/Source/WebInspectorUI/ChangeLog 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/WebInspectorUI/ChangeLog 2014-11-19 23:49:36 UTC (rev 176357)
@@ -1,5 +1,20 @@
2014-11-19 Joseph Pecoraro <[email protected]>
+ Web Inspector: Provide $exception in the console for the thrown exception value
+ https://bugs.webkit.org/show_bug.cgi?id=138726
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Base/Test.js:
+ (WebInspector.loaded):
+ In order to use RuntimeManager to execute in the global context or on the
+ active debugger call frame, we need to expose the quickConsole controller.
+
+ * UserInterface/Controllers/_javascript_RuntimeCompletionProvider.js:
+ Expose $exception to completion when we paused because of an exception.
+
+2014-11-19 Joseph Pecoraro <[email protected]>
+
Web Inspector: Debugger should not mutate variable when hovering mouse over ++n _expression_
https://bugs.webkit.org/show_bug.cgi?id=138839
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Test.js (176356 => 176357)
--- trunk/Source/WebInspectorUI/UserInterface/Base/Test.js 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Test.js 2014-11-19 23:49:36 UTC (rev 176357)
@@ -56,6 +56,9 @@
this.probeManager = new WebInspector.ProbeManager;
this.replayManager = new WebInspector.ReplayManager;
+ // Global controllers.
+ this.quickConsole = {executionContextIdentifier: undefined};
+
document.addEventListener("DOMContentLoaded", this.contentLoaded.bind(this));
// Enable agents.
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/_javascript_RuntimeCompletionProvider.js (176356 => 176357)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/_javascript_RuntimeCompletionProvider.js 2014-11-19 23:48:53 UTC (rev 176356)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/_javascript_RuntimeCompletionProvider.js 2014-11-19 23:49:36 UTC (rev 176357)
@@ -174,7 +174,9 @@
RuntimeAgent.releaseObjectGroup("completion");
if (!base) {
- const commandLineAPI = ["$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners", "$0", "$1", "$2", "$3", "$4", "$_"];
+ var commandLineAPI = ["$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners", "$0", "$1", "$2", "$3", "$4", "$_"];
+ if (WebInspector.debuggerManager.paused && WebInspector.debuggerManager.pauseReason === WebInspector.DebuggerManager.PauseReason.Exception)
+ commandLineAPI.push("$exception");
for (var i = 0; i < commandLineAPI.length; ++i)
propertyNames[commandLineAPI[i]] = true;
}