Skip to content

Conversation

@robertsipka
Copy link
Contributor

@robertsipka robertsipka commented Oct 8, 2018

It supports to list the scope chain of the current execution context and see which variables are available.

Please note that this is not a complete list, virtual properties are not included. I plan to expand them in a follow-up patch.

An example run should look like this:

test.js

1 var c = 4;
2 var z = 5;
3 
4 function addX(x) {
5  return function(n) {
6     var b = 2;
7     return n + x;
8   }
9 }
10 addThree = addX(3);
11 d = addThree(c+z);
12 
13 function f() {
14   var x = true;
15   var g = 0;
16   (function() {
17     var a = [1,2,3]
18     a.y = "abc";
20     with (a) {
21       var h = [4,5,6]
22       with (h) {
23         h.d = "dfg"
24       }
25       a.d = x + g;
26     }
27   })();
28 }
29 
30 f();
$ ./build/bin/jerry --start-debug-server test.js
$ ./jerry-debugger/jerry_client.py
Connecting to: localhost:5001
Stopped at test.js:1
(jerry-debugger) b test.js:21
Breakpoint 1 at test.js:21 (in function() at line:16, col:4)
(jerry-debugger) c
Press enter to stop JavaScript execution.
Stopped at breakpoint:1 test.js:21 (in function() at line:16, col:4)
(jerry-debugger) scopes
level | type    
0     | with    
1     | local   
2     | closure 
3     | global  
(jerry-debugger) variables 0
name | type   | value 
y    | String | abc   
2    | Number | 3     
1    | Number | 2     
0    | Number | 1     
(jerry-debugger) variables 1
name | type  | value   
h    | Array | [4,5,6] 
a    | Array | [1,2,3] 
(jerry-debugger) variables 2
name | type    | value 
g    | Number  | 0     
x    | Boolean | true  
(jerry-debugger) variables 3
name     | type     | value                        
d        | Number   | 12                           
addThree | Function | function(){/* ecmascript */} 
f        | Function | function(){/* ecmascript */} 
addX     | Function | function(){/* ecmascript */} 
z        | Number   | 5                            
c        | Number   | 4                            
print    | Function | function(){/* ecmascript */} 
gc       | Function | function(){/* ecmascript */} 
assert   | Function | function(){/* ecmascript */} 
(jerry-debugger)

@robertsipka robertsipka force-pushed the variables_list branch 6 times, most recently from a342847 to ba01461 Compare October 12, 2018 13:05
@robertsipka robertsipka changed the title (WIP) List scope chain levels and their variables to the selected stack frame. List scope chain levels and their variables to the selected stack frame. Oct 12, 2018
}
}

memcpy (message_type_p->string + buffer_pos++, &level_type, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need memcpy to copy 1 byte. To prepare classes ignore non-declarative and non-object-bound lex envs.

const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);

ECMA_STRING_TO_UTF8_STRING (value_str, str_buff, str_buff_size);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a cesu8 string or some costly conversion?

Copy link
Contributor Author

@robertsipka robertsipka Oct 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the name or value of the property. So, it is always returns with the cesu8 character array of a string.

{
if (!jerry_debugger_send (max_message_size))
{
ECMA_FINALIZE_UTF8_STRING (str_buff, str_buff_size);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have never seen such a macro used for early return. They should behave block like.

jerry_debugger_send_type (JERRY_DEBUGGER_SCOPE_VARIABLES_END);
return;
}
chain_index--;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore non this object or declarative lex envs as well.

Copy link
Contributor Author

@robertsipka robertsipka Oct 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand exactly what you mean. It will steps through the outer references of the current lexical environment until the chain_index argument reach zero. It is always touch a declarative or this object bound lexical environment. If not, it will returns with an empty message with JERRY_DEBUGGER_SCOPE_VARIABLES_END type (e.g.: the chain_index argument is invalid / bigger than the scope chain).

Copy link
Member

@zherczeg zherczeg Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future classes will introduces a new scope type. This type should not be shared by the debugger client side, and when encountered it should be skipped. Therefore only the two currently supported types should be handled by this loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, thanks. I've updated it.

d | Number | 12
addThree | Function | function(){/* ecmascript */}
f | Function | function(){/* ecmascript */}
addX | Function | function(){/* ecmascript */}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should send no values for functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, it makes sense. I've updated it accordingly.

f | Function | function(){/* ecmascript */}
addX | Function | function(){/* ecmascript */}
z | undefined | undefined
c | undefined | undefined
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about objects?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really missed. I've added.

@robertsipka robertsipka force-pushed the variables_list branch 2 times, most recently from 567553b to e1ae997 Compare October 19, 2018 07:54
else
{
level_type = JERRY_DEBUGGER_SCOPE_WITH;
next_func_is_local = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this value is set to true here? I might misunderstood its purpose.


if (ecma_get_lex_env_outer_reference (lex_env_p) == NULL)
{
level_type = JERRY_DEBUGGER_SCOPE_GLOBAL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A break could be added here, and change the loop to while(true)


if (ecma_is_value_undefined (value))
{
ret_value = JERRY_DEBUGGER_VARIABLE_UNDEFINED;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nitpicking, but I think VALUE is better than VARIABLE, since the value of a variable is undefined, rather than the variable, which would mean it does not exist.

*buffer_pos = 0;
}

if (copied_values == 3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like a state for a switch. Furthermore the last case is handled specially, I would take it out from this loop and done separately, since it already has a copy loop.

{
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);

if (lex_env_p == NULL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JERRY_UNLIKELY


for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure all names are printable. I think Promises has some internal properties with special magic string names. They should be ignored.

/**
* Catch clause.
*/
#define ECMA_OBJECT_FLAG_CATCH_CLAUSE 0x20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call it local scope, since we might add let/const at some day and they would be marked this flag as well.

@robertsipka robertsipka force-pushed the variables_list branch 3 times, most recently from 434fb3b to 3004684 Compare October 24, 2018 10:34
@robertsipka
Copy link
Contributor Author

@zherczeg : Thanks for the review, I've updated the patch based on your suggestions.

}

ecma_object_t *catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
catch_env_p->type_flags_refs = (uint16_t) (catch_env_p->type_flags_refs | ECMA_OBJECT_FLAG_NON_CLOSURE);
Copy link
Member

@akosthekiss akosthekiss Oct 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two questions:

  1. Is this code debugger-specific? If so, it should be wrapped into #ifdef JERRY_DEBUGGER / #endif /* JERRY_DEBUGGER */.
  2. Isn't this equivalent to catch_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_NON_CLOSURE;?

JERRY_ASSERT (ret_value != JERRY_DEBUGGER_VALUE_NONE);

return ret_value;
} /* ecma_get_typeof_scope_variable */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The names of the new static functions are somewhat inconsistent. Most are prefixed with jerry_debugger_ but this one here is ecma_get_typeof_scope_variable while the next one is simply copy_scope_variables_to_string_message without any obvious prefix. Is this intentional?

@akosthekiss akosthekiss added debugger Related to the debugger development Feature implementation labels Oct 26, 2018
Copy link
Member

@zherczeg zherczeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty good now.

{
if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_NON_CLOSURE) != 0)
{
message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_CATCH;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don\t call this catch.

* false - otherwise
*/
static bool
jerry_debugger_copy_variables_to_string_message (jerry_debugger_scope_variable_type_t variable_type, /**< type */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check-vera.sh is reporting a style issue here (extra space at the start of the line)

It supports to list the scope chain of the current execution context and see
which variables are available.

JerryScript-DCO-1.0-Signed-off-by: Robert Sipka rsipka.uszeged@partner.samsung.com
Copy link
Member

@zherczeg zherczeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@akosthekiss akosthekiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@akosthekiss akosthekiss merged commit 34c5e22 into jerryscript-project:master Oct 29, 2018
@robertsipka robertsipka deleted the variables_list branch October 27, 2021 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

debugger Related to the debugger development Feature implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants