List scope chain levels and their variables to the selected stack frame. (#2557)

It supports to list the scope chain of the current execution context and see
which variables are available.

JerryScript-DCO-1.0-Signed-off-by: Robert Sipka rsipka.uszeged@partner.samsung.com
This commit is contained in:
Robert Sipka
2018-10-29 14:33:31 +01:00
committed by Akos Kiss
parent 7120b8ec02
commit 34c5e229ee
14 changed files with 914 additions and 13 deletions
+348 -3
View File
@@ -18,6 +18,7 @@
#include "ecma-builtin-helpers.h"
#include "ecma-conversion.h"
#include "ecma-eval.h"
#include "ecma-function-object.h"
#include "ecma-objects.h"
#include "jcontext.h"
#include "jerryscript-port.h"
@@ -37,9 +38,9 @@ typedef struct
* The number of message types in the debugger should reflect the
* debugger versioning.
*/
JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 28
&& JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 19
&& JERRY_DEBUGGER_VERSION == 6,
JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 32
&& JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 21
&& JERRY_DEBUGGER_VERSION == 7,
debugger_version_correlates_to_message_type_count);
/**
@@ -195,6 +196,332 @@ jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the
jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + message_size);
} /* jerry_debugger_send_backtrace */
/**
* Send the scope chain types.
*/
static void
jerry_debugger_send_scope_chain (void)
{
vm_frame_ctx_t *iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);
JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t, message_type_p);
message_type_p->type = JERRY_DEBUGGER_SCOPE_CHAIN;
size_t buffer_pos = 0;
bool next_func_is_local = true;
ecma_object_t *lex_env_p = iter_frame_ctx_p->lex_env_p;
while (true)
{
JERRY_ASSERT (ecma_is_lexical_environment (lex_env_p));
if (buffer_pos == max_byte_count)
{
if (!jerry_debugger_send (max_message_size))
{
return;
}
buffer_pos = 0;
}
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_NON_CLOSURE) != 0)
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_NON_CLOSURE;
}
else if (next_func_is_local)
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_LOCAL;
next_func_is_local = false;
}
else
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_CLOSURE;
}
}
else if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
{
if (ecma_get_lex_env_outer_reference (lex_env_p) == NULL)
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_GLOBAL;
break;
}
else
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_WITH;
}
}
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
}
message_type_p->type = JERRY_DEBUGGER_SCOPE_CHAIN_END;
jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + buffer_pos);
} /* jerry_debugger_send_scope_chain */
/**
* Get type of the scope variable property.
*/
static jerry_debugger_scope_variable_type_t
jerry_debugger_get_variable_type (ecma_value_t value) /**< input ecma value */
{
jerry_debugger_scope_variable_type_t ret_value = JERRY_DEBUGGER_VALUE_NONE;
if (ecma_is_value_undefined (value))
{
ret_value = JERRY_DEBUGGER_VALUE_UNDEFINED;
}
else if (ecma_is_value_null (value))
{
ret_value = JERRY_DEBUGGER_VALUE_NULL;
}
else if (ecma_is_value_boolean (value))
{
ret_value = JERRY_DEBUGGER_VALUE_BOOLEAN;
}
else if (ecma_is_value_number (value))
{
ret_value = JERRY_DEBUGGER_VALUE_NUMBER;
}
else if (ecma_is_value_string (value))
{
ret_value = JERRY_DEBUGGER_VALUE_STRING;
}
else
{
JERRY_ASSERT (ecma_is_value_object (value));
if (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)
{
ret_value = JERRY_DEBUGGER_VALUE_ARRAY;
}
else
{
ret_value = ecma_op_is_callable (value) ? JERRY_DEBUGGER_VALUE_FUNCTION : JERRY_DEBUGGER_VALUE_OBJECT;
}
}
JERRY_ASSERT (ret_value != JERRY_DEBUGGER_VALUE_NONE);
return ret_value;
} /* jerry_debugger_get_variable_type */
/**
* Helper function for jerry_debugger_send_scope_variables.
*
* It will copies the given scope values type, length and value into the outgoing message string.
*
* @return true - if the copy was successfully
* false - otherwise
*/
static bool
jerry_debugger_copy_variables_to_string_message (jerry_debugger_scope_variable_type_t variable_type, /**< type */
ecma_string_t *value_str, /**< property name or value string */
jerry_debugger_send_string_t *message_string_p, /**< msg pointer */
size_t *buffer_pos) /**< string data position of the message */
{
const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);
ECMA_STRING_TO_UTF8_STRING (value_str, str_buff, str_buff_size);
size_t str_size = 0;
size_t str_limit = 255;
bool result = true;
bool type_processed = false;
while (true)
{
if (*buffer_pos == max_byte_count)
{
if (!jerry_debugger_send (max_message_size))
{
result = false;
break;
}
*buffer_pos = 0;
}
if (!type_processed)
{
if (variable_type != JERRY_DEBUGGER_VALUE_NONE)
{
message_string_p->string[*buffer_pos] = variable_type;
*buffer_pos += 1;
}
type_processed = true;
continue;
}
if (variable_type == JERRY_DEBUGGER_VALUE_FUNCTION)
{
str_size = 0; // do not copy function values
}
else
{
str_size = (str_buff_size > str_limit) ? str_limit : str_buff_size;
}
message_string_p->string[*buffer_pos] = (uint8_t) str_size;
*buffer_pos += 1;
break;
}
if (result)
{
size_t free_bytes = max_byte_count - *buffer_pos;
const uint8_t *string_p = str_buff;
while (str_size > free_bytes)
{
memcpy (message_string_p->string + *buffer_pos, string_p, free_bytes);
if (!jerry_debugger_send (max_message_size))
{
result = false;
break;
}
string_p += free_bytes;
str_size -= free_bytes;
free_bytes = max_byte_count;
*buffer_pos = 0;
}
if (result)
{
memcpy (message_string_p->string + *buffer_pos, string_p, str_size);
*buffer_pos += str_size;
}
}
ECMA_FINALIZE_UTF8_STRING (str_buff, str_buff_size);
return result;
} /* jerry_debugger_copy_variables_to_string_message */
/**
* Send variables of the given scope chain level.
*/
static void
jerry_debugger_send_scope_variables (const uint8_t *recv_buffer_p) /**< pointer to the received data */
{
JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_get_scope_variables_t, get_scope_variables_p);
uint32_t chain_index;
memcpy (&chain_index, get_scope_variables_p->chain_index, sizeof (uint32_t));
vm_frame_ctx_t *iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
ecma_object_t *lex_env_p = iter_frame_ctx_p->lex_env_p;
while (chain_index != 0)
{
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
if (JERRY_UNLIKELY (lex_env_p == NULL))
{
jerry_debugger_send_type (JERRY_DEBUGGER_SCOPE_VARIABLES_END);
return;
}
if ((ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
|| (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE))
{
chain_index--;
}
}
ecma_property_header_t *prop_iter_p;
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
prop_iter_p = ecma_get_property_list (lex_env_p);
}
else
{
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
prop_iter_p = ecma_get_property_list (binding_obj_p);
}
JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t, message_string_p);
message_string_p->type = JERRY_DEBUGGER_SCOPE_VARIABLES;
size_t buffer_pos = 0;
while (prop_iter_p != NULL)
{
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]))
{
if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[i]) == ECMA_DIRECT_STRING_MAGIC
&& prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT)
{
continue;
}
ecma_string_t *prop_name = ecma_string_from_property_name (prop_iter_p->types[i],
prop_pair_p->names_cp[i]);
if (!jerry_debugger_copy_variables_to_string_message (JERRY_DEBUGGER_VALUE_NONE,
prop_name,
message_string_p,
&buffer_pos))
{
ecma_deref_ecma_string (prop_name);
return;
}
ecma_deref_ecma_string (prop_name);
ecma_property_value_t prop_value_p = prop_pair_p->values[i];
ecma_value_t property_value;
jerry_debugger_scope_variable_type_t variable_type = jerry_debugger_get_variable_type (prop_value_p.value);
if (variable_type == JERRY_DEBUGGER_VALUE_OBJECT)
{
property_value = ecma_builtin_json_string_from_object (prop_value_p.value);
}
else
{
property_value = ecma_op_to_string (prop_value_p.value);
}
if (!jerry_debugger_copy_variables_to_string_message (variable_type,
ecma_get_string_from_value (property_value),
message_string_p,
&buffer_pos))
{
ecma_free_value (property_value);
return;
}
ecma_free_value (property_value);
}
}
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
prop_iter_p->next_property_cp);
}
message_string_p->type = JERRY_DEBUGGER_SCOPE_VARIABLES_END;
jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + buffer_pos);
} /* jerry_debugger_send_scope_variables */
/**
* Send result of evaluated expression or throw an error.
*
@@ -525,6 +852,24 @@ jerry_debugger_process_message (const uint8_t *recv_buffer_p, /**< pointer to th
return true;
}
case JERRY_DEBUGGER_GET_SCOPE_CHAIN:
{
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
jerry_debugger_send_scope_chain ();
return true;
}
case JERRY_DEBUGGER_GET_SCOPE_VARIABLES:
{
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_scope_variables_t);
jerry_debugger_send_scope_variables (recv_buffer_p);
return true;
}
case JERRY_DEBUGGER_EXCEPTION_CONFIG:
{
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t);
+52 -2
View File
@@ -152,7 +152,10 @@ typedef enum
JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25, /**< engine waiting for source code */
JERRY_DEBUGGER_OUTPUT_RESULT = 26, /**< output sent by the program to the debugger */
JERRY_DEBUGGER_OUTPUT_RESULT_END = 27, /**< last output result data */
JERRY_DEBUGGER_SCOPE_CHAIN = 28, /**< scope chain */
JERRY_DEBUGGER_SCOPE_CHAIN_END = 29, /**< last output of scope chain */
JERRY_DEBUGGER_SCOPE_VARIABLES = 30, /**< scope variables */
JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31, /**< last output of scope variables */
JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT, /**< number of different type of output messages by the debugger */
/* Messages sent by the client to server. */
@@ -182,7 +185,8 @@ typedef enum
JERRY_DEBUGGER_GET_BACKTRACE = 16, /**< get backtrace */
JERRY_DEBUGGER_EVAL = 17, /**< first message of evaluating a string */
JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */
JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19, /**< get type names of the scope chain */
JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20, /**< get variables of a scope */
JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
} jerry_debugger_header_type_t;
@@ -229,6 +233,34 @@ typedef enum
JERRY_DEBUGGER_OUTPUT_TRACE = 5, /**< output result, trace */
} jerry_debugger_output_subtype_t;
/**
* Types of scopes.
*/
typedef enum
{
JERRY_DEBUGGER_SCOPE_WITH = 1, /**< with */
JERRY_DEBUGGER_SCOPE_LOCAL = 2, /**< local */
JERRY_DEBUGGER_SCOPE_CLOSURE = 3, /**< closure */
JERRY_DEBUGGER_SCOPE_GLOBAL = 4, /**< global */
JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5 /**< non closure */
} jerry_debugger_scope_chain_type_t;
/**
* Type of scope variables.
*/
typedef enum
{
JERRY_DEBUGGER_VALUE_NONE = 1,
JERRY_DEBUGGER_VALUE_UNDEFINED = 2,
JERRY_DEBUGGER_VALUE_NULL = 3,
JERRY_DEBUGGER_VALUE_BOOLEAN = 4,
JERRY_DEBUGGER_VALUE_NUMBER = 5,
JERRY_DEBUGGER_VALUE_STRING = 6,
JERRY_DEBUGGER_VALUE_FUNCTION = 7,
JERRY_DEBUGGER_VALUE_ARRAY = 8,
JERRY_DEBUGGER_VALUE_OBJECT = 9
} jerry_debugger_scope_variable_type_t;
/**
* Byte data for evaluating expressions and receiving client source.
*/
@@ -364,6 +396,15 @@ typedef struct
jerry_debugger_frame_t frames[]; /**< frames */
} jerry_debugger_send_backtrace_t;
/**
* Outgoing message: scope chain.
*/
typedef struct
{
uint8_t type; /**< type of the message */
uint8_t scope_types[]; /**< scope types */
} jerry_debugger_send_scope_chain_t;
/**
* Outgoing message: number of total frames in backtrace.
*/
@@ -411,6 +452,15 @@ typedef struct
uint8_t eval_size[sizeof (uint32_t)]; /**< total size of the message */
} jerry_debugger_receive_eval_first_t;
/**
* Incoming message: get scope variables
*/
typedef struct
{
uint8_t type; /**< type of the message */
uint8_t chain_index[sizeof (uint32_t)]; /**< index element of the scope */
} jerry_debugger_receive_get_scope_variables_t;
/**
* Incoming message: first message of client source.
*/
+8 -1
View File
@@ -700,6 +700,13 @@ typedef enum
*/
#define ECMA_OBJECT_FLAG_EXTENSIBLE 0x20
/**
* Non closure flag for debugger.
*/
#ifdef JERRY_DEBUGGER
#define ECMA_OBJECT_FLAG_NON_CLOSURE 0x20
#endif /* JERRY_DEBUGGER */
/**
* Value for increasing or decreasing the object reference counter.
*/
@@ -719,7 +726,7 @@ typedef struct
/** type : 4 bit : ecma_object_type_t or ecma_lexical_environment_type_t
depending on ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV
flags : 2 bit : ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
ECMA_OBJECT_FLAG_EXTENSIBLE
ECMA_OBJECT_FLAG_EXTENSIBLE or ECMA_OBJECT_FLAG_NON_CLOSURE
refs : 10 bit (max 1023) */
uint16_t type_flags_refs;
+1 -1
View File
@@ -31,7 +31,7 @@ extern "C"
/**
* JerryScript debugger protocol version.
*/
#define JERRY_DEBUGGER_VERSION (6)
#define JERRY_DEBUGGER_VERSION (7)
/**
* Types for the client source wait and run method.
+3
View File
@@ -3315,6 +3315,9 @@ error:
}
ecma_object_t *catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
#ifdef JERRY_DEBUGGER
catch_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_NON_CLOSURE;
#endif /* JERRY_DEBUGGER */
ecma_string_t *catch_name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
ecma_op_create_mutable_binding (catch_env_p, catch_name_p, false);
+10
View File
@@ -118,6 +118,11 @@ class DebuggerPrompt(Cmd):
self.stop = True
do_bt = do_backtrace
def do_variables(self, args):
""" Get scope variables from debugger """
write(self.debugger.scope_variables(args))
self.stop = True
def do_src(self, args):
""" Get current source code """
if args:
@@ -172,6 +177,11 @@ class DebuggerPrompt(Cmd):
self.stop = True
do_ms = do_memstats
def do_scopes(self, _):
""" Memory statistics """
self.debugger.scope_chain()
self.stop = True
def do_abort(self, args):
""" Throw an exception """
self.debugger.abort(args)
+149 -2
View File
@@ -24,7 +24,7 @@ import struct
import sys
# Expected debugger protocol version.
JERRY_DEBUGGER_VERSION = 6
JERRY_DEBUGGER_VERSION = 7
# Messages sent by the server to client.
JERRY_DEBUGGER_CONFIGURATION = 1
@@ -54,6 +54,10 @@ JERRY_DEBUGGER_EVAL_RESULT_END = 24
JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25
JERRY_DEBUGGER_OUTPUT_RESULT = 26
JERRY_DEBUGGER_OUTPUT_RESULT_END = 27
JERRY_DEBUGGER_SCOPE_CHAIN = 28
JERRY_DEBUGGER_SCOPE_CHAIN_END = 29
JERRY_DEBUGGER_SCOPE_VARIABLES = 30
JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31
# Debugger option flags
JERRY_DEBUGGER_LITTLE_ENDIAN = 0x1
@@ -94,11 +98,28 @@ JERRY_DEBUGGER_FINISH = 15
JERRY_DEBUGGER_GET_BACKTRACE = 16
JERRY_DEBUGGER_EVAL = 17
JERRY_DEBUGGER_EVAL_PART = 18
JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19
JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20
MAX_BUFFER_SIZE = 128
WEBSOCKET_BINARY_FRAME = 2
WEBSOCKET_FIN_BIT = 0x80
JERRY_DEBUGGER_SCOPE_WITH = 1
JERRY_DEBUGGER_SCOPE_LOCAL = 2
JERRY_DEBUGGER_SCOPE_CLOSURE = 3
JERRY_DEBUGGER_SCOPE_GLOBAL = 4
JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5
JERRY_DEBUGGER_VALUE_NONE = 1
JERRY_DEBUGGER_VALUE_UNDEFINED = 2
JERRY_DEBUGGER_VALUE_NULL = 3
JERRY_DEBUGGER_VALUE_BOOLEAN = 4
JERRY_DEBUGGER_VALUE_NUMBER = 5
JERRY_DEBUGGER_VALUE_STRING = 6
JERRY_DEBUGGER_VALUE_FUNCTION = 7
JERRY_DEBUGGER_VALUE_ARRAY = 8
JERRY_DEBUGGER_VALUE_OBJECT = 9
def arguments_parse():
parser = argparse.ArgumentParser(description="JerryScript debugger client")
@@ -264,6 +285,8 @@ class JerryDebugger(object):
self.source_name = ''
self.exception_string = ''
self.frame_index = 0
self.scope_vars = ""
self.scopes = ""
self.client_sources = []
self.last_breakpoint_hit = None
self.next_breakpoint_index = 0
@@ -394,6 +417,10 @@ class JerryDebugger(object):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_MEMSTATS)
def scope_chain(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_GET_SCOPE_CHAIN)
def set_break(self, args):
if not args:
return "Error: Breakpoint index expected"
@@ -500,6 +527,28 @@ class JerryDebugger(object):
self.prompt = False
return ""
def scope_variables(self, args):
index = 0
if args:
try:
index = int(args)
if index < 0:
print ("Error: A non negative integer number expected")
return
except ValueError as val_errno:
return "Error: Non negative integer number expected, %s\n" % (val_errno)
message = struct.pack(self.byte_order + "BBIB" + self.idx_format,
WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT,
WEBSOCKET_FIN_BIT + 1 + 4,
0,
JERRY_DEBUGGER_GET_SCOPE_VARIABLES,
index)
self.send_message(message)
self.prompt = False
return ""
def eval(self, code):
self._send_string(JERRY_DEBUGGER_EVAL_EVAL + code, JERRY_DEBUGGER_EVAL)
self.prompt = False
@@ -724,7 +773,6 @@ class JerryDebugger(object):
while True:
data = self.get_message(False)
if not self.non_interactive:
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
sys.stdin.readline()
@@ -848,6 +896,29 @@ class JerryDebugger(object):
elif buffer_type == JERRY_DEBUGGER_WAIT_FOR_SOURCE:
self.send_client_source()
elif buffer_type in [JERRY_DEBUGGER_SCOPE_CHAIN, JERRY_DEBUGGER_SCOPE_CHAIN_END]:
self.scopes = data[3:]
if buffer_type == JERRY_DEBUGGER_SCOPE_CHAIN_END:
result = self.process_scopes()
self.scopes = ""
self.prompt = True
return DebuggerAction(DebuggerAction.TEXT, result)
elif buffer_type in [JERRY_DEBUGGER_SCOPE_VARIABLES, JERRY_DEBUGGER_SCOPE_VARIABLES_END]:
self.scope_vars += "".join(data[3:])
if buffer_type == JERRY_DEBUGGER_SCOPE_VARIABLES_END:
result = self.process_scope_variables()
self.scope_vars = ""
self.prompt = True
return DebuggerAction(DebuggerAction.TEXT, result)
else:
raise Exception("Unknown message")
@@ -1203,3 +1274,79 @@ class JerryDebugger(object):
if subtype == JERRY_DEBUGGER_EVAL_ERROR:
return "Uncaught exception: %s" % (message)
return message
def process_scope_variables(self):
buff_size = len(self.scope_vars)
buff_pos = 0
table = [['name', 'type', 'value']]
while buff_pos != buff_size:
# Process name
name_length = ord(self.scope_vars[buff_pos:buff_pos + 1])
buff_pos += 1
name = self.scope_vars[buff_pos:buff_pos + name_length]
buff_pos += name_length
# Process type
value_type = ord(self.scope_vars[buff_pos:buff_pos + 1])
buff_pos += 1
value_length = ord(self.scope_vars[buff_pos:buff_pos + 1])
buff_pos += 1
value = self.scope_vars[buff_pos: buff_pos + value_length]
buff_pos += value_length
if value_type == JERRY_DEBUGGER_VALUE_UNDEFINED:
table.append([name, 'undefined', value])
elif value_type == JERRY_DEBUGGER_VALUE_NULL:
table.append([name, 'Null', value])
elif value_type == JERRY_DEBUGGER_VALUE_BOOLEAN:
table.append([name, 'Boolean', value])
elif value_type == JERRY_DEBUGGER_VALUE_NUMBER:
table.append([name, 'Number', value])
elif value_type == JERRY_DEBUGGER_VALUE_STRING:
table.append([name, 'String', value])
elif value_type == JERRY_DEBUGGER_VALUE_FUNCTION:
table.append([name, 'Function', value])
elif value_type == JERRY_DEBUGGER_VALUE_ARRAY:
table.append([name, 'Array', '[' + value + ']'])
elif value_type == JERRY_DEBUGGER_VALUE_OBJECT:
table.append([name, 'Object', value])
result = self.form_table(table)
return result
def process_scopes(self):
result = ""
table = [['level', 'type']]
for i, level in enumerate(self.scopes):
if ord(level) == JERRY_DEBUGGER_SCOPE_WITH:
table.append([str(i), 'with'])
elif ord(level) == JERRY_DEBUGGER_SCOPE_GLOBAL:
table.append([str(i), 'global'])
elif ord(level) == JERRY_DEBUGGER_SCOPE_NON_CLOSURE:
# Currently it is only marks the catch closure.
table.append([str(i), 'catch'])
elif ord(level) == JERRY_DEBUGGER_SCOPE_LOCAL:
table.append([str(i), 'local'])
elif ord(level) == JERRY_DEBUGGER_SCOPE_CLOSURE:
table.append([str(i), 'closure'])
else:
raise Exception("Unexpected scope chain element")
result = self.form_table(table)
return result
def form_table(self, table):
result = ""
col_width = [max(len(x) for x in col) for col in zip(*table)]
for line in table:
result += " | ".join("{:{}}".format(x, col_width[i])
for i, x in enumerate(line)) + " \n"
return result
+4 -4
View File
@@ -4,9 +4,9 @@ Stopped at tests/debugger/do_help.js:15
Documented commands (type help <topic>):
========================================
abort bt display exception list next s step
b c dump f memstats quit scroll throw
backtrace continue e finish ms res source
break delete eval help n restart src
abort bt display exception list next s src
b c dump f memstats quit scopes step
backtrace continue e finish ms res scroll throw
break delete eval help n restart source variables
(jerry-debugger) quit
+19
View File
@@ -0,0 +1,19 @@
scopes
b do_scopes.js:22
c
scopes
c
scopes
b do_scopes.js:28
c
scopes
b do_scopes.js:31
c
scopes
b do_scopes.js:33
c
scopes
b do_scopes.js:35
c
scopes
c
+63
View File
@@ -0,0 +1,63 @@
Connecting to: localhost:5001
Stopped at tests/debugger/do_scopes.js:15
(jerry-debugger) scopes
level | type
0 | global
(jerry-debugger) b do_scopes.js:22
Breakpoint 1 at tests/debugger/do_scopes.js:22 (in f() at line:17, col:1)
(jerry-debugger) c
Exception throw detected (to disable automatic stop type exception 0)
Exception hint: error
Stopped at tests/debugger/do_scopes.js:19 (in f() at line:17, col:1)
(jerry-debugger) scopes
level | type
0 | local
1 | global
(jerry-debugger) c
Stopped at breakpoint:1 tests/debugger/do_scopes.js:22 (in f() at line:17, col:1)
(jerry-debugger) scopes
level | type
0 | catch
1 | local
2 | global
(jerry-debugger) b do_scopes.js:28
Breakpoint 2 at tests/debugger/do_scopes.js:28 (in function() at line:27, col:4)
(jerry-debugger) c
Stopped at breakpoint:2 tests/debugger/do_scopes.js:28 (in function() at line:27, col:4)
(jerry-debugger) scopes
level | type
0 | local
1 | closure
2 | global
(jerry-debugger) b do_scopes.js:31
Breakpoint 3 at tests/debugger/do_scopes.js:31 (in function() at line:27, col:4)
(jerry-debugger) c
Stopped at breakpoint:3 tests/debugger/do_scopes.js:31 (in function() at line:27, col:4)
(jerry-debugger) scopes
level | type
0 | with
1 | local
2 | closure
3 | global
(jerry-debugger) b do_scopes.js:33
Breakpoint 4 at tests/debugger/do_scopes.js:33 (in function() at line:27, col:4)
(jerry-debugger) c
Stopped at breakpoint:4 tests/debugger/do_scopes.js:33 (in function() at line:27, col:4)
(jerry-debugger) scopes
level | type
0 | with
1 | with
2 | local
3 | closure
4 | global
(jerry-debugger) b do_scopes.js:35
Breakpoint 5 at tests/debugger/do_scopes.js:35 (in function() at line:27, col:4)
(jerry-debugger) c
Stopped at breakpoint:5 tests/debugger/do_scopes.js:35 (in function() at line:27, col:4)
(jerry-debugger) scopes
level | type
0 | with
1 | local
2 | closure
3 | global
(jerry-debugger) c
+41
View File
@@ -0,0 +1,41 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var c = 4;
function f() {
try {
throw "error";
}
catch (err) {
var c = 10;
}
var z = true;
var g = 0;
(function() {
var a = [1,2,3]
a.y = "abc";
with (a) {
var h = [4,5,6]
with (h) {
h.d = "dfg"
}
a.d = g + c;
}
})();
}
f();
+28
View File
@@ -0,0 +1,28 @@
scopes
variables
variables 1
variables 0
b tests/debugger/do_variables.js:20
c
scopes
variables 0
variables 1
variables 2
b tests/debugger/do_variables.js:30
c
scopes
variables 1
variables 0
b tests/debugger/do_variables.js:33
c
c
scopes
variables 0
variables 1
b tests/debugger/do_variables.js:50
c
scopes
variables 0
variables 1
variables 2
c
+128
View File
@@ -0,0 +1,128 @@
Connecting to: localhost:5001
Stopped at tests/debugger/do_variables.js:15
(jerry-debugger) scopes
level | type
0 | global
(jerry-debugger) variables
name | type | value
f | Function |
addX | Function |
z | undefined | undefined
c | undefined | undefined
print | Function |
gc | Function |
assert | Function |
(jerry-debugger) variables 1
name | type | value
(jerry-debugger) variables 0
name | type | value
f | Function |
addX | Function |
z | undefined | undefined
c | undefined | undefined
print | Function |
gc | Function |
assert | Function |
(jerry-debugger) b tests/debugger/do_variables.js:20
Breakpoint 1 at tests/debugger/do_variables.js:20 (in function() at line:19, col:10)
(jerry-debugger) c
Stopped at breakpoint:1 tests/debugger/do_variables.js:20 (in function() at line:19, col:10)
(jerry-debugger) scopes
level | type
0 | local
1 | closure
2 | global
(jerry-debugger) variables 0
name | type | value
n | Number | 9
b | undefined | undefined
(jerry-debugger) variables 1
name | type | value
x | Number | 3
(jerry-debugger) variables 2
name | type | value
addThree | Function |
f | Function |
addX | Function |
z | Number | 5
c | Number | 4
print | Function |
gc | Function |
assert | Function |
(jerry-debugger) b tests/debugger/do_variables.js:30
Breakpoint 2 at tests/debugger/do_variables.js:30 (in f() at line:28, col:1)
(jerry-debugger) c
Stopped at breakpoint:2 tests/debugger/do_variables.js:30 (in f() at line:28, col:1)
(jerry-debugger) scopes
level | type
0 | local
1 | global
(jerry-debugger) variables 1
name | type | value
d | Number | 12
addThree | Function |
f | Function |
addX | Function |
z | Number | 5
c | Number | 4
print | Function |
gc | Function |
assert | Function |
(jerry-debugger) variables 0
name | type | value
b | undefined | undefined
x | undefined | undefined
user | undefined | undefined
m | undefined | undefined
c | undefined | undefined
(jerry-debugger) b tests/debugger/do_variables.js:33
Breakpoint 3 at tests/debugger/do_variables.js:33 (in f() at line:28, col:1)
(jerry-debugger) c
Exception throw detected (to disable automatic stop type exception 0)
Exception hint: error
Stopped at breakpoint:2 tests/debugger/do_variables.js:30 (in f() at line:28, col:1)
(jerry-debugger) c
Stopped at breakpoint:3 tests/debugger/do_variables.js:33 (in f() at line:28, col:1)
(jerry-debugger) scopes
level | type
0 | catch
1 | local
2 | global
(jerry-debugger) variables 0
name | type | value
err | String | error
(jerry-debugger) variables 1
name | type | value
b | undefined | undefined
x | undefined | undefined
user | undefined | undefined
m | undefined | undefined
c | undefined | undefined
(jerry-debugger) b tests/debugger/do_variables.js:50
Breakpoint 4 at tests/debugger/do_variables.js:50 (in function() at line:46, col:4)
(jerry-debugger) c
Stopped at breakpoint:4 tests/debugger/do_variables.js:50 (in function() at line:46, col:4)
(jerry-debugger) scopes
level | type
0 | with
1 | local
2 | closure
3 | global
(jerry-debugger) variables 0
name | type | value
y | String | abc
2 | Number | 3
1 | Number | 2
0 | Number | 1
(jerry-debugger) variables 1
name | type | value
h | undefined | undefined
a | Array | [1,2,3]
(jerry-debugger) variables 2
name | type | value
b | Number | 10
x | Boolean | true
user | Object | {"name":"John","age":30}
m | Null | null
c | Number | 10
(jerry-debugger) c
+60
View File
@@ -0,0 +1,60 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var c = 4;
var z = 5;
function addX(x) {
return function(n) {
var b = 2;
return n + x;
}
}
addThree = addX(3);
d = addThree(c+z);
function f() {
try {
throw "error";
}
catch (err) {
var c = 10;
}
var m = null;
var user = {
name: "John",
age: 30
};
var x = true;
var b = 10;
(function() {
var a = [1,2,3]
a.y = "abc";
with (a) {
var h = [4,5,6]
with (h) {
h.d = "dfg"
}
a.d = x;
}
})();
}
f();