1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "debugger.h" 17#include "jcontext.h" 18#include "jerryscript.h" 19 20/** 21 * Checks whether the debugger is connected. 22 * 23 * @return true - if the debugger is connected 24 * false - otherwise 25 */ 26bool 27jerry_debugger_is_connected (void) 28{ 29#if ENABLED (JERRY_DEBUGGER) 30 return JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED; 31#else /* !ENABLED (JERRY_DEBUGGER) */ 32 return false; 33#endif /* ENABLED (JERRY_DEBUGGER) */ 34} /* jerry_debugger_is_connected */ 35 36/** 37 * Stop execution at the next available breakpoint. 38 */ 39void 40jerry_debugger_stop (void) 41{ 42#if ENABLED (JERRY_DEBUGGER) 43 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 44 && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) 45 { 46 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); 47 JERRY_CONTEXT (debugger_stop_context) = NULL; 48 } 49#endif /* ENABLED (JERRY_DEBUGGER) */ 50} /* jerry_debugger_stop */ 51 52/** 53 * Continue execution. 54 */ 55void 56jerry_debugger_continue (void) 57{ 58#if ENABLED (JERRY_DEBUGGER) 59 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 60 && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) 61 { 62 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP); 63 JERRY_CONTEXT (debugger_stop_context) = NULL; 64 } 65#endif /* ENABLED (JERRY_DEBUGGER) */ 66} /* jerry_debugger_continue */ 67 68/** 69 * Sets whether the engine should stop at breakpoints. 70 */ 71void 72jerry_debugger_stop_at_breakpoint (bool enable_stop_at_breakpoint) /**< enable/disable stop at breakpoint */ 73{ 74#if ENABLED (JERRY_DEBUGGER) 75 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED 76 && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) 77 { 78 if (enable_stop_at_breakpoint) 79 { 80 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE); 81 } 82 else 83 { 84 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE); 85 } 86 } 87#else /* !ENABLED (JERRY_DEBUGGER) */ 88 JERRY_UNUSED (enable_stop_at_breakpoint); 89#endif /* ENABLED (JERRY_DEBUGGER) */ 90} /* jerry_debugger_stop_at_breakpoint */ 91 92/** 93 * Sets whether the engine should wait and run a source. 94 * 95 * @return enum JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED - if the source is not received 96 * JERRY_DEBUGGER_SOURCE_RECEIVED - if a source code received 97 * JERRY_DEBUGGER_SOURCE_END - the end of the source codes 98 * JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED - the end of the context 99 */ 100jerry_debugger_wait_for_source_status_t 101jerry_debugger_wait_for_client_source (jerry_debugger_wait_for_source_callback_t callback_p, /**< callback function */ 102 void *user_p, /**< user pointer passed to the callback */ 103 jerry_value_t *return_value) /**< [out] parse and run return value */ 104{ 105 *return_value = jerry_create_undefined (); 106 107#if ENABLED (JERRY_DEBUGGER) 108 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 109 && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) 110 { 111 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); 112 jerry_debugger_uint8_data_t *client_source_data_p = NULL; 113 jerry_debugger_wait_for_source_status_t ret_type = JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED; 114 115 /* Notify the client about that the engine is waiting for a source. */ 116 jerry_debugger_send_type (JERRY_DEBUGGER_WAIT_FOR_SOURCE); 117 118 while (true) 119 { 120 if (jerry_debugger_receive (&client_source_data_p)) 121 { 122 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)) 123 { 124 break; 125 } 126 127 /* Stop executing the current context. */ 128 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONTEXT_RESET_MODE)) 129 { 130 ret_type = JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED; 131 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CONTEXT_RESET_MODE); 132 break; 133 } 134 135 /* Stop waiting for a new source file. */ 136 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_NO_SOURCE)) 137 { 138 ret_type = JERRY_DEBUGGER_SOURCE_END; 139 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); 140 break; 141 } 142 143 /* The source arrived. */ 144 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) 145 { 146 JERRY_ASSERT (client_source_data_p != NULL); 147 148 jerry_char_t *resource_name_p = (jerry_char_t *) (client_source_data_p + 1); 149 size_t resource_name_size = strlen ((const char *) resource_name_p); 150 151 *return_value = callback_p (resource_name_p, 152 resource_name_size, 153 resource_name_p + resource_name_size + 1, 154 client_source_data_p->uint8_size - resource_name_size - 1, 155 user_p); 156 157 ret_type = JERRY_DEBUGGER_SOURCE_RECEIVED; 158 break; 159 } 160 } 161 162 jerry_debugger_transport_sleep (); 163 } 164 165 JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE) 166 || !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)); 167 168 if (client_source_data_p != NULL) 169 { 170 /* The data may partly arrived. */ 171 jmem_heap_free_block (client_source_data_p, 172 client_source_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); 173 } 174 175 return ret_type; 176 } 177 178 return JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED; 179#else /* !ENABLED (JERRY_DEBUGGER) */ 180 JERRY_UNUSED (callback_p); 181 JERRY_UNUSED (user_p); 182 183 return JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED; 184#endif /* ENABLED (JERRY_DEBUGGER) */ 185} /* jerry_debugger_wait_for_client_source */ 186 187/** 188 * Send the output of the program to the debugger client. 189 * Currently only sends print output. 190 */ 191void 192jerry_debugger_send_output (const jerry_char_t *buffer, /**< buffer */ 193 jerry_size_t str_size) /**< string size */ 194{ 195#if ENABLED (JERRY_DEBUGGER) 196 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 197 { 198 jerry_debugger_send_string (JERRY_DEBUGGER_OUTPUT_RESULT, 199 JERRY_DEBUGGER_OUTPUT_OK, 200 (const uint8_t *) buffer, 201 sizeof (uint8_t) * str_size); 202 } 203#else /* !ENABLED (JERRY_DEBUGGER) */ 204 JERRY_UNUSED (buffer); 205 JERRY_UNUSED (str_size); 206#endif /* ENABLED (JERRY_DEBUGGER) */ 207} /* jerry_debugger_send_output */ 208 209/** 210 * Send the log of the program to the debugger client. 211 */ 212void 213jerry_debugger_send_log (jerry_log_level_t level, /**< level of the diagnostics message */ 214 const jerry_char_t *buffer, /**< buffer */ 215 jerry_size_t str_size) /**< string size */ 216{ 217#if ENABLED (JERRY_DEBUGGER) 218 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 219 { 220 jerry_debugger_send_string (JERRY_DEBUGGER_OUTPUT_RESULT, 221 (uint8_t) (level + 2), 222 (const uint8_t *) buffer, 223 sizeof (uint8_t) * str_size); 224 } 225#else /* !ENABLED (JERRY_DEBUGGER) */ 226 JERRY_UNUSED (level); 227 JERRY_UNUSED (buffer); 228 JERRY_UNUSED (str_size); 229#endif /* ENABLED (JERRY_DEBUGGER) */ 230} /* jerry_debugger_send_log */ 231