Rework external function handlers (#4599)

Instead of a fixed number of arguments, a call info structure is passed
to the handlers, which can be extended in the future without breaknig the
API. This structure holds new.target value, so its getter function is removed.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-02-17 17:52:19 +01:00
committed by GitHub
parent 488a0bf7e8
commit 112ad83aaa
51 changed files with 322 additions and 586 deletions
+35 -154
View File
@@ -603,6 +603,29 @@ typedef struct
- [jerry_get_memory_stats](#jerry_get_memory_stats)
## jerry_call_info_t
**Summary**
Call related information passed to [jerry_external_handler_t](#jerry_external_handler_t).
**Prototype**
```c
typedef struct jerry_call_info_t
{
jerry_value_t function; /**< invoked function object */
jerry_value_t this_value; /**< this value passed to the function */
jerry_value_t new_target; /**< current new target value, undefined for non-constructor calls */
} jerry_call_info_t;
```
*New in version [[NEXT_RELEASE]]*.
**See also**
- [jerry_external_handler_t](#jerry_external_handler_t)
## jerry_external_handler_t
**Summary**
@@ -612,14 +635,13 @@ Type of an external function handler
**Prototype**
```c
typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_obj,
const jerry_value_t this_val,
typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_count);
```
- `function_object` - the JavaScript function object which was invoked.
- `this_val` - the `this` value provided for the function call.
- `call_info_p` - pointer to a [jerry_call_info_t](#jerry_call_info_t)
structure which holds call related information.
- `args_p` - the function arguments, array of JavaScript values.
- `args_count` - the number of arguments.
- return value
@@ -2830,8 +2852,7 @@ jerry_binary_operation (jerry_binary_operation_t op,
#include "jerryscript.h"
static jerry_value_t
my_constructor (const jerry_value_t func_val,
const jerry_value_t this_val,
my_constructor (const jerry_call_info_t *call_info_p,
const jerry_value_t argv[],
const jerry_length_t argc)
{
@@ -5161,12 +5182,11 @@ jerry_create_external_function (jerry_external_handler_t handler_p);
#include "jerryscript.h"
static jerry_value_t
handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_cnt)
{
printf ("native handler called!\n");
printf ("Native handler called!\n");
return jerry_create_boolean (true);
}
@@ -7139,8 +7159,7 @@ Registering a getter/setter property via the `jerry_define_own_property` method:
static int counter = 0;
static jerry_value_t
method_getter (const jerry_value_t this_obj,
const jerry_value_t func_obj,
method_getter (const jerry_call_info_t *call_info_p,
const jerry_value_t args[],
const jerry_length_t argc)
{
@@ -7151,8 +7170,7 @@ method_getter (const jerry_value_t this_obj,
}
static jerry_value_t
method_setter (const jerry_value_t this_obj,
const jerry_value_t func_obj,
method_setter (const jerry_call_info_t *call_info_p,
const jerry_value_t args[],
const jerry_length_t argc)
{
@@ -9052,8 +9070,7 @@ jerry_get_backtrace (uint32_t max_depth);
#include "jerryscript.h"
static jerry_value_t
backtrace_handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
backtrace_handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_count)
{
@@ -9178,13 +9195,11 @@ backtrace_callback (jerry_backtrace_frame_t *frame_p,
}
static jerry_value_t
backtrace_handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
backtrace_handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_count)
{
(void) function_obj;
(void) this_val;
(void) call_info_p;
(void) args_p;
(void) args_count;
@@ -9594,8 +9609,7 @@ jerry_get_resource_name (jerry_value_t value);
#include "jerryscript.h"
static jerry_value_t
resource_name_handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
resource_name_handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_count)
{
@@ -9655,139 +9669,6 @@ main (void)
- [jerry_create_external_function](#jerry_create_external_function)
## jerry_get_new_target
**Summary**
Returns the current "new.target" JavaScript function at the call site.
If used outside of a native C function it will return "undefined" value.
*Notes*:
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
- This feature depends on build option (`JERRY_ESNEXT`) and can be checked
in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value (as symbols are enabled in case of ES.next),
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
- If the ES.next mode is not enabled this method will always return the "undefined" value.
**Prototype**
```c
jerry_value_t
jerry_get_new_target (void);
```
- return
- "undefined" - if at the call site it was not a constructor call.
- function object - if the current call site is in a constructor call.
*New in version 2.2*.
**Example 1**
[doctest]: # (name="02.API-REFERENCE-jsnewtarget-01.c")
```c
#include <stdio.h>
#include <string.h>
#include <jerryscript.h>
static jerry_value_t
demo_handler (const jerry_value_t func_obj_val,
const jerry_value_t this_val,
const jerry_value_t args_p[],
const jerry_length_t args_cnt)
{
jerry_value_t new_target = jerry_get_new_target ();
/* new_target is the "demo" JS function object */
if (jerry_value_get_type (new_target) == JERRY_TYPE_FUNCTION)
{
printf ("This is a construct call\r\n");
}
jerry_release_value (new_target);
return jerry_create_undefined ();
}
int
main (int argc, char** argv)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t function_val = jerry_create_external_function (demo_handler);
jerry_value_t ret_val = jerry_construct_object (function_val, NULL, 0);
jerry_release_value (ret_val);
jerry_release_value (function_val);
jerry_cleanup ();
return 0;
}
```
**Example 2**
[doctest]: # (name="02.API-REFERENCE-jsnewtarget-02.c")
```c
#include <stdio.h>
#include <string.h>
#include <jerryscript.h>
static jerry_value_t
demo_handler (const jerry_value_t func_obj_val,
const jerry_value_t this_val,
const jerry_value_t args_p[],
const jerry_length_t args_cnt)
{
jerry_value_t new_target = jerry_get_new_target ();
/* new_target is a JS function object */
if (jerry_value_get_type (new_target) == JERRY_TYPE_FUNCTION)
{
printf ("This is a construct call\r\n");
}
jerry_release_value (new_target);
return jerry_create_undefined ();
}
int
main (int argc, char** argv)
{
jerry_init (JERRY_INIT_EMPTY);
/* register C method */
jerry_value_t global_obj_val = jerry_get_global_object ();
jerry_value_t function_val = jerry_create_external_function (demo_handler);
jerry_value_t function_name_val = jerry_create_string ((const jerry_char_t *) "demo");
jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val);
jerry_release_value (result_val);
jerry_release_value (function_name_val);
jerry_release_value (function_val);
jerry_release_value (global_obj_val);
/* Invoke C method via JS */
const char *src = "new demo ()";
jerry_value_t ret_val = jerry_eval ((const jerry_char_t *) src,
strlen (src),
JERRY_PARSE_NO_OPTS);
jerry_release_value (ret_val);
jerry_cleanup ();
return 0;
}
```
**See also**
- [jerry_construct_object](#jerry_construct_object)
# Functions for realm objects
These APIs all depend on build option (`JERRY_BUILTIN_REALMS`).
+6 -10
View File
@@ -214,8 +214,7 @@ The `api-example-4.c` file should contain the following code:
#include "jerryscript.h"
static jerry_value_t
print_handler (const jerry_value_t function_object,
const jerry_value_t function_this,
print_handler (const jerry_call_info_t *call_info_p,
const jerry_value_t arguments[],
const jerry_length_t argument_count)
{
@@ -316,8 +315,7 @@ The `api-example-5.c` file should contain the following code:
#include "jerryscript.h"
static jerry_value_t
print_handler (const jerry_value_t function_object,
const jerry_value_t function_this,
print_handler (const jerry_call_info_t *call_info_p,
const jerry_value_t arguments[],
const jerry_length_t arguments_count)
{
@@ -851,8 +849,7 @@ struct my_struct
* Get a string from a native object
*/
static jerry_value_t
get_msg_handler (const jerry_value_t func_value, /**< function object */
const jerry_value_t this_value, /**< this arg */
get_msg_handler (const jerry_call_info_t *call_info_p, /**< call information */
const jerry_value_t *args_p, /**< function arguments */
const jerry_length_t args_cnt) /**< number of function arguments */
{
@@ -955,8 +952,7 @@ Use the following code for `api-example-10.c`:
* Add param to 'this.x'
*/
static jerry_value_t
add_handler (const jerry_value_t func_value, /**< function object */
const jerry_value_t this_val, /**< this arg */
add_handler (const jerry_call_info_t *call_info_p, /**< call information */
const jerry_value_t args_p[], /**< function arguments */
const jerry_length_t args_cnt) /**< number of function arguments */
{
@@ -965,7 +961,7 @@ add_handler (const jerry_value_t func_value, /**< function object */
/* Get 'this.x' */
jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "x");
jerry_value_t x_val = jerry_get_property (this_val, prop_name);
jerry_value_t x_val = jerry_get_property (call_info_p->this_value, prop_name);
if (!jerry_value_is_error (x_val))
{
@@ -977,7 +973,7 @@ add_handler (const jerry_value_t func_value, /**< function object */
jerry_value_t res_val = jerry_create_number (x + d);
/* Set the new value of 'this.x' */
jerry_release_value (jerry_set_property (this_val, prop_name, res_val));
jerry_release_value (jerry_set_property (call_info_p->this_value, prop_name, res_val));
jerry_release_value (res_val);
}
+2 -4
View File
@@ -267,8 +267,7 @@ jerryx_set_properties (const jerry_value_t target_object,
#include "jerryscript-ext/handler.h"
static jerry_value_t
handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_cnt)
{
@@ -331,8 +330,7 @@ when setting a property entry:
#include "jerryscript-ext/handler.h"
static jerry_value_t
handler (const jerry_value_t function_obj,
const jerry_value_t this_val,
handler (const jerry_call_info_t *call_info_p,
const jerry_value_t args_p[],
const jerry_length_t args_cnt)
{