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