mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add restart command to the debugger (#2401)
With this feature the use can restart the actual debug session (similar to the multiple source context reset) within a client. JerryScript-DCO-1.0-Signed-off-by: Imre Kiss kissi.szeged@partner.samsung.com
This commit is contained in:
parent
35ac0e0445
commit
e3265883fd
@ -30,7 +30,7 @@
|
||||
*/
|
||||
JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 27
|
||||
&& JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 19
|
||||
&& JERRY_DEBUGGER_VERSION == 3,
|
||||
&& JERRY_DEBUGGER_VERSION == 4,
|
||||
debugger_version_correlates_to_message_type_count);
|
||||
|
||||
/**
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
/**
|
||||
* JerryScript debugger protocol version.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_VERSION (3)
|
||||
#define JERRY_DEBUGGER_VERSION (4)
|
||||
|
||||
/**
|
||||
* Frequency of calling jerry_debugger_receive() by the VM.
|
||||
|
||||
@ -28,7 +28,7 @@ import math
|
||||
import time
|
||||
|
||||
# Expected debugger protocol version.
|
||||
JERRY_DEBUGGER_VERSION = 3
|
||||
JERRY_DEBUGGER_VERSION = 4
|
||||
|
||||
# Messages sent by the server to client.
|
||||
JERRY_DEBUGGER_CONFIGURATION = 1
|
||||
@ -513,6 +513,12 @@ class DebuggerPrompt(Cmd):
|
||||
|
||||
do_ms = do_memstats
|
||||
|
||||
def do_restart(self, _):
|
||||
""" Restart the engine's debug session """
|
||||
self._send_string(JERRY_DEBUGGER_EVAL_ABORT + "\"r353t\"", JERRY_DEBUGGER_EVAL)
|
||||
|
||||
do_res = do_restart
|
||||
|
||||
def store_client_sources(self, args):
|
||||
self.client_sources = args
|
||||
|
||||
|
||||
@ -412,6 +412,25 @@ instance_alloc (size_t size,
|
||||
|
||||
#endif /* JERRY_ENABLE_EXTERNAL_CONTEXT */
|
||||
|
||||
/**
|
||||
* Inits the engine and the debugger
|
||||
*/
|
||||
static void
|
||||
init_engine (jerry_init_flag_t flags, /**< initialized flags for the engine */
|
||||
bool debug_server, /**< enable the debugger init or not */
|
||||
uint16_t debug_port) /**< the debugger port */
|
||||
{
|
||||
jerry_init (flags);
|
||||
if (debug_server)
|
||||
{
|
||||
jerry_debugger_init (debug_port);
|
||||
}
|
||||
|
||||
register_js_function ("assert", jerryx_handler_assert);
|
||||
register_js_function ("gc", jerryx_handler_gc);
|
||||
register_js_function ("print", jerryx_handler_print);
|
||||
} /* init_engine */
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
@ -591,15 +610,7 @@ main (int argc,
|
||||
|
||||
#endif /* JERRY_ENABLE_EXTERNAL_CONTEXT */
|
||||
|
||||
jerry_init (flags);
|
||||
if (start_debug_server)
|
||||
{
|
||||
jerry_debugger_init (debug_port);
|
||||
}
|
||||
|
||||
register_js_function ("assert", jerryx_handler_assert);
|
||||
register_js_function ("gc", jerryx_handler_gc);
|
||||
register_js_function ("print", jerryx_handler_print);
|
||||
init_engine (flags, start_debug_server, debug_port);
|
||||
|
||||
jerry_value_t ret_value = jerry_create_undefined ();
|
||||
|
||||
@ -629,99 +640,139 @@ main (int argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (!jerry_value_is_error (ret_value))
|
||||
while (true)
|
||||
{
|
||||
for (int i = 0; i < files_counter; i++)
|
||||
|
||||
if (!jerry_value_is_error (ret_value))
|
||||
{
|
||||
size_t source_size;
|
||||
const jerry_char_t *source_p = (jerry_char_t *) read_file (file_names[i], &source_size);
|
||||
|
||||
if (source_p == NULL)
|
||||
for (int i = 0; i < files_counter; i++)
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Source file load error");
|
||||
break;
|
||||
}
|
||||
size_t source_size;
|
||||
const jerry_char_t *source_p = (jerry_char_t *) read_file (file_names[i], &source_size);
|
||||
|
||||
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_size))
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ("Input must be a valid UTF-8 string."));
|
||||
break;
|
||||
}
|
||||
|
||||
ret_value = jerry_parse ((jerry_char_t *) file_names[i],
|
||||
strlen (file_names[i]),
|
||||
source_p,
|
||||
source_size,
|
||||
JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (ret_value) && !is_parse_only)
|
||||
{
|
||||
jerry_value_t func_val = ret_value;
|
||||
ret_value = jerry_run (func_val);
|
||||
jerry_release_value (func_val);
|
||||
}
|
||||
|
||||
if (jerry_value_is_error (ret_value))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
ret_value = jerry_create_undefined ();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_wait_mode)
|
||||
{
|
||||
is_repl_mode = false;
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
jerry_debugger_wait_for_source_status_t receive_status;
|
||||
|
||||
do
|
||||
if (source_p == NULL)
|
||||
{
|
||||
jerry_value_t run_result;
|
||||
|
||||
receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
|
||||
NULL,
|
||||
&run_result);
|
||||
|
||||
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON,
|
||||
(jerry_char_t *) "Connection aborted before source arrived.");
|
||||
}
|
||||
|
||||
if (receive_status == JERRY_DEBUGGER_SOURCE_END)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
|
||||
}
|
||||
|
||||
jerry_release_value (run_result);
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Source file load error");
|
||||
break;
|
||||
}
|
||||
while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
|
||||
|
||||
if (receive_status != JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED)
|
||||
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_size))
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ("Input must be a valid UTF-8 string."));
|
||||
break;
|
||||
}
|
||||
|
||||
ret_value = jerry_parse ((jerry_char_t *) file_names[i],
|
||||
strlen (file_names[i]),
|
||||
source_p,
|
||||
source_size,
|
||||
JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (ret_value) && !is_parse_only)
|
||||
{
|
||||
jerry_value_t func_val = ret_value;
|
||||
ret_value = jerry_run (func_val);
|
||||
jerry_release_value (func_val);
|
||||
}
|
||||
|
||||
if (jerry_value_is_error (ret_value))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
jerry_init (flags);
|
||||
jerry_debugger_init (debug_port);
|
||||
|
||||
register_js_function ("assert", jerryx_handler_assert);
|
||||
register_js_function ("gc", jerryx_handler_gc);
|
||||
register_js_function ("print", jerryx_handler_print);
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
ret_value = jerry_create_undefined ();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_wait_mode)
|
||||
{
|
||||
is_repl_mode = false;
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
jerry_debugger_wait_for_source_status_t receive_status;
|
||||
|
||||
do
|
||||
{
|
||||
jerry_value_t run_result;
|
||||
|
||||
receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
|
||||
NULL,
|
||||
&run_result);
|
||||
|
||||
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON,
|
||||
(jerry_char_t *) "Connection aborted before source arrived.");
|
||||
}
|
||||
|
||||
if (receive_status == JERRY_DEBUGGER_SOURCE_END)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
|
||||
}
|
||||
|
||||
if (jerry_value_is_abort (run_result))
|
||||
{
|
||||
ret_value = jerry_acquire_value (run_result);
|
||||
}
|
||||
|
||||
jerry_release_value (run_result);
|
||||
}
|
||||
while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
|
||||
|
||||
if (receive_status != JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
init_engine (flags, true, debug_port);
|
||||
|
||||
ret_value = jerry_create_undefined ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool restart = false;
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER) && jerry_value_is_abort (ret_value))
|
||||
{
|
||||
jerry_value_t abort_value = jerry_get_value_from_error (ret_value, false);
|
||||
if (jerry_value_is_string (abort_value))
|
||||
{
|
||||
jerry_char_t str_buf[5];
|
||||
jerry_value_t str_val = jerry_value_to_string (abort_value);
|
||||
jerry_size_t str_size = jerry_get_string_size (str_val);
|
||||
|
||||
if (str_size == 5)
|
||||
{
|
||||
jerry_string_to_char_buffer (str_val, str_buf, str_size);
|
||||
if (memcmp ("r353t", (char *) (str_buf), 5) == 0)
|
||||
{
|
||||
jerry_release_value (ret_value);
|
||||
restart = true;
|
||||
}
|
||||
}
|
||||
|
||||
jerry_release_value (str_val);
|
||||
}
|
||||
|
||||
jerry_release_value (abort_value);
|
||||
}
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
init_engine (flags, true, debug_port);
|
||||
|
||||
ret_value = jerry_create_undefined ();
|
||||
}
|
||||
|
||||
if (is_repl_mode)
|
||||
|
||||
@ -4,9 +4,9 @@ Stopped at tests/debugger/do_help.js:15
|
||||
|
||||
Documented commands (type help <topic>):
|
||||
========================================
|
||||
abort bt display exception list next source
|
||||
b c dump f memstats quit src
|
||||
backtrace continue e finish ms s step
|
||||
break delete eval help n scroll throw
|
||||
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
|
||||
|
||||
(jerry-debugger) quit
|
||||
|
||||
4
tests/debugger/do_restart.cmd
Normal file
4
tests/debugger/do_restart.cmd
Normal file
@ -0,0 +1,4 @@
|
||||
n
|
||||
n
|
||||
n
|
||||
restart
|
||||
18
tests/debugger/do_restart.expected
Normal file
18
tests/debugger/do_restart.expected
Normal file
@ -0,0 +1,18 @@
|
||||
Connecting to: localhost:5001
|
||||
Stopped at tests/debugger/do_restart.js:23
|
||||
(jerry-debugger) n
|
||||
Stopped at tests/debugger/do_restart.js:24
|
||||
(jerry-debugger) n
|
||||
out: foo
|
||||
Stopped at tests/debugger/do_restart.js:25
|
||||
(jerry-debugger) n
|
||||
out: bar
|
||||
Stopped at tests/debugger/do_restart.js:24
|
||||
(jerry-debugger) restart
|
||||
Connecting to: localhost:5001
|
||||
Stopped at tests/debugger/do_restart.js:23
|
||||
(jerry-debugger) continue
|
||||
out: foo
|
||||
out: bar
|
||||
out: foo
|
||||
out: bar
|
||||
26
tests/debugger/do_restart.js
Normal file
26
tests/debugger/do_restart.js
Normal file
@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
function foo() {
|
||||
print("foo");
|
||||
}
|
||||
|
||||
function bar() {
|
||||
print("bar");
|
||||
}
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
@ -37,6 +37,12 @@ sleep 1s
|
||||
RESULT_TEMP=`mktemp ${TEST_CASE}.out.XXXXXXXXXX`
|
||||
|
||||
(cat "${TEST_CASE}.cmd" | ${DEBUGGER_CLIENT} --non-interactive ${CLIENT_ARGS}) &> ${RESULT_TEMP}
|
||||
|
||||
if [[ $TEST_CASE == *"restart"* ]]; then
|
||||
CONTINUE_CASE=$(sed "s/restart/continue/g" <<< "$TEST_CASE")
|
||||
(cat "${CONTINUE_CASE}.cmd" | ${DEBUGGER_CLIENT} --non-interactive ${CLIENT_ARGS}) &>> ${RESULT_TEMP}
|
||||
fi
|
||||
|
||||
diff -U0 ${TEST_CASE}.expected ${RESULT_TEMP}
|
||||
STATUS_CODE=$?
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user