Skip to content

Commit 24af089

Browse files
galpeterdbatyai
authored andcommitted
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
1 parent f46d061 commit 24af089

4 files changed

Lines changed: 164 additions & 13 deletions

File tree

docs/02.API-REFERENCE.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7655,6 +7655,138 @@ main (void)
76557655

76567656
- [jerry_create_external_function](#jerry_create_external_function)
76577657

7658+
## jerry_get_new_target
7659+
7660+
**Summary**
7661+
7662+
Returns the current "new.target" JavaScript function at the call site.
7663+
7664+
If used outside of a native C function it will return "undefined" value.
7665+
7666+
*Notes*:
7667+
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
7668+
is no longer needed.
7669+
- This feature depends on build option (`JERRY_ES2015`) and can be checked
7670+
in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value (as symbols are enabled in case of ES2015),
7671+
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
7672+
- If the ES2015 mode is not enabled this method will always return the "undefined" value.
7673+
7674+
**Prototype**
7675+
7676+
```c
7677+
jerry_value_t
7678+
jerry_get_new_target (void);
7679+
```
7680+
- return
7681+
- "undefined" - if at the call site it was not a constructor call.
7682+
- function object - if the current call site is in a constructor call.
7683+
7684+
*New in version 2.2*.
7685+
7686+
**Example 1**
7687+
7688+
[doctest]: # (name="02.API-REFERENCE-jsnewtarget-01.c")
7689+
7690+
```c
7691+
#include <stdio.h>
7692+
#include <string.h>
7693+
#include <jerryscript.h>
7694+
7695+
static jerry_value_t
7696+
demo_handler (const jerry_value_t func_obj_val,
7697+
const jerry_value_t this_val,
7698+
const jerry_value_t args_p[],
7699+
const jerry_length_t args_cnt)
7700+
{
7701+
jerry_value_t new_target = jerry_get_new_target ();
7702+
7703+
/* new_target is the "demo" JS function object */
7704+
if (jerry_value_get_type (new_target) == JERRY_TYPE_FUNCTION)
7705+
{
7706+
printf ("This is a construct call\r\n");
7707+
}
7708+
7709+
jerry_release_value (new_target);
7710+
7711+
return jerry_create_undefined ();
7712+
}
7713+
7714+
int
7715+
main (int argc, char** argv)
7716+
{
7717+
jerry_init (JERRY_INIT_EMPTY);
7718+
7719+
jerry_value_t function_val = jerry_create_external_function (demo_handler);
7720+
7721+
jerry_value_t ret_val = jerry_construct_object (function_val, NULL, 0);
7722+
7723+
jerry_release_value (ret_val);
7724+
jerry_release_value (function_val);
7725+
7726+
jerry_cleanup ();
7727+
return 0;
7728+
}
7729+
```
7730+
7731+
**Example 2**
7732+
7733+
[doctest]: # (name="02.API-REFERENCE-jsnewtarget-02.c")
7734+
7735+
```c
7736+
#include <stdio.h>
7737+
#include <string.h>
7738+
#include <jerryscript.h>
7739+
7740+
static jerry_value_t
7741+
demo_handler (const jerry_value_t func_obj_val,
7742+
const jerry_value_t this_val,
7743+
const jerry_value_t args_p[],
7744+
const jerry_length_t args_cnt)
7745+
{
7746+
jerry_value_t new_target = jerry_get_new_target ();
7747+
7748+
/* new_target is a JS function object */
7749+
if (jerry_value_get_type (new_target) == JERRY_TYPE_FUNCTION)
7750+
{
7751+
printf ("This is a construct call\r\n");
7752+
}
7753+
7754+
jerry_release_value (new_target);
7755+
7756+
return jerry_create_undefined ();
7757+
}
7758+
7759+
int
7760+
main (int argc, char** argv)
7761+
{
7762+
jerry_init (JERRY_INIT_EMPTY);
7763+
7764+
/* register C method */
7765+
jerry_value_t global_obj_val = jerry_get_global_object ();
7766+
jerry_value_t function_val = jerry_create_external_function (demo_handler);
7767+
jerry_value_t function_name_val = jerry_create_string ((const jerry_char_t *) "demo");
7768+
jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val);
7769+
jerry_release_value (result_val);
7770+
jerry_release_value (function_name_val);
7771+
jerry_release_value (function_val);
7772+
jerry_release_value (global_obj_val);
7773+
7774+
/* Invoke C method via JS */
7775+
const char *src = "new demo ()";
7776+
jerry_value_t ret_val = jerry_eval ((const jerry_char_t *) src,
7777+
strlen (src),
7778+
JERRY_PARSE_NO_OPTS);
7779+
7780+
jerry_release_value (ret_val);
7781+
7782+
jerry_cleanup ();
7783+
return 0;
7784+
}
7785+
```
7786+
7787+
**See also**
7788+
7789+
- [jerry_construct_object](#jerry_construct_object)
76587790

76597791
# ArrayBuffer and TypedArray functions
76607792

jerry-core/api/jerry.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,6 +3395,34 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
33953395
return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
33963396
} /* jerry_get_resource_name */
33973397

3398+
/**
3399+
* Access the "new.target" value.
3400+
*
3401+
* The "new.target" value depends on the current call site. That is
3402+
* this method will only have a function object result if, at the call site
3403+
* it was called inside a constructor method invoked with "new".
3404+
*
3405+
* @return "undefined" - if at the call site it was not a constructor call.
3406+
* function object - if the current call site is in a constructor call.
3407+
*/
3408+
jerry_value_t
3409+
jerry_get_new_target (void)
3410+
{
3411+
#if ENABLED (JERRY_ES2015)
3412+
ecma_object_t *current_new_target = JERRY_CONTEXT (current_new_target);
3413+
3414+
if (current_new_target == NULL || current_new_target == JERRY_CONTEXT_INVALID_NEW_TARGET)
3415+
{
3416+
return jerry_create_undefined ();
3417+
}
3418+
3419+
ecma_ref_object (current_new_target);
3420+
return ecma_make_object_value (current_new_target);
3421+
#else /* !ENABLED (JERRY_ES2015) */
3422+
return jerry_create_undefined ();
3423+
#endif /* ENABLED (JERRY_ES2015) */
3424+
} /* jerry_get_new_target */
3425+
33983426
/**
33993427
* Check if the given value is an ArrayBuffer object.
34003428
*

jerry-core/include/jerryscript-core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ jerry_context_t *jerry_create_context (uint32_t heap_size, jerry_context_alloc_t
606606
void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency);
607607
jerry_value_t jerry_get_backtrace (uint32_t max_depth);
608608
jerry_value_t jerry_get_resource_name (const jerry_value_t value);
609+
jerry_value_t jerry_get_new_target (void);
609610

610611
/**
611612
* Array buffer components.

tests/unit-core/test-newtarget.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,6 @@ enum
4646
TEST_ID_CONSTRUCT_AND_CALL_SUB = 3,
4747
};
4848

49-
/**
50-
* Helper method to access the "new.target" via an eval call.
51-
*/
52-
static jerry_value_t
53-
get_new_target (void)
54-
{
55-
const char *src = "new.target";
56-
return jerry_eval ((const jerry_char_t *) src, strlen (src), 0);
57-
} /* get_new_target */
58-
5949
static jerry_value_t
6050
construct_handler (const jerry_value_t func_obj_val, /**< function object */
6151
const jerry_value_t this_val, /**< this arg */
@@ -78,7 +68,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
7868
case TEST_ID_SIMPLE_CONSTRUCT:
7969
{
8070
/* Method was called with "new": new.target should be equal to the function object. */
81-
jerry_value_t target = get_new_target ();
71+
jerry_value_t target = jerry_get_new_target ();
8272
TEST_ASSERT (!jerry_value_is_undefined (target));
8373
TEST_ASSERT (target == func_obj_val);
8474
jerry_release_value (target);
@@ -87,7 +77,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
8777
case TEST_ID_SIMPLE_CALL:
8878
{
8979
/* Method was called directly without "new": new.target should be equal undefined. */
90-
jerry_value_t target = get_new_target ();
80+
jerry_value_t target = jerry_get_new_target ();
9181
TEST_ASSERT (jerry_value_is_undefined (target));
9282
TEST_ASSERT (target != func_obj_val);
9383
jerry_release_value (target);
@@ -96,7 +86,7 @@ construct_handler (const jerry_value_t func_obj_val, /**< function object */
9686
case TEST_ID_CONSTRUCT_AND_CALL_SUB:
9787
{
9888
/* Method was called with "new": new.target should be equal to the function object. */
99-
jerry_value_t target = get_new_target ();
89+
jerry_value_t target = jerry_get_new_target ();
10090
TEST_ASSERT (!jerry_value_is_undefined (target));
10191
TEST_ASSERT (target == func_obj_val);
10292
jerry_release_value (target);

0 commit comments

Comments
 (0)