Introduce new.target C api (#3522)
Added new "jerry_get_new_target" API function and updated the unit test. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
@@ -7655,6 +7655,138 @@ main (void)
|
|||||||
|
|
||||||
- [jerry_create_external_function](#jerry_create_external_function)
|
- [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_ES2015`) and can be checked
|
||||||
|
in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value (as symbols are enabled in case of ES2015),
|
||||||
|
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||||
|
- If the ES2015 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)
|
||||||
|
|
||||||
# ArrayBuffer and TypedArray functions
|
# ArrayBuffer and TypedArray functions
|
||||||
|
|
||||||
|
|||||||
@@ -3395,6 +3395,34 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
|
|||||||
return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
|
return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
|
||||||
} /* jerry_get_resource_name */
|
} /* jerry_get_resource_name */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access the "new.target" value.
|
||||||
|
*
|
||||||
|
* The "new.target" value depends on the current call site. That is
|
||||||
|
* this method will only have a function object result if, at the call site
|
||||||
|
* it was called inside a constructor method invoked with "new".
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
jerry_value_t
|
||||||
|
jerry_get_new_target (void)
|
||||||
|
{
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
ecma_object_t *current_new_target = JERRY_CONTEXT (current_new_target);
|
||||||
|
|
||||||
|
if (current_new_target == NULL || current_new_target == JERRY_CONTEXT_INVALID_NEW_TARGET)
|
||||||
|
{
|
||||||
|
return jerry_create_undefined ();
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_ref_object (current_new_target);
|
||||||
|
return ecma_make_object_value (current_new_target);
|
||||||
|
#else /* !ENABLED (JERRY_ES2015) */
|
||||||
|
return jerry_create_undefined ();
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
} /* jerry_get_new_target */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given value is an ArrayBuffer object.
|
* Check if the given value is an ArrayBuffer object.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -606,6 +606,7 @@ jerry_context_t *jerry_create_context (uint32_t heap_size, jerry_context_alloc_t
|
|||||||
void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency);
|
void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency);
|
||||||
jerry_value_t jerry_get_backtrace (uint32_t max_depth);
|
jerry_value_t jerry_get_backtrace (uint32_t max_depth);
|
||||||
jerry_value_t jerry_get_resource_name (const jerry_value_t value);
|
jerry_value_t jerry_get_resource_name (const jerry_value_t value);
|
||||||
|
jerry_value_t jerry_get_new_target (void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array buffer components.
|
* Array buffer components.
|
||||||
|
|||||||
@@ -46,16 +46,6 @@ enum
|
|||||||
TEST_ID_CONSTRUCT_AND_CALL_SUB = 3,
|
TEST_ID_CONSTRUCT_AND_CALL_SUB = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to access the "new.target" via an eval call.
|
|
||||||
*/
|
|
||||||
static jerry_value_t
|
|
||||||
get_new_target (void)
|
|
||||||
{
|
|
||||||
const char *src = "new.target";
|
|
||||||
return jerry_eval ((const jerry_char_t *) src, strlen (src), 0);
|
|
||||||
} /* get_new_target */
|
|
||||||
|
|
||||||
static jerry_value_t
|
static jerry_value_t
|
||||||
construct_handler (const jerry_value_t func_obj_val, /**< function object */
|
construct_handler (const jerry_value_t func_obj_val, /**< function object */
|
||||||
const jerry_value_t this_val, /**< this arg */
|
const jerry_value_t this_val, /**< this arg */
|
||||||
@@ -78,7 +68,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
|
|||||||
case TEST_ID_SIMPLE_CONSTRUCT:
|
case TEST_ID_SIMPLE_CONSTRUCT:
|
||||||
{
|
{
|
||||||
/* Method was called with "new": new.target should be equal to the function object. */
|
/* Method was called with "new": new.target should be equal to the function object. */
|
||||||
jerry_value_t target = get_new_target ();
|
jerry_value_t target = jerry_get_new_target ();
|
||||||
TEST_ASSERT (!jerry_value_is_undefined (target));
|
TEST_ASSERT (!jerry_value_is_undefined (target));
|
||||||
TEST_ASSERT (target == func_obj_val);
|
TEST_ASSERT (target == func_obj_val);
|
||||||
jerry_release_value (target);
|
jerry_release_value (target);
|
||||||
@@ -87,7 +77,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
|
|||||||
case TEST_ID_SIMPLE_CALL:
|
case TEST_ID_SIMPLE_CALL:
|
||||||
{
|
{
|
||||||
/* Method was called directly without "new": new.target should be equal undefined. */
|
/* Method was called directly without "new": new.target should be equal undefined. */
|
||||||
jerry_value_t target = get_new_target ();
|
jerry_value_t target = jerry_get_new_target ();
|
||||||
TEST_ASSERT (jerry_value_is_undefined (target));
|
TEST_ASSERT (jerry_value_is_undefined (target));
|
||||||
TEST_ASSERT (target != func_obj_val);
|
TEST_ASSERT (target != func_obj_val);
|
||||||
jerry_release_value (target);
|
jerry_release_value (target);
|
||||||
@@ -96,7 +86,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
|
|||||||
case TEST_ID_CONSTRUCT_AND_CALL_SUB:
|
case TEST_ID_CONSTRUCT_AND_CALL_SUB:
|
||||||
{
|
{
|
||||||
/* Method was called with "new": new.target should be equal to the function object. */
|
/* Method was called with "new": new.target should be equal to the function object. */
|
||||||
jerry_value_t target = get_new_target ();
|
jerry_value_t target = jerry_get_new_target ();
|
||||||
TEST_ASSERT (!jerry_value_is_undefined (target));
|
TEST_ASSERT (!jerry_value_is_undefined (target));
|
||||||
TEST_ASSERT (target == func_obj_val);
|
TEST_ASSERT (target == func_obj_val);
|
||||||
jerry_release_value (target);
|
jerry_release_value (target);
|
||||||
|
|||||||
Reference in New Issue
Block a user