Skip to content

Commit

Permalink
Implement showing Exceptions.
Browse files Browse the repository at this point in the history
Signed-off-by: Zoltan Herczeg [email protected]
  • Loading branch information
zherczeg authored and clover2123 committed Apr 14, 2020
1 parent 46d8f20 commit 161899b
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 43 deletions.
30 changes: 18 additions & 12 deletions src/debugger/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ void Debugger::sendBreakpointLocations(std::vector<Debugger::BreakpointLocation>
send(ESCARGOT_MESSAGE_BREAKPOINT_LOCATION, ptr, length * sizeof(BreakpointLocation));
}

void Debugger::sendBacktraceInfo(uint8_t type, ByteCodeBlock* byteCodeBlock, uint32_t line, uint32_t column)
{
BacktraceInfo backtraceInfo;

char* byteCode = byteCodeBlock->m_code.data();
memcpy(&backtraceInfo.byteCode, &byteCode, sizeof(void*));
memcpy(&backtraceInfo.line, &line, sizeof(uint32_t));
memcpy(&backtraceInfo.column, &column, sizeof(uint32_t));

send(type, &backtraceInfo, sizeof(BacktraceInfo));
}

void Debugger::stopAtBreakpoint(ByteCodeBlock* byteCodeBlock, uint32_t offset, ExecutionState* state)
{
if (m_stopState == ESCARGOT_DEBUGGER_IN_EVAL_MODE) {
Expand Down Expand Up @@ -227,7 +239,6 @@ bool Debugger::doEval(ExecutionState* state, ByteCodeBlock* byteCodeBlock, uint8

void Debugger::getBacktrace(ExecutionState* state, uint32_t minDepth, uint32_t maxDepth, bool getTotal)
{
BacktraceInfo backtraceInfo;
SandBox::StackTraceDataVector stackTraceData;

SandBox::createStackTraceData(stackTraceData, *state);
Expand All @@ -251,16 +262,11 @@ void Debugger::getBacktrace(ExecutionState* state, uint32_t minDepth, uint32_t m
ByteCodeBlock* byteCodeBlock = stackTraceData[i].second.loc.actualCodeBlock;
size_t byteCodePosition = stackTraceData[i].second.loc.byteCodePosition;

char* byteCode = byteCodeBlock->m_code.data();
memcpy(&backtraceInfo.byteCode, &byteCode, sizeof(void*));

ExtendedNodeLOC loc = byteCodeBlock->computeNodeLOCFromByteCode(state->context(), byteCodePosition, byteCodeBlock->m_codeBlock);
uint32_t data = (uint32_t)loc.line;
memcpy(&backtraceInfo.line, &data, sizeof(uint32_t));
data = (uint32_t)loc.column;
memcpy(&backtraceInfo.column, &data, sizeof(uint32_t));

if (!send(ESCARGOT_MESSAGE_BACKTRACE, &backtraceInfo, sizeof(BacktraceInfo))) {
sendBacktraceInfo(ESCARGOT_MESSAGE_BACKTRACE, byteCodeBlock, (uint32_t)loc.line, (uint32_t)loc.column);

if (!enabled()) {
return;
}
}
Expand Down Expand Up @@ -373,11 +379,11 @@ static void sendProperty(Debugger* debugger, ExecutionState* state, AtomicString

if (debugger->enabled()) {
StringView* nameView = new StringView(name.string(), 0, nameLength);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_VARIABLE_8BIT, nameView);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_STRING_8BIT, nameView);
}

if (valueView && debugger->enabled()) {
debugger->sendString(Debugger::ESCARGOT_MESSAGE_VARIABLE_8BIT, valueView);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_STRING_8BIT, valueView);
}
}

Expand All @@ -395,7 +401,7 @@ static void sendUnaccessibleProperty(Debugger* debugger, AtomicString name)

if (debugger->enabled()) {
StringView* nameView = new StringView(name.string(), 0, nameLength);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_VARIABLE_8BIT, nameView);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_STRING_8BIT, nameView);
}
}

Expand Down
20 changes: 9 additions & 11 deletions src/debugger/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,15 @@ class Debugger : public gc {
ESCARGOT_MESSAGE_BACKTRACE_END = 32,
ESCARGOT_MESSAGE_SCOPE_CHAIN = 33,
ESCARGOT_MESSAGE_SCOPE_CHAIN_END = 34,
ESCARGOT_MESSAGE_VARIABLE = 35,
// These four must be in the same order.
ESCARGOT_MESSAGE_VARIABLE_8BIT = 36,
ESCARGOT_MESSAGE_VARIABLE_8BIT_END = 37,
ESCARGOT_MESSAGE_VARIABLE_16BIT = 38,
ESCARGOT_MESSAGE_VARIABLE_16BIT_END = 39,
// These four must be in the same order.
// These four must be in the same order.
ESCARGOT_MESSAGE_PRINT_8BIT = 40,
ESCARGOT_MESSAGE_PRINT_8BIT_END = 41,
ESCARGOT_MESSAGE_PRINT_16BIT = 42,
ESCARGOT_MESSAGE_PRINT_16BIT_END = 43,
ESCARGOT_MESSAGE_STRING_8BIT = 35,
ESCARGOT_MESSAGE_STRING_8BIT_END = 36,
ESCARGOT_MESSAGE_STRING_16BIT = 37,
ESCARGOT_MESSAGE_STRING_16BIT_END = 38,
ESCARGOT_MESSAGE_VARIABLE = 39,
ESCARGOT_MESSAGE_PRINT = 40,
ESCARGOT_MESSAGE_EXCEPTION = 41,
ESCARGOT_MESSAGE_EXCEPTION_BACKTRACE = 42,
};

// Messages sent by the debugger client to Escargot
Expand Down Expand Up @@ -199,6 +196,7 @@ class Debugger : public gc {
void sendPointer(uint8_t type, const void* ptr);
void sendFunctionInfo(InterpretedCodeBlock* codeBlock);
void sendBreakpointLocations(std::vector<Debugger::BreakpointLocation>& locations);
void sendBacktraceInfo(uint8_t type, ByteCodeBlock* byteCodeBlock, uint32_t line, uint32_t column);
void stopAtBreakpoint(ByteCodeBlock* byteCodeBlock, uint32_t offset, ExecutionState* state);
void releaseFunction(const void* ptr);

Expand Down
5 changes: 4 additions & 1 deletion src/runtime/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ void Context::printDebugger(StringView* output)
if (!m_debugger || !m_debugger->enabled()) {
return;
}
m_debugger->sendString(Debugger::ESCARGOT_MESSAGE_PRINT_8BIT, output);
m_debugger->sendType(Debugger::ESCARGOT_MESSAGE_PRINT);
if (m_debugger->enabled()) {
m_debugger->sendString(Debugger::ESCARGOT_MESSAGE_STRING_8BIT, output);
}
}

#endif /* ESCARGOT_DEBUGGER */
Expand Down
21 changes: 21 additions & 0 deletions src/runtime/SandBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ void SandBox::processCatch(const Value& error, SandBoxResult& result)

fillStackDataIntoErrorObject(error);

#ifdef ESCARGOT_DEBUGGER
Debugger* debugger = m_context->debugger();
if (debugger && debugger->enabled()) {
ExecutionState state(m_context);
String* message = error.toStringWithoutException(state);

debugger->sendType(Debugger::ESCARGOT_MESSAGE_EXCEPTION);
if (debugger->enabled()) {
StringView* messageView = new StringView(message);
debugger->sendString(Debugger::ESCARGOT_MESSAGE_STRING_8BIT, messageView);
}
}
#endif /* ESCARGOT_DEBUGGER */

for (size_t i = 0; i < m_stackTraceData.size(); i++) {
if ((size_t)m_stackTraceData[i].second.loc.index == SIZE_MAX && (size_t)m_stackTraceData[i].second.loc.actualCodeBlock != SIZE_MAX) {
// this means loc not computed yet.
Expand All @@ -69,6 +83,13 @@ void SandBox::processCatch(const Value& error, SandBoxResult& result)
traceData.isEval = m_stackTraceData[i].second.isEval;

result.stackTraceData.pushBack(traceData);

#ifdef ESCARGOT_DEBUGGER
if (i < 8 && debugger && debugger->enabled()) {
debugger->sendBacktraceInfo(Debugger::ESCARGOT_MESSAGE_EXCEPTION_BACKTRACE,
m_stackTraceData[i].second.loc.actualCodeBlock, (uint32_t)loc.line, (uint32_t)loc.column);
}
#endif /* ESCARGOT_DEBUGGER */
} else {
result.stackTraceData.pushBack(m_stackTraceData[i].second);
}
Expand Down
40 changes: 21 additions & 19 deletions tools/debugger/debugger_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,14 @@
ESCARGOT_MESSAGE_BACKTRACE_END = 32
ESCARGOT_MESSAGE_SCOPE_CHAIN = 33
ESCARGOT_MESSAGE_SCOPE_CHAIN_END = 34
ESCARGOT_MESSAGE_VARIABLE = 35
ESCARGOT_MESSAGE_VARIABLE_8BIT = 36
ESCARGOT_MESSAGE_VARIABLE_8BIT_END = 37
ESCARGOT_MESSAGE_VARIABLE_16BIT = 38
ESCARGOT_MESSAGE_VARIABLE_16BIT_END = 39
ESCARGOT_MESSAGE_PRINT_8BIT = 40
ESCARGOT_MESSAGE_PRINT_8BIT_END = 41
ESCARGOT_MESSAGE_PRINT_16BIT = 42
ESCARGOT_MESSAGE_PRINT_16BIT_END = 43
ESCARGOT_MESSAGE_STRING_8BIT = 35
ESCARGOT_MESSAGE_STRING_8BIT_END = 36
ESCARGOT_MESSAGE_STRING_16BIT = 37
ESCARGOT_MESSAGE_STRING_16BIT_END = 38
ESCARGOT_MESSAGE_VARIABLE = 39
ESCARGOT_MESSAGE_PRINT = 40
ESCARGOT_MESSAGE_EXCEPTION = 41
ESCARGOT_MESSAGE_EXCEPTION_BACKTRACE = 42


# Messages sent by the debugger client to Escargot.
Expand Down Expand Up @@ -397,15 +396,18 @@ def process_messages(self):
result = self._receive_string(ESCARGOT_MESSAGE_EVAL_RESULT_8BIT, data);
return DebuggerAction(DebuggerAction.TEXT, "%sException: %s%s" % (self.red, result, self.no_color));

elif buffer_type == ESCARGOT_MESSAGE_BACKTRACE:
elif buffer_type in [ESCARGOT_MESSAGE_BACKTRACE,
ESCARGOT_MESSAGE_EXCEPTION_BACKTRACE]:
backtrace_info = struct.unpack(self.byte_order + self.pointer_format + self.idx_format + self.idx_format, data[1:])
function = self.function_list[backtrace_info[0]]

result = "%s:%d:%d" % (function.source_name, backtrace_info[1], backtrace_info[2])
if function.name != "":
result += " (in %s)" % (function.name)

return DebuggerAction(DebuggerAction.TEXT, result + "\n")
if buffer_type == ESCARGOT_MESSAGE_BACKTRACE:
return DebuggerAction(DebuggerAction.TEXT, result + "\n")
return DebuggerAction(DebuggerAction.TEXT, "%s%s%s\n" % (self.red, result, self.nocolor))

elif buffer_type == ESCARGOT_MESSAGE_BACKTRACE_END:
self.prompt = True
Expand Down Expand Up @@ -478,25 +480,25 @@ def process_messages(self):
elif variable_type == ESCARGOT_VARIABLE_FUNCTION:
value_str = "function"

name = self._receive_string(ESCARGOT_MESSAGE_VARIABLE_8BIT, self.channel.get_message(True));
name = self._receive_string(ESCARGOT_MESSAGE_STRING_8BIT, self.channel.get_message(True));
if variable_full_type & ESCARGOT_VARIABLE_LONG_NAME != 0:
name += "..."

if variable_has_value:
value_str += self._receive_string(ESCARGOT_MESSAGE_VARIABLE_8BIT, self.channel.get_message(True));
value_str += self._receive_string(ESCARGOT_MESSAGE_STRING_8BIT, self.channel.get_message(True));
if variable_full_type & ESCARGOT_VARIABLE_LONG_VALUE:
value_str += "..."

return DebuggerAction(DebuggerAction.TEXT, "%s: %s\n" % (name, value_str))

elif buffer_type in [ESCARGOT_MESSAGE_PRINT_8BIT,
ESCARGOT_MESSAGE_PRINT_8BIT_END,
ESCARGOT_MESSAGE_PRINT_16BIT,
ESCARGOT_MESSAGE_PRINT_16BIT_END]:

printMessage ="Print: %s\n" % (self._receive_string(ESCARGOT_MESSAGE_PRINT_8BIT, data))
elif buffer_type == ESCARGOT_MESSAGE_PRINT:
printMessage ="Print: %s\n" % (self._receive_string(ESCARGOT_MESSAGE_STRING_8BIT, self.channel.get_message(True)))
return DebuggerAction(DebuggerAction.TEXT, printMessage);

elif buffer_type == ESCARGOT_MESSAGE_EXCEPTION:
exceptionMessage ="%sException: %s%s\n" % (self.red, self._receive_string(ESCARGOT_MESSAGE_STRING_8BIT, self.channel.get_message(True)), self.nocolor)
return DebuggerAction(DebuggerAction.TEXT, exceptionMessage);

else:
raise Exception("Unknown message: %d" % (buffer_type))

Expand Down
1 change: 1 addition & 0 deletions tools/debugger/tests/do_exception.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c
9 changes: 9 additions & 0 deletions tools/debugger/tests/do_exception.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Connecting to: localhost:6501
Connection created!!!
Stopped at tools/debugger/tests/do_exception.js:28
(escargot-debugger) c
Exception: RangeError: Test exception
tools/debugger/tests/do_exception.js:22:2 (in g)
tools/debugger/tests/do_exception.js:25:4 (in f)
tools/debugger/tests/do_exception.js:28:1
Connection closed.
28 changes: 28 additions & 0 deletions tools/debugger/tests/do_exception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2020-present Samsung Electronics Co., Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/

function g() {
throw RangeError("Test exception");
}

function f() {
g();
}

f();

0 comments on commit 161899b

Please sign in to comment.