diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index 1de4a9a1ad..5641d9023b 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -57,6 +57,20 @@ typedef enum JERRY_API_DATA_TYPE_OBJECT /**< object */ } jerry_api_data_type_t; +/** + * Jerry API Error object types + */ +typedef enum +{ + JERRY_API_ERROR_COMMON, /**< Error */ + JERRY_API_ERROR_EVAL, /**< EvalError */ + JERRY_API_ERROR_RANGE, /**< RangeError */ + JERRY_API_ERROR_REFERENCE, /**< ReferenceError */ + JERRY_API_ERROR_SYNTAX, /**< SyntaxError */ + JERRY_API_ERROR_TYPE, /**< TypeError */ + JERRY_API_ERROR_URI /**< URIError */ +} jerry_api_error_t; + /** * Jerry's string value */ @@ -127,6 +141,8 @@ jerry_api_string_t* jerry_api_create_string (const char *v); extern EXTERN_C jerry_api_object_t* jerry_api_create_object (void); extern EXTERN_C +jerry_api_object_t* jerry_api_create_error (jerry_api_error_t error_type, const char *message_p); +extern EXTERN_C jerry_api_object_t* jerry_api_create_external_function (jerry_external_handler_t handler_p); extern EXTERN_C diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 9643014af0..c8af1c283e 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -17,6 +17,7 @@ #include "ecma-alloc.h" #include "ecma-builtins.h" +#include "ecma-exceptions.h" #include "ecma-extension.h" #include "ecma-eval.h" #include "ecma-function-object.h" @@ -415,6 +416,80 @@ jerry_api_create_object (void) return ecma_op_create_object_object_noarg (); } /* jerry_api_create_object */ +/** + * Create an error object + * + * Note: + * caller should release the object with jerry_api_release_object, just when the value becomes unnecessary. + * + * @return pointer to created error object + */ +jerry_api_object_t* +jerry_api_create_error (jerry_api_error_t error_type, const char *message_p) +{ + jerry_assert_api_available (); + + ecma_standard_error_t standard_error_type = ECMA_ERROR_COMMON; + + switch (error_type) + { + case JERRY_API_ERROR_COMMON: + { + standard_error_type = ECMA_ERROR_COMMON; + break; + } + case JERRY_API_ERROR_EVAL: + { + standard_error_type = ECMA_ERROR_EVAL; + break; + } + case JERRY_API_ERROR_RANGE: + { + standard_error_type = ECMA_ERROR_RANGE; + break; + } + case JERRY_API_ERROR_REFERENCE: + { + standard_error_type = ECMA_ERROR_REFERENCE; + break; + } + case JERRY_API_ERROR_SYNTAX: + { + standard_error_type = ECMA_ERROR_SYNTAX; + break; + } + case JERRY_API_ERROR_TYPE: + { + standard_error_type = ECMA_ERROR_TYPE; + break; + } + case JERRY_API_ERROR_URI: + { + standard_error_type = ECMA_ERROR_URI; + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + if (message_p == NULL) + { + return ecma_new_standard_error (standard_error_type); + } + else + { + ecma_string_t* message_string_p = ecma_new_ecma_string ((const ecma_char_t*) message_p); + + ecma_object_t* error_object_p = ecma_new_standard_error_with_message (standard_error_type, message_string_p); + + ecma_deref_ecma_string (message_string_p); + + return error_object_p; + } +} + /** * Create an external function object * diff --git a/tests/unit/test_api.cpp b/tests/unit/test_api.cpp index 9947f3421d..84f2d2e28f 100644 --- a/tests/unit/test_api.cpp +++ b/tests/unit/test_api.cpp @@ -34,10 +34,21 @@ const char *test_source = ( "this.t = 12; " "} " "this.A = A; " - "this.a = new A ();" - "function call_external () {" - " return this.external ('1', true);" - "}" + "this.a = new A (); " + "function call_external () { " + " return this.external ('1', true); " + "} " + "function call_throw_test() { " + " bool catched = false " + " try { " + " this.throw_test(); " + " } catch (e) { " + " catched = true; " + " assert(e.name == 'TypeError'); " + " assert(e.message == 'error'); " + " } " + " assert(catched); " + "} " ); bool test_api_is_free_callback_was_called = false; @@ -117,6 +128,24 @@ handler (const jerry_api_object_t *function_obj_p, return true; } /* handler */ +static bool +handler_throw_test (const jerry_api_object_t *function_obj_p, + const jerry_api_value_t *this_p, + jerry_api_value_t *ret_val_p, + const jerry_api_value_t args_p[], + const uint16_t args_cnt) +{ + printf ("ok %p %p %p %d %p\n", function_obj_p, this_p, args_p, args_cnt, ret_val_p); + + jerry_api_object_t* error_p = jerry_api_create_error (JERRY_API_ERROR_TYPE, "error"); + + test_api_init_api_value_object (ret_val_p, error_p); + + jerry_api_release_object (error_p); + + return false; +} + static void handler_construct_freecb (uintptr_t native_p) { @@ -162,6 +191,7 @@ main (void) jerry_api_value_t val_external, val_external_construct, val_call_external; jerry_api_object_t* global_obj_p; jerry_api_object_t* external_func_p, *external_construct_p; + jerry_api_object_t* throw_test_handler_p; jerry_api_value_t res, args[2]; char buffer[32]; @@ -308,8 +338,6 @@ main (void) jerry_api_release_value (&res); assert (!strcmp (buffer, "string from handler")); - jerry_api_release_object (global_obj_p); - // Create native handler bound function object and set it to 'external_construct' variable external_construct_p = jerry_api_create_external_function (handler_construct); assert (external_construct_p != NULL @@ -346,6 +374,36 @@ main (void) jerry_api_release_value (&res); + + // Test: Throwing exception from native handler. + throw_test_handler_p = jerry_api_create_external_function (handler_throw_test); + assert (throw_test_handler_p != NULL + && jerry_api_is_function (throw_test_handler_p)); + + test_api_init_api_value_object (&val_t, throw_test_handler_p); + is_ok = jerry_api_set_object_field_value (global_obj_p, + "throw_test", + &val_t); + assert (is_ok); + jerry_api_release_value (&val_t); + jerry_api_release_object (throw_test_handler_p); + + is_ok = jerry_api_get_object_field_value (global_obj_p, "call_throw_test", &val_t); + assert (is_ok + && val_t.type == JERRY_API_DATA_TYPE_OBJECT); + + is_ok = jerry_api_call_function (val_t.v_object, + global_obj_p, + &res, + NULL, 0); + assert (is_ok); + jerry_api_release_value (&val_t); + jerry_api_release_value (&res); + + + // cleanup. + jerry_api_release_object (global_obj_p); + jerry_cleanup (); assert (test_api_is_free_callback_was_called);