Support this binding retrieval for backtrace frames (#4669)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg 2021-05-17 11:41:29 +02:00 committed by GitHub
parent a67f198134
commit 67a61bc211
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 8 deletions

View File

@ -10606,6 +10606,7 @@ main (void)
- [jerry_backtrace_get_frame_type](#jerry_backtrace_get_frame_type)
- [jerry_backtrace_get_location](#jerry_backtrace_get_location)
- [jerry_backtrace_get_function](#jerry_backtrace_get_function)
- [jerry_backtrace_get_this](#jerry_backtrace_get_this)
- [jerry_backtrace_is_strict](#jerry_backtrace_is_strict)
@ -10785,6 +10786,63 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p,
- [jerry_backtrace_capture](#jerry_backtrace_capture)
## jerry_backtrace_get_this
**Summary**
Initialize and return with the 'this' binding private field of a backtrace frame.
The 'this' binding is a hidden value passed to the called function. As for arrow
functions, the 'this' binding is assigned at function creation. This getter
function can only be called from the callback function of
[jerry_backtrace_capture](#jerry_backtrace_capture), and the value becomes invalid
after the callback returns.
*Notes*:
- The returned data must not be modified, and does not need to be freed.
Any cleanup is done automatically after the callback is returned.
**Prototype**
```c
const jerry_value_t *
jerry_backtrace_get_this (jerry_backtrace_frame_t *frame_p);
```
- `frame_p` - a frame passed to the [jerry_backtrace_callback_t](#jerry_backtrace_callback_t) callback
- return value
- pointer to the 'this' binding if the binding is available,
- NULL otherwise
*New in version [[NEXT_RELEASE]]*.
**Example**
See the example of [jerry_backtrace_capture](#jerry_backtrace_capture)
with the following callback function:
```c
static bool
backtrace_callback (jerry_backtrace_frame_t *frame_p,
void *user_p)
{
jerry_value_t *this_p = jerry_backtrace_get_this (frame_p);
if (this_p != NULL)
{
printf ("The 'this' binding is available");
return true;
}
printf ("The 'this' binding is NOT available");
return true;
}
```
**See also**
- [jerry_backtrace_capture](#jerry_backtrace_capture)
## jerry_backtrace_is_strict
**Summary**

View File

@ -5276,6 +5276,26 @@ jerry_backtrace_get_function (jerry_backtrace_frame_t *frame_p) /**< frame point
return NULL;
} /* jerry_backtrace_get_function */
/**
* Initialize and return with the 'this' binding private field of a backtrace frame.
* The 'this' binding is a hidden value passed to the called function. As for arrow
* functions, the 'this' binding is assigned at function creation.
*
* @return pointer to the 'this' binding - if the binding is available,
* NULL - otherwise
*/
const jerry_value_t *
jerry_backtrace_get_this (jerry_backtrace_frame_t *frame_p) /**< frame pointer */
{
if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS)
{
frame_p->this_binding = frame_p->context_p->this_binding;
return &frame_p->this_binding;
}
return NULL;
} /* jerry_backtrace_get_this */
/**
* Returns true, if the code bound to the backtrace frame is strict mode code.
*

View File

@ -350,6 +350,7 @@ void jerry_backtrace_capture (jerry_backtrace_callback_t callback, void *user_p)
jerry_backtrace_frame_types_t jerry_backtrace_get_frame_type (jerry_backtrace_frame_t *frame_p);
const jerry_backtrace_location_t *jerry_backtrace_get_location (jerry_backtrace_frame_t *frame_p);
const jerry_value_t *jerry_backtrace_get_function (jerry_backtrace_frame_t *frame_p);
const jerry_value_t *jerry_backtrace_get_this (jerry_backtrace_frame_t *frame_p);
bool jerry_backtrace_is_strict (jerry_backtrace_frame_t *frame_p);
/**

View File

@ -157,6 +157,7 @@ struct jerry_backtrace_frame_internal_t
uint8_t frame_type; /**< frame type */
jerry_backtrace_location_t location; /**< location information */
ecma_value_t function; /**< function reference */
ecma_value_t this_binding; /**< this binding passed to the function */
};
/**

View File

@ -61,9 +61,11 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
const jerry_backtrace_location_t *location_p = jerry_backtrace_get_location (frame_p);
const jerry_value_t *function_p = jerry_backtrace_get_function (frame_p);
const jerry_value_t *this_p = jerry_backtrace_get_this (frame_p);
TEST_ASSERT (location_p != NULL);
TEST_ASSERT (function_p != NULL);
TEST_ASSERT (this_p != NULL);
compare_string (location_p->resource_name, "capture_test.js");
@ -75,6 +77,7 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
TEST_ASSERT (location_p->line == 2);
TEST_ASSERT (location_p->column == 1);
TEST_ASSERT (handler_args_p[0] == *function_p);
TEST_ASSERT (handler_args_p[1] == *this_p);
return true;
}
@ -83,15 +86,21 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
TEST_ASSERT (jerry_backtrace_is_strict (frame_p));
TEST_ASSERT (location_p->line == 7);
TEST_ASSERT (location_p->column == 1);
TEST_ASSERT (handler_args_p[1] == *function_p);
TEST_ASSERT (handler_args_p[2] == *function_p);
TEST_ASSERT (jerry_value_is_undefined (*this_p));
return true;
}
jerry_value_t global = jerry_get_global_object ();
TEST_ASSERT (frame_index == 3);
TEST_ASSERT (!jerry_backtrace_is_strict (frame_p));
TEST_ASSERT (location_p->line == 11);
TEST_ASSERT (location_p->column == 1);
TEST_ASSERT (handler_args_p[2] == *function_p);
TEST_ASSERT (handler_args_p[3] == *function_p);
TEST_ASSERT (global == *this_p);
jerry_release_value (global);
return false;
} /* backtrace_callback */
@ -170,7 +179,7 @@ capture_handler (const jerry_call_info_t *call_info_p, /**< call information */
JERRY_UNUSED (args_p);
JERRY_UNUSED (args_count);
TEST_ASSERT (args_count == 0 || args_count == 2 || args_count == 3);
TEST_ASSERT (args_count == 0 || args_count == 2 || args_count == 4);
TEST_ASSERT (args_count == 0 || frame_index == 0);
jerry_backtrace_callback_t callback = backtrace_callback;
@ -187,7 +196,7 @@ capture_handler (const jerry_call_info_t *call_info_p, /**< call information */
handler_args_p = args_p;
jerry_backtrace_capture (callback, (void *) args_p);
TEST_ASSERT (args_count == 0 || frame_index == (int) args_count);
TEST_ASSERT (args_count == 0 || frame_index == (args_count == 4 ? 3 : 2));
return jerry_create_undefined ();
} /* capture_handler */
@ -323,13 +332,13 @@ test_get_backtrace_api_call (void)
/* Test frame capturing. */
frame_index = 0;
source_p = ("function f() {\n"
" return capture(f, g, h);\n"
"}\n"
source_p = ("var o = { f:function() {\n"
" return capture(o.f, o, g, h);\n"
"} }\n"
"\n"
"function g() {\n"
" 'use strict';\n"
" return f();\n"
" return o.f();\n"
"}\n"
"\n"
"function h() {\n"