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,328 @@ 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+ * Send the scope chain types.
201+ */
202+ static void
203+ jerry_debugger_send_scope_chain (void )
204+ {
205+ vm_frame_ctx_t * iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p );
206+
207+ const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t );
208+ const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count , uint8_t );
209+
210+ JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t , message_type_p );
211+ message_type_p -> type = JERRY_DEBUGGER_SCOPE_CHAIN ;
212+
213+ size_t buffer_pos = 0 ;
214+ bool next_func_is_local = true;
215+ ecma_object_t * lex_env_p = iter_frame_ctx_p -> lex_env_p ;
216+
217+ while (true)
218+ {
219+ JERRY_ASSERT (ecma_is_lexical_environment (lex_env_p ));
220+
221+ if (buffer_pos == max_byte_count )
222+ {
223+ if (!jerry_debugger_send (max_message_size ))
224+ {
225+ return ;
226+ }
227+
228+ buffer_pos = 0 ;
229+ }
230+
231+ if (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE )
232+ {
233+ if ((lex_env_p -> type_flags_refs & ECMA_OBJECT_FLAG_CATCH_CLAUSE ) != 0 )
234+ {
235+ message_type_p -> string [buffer_pos ++ ] = JERRY_DEBUGGER_SCOPE_CATCH ;
236+ }
237+ else if (next_func_is_local )
238+ {
239+ message_type_p -> string [buffer_pos ++ ] = JERRY_DEBUGGER_SCOPE_LOCAL ;
240+ next_func_is_local = false;
241+ }
242+ else
243+ {
244+ message_type_p -> string [buffer_pos ++ ] = JERRY_DEBUGGER_SCOPE_CLOSURE ;
245+ next_func_is_local = false;
246+ }
247+ }
248+ else if (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND )
249+ {
250+ if (ecma_get_lex_env_outer_reference (lex_env_p ) == NULL )
251+ {
252+ message_type_p -> string [buffer_pos ++ ] = JERRY_DEBUGGER_SCOPE_GLOBAL ;
253+ break ;
254+ }
255+ else
256+ {
257+ message_type_p -> string [buffer_pos ++ ] = JERRY_DEBUGGER_SCOPE_WITH ;
258+ next_func_is_local = true;
259+ }
260+ }
261+
262+ lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p );
263+ }
264+
265+ message_type_p -> type = JERRY_DEBUGGER_SCOPE_CHAIN_END ;
266+
267+ jerry_debugger_send (sizeof (jerry_debugger_send_type_t ) + buffer_pos );
268+ } /* jerry_debugger_send_scope_chain */
269+
270+ /**
271+ * Get type of the scope variable property.
272+ */
273+ static jerry_debugger_scope_variable_type_t
274+ ecma_get_typeof_scope_variable (ecma_value_t value ) /**< input ecma value */
275+ {
276+ jerry_debugger_scope_variable_type_t ret_value = JERRY_DEBUGGER_VALUE_NONE ;
277+
278+ if (ecma_is_value_undefined (value ))
279+ {
280+ ret_value = JERRY_DEBUGGER_VALUE_UNDEFINED ;
281+ }
282+ else if (ecma_is_value_null (value ))
283+ {
284+ ret_value = JERRY_DEBUGGER_VALUE_NULL ;
285+ }
286+ else if (ecma_is_value_boolean (value ))
287+ {
288+ ret_value = JERRY_DEBUGGER_VALUE_BOOLEAN ;
289+ }
290+ else if (ecma_is_value_number (value ))
291+ {
292+ ret_value = JERRY_DEBUGGER_VALUE_NUMBER ;
293+ }
294+ else if (ecma_is_value_string (value ))
295+ {
296+ ret_value = JERRY_DEBUGGER_VALUE_STRING ;
297+ }
298+ else
299+ {
300+ JERRY_ASSERT (ecma_is_value_object (value ));
301+
302+ if (ecma_object_get_class_name (ecma_get_object_from_value (value )) == LIT_MAGIC_STRING_ARRAY_UL )
303+ {
304+ ret_value = JERRY_DEBUGGER_VALUE_ARRAY ;
305+ }
306+ else
307+ {
308+ ret_value = ecma_op_is_callable (value ) ? JERRY_DEBUGGER_VALUE_FUNCTION : JERRY_DEBUGGER_VALUE_OBJECT ;
309+ }
310+ }
311+
312+ JERRY_ASSERT (ret_value != JERRY_DEBUGGER_VALUE_NONE );
313+
314+ return ret_value ;
315+ } /* ecma_get_typeof_scope_variable */
316+
317+ /**
318+ * Helper function for jerry_debugger_send_scope_variables.
319+ *
320+ * It will copies the given scope values type, length and value into the outgoing message string.
321+ *
322+ * @return true - if the copy was successfully
323+ * false - otherwise
324+ */
325+ static bool
326+ copy_scope_variables_to_string_message (jerry_debugger_scope_variable_type_t variable_type , /**< variable type */
327+ ecma_string_t * value_str , /**< property name or value string */
328+ jerry_debugger_send_string_t * message_string_p , /**< message pointer */
329+ size_t * buffer_pos ) /**< string data position of the message */
330+ {
331+ const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t );
332+ const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count , uint8_t );
333+
334+ ECMA_STRING_TO_UTF8_STRING (value_str , str_buff , str_buff_size );
335+
336+ size_t str_size = 0 ;
337+ size_t str_limit = 255 ;
338+ bool result = true;
339+
340+ bool type_processed = false;
341+
342+ while (true)
343+ {
344+ if (* buffer_pos == max_byte_count )
345+ {
346+ if (!jerry_debugger_send (max_message_size ))
347+ {
348+ result = false;
349+ break ;
350+ }
351+
352+ * buffer_pos = 0 ;
353+ }
354+
355+ if (!type_processed )
356+ {
357+ if (variable_type != JERRY_DEBUGGER_VALUE_NONE )
358+ {
359+ message_string_p -> string [* buffer_pos ] = variable_type ;
360+ * buffer_pos += 1 ;
361+ }
362+ type_processed = true;
363+ continue ;
364+ }
365+
366+ if (variable_type == JERRY_DEBUGGER_VALUE_FUNCTION )
367+ {
368+ str_size = 0 ; // do not copy function values
369+ }
370+ else
371+ {
372+ str_size = (str_buff_size > str_limit ) ? str_limit : str_buff_size ;
373+ }
374+
375+ message_string_p -> string [* buffer_pos ] = (uint8_t ) str_size ;
376+ * buffer_pos += 1 ;
377+ break ;
378+ }
379+
380+ if (result )
381+ {
382+ size_t free_bytes = max_byte_count - * buffer_pos ;
383+ const uint8_t * string_p = str_buff ;
384+
385+ while (str_size > free_bytes )
386+ {
387+ memcpy (message_string_p -> string + * buffer_pos , string_p , free_bytes );
388+
389+ if (!jerry_debugger_send (max_message_size ))
390+ {
391+ result = false;
392+ break ;
393+ }
394+
395+ string_p += free_bytes ;
396+ str_size -= free_bytes ;
397+ free_bytes = max_byte_count ;
398+ * buffer_pos = 0 ;
399+ }
400+
401+ if (result )
402+ {
403+ memcpy (message_string_p -> string + * buffer_pos , string_p , str_size );
404+ * buffer_pos += str_size ;
405+ }
406+ }
407+
408+ ECMA_FINALIZE_UTF8_STRING (str_buff , str_buff_size );
409+
410+ return result ;
411+ } /* copy_scope_variables_to_string_message */
412+
413+ /**
414+ * Send variables of the given scope chain level.
415+ */
416+ static void
417+ jerry_debugger_send_scope_variables (const uint8_t * recv_buffer_p ) /**< pointer to the received data */
418+ {
419+ JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_get_scope_variables_t , get_scope_variables_p );
420+
421+ uint32_t chain_index ;
422+ memcpy (& chain_index , get_scope_variables_p -> chain_index , sizeof (uint32_t ));
423+
424+ vm_frame_ctx_t * iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p );
425+ ecma_object_t * lex_env_p = iter_frame_ctx_p -> lex_env_p ;
426+
427+ while (chain_index != 0 )
428+ {
429+ lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p );
430+
431+ if (JERRY_UNLIKELY (lex_env_p == NULL ))
432+ {
433+ jerry_debugger_send_type (JERRY_DEBUGGER_SCOPE_VARIABLES_END );
434+ return ;
435+ }
436+
437+ if ((ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND )
438+ || (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE ))
439+ {
440+ chain_index -- ;
441+ }
442+ }
443+
444+ ecma_property_header_t * prop_iter_p ;
445+
446+ if (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE )
447+ {
448+ prop_iter_p = ecma_get_property_list (lex_env_p );
449+ }
450+ else
451+ {
452+ JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p ) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND );
453+ ecma_object_t * binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p );
454+ prop_iter_p = ecma_get_property_list (binding_obj_p );
455+ }
456+
457+ JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t , message_string_p );
458+ message_string_p -> type = JERRY_DEBUGGER_SCOPE_VARIABLES ;
459+
460+ size_t buffer_pos = 0 ;
461+
462+ while (prop_iter_p != NULL )
463+ {
464+ JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p ));
465+
466+ ecma_property_pair_t * prop_pair_p = (ecma_property_pair_t * ) prop_iter_p ;
467+
468+ for (int i = 0 ; i < ECMA_PROPERTY_PAIR_ITEM_COUNT ; i ++ )
469+ {
470+ if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p -> types [i ]))
471+ {
472+ ecma_string_t * prop_name = ecma_string_from_property_name (prop_iter_p -> types [i ],
473+ prop_pair_p -> names_cp [i ]);
474+
475+ if (!copy_scope_variables_to_string_message (JERRY_DEBUGGER_VALUE_NONE ,
476+ prop_name ,
477+ message_string_p ,
478+ & buffer_pos ))
479+ {
480+ ecma_deref_ecma_string (prop_name );
481+ return ;
482+ }
483+
484+ ecma_deref_ecma_string (prop_name );
485+
486+ ecma_property_value_t prop_value_p = prop_pair_p -> values [i ];
487+ ecma_value_t property_value ;
488+
489+ jerry_debugger_scope_variable_type_t variable_type = ecma_get_typeof_scope_variable (prop_value_p .value );
490+
491+ if (variable_type == JERRY_DEBUGGER_VALUE_OBJECT )
492+ {
493+ property_value = ecma_builtin_json_string_from_object (prop_value_p .value );
494+ }
495+ else
496+ {
497+ property_value = ecma_op_to_string (prop_value_p .value );
498+ }
499+
500+ if (!copy_scope_variables_to_string_message (variable_type ,
501+ ecma_get_string_from_value (property_value ),
502+ message_string_p ,
503+ & buffer_pos ))
504+ {
505+ ecma_free_value (property_value );
506+ return ;
507+ }
508+
509+ ecma_free_value (property_value );
510+ }
511+ }
512+
513+ prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t ,
514+ prop_iter_p -> next_property_cp );
515+ }
516+
517+ message_string_p -> type = JERRY_DEBUGGER_SCOPE_VARIABLES_END ;
518+ jerry_debugger_send (sizeof (jerry_debugger_send_type_t ) + buffer_pos );
519+ } /* jerry_debugger_send_scope_variables */
520+
198521/**
199522 * Send result of evaluated expression or throw an error.
200523 *
@@ -525,6 +848,24 @@ jerry_debugger_process_message (const uint8_t *recv_buffer_p, /**< pointer to th
525848 return true;
526849 }
527850
851+ case JERRY_DEBUGGER_GET_SCOPE_CHAIN :
852+ {
853+ JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t );
854+
855+ jerry_debugger_send_scope_chain ();
856+
857+ return true;
858+ }
859+
860+ case JERRY_DEBUGGER_GET_SCOPE_VARIABLES :
861+ {
862+ JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_scope_variables_t );
863+
864+ jerry_debugger_send_scope_variables (recv_buffer_p );
865+
866+ return true;
867+ }
868+
528869 case JERRY_DEBUGGER_EXCEPTION_CONFIG :
529870 {
530871 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t );
0 commit comments