Skip to content

Commit 5da7d7f

Browse files
Update API for invocation of functions and constructors.
With the change, if exception is thrown in `jerry_api_function_call` and `jerry_api_construct_object`, the exception object is returned to the caller. JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
1 parent 5d5e75f commit 5da7d7f

File tree

2 files changed

+124
-31
lines changed

2 files changed

+124
-31
lines changed

jerry-core/jerry.cpp

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -866,8 +866,8 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to
866866
* Invoke function specified by a function object
867867
*
868868
* Note:
869-
* if invocation was performed successfully, returned value should be freed
870-
* with jerry_api_release_value just when the value becomes unnecessary.
869+
* returned value should be freed with jerry_api_release_value
870+
* just when the value becomes unnecessary.
871871
*
872872
* Note:
873873
* If function is invoked as constructor, it should support [[Construct]] method,
@@ -887,8 +887,9 @@ jerry_api_invoke_function (bool is_invoke_as_constructor, /**< true - invoke fun
887887
* if function is invoked as constructor;
888888
* in case of simple function call set 'this'
889889
* binding to the global object) */
890-
jerry_api_value_t *retval_p, /**< pointer to place for function's return value
891-
* or NULL (to ignore the return value) */
890+
jerry_api_value_t *retval_p, /**< pointer to place for function's
891+
* return value / thrown exception value
892+
* or NULL (to ignore the values) */
892893
const jerry_api_value_t args_p[], /**< function's call arguments
893894
* (NULL if arguments number is zero) */
894895
uint16_t args_count) /**< number of the arguments */
@@ -937,28 +938,20 @@ jerry_api_invoke_function (bool is_invoke_as_constructor, /**< true - invoke fun
937938
args_count);
938939
}
939940

940-
if (ecma_is_completion_value_normal (call_completion))
941-
{
942-
if (retval_p != NULL)
943-
{
944-
jerry_api_convert_ecma_value_to_api_value (retval_p,
945-
ecma_get_completion_value_value (call_completion));
946-
}
947-
}
948-
else
941+
if (!ecma_is_completion_value_normal (call_completion))
949942
{
950943
/* unhandled exception during the function call */
951-
952944
JERRY_ASSERT (ecma_is_completion_value_throw (call_completion));
953945

954-
if (retval_p != NULL)
955-
{
956-
jerry_api_convert_ecma_value_to_api_value (retval_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));
957-
}
958-
959946
is_successful = false;
960947
}
961948

949+
if (retval_p != NULL)
950+
{
951+
jerry_api_convert_ecma_value_to_api_value (retval_p,
952+
ecma_get_completion_value_value (call_completion));
953+
}
954+
962955
ecma_free_completion_value (call_completion);
963956

964957
for (uint32_t i = 0; i < args_count; i++)
@@ -971,24 +964,42 @@ jerry_api_invoke_function (bool is_invoke_as_constructor, /**< true - invoke fun
971964
return is_successful;
972965
} /* jerry_api_invoke_function */
973966

967+
/**
968+
* Construct new TypeError object
969+
*/
970+
static void
971+
jerry_api_construct_type_error (jerry_api_value_t *retval_p) /**< out: value with constructed
972+
* TypeError object */
973+
{
974+
ecma_object_t *type_error_obj_p = ecma_new_standard_error (ECMA_ERROR_TYPE);
975+
ecma_value_t type_error_value = ecma_make_object_value (type_error_obj_p);
976+
977+
jerry_api_convert_ecma_value_to_api_value (retval_p, type_error_value);
978+
979+
ecma_deref_object (type_error_obj_p);
980+
} /* jerry_api_throw_type_error */
981+
974982
/**
975983
* Call function specified by a function object
976984
*
977985
* Note:
978-
* if call was performed successfully, returned value should be freed
979-
* with jerry_api_release_value just when the value becomes unnecessary.
986+
* returned value should be freed with jerry_api_release_value
987+
* just when the value becomes unnecessary.
980988
*
981989
* @return true, if call was performed successfully, i.e.:
982990
* - specified object is a function object (see also jerry_api_is_function);
983991
* - no unhandled exceptions were thrown in connection with the call;
984-
* false - otherwise.
992+
* false - otherwise, 'retval_p' contains thrown exception:
993+
* if called object is not function object - a TypeError instance;
994+
* else - exception, thrown during the function call.
985995
*/
986996
bool
987997
jerry_api_call_function (jerry_api_object_t *function_object_p, /**< function object to call */
988998
jerry_api_object_t *this_arg_p, /**< object for 'this' binding
989999
* or NULL (set 'this' binding to the global object) */
990-
jerry_api_value_t *retval_p, /**< pointer to place for function's return value
991-
* or NULL (to ignore the return value) */
1000+
jerry_api_value_t *retval_p, /**< pointer to place for function's
1001+
* return value / thrown exception value
1002+
* or NULL (to ignore the values) */
9921003
const jerry_api_value_t args_p[], /**< function's call arguments
9931004
* (NULL if arguments number is zero) */
9941005
uint16_t args_count) /**< number of the arguments */
@@ -999,7 +1010,13 @@ jerry_api_call_function (jerry_api_object_t *function_object_p, /**< function ob
9991010
{
10001011
return jerry_api_invoke_function (false, function_object_p, this_arg_p, retval_p, args_p, args_count);
10011012
}
1013+
else
10021014
{
1015+
if (retval_p != NULL)
1016+
{
1017+
jerry_api_construct_type_error (retval_p);
1018+
}
1019+
10031020
return false;
10041021
}
10051022
} /* jerry_api_call_function */
@@ -1008,18 +1025,21 @@ jerry_api_call_function (jerry_api_object_t *function_object_p, /**< function ob
10081025
* Construct object invoking specified function object as a constructor
10091026
*
10101027
* Note:
1011-
* if construction was performed successfully, returned value should be freed
1012-
* with jerry_api_release_value just when the value becomes unnecessary.
1028+
* returned value should be freed with jerry_api_release_value
1029+
* just when the value becomes unnecessary.
10131030
*
10141031
* @return true, if construction was performed successfully, i.e.:
10151032
* - specified object is a constructor function object (see also jerry_api_is_constructor);
10161033
* - no unhandled exceptions were thrown in connection with the invocation;
1017-
* false - otherwise.
1034+
* false - otherwise, 'retval_p' contains thrown exception:
1035+
* if specified object is not a constructor function object - a TypeError instance;
1036+
* else - exception, thrown during the invocation.
10181037
*/
10191038
bool
10201039
jerry_api_construct_object (jerry_api_object_t *function_object_p, /**< function object to call */
1021-
jerry_api_value_t *retval_p, /**< pointer to place for function's return value
1022-
* or NULL (to ignore the return value) */
1040+
jerry_api_value_t *retval_p, /**< pointer to place for function's
1041+
* return value / thrown exception value
1042+
* or NULL (to ignore the values) */
10231043
const jerry_api_value_t args_p[], /**< function's call arguments
10241044
* (NULL if arguments number is zero) */
10251045
uint16_t args_count) /**< number of the arguments */
@@ -1032,6 +1052,11 @@ jerry_api_construct_object (jerry_api_object_t *function_object_p, /**< function
10321052
}
10331053
else
10341054
{
1055+
if (retval_p != NULL)
1056+
{
1057+
jerry_api_construct_type_error (retval_p);
1058+
}
1059+
10351060
return false;
10361061
}
10371062
} /* jerry_api_construct_object */

tests/unit/test-api.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ const char *test_source = (
4646
" } "
4747
" assert(catched); "
4848
"} "
49+
"function throw_reference_error() { "
50+
" throw new ReferenceError ();"
51+
"} "
4952
);
5053

5154
bool test_api_is_free_callback_was_called = false;
@@ -220,11 +223,11 @@ main (void)
220223
{
221224
jerry_init (JERRY_FLAG_EMPTY);
222225

223-
bool is_ok;
226+
bool is_ok, is_exception;
224227
ssize_t sz;
225228
jerry_api_value_t val_t, val_foo, val_bar, val_A, val_A_prototype, val_a, val_a_foo, val_value_field;
226229
jerry_api_value_t val_external, val_external_construct, val_call_external;
227-
jerry_api_object_t* global_obj_p;
230+
jerry_api_object_t* global_obj_p, *obj_p;
228231
jerry_api_object_t* external_func_p, *external_construct_p;
229232
jerry_api_object_t* throw_test_handler_p;
230233
jerry_api_value_t res, args[2];
@@ -435,6 +438,71 @@ main (void)
435438
jerry_api_release_value (&val_t);
436439
jerry_api_release_value (&res);
437440

441+
// Test: Unhandled exception in called function
442+
is_ok = jerry_api_get_object_field_value (global_obj_p, "throw_reference_error", &val_t);
443+
JERRY_ASSERT (is_ok
444+
&& val_t.type == JERRY_API_DATA_TYPE_OBJECT);
445+
446+
is_ok = jerry_api_call_function (val_t.v_object,
447+
global_obj_p,
448+
&res,
449+
NULL, 0);
450+
is_exception = !is_ok;
451+
452+
JERRY_ASSERT (is_exception);
453+
jerry_api_release_value (&val_t);
454+
455+
// 'res' should contain exception object
456+
JERRY_ASSERT (res.type == JERRY_API_DATA_TYPE_OBJECT);
457+
jerry_api_release_value (&res);
458+
459+
// Test: Call of non-function
460+
obj_p = jerry_api_create_object ();
461+
is_ok = jerry_api_call_function (obj_p,
462+
global_obj_p,
463+
&res,
464+
NULL, 0);
465+
is_exception = !is_ok;
466+
JERRY_ASSERT (is_exception);
467+
468+
// 'res' should contain exception object
469+
JERRY_ASSERT (res.type == JERRY_API_DATA_TYPE_OBJECT);
470+
jerry_api_release_value (&res);
471+
472+
jerry_api_release_object (obj_p);
473+
474+
// Test: Unhandled exception in function called, as constructor
475+
is_ok = jerry_api_get_object_field_value (global_obj_p, "throw_reference_error", &val_t);
476+
JERRY_ASSERT (is_ok
477+
&& val_t.type == JERRY_API_DATA_TYPE_OBJECT);
478+
479+
is_ok = jerry_api_construct_object (val_t.v_object,
480+
&res,
481+
NULL, 0);
482+
is_exception = !is_ok;
483+
484+
JERRY_ASSERT (is_exception);
485+
jerry_api_release_value (&val_t);
486+
487+
// 'res' should contain exception object
488+
JERRY_ASSERT (res.type == JERRY_API_DATA_TYPE_OBJECT);
489+
jerry_api_release_value (&res);
490+
491+
// Test: Call of non-function as constructor
492+
obj_p = jerry_api_create_object ();
493+
is_ok = jerry_api_construct_object (obj_p,
494+
&res,
495+
NULL, 0);
496+
is_exception = !is_ok;
497+
JERRY_ASSERT (is_exception);
498+
499+
// 'res' should contain exception object
500+
JERRY_ASSERT (res.type == JERRY_API_DATA_TYPE_OBJECT);
501+
jerry_api_release_value (&res);
502+
503+
jerry_api_release_object (obj_p);
504+
505+
// Test: eval
438506
const char *eval_code_src_p = "(function () { return 123; })";
439507
jerry_completion_code_t status = jerry_api_eval (eval_code_src_p,
440508
strlen (eval_code_src_p),

0 commit comments

Comments
 (0)