mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Support function object retrieval for async functions (#4668)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
a58884c169
commit
e042998f02
@ -5266,11 +5266,9 @@ jerry_backtrace_get_function (jerry_backtrace_frame_t *frame_p) /**< frame point
|
||||
{
|
||||
vm_frame_ctx_t *context_p = frame_p->context_p;
|
||||
|
||||
if (context_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST)
|
||||
if (context_p->shared_p->function_object_p != NULL)
|
||||
{
|
||||
vm_frame_ctx_shared_args_t *shared_args_p = (vm_frame_ctx_shared_args_t *) context_p->shared_p;
|
||||
|
||||
frame_p->function = ecma_make_object_value (shared_args_p->function_object_p);
|
||||
frame_p->function = ecma_make_object_value (context_p->shared_p->function_object_p);
|
||||
return &frame_p->function;
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,6 +640,7 @@ ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */
|
||||
}
|
||||
|
||||
ecma_gc_set_object_visited (executable_object_p->frame_ctx.lex_env_p);
|
||||
ecma_gc_set_object_visited (executable_object_p->shared.function_object_p);
|
||||
|
||||
if (!ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p))
|
||||
{
|
||||
|
||||
@ -46,7 +46,7 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar
|
||||
ecma_object_t *lex_env_p) /**< lexical environment the Arguments
|
||||
* object is created for */
|
||||
{
|
||||
ecma_object_t *func_obj_p = shared_p->function_object_p;
|
||||
ecma_object_t *func_obj_p = shared_p->header.function_object_p;
|
||||
const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p;
|
||||
uint16_t formal_params_number;
|
||||
|
||||
|
||||
@ -1040,7 +1040,7 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
vm_frame_ctx_shared_args_t shared_args;
|
||||
shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST;
|
||||
shared_args.function_object_p = func_obj_p;
|
||||
shared_args.header.function_object_p = func_obj_p;
|
||||
shared_args.arg_list_p = arguments_list_p;
|
||||
shared_args.arg_list_len = arguments_list_len;
|
||||
|
||||
|
||||
@ -621,7 +621,7 @@ opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context
|
||||
}
|
||||
|
||||
JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC);
|
||||
proto_p = ecma_op_get_prototype_from_constructor (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p),
|
||||
proto_p = ecma_op_get_prototype_from_constructor (frame_ctx_p->shared_p->function_object_p,
|
||||
default_proto_id);
|
||||
}
|
||||
|
||||
@ -645,6 +645,7 @@ opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context
|
||||
/* Copy shared data and frame context. */
|
||||
vm_frame_ctx_shared_t *new_shared_p = &(executable_object_p->shared);
|
||||
*new_shared_p = *(frame_ctx_p->shared_p);
|
||||
new_shared_p->status_flags &= (uint32_t) ~VM_FRAME_CTX_SHARED_HAS_ARG_LIST;
|
||||
|
||||
vm_frame_ctx_t *new_frame_ctx_p = &(executable_object_p->frame_ctx);
|
||||
*new_frame_ctx_p = *frame_ctx_p;
|
||||
|
||||
@ -57,6 +57,7 @@ typedef enum
|
||||
typedef struct
|
||||
{
|
||||
const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */
|
||||
ecma_object_t *function_object_p; /**< function obj */
|
||||
uint32_t status_flags; /**< combination of vm_frame_ctx_shared_flags_t bits */
|
||||
} vm_frame_ctx_shared_t;
|
||||
|
||||
@ -66,16 +67,12 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
vm_frame_ctx_shared_t header; /**< shared data header */
|
||||
ecma_object_t *function_object_p; /**< function obj */
|
||||
const ecma_value_t *arg_list_p; /**< arguments list */
|
||||
uint32_t arg_list_len; /**< arguments list length */
|
||||
} vm_frame_ctx_shared_args_t;
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
|
||||
#define VM_FRAME_CTX_GET_FUNCTION_OBJECT(frame_ctx_p) \
|
||||
(((vm_frame_ctx_shared_args_t *) (frame_ctx_p)->shared_p)->function_object_p)
|
||||
|
||||
/**
|
||||
* Shared data extended with computed class fields
|
||||
*/
|
||||
|
||||
@ -290,6 +290,7 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = bytecode_p;
|
||||
shared.function_object_p = NULL;
|
||||
shared.status_flags = 0;
|
||||
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
@ -386,6 +387,7 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = bytecode_data_p;
|
||||
shared.function_object_p = NULL;
|
||||
shared.status_flags = (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_FRAME_CTX_SHARED_DIRECT_EVAL : 0;
|
||||
|
||||
ecma_value_t completion_value = vm_run (&shared, this_binding, lex_env_p);
|
||||
@ -427,6 +429,7 @@ vm_run_module (ecma_module_t *module_p) /**< module to be executed */
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = module_p->u.compiled_code_p;
|
||||
shared.function_object_p = &module_p->header.object;
|
||||
shared.status_flags = 0;
|
||||
|
||||
return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
|
||||
@ -540,7 +543,7 @@ vm_get_class_function (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
if (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC)
|
||||
{
|
||||
return VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p);
|
||||
return frame_ctx_p->shared_p->function_object_p;
|
||||
}
|
||||
|
||||
ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p);
|
||||
@ -2117,7 +2120,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
case VM_OC_RUN_FIELD_INIT:
|
||||
{
|
||||
JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC);
|
||||
result = opfunc_init_class_fields (ecma_make_object_value (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p)),
|
||||
result = opfunc_init_class_fields (ecma_make_object_value (frame_ctx_p->shared_p->function_object_p),
|
||||
frame_ctx_p->this_binding);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
|
||||
@ -95,6 +95,40 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
|
||||
return false;
|
||||
} /* backtrace_callback */
|
||||
|
||||
static bool
|
||||
async_backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
|
||||
void *user_p) /* user data */
|
||||
{
|
||||
TEST_ASSERT ((void *) handler_args_p == user_p);
|
||||
TEST_ASSERT (jerry_backtrace_get_frame_type (frame_p) == JERRY_BACKTRACE_FRAME_JS);
|
||||
|
||||
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);
|
||||
|
||||
TEST_ASSERT (location_p != NULL);
|
||||
TEST_ASSERT (function_p != NULL);
|
||||
|
||||
compare_string (location_p->resource_name, "async_capture_test.js");
|
||||
|
||||
++frame_index;
|
||||
|
||||
if (frame_index == 1)
|
||||
{
|
||||
TEST_ASSERT (jerry_backtrace_is_strict (frame_p));
|
||||
TEST_ASSERT (location_p->line == 3);
|
||||
TEST_ASSERT (location_p->column == 1);
|
||||
TEST_ASSERT (handler_args_p[0] == *function_p);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_ASSERT (frame_index == 2);
|
||||
TEST_ASSERT (!jerry_backtrace_is_strict (frame_p));
|
||||
TEST_ASSERT (location_p->line == 8);
|
||||
TEST_ASSERT (location_p->column == 1);
|
||||
TEST_ASSERT (handler_args_p[1] == *function_p);
|
||||
return true;
|
||||
} /* async_backtrace_callback */
|
||||
|
||||
static jerry_value_t
|
||||
capture_handler (const jerry_call_info_t *call_info_p, /**< call information */
|
||||
const jerry_value_t args_p[], /**< argument list */
|
||||
@ -104,12 +138,14 @@ capture_handler (const jerry_call_info_t *call_info_p, /**< call information */
|
||||
JERRY_UNUSED (args_p);
|
||||
JERRY_UNUSED (args_count);
|
||||
|
||||
TEST_ASSERT (args_count == 3);
|
||||
TEST_ASSERT (args_count == 2 || args_count == 3);
|
||||
TEST_ASSERT (frame_index == 0);
|
||||
|
||||
frame_index = 0;
|
||||
handler_args_p = args_p;
|
||||
jerry_backtrace_capture (backtrace_callback, (void *) args_p);
|
||||
TEST_ASSERT (frame_index == 3);
|
||||
|
||||
jerry_backtrace_capture (args_count == 3 ? backtrace_callback : async_backtrace_callback, (void *) args_p);
|
||||
|
||||
TEST_ASSERT (frame_index == (int) args_count);
|
||||
|
||||
return jerry_create_undefined ();
|
||||
} /* capture_handler */
|
||||
@ -186,21 +222,21 @@ test_get_backtrace_api_call (void)
|
||||
register_callback (backtrace_handler, "backtrace");
|
||||
register_callback (capture_handler, "capture");
|
||||
|
||||
const char *source = ("function f() {\n"
|
||||
" return backtrace(0);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
const char *source_p = ("function f() {\n"
|
||||
" return backtrace(0);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
|
||||
jerry_value_t backtrace = run ("something.js", source);
|
||||
jerry_value_t backtrace = run ("something.js", source_p);
|
||||
|
||||
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
||||
&& jerry_value_is_array (backtrace));
|
||||
@ -216,21 +252,21 @@ test_get_backtrace_api_call (void)
|
||||
|
||||
/* Depth set to 2 this time. */
|
||||
|
||||
source = ("function f() {\n"
|
||||
" return backtrace(2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
source_p = ("function f() {\n"
|
||||
" return backtrace(2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
|
||||
backtrace = run ("something_else.js", source);
|
||||
backtrace = run ("something_else.js", source_p);
|
||||
|
||||
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
||||
&& jerry_value_is_array (backtrace));
|
||||
@ -244,25 +280,68 @@ test_get_backtrace_api_call (void)
|
||||
|
||||
/* Test frame capturing. */
|
||||
|
||||
source = ("function f() {\n"
|
||||
" return capture(f, g, h);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" 'use strict';\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
frame_index = 0;
|
||||
source_p = ("function f() {\n"
|
||||
" return capture(f, g, h);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" 'use strict';\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function h() {\n"
|
||||
" return g();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"h();\n");
|
||||
|
||||
backtrace = run ("capture_test.js", source);
|
||||
jerry_value_t result = run ("capture_test.js", source_p);
|
||||
|
||||
TEST_ASSERT (jerry_value_is_undefined (backtrace));
|
||||
jerry_release_value (backtrace);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (frame_index == 3);
|
||||
|
||||
/* Test async frame capturing. */
|
||||
source_p = "async function f() {}";
|
||||
result = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (result))
|
||||
{
|
||||
jerry_release_value (result);
|
||||
|
||||
frame_index = 0;
|
||||
source_p = ("function f() {\n"
|
||||
" 'use strict';\n"
|
||||
" return capture(f, g);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"async function g() {\n"
|
||||
" await 0;\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"g();\n");
|
||||
|
||||
result = run ("async_capture_test.js", source_p);
|
||||
|
||||
TEST_ASSERT (jerry_value_is_promise (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (frame_index == 0);
|
||||
|
||||
result = jerry_run_all_enqueued_jobs ();
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
|
||||
TEST_ASSERT (frame_index == 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT (jerry_get_error_type (result) == JERRY_ERROR_SYNTAX);
|
||||
}
|
||||
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_cleanup ();
|
||||
} /* test_get_backtrace_api_call */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user