1818#include "ecma-builtin-helpers.h"
1919#include "ecma-conversion.h"
2020#include "ecma-eval.h"
21+ #include "ecma-function-object.h"
2122#include "ecma-objects.h"
2223#include "jcontext.h"
2324#include "jerryscript-port.h"
@@ -37,9 +38,9 @@ typedef struct
3738 * The number of message types in the debugger should reflect the
3839 * debugger versioning.
3940 */
40- JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 28
41- && JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 19
42- && JERRY_DEBUGGER_VERSION == 6 ,
41+ JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 32
42+ && JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 21
43+ && JERRY_DEBUGGER_VERSION == 7 ,
4344 debugger_version_correlates_to_message_type_count );
4445
4546/**
@@ -195,6 +196,305 @@ jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the
195196 jerry_debugger_send (sizeof (jerry_debugger_send_type_t ) + message_size );
196197} /* jerry_debugger_send_backtrace */
197198
199+
200+ /**
201+ * Send the scope chain types.
202+ */
203+ static void
204+ jerry_debugger_send_scope_chain (void )
205+ {
206+ vm_frame_ctx_t * iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p );
207+
208+ const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t );
209+ const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count , uint8_t );
210+
211+ JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t , message_type_p );
212+ message_type_p -> type = JERRY_DEBUGGER_SCOPE_CHAIN ;
213+
214+ size_t buffer_pos = 0 ;
215+ uint8_t level_type ;
216+ bool next_func_is_local = true;
217+
218+ for (ecma_object_t * lex_env_p = iter_frame_ctx_p -> lex_env_p ;
219+ lex_env_p != NULL ;
220+ lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p ))
221+ {
222+ JERRY_ASSERT (ecma_is_lexical_environment (lex_env_p ));
223+
224+ if (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE )
225+ {
226+ if ((lex_env_p -> type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE ) != 0 )
227+ {
228+ level_type = JERRY_DEBUGGER_SCOPE_CATCH ;
229+ }
230+ else if (next_func_is_local )
231+ {
232+ level_type = JERRY_DEBUGGER_SCOPE_LOCAL ;
233+ next_func_is_local = false;
234+ }
235+ else
236+ {
237+ level_type = JERRY_DEBUGGER_SCOPE_CLOSURE ;
238+ next_func_is_local = false;
239+ }
240+ }
241+ else
242+ {
243+ JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND );
244+
245+ if (ecma_get_lex_env_outer_reference (lex_env_p ) == NULL )
246+ {
247+ level_type = JERRY_DEBUGGER_SCOPE_GLOBAL ;
248+ }
249+ else
250+ {
251+ level_type = JERRY_DEBUGGER_SCOPE_WITH ;
252+ next_func_is_local = true;
253+ }
254+ }
255+
256+ memcpy (message_type_p -> string + buffer_pos ++ , & level_type , 1 );
257+
258+ if (buffer_pos == max_byte_count )
259+ {
260+ if (!jerry_debugger_send (max_message_size ))
261+ {
262+ return ;
263+ }
264+
265+ buffer_pos = 0 ;
266+ }
267+ }
268+
269+ message_type_p -> type = JERRY_DEBUGGER_SCOPE_CHAIN_END ;
270+
271+ jerry_debugger_send (sizeof (jerry_debugger_send_type_t ) + buffer_pos );
272+ } /* jerry_debugger_send_scope_chain */
273+
274+ /**
275+ * Get type of the scope variable property.
276+ */
277+ static jerry_debugger_scope_variable_type_t
278+ ecma_get_typeof_scope_variable (ecma_value_t value ) /**< input ecma value */
279+ {
280+ jerry_debugger_scope_variable_type_t ret_value = JERRY_DEBUGGER_VARIABLE_NONE ;
281+
282+ if (ecma_is_value_undefined (value ))
283+ {
284+ ret_value = JERRY_DEBUGGER_VARIABLE_UNDEFINED ;
285+ }
286+ else if (ecma_is_value_null (value ))
287+ {
288+ ret_value = JERRY_DEBUGGER_VARIABLE_OBJECT ;
289+ }
290+ else if (ecma_is_value_boolean (value ))
291+ {
292+ ret_value = JERRY_DEBUGGER_VARIABLE_BOOLEAN ;
293+ }
294+ else if (ecma_is_value_number (value ))
295+ {
296+ ret_value = JERRY_DEBUGGER_VARIABLE_NUMBER ;
297+ }
298+ else if (ecma_is_value_string (value ))
299+ {
300+ ret_value = JERRY_DEBUGGER_VARIABLE_STRING ;
301+ }
302+ else
303+ {
304+ JERRY_ASSERT (ecma_is_value_object (value ));
305+
306+ if (ecma_object_get_class_name (ecma_get_object_from_value (value )) == LIT_MAGIC_STRING_ARRAY_UL )
307+ {
308+ ret_value = JERRY_DEBUGGER_VARIABLE_ARRAY ;
309+ }
310+ else
311+ {
312+ ret_value = ecma_op_is_callable (value ) ? JERRY_DEBUGGER_VARIABLE_FUNCTION : JERRY_DEBUGGER_VARIABLE_OBJECT ;
313+ }
314+ }
315+
316+ JERRY_ASSERT (ret_value != JERRY_DEBUGGER_VARIABLE_NONE );
317+
318+ return ret_value ;
319+ } /* ecma_get_typeof_scope_variable */
320+
321+ /**
322+ * Helper function for jerry_debugger_send_scope_variables.
323+ *
324+ * It will copies the given scope values type, length and value into the outgoing message string.
325+ *
326+ * @return true - if the copy was successfully
327+ * false - otherwise
328+ */
329+ static bool
330+ copy_scope_variables_to_string_message (jerry_debugger_scope_variable_type_t variable_type , /**< variable type */
331+ ecma_string_t * value_str , /**< property name or value string */
332+ jerry_debugger_send_string_t * message_string_p , /**< message pointer */
333+ size_t * buffer_pos ) /**< string data position of the message */
334+ {
335+ const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t );
336+ const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count , uint8_t );
337+
338+ ECMA_STRING_TO_UTF8_STRING (value_str , str_buff , str_buff_size );
339+
340+ int copied_values = 3 ; // type, length, value
341+ size_t str_size = 0 ;
342+ size_t str_limit = 255 ;
343+
344+ while (copied_values > 0 )
345+ {
346+ if (* buffer_pos == max_byte_count )
347+ {
348+ if (!jerry_debugger_send (max_message_size ))
349+ {
350+ ECMA_FINALIZE_UTF8_STRING (str_buff , str_buff_size );
351+ return false;
352+ }
353+
354+ * buffer_pos = 0 ;
355+ }
356+
357+ if (copied_values == 3 )
358+ {
359+ if (variable_type != JERRY_DEBUGGER_VARIABLE_NONE )
360+ {
361+ memcpy (message_string_p -> string + * buffer_pos , & variable_type , 1 );
362+ * buffer_pos += 1 ;
363+ }
364+ }
365+ else if (copied_values == 2 )
366+ {
367+ str_size = (str_buff_size > str_limit ) ? str_limit : str_buff_size ;
368+
369+ memcpy (message_string_p -> string + * buffer_pos , & str_size , 1 );
370+ * buffer_pos += 1 ;
371+ }
372+ else
373+ {
374+ size_t free_bytes = max_byte_count - * buffer_pos ;
375+ const uint8_t * string_p = str_buff ;
376+
377+ while (str_size > free_bytes )
378+ {
379+ memcpy (message_string_p -> string + * buffer_pos , string_p , free_bytes );
380+
381+ if (!jerry_debugger_send (max_message_size ))
382+ {
383+ ECMA_FINALIZE_UTF8_STRING (str_buff , str_buff_size );
384+
385+ return false;
386+ }
387+
388+ string_p += free_bytes ;
389+ str_size -= free_bytes ;
390+ free_bytes = max_byte_count ;
391+ * buffer_pos = 0 ;
392+ }
393+
394+ memcpy (message_string_p -> string + * buffer_pos , string_p , str_size );
395+ * buffer_pos += str_size ;
396+ }
397+
398+ copied_values -- ;
399+ }
400+
401+ ECMA_FINALIZE_UTF8_STRING (str_buff , str_buff_size );
402+
403+ return true;
404+ } /* copy_scope_variables_to_string_message */
405+
406+ /**
407+ * Send variables of the given scope chain level.
408+ */
409+ static void
410+ jerry_debugger_send_scope_variables (const uint8_t * recv_buffer_p ) /**< pointer to the received data */
411+ {
412+ JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_get_scope_variables_t , get_scope_variables_p );
413+
414+ uint32_t chain_index ;
415+ memcpy (& chain_index , get_scope_variables_p -> chain_index , sizeof (uint32_t ));
416+
417+ vm_frame_ctx_t * iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p );
418+ ecma_object_t * lex_env_p = iter_frame_ctx_p -> lex_env_p ;
419+
420+ while (chain_index != 0 )
421+ {
422+ lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p );
423+
424+ if (lex_env_p == NULL )
425+ {
426+ jerry_debugger_send_type (JERRY_DEBUGGER_SCOPE_VARIABLES_END );
427+ return ;
428+ }
429+ chain_index -- ;
430+ }
431+
432+ ecma_property_header_t * prop_iter_p ;
433+
434+ if (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE )
435+ {
436+ prop_iter_p = ecma_get_property_list (lex_env_p );
437+ }
438+ else
439+ {
440+ JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND );
441+ ecma_object_t * binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p );
442+ prop_iter_p = ecma_get_property_list (binding_obj_p );
443+ }
444+
445+ JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t , message_string_p );
446+ message_string_p -> type = JERRY_DEBUGGER_SCOPE_VARIABLES ;
447+
448+ size_t buffer_pos = 0 ;
449+
450+ while (prop_iter_p != NULL )
451+ {
452+ JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p ));
453+
454+ ecma_property_pair_t * prop_pair_p = (ecma_property_pair_t * ) prop_iter_p ;
455+
456+ for (int i = 0 ; i < ECMA_PROPERTY_PAIR_ITEM_COUNT ; i ++ )
457+ {
458+ if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p -> types [i ]))
459+ {
460+ ecma_string_t * prop_name = ecma_string_from_property_name (prop_iter_p -> types [i ],
461+ prop_pair_p -> names_cp [i ]);
462+
463+ if (!copy_scope_variables_to_string_message (JERRY_DEBUGGER_VARIABLE_NONE ,
464+ prop_name ,
465+ message_string_p ,
466+ & buffer_pos ))
467+ {
468+ ecma_deref_ecma_string (prop_name );
469+ return ;
470+ }
471+
472+ ecma_deref_ecma_string (prop_name );
473+
474+ ecma_property_value_t prop_value_p = prop_pair_p -> values [i ];
475+ ecma_value_t final_str = ecma_op_to_string (prop_value_p .value );
476+
477+ if (!copy_scope_variables_to_string_message (ecma_get_typeof_scope_variable (prop_value_p .value ),
478+ ecma_get_string_from_value (final_str ),
479+ message_string_p ,
480+ & buffer_pos ))
481+ {
482+ ecma_free_value (final_str );
483+ return ;
484+ }
485+
486+ ecma_free_value (final_str );
487+ }
488+ }
489+
490+ prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t ,
491+ prop_iter_p -> next_property_cp );
492+ }
493+
494+ message_string_p -> type = JERRY_DEBUGGER_SCOPE_VARIABLES_END ;
495+ jerry_debugger_send (sizeof (jerry_debugger_send_type_t ) + buffer_pos );
496+ } /* jerry_debugger_send_scope_variables */
497+
198498/**
199499 * Send result of evaluated expression or throw an error.
200500 *
@@ -525,6 +825,24 @@ jerry_debugger_process_message (const uint8_t *recv_buffer_p, /**< pointer to th
525825 return true;
526826 }
527827
828+ case JERRY_DEBUGGER_GET_SCOPE_CHAIN :
829+ {
830+ JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t );
831+
832+ jerry_debugger_send_scope_chain ();
833+
834+ return true;
835+ }
836+
837+ case JERRY_DEBUGGER_GET_SCOPE_VARIABLES :
838+ {
839+ JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_scope_variables_t );
840+
841+ jerry_debugger_send_scope_variables (recv_buffer_p );
842+
843+ return true;
844+ }
845+
528846 case JERRY_DEBUGGER_EXCEPTION_CONFIG :
529847 {
530848 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t );
0 commit comments